npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@capsium/packager

v0.2.1

Published

Node-side .cap tooling: read/validate packages, generate manifest/routes, SHA-256 checksums, write and extract .cap archives, verify integrity.

Readme

@capsium/packager

Node-side .cap tooling for the Capsium runtime: read, write, sign, encrypt, verify and extract packages, and resolve composite-package dependencies from a store directory.

Status: 0.2.0 — published to npm under the @capsium org (see the repo-root release docs).

Install

npm install @capsium/packager

All classes are small and dependency-injected (file system, archive, hash/signature providers have defaults backed by node:fs and node:crypto).

Reading and writing

import { PackageReader, PackageWriter, IntegrityVerifier } from '@capsium/packager';

const writer = new PackageWriter();
await writer.writeCap('path/to/package-dir', 'out.cap'); // generates manifest/routes/security

const reader = new PackageReader();
const model = await reader.readCap('out.cap'); // validates; verifies signatures when declared

const report = await new IntegrityVerifier().verifyCap('out.cap'); // typed issue list

PackageReader gates on two §6 features while reading:

  • Signatures (§6a): when security.json declares digitalSignatures, the signature is verified against the embedded public key and the package is rejected with SignatureMismatchError on mismatch (signaturePublicKeyPem overrides the embedded key; skipSignatureVerification opts out).
  • Encryption (§6b): an encrypted package (layout below) is decrypted transparently when decryptionKeyPem is given; without a key it is rejected with EncryptedPackageError.

Digital signatures (§6a)

import { PackageSigner } from '@capsium/packager';

const signer = new PackageSigner();
await signer.sign('path/to/package-dir', privateKeyPem, publicKeyPem);
// embeds signature.pub.pem, regenerates security.json (+ digitalSignatures),
// writes signature.sig (raw RSA-SHA256, >= 2048-bit keys enforced)
await signer.verifyDirectory('path/to/package-dir'); // throws typed errors

The signed payload is the concatenation, in sorted package-relative path order, of the bytes of every checksum-covered file — identical to the Ruby gem's construction, verifiable with openssl dgst -sha256 -verify signature.pub.pem -signature signature.sig payload.bin. X.509 certificate PEMs are accepted in place of the public key.

Encryption (§6b)

import { PackageCipher } from '@capsium/packager';

const cipher = new PackageCipher();
await cipher.encrypt('package.cap', recipientPublicKeyPem, 'package.encrypted.cap');
await cipher.decrypt('package.encrypted.cap', recipientPrivateKeyPem, 'package.cap');

Encrypted .cap layout: metadata.json (cleartext), signature.json (cleartext envelope), package.enc (AES-256-GCM ciphertext of the inner zip). The 32-byte DEK is wrapped with the recipient's RSA public key (RSA-OAEP-SHA256, MGF1-SHA256); GCM IV is 12 bytes, auth tag 16 bytes. OpenPGP is out of scope. Wrong keys and tampered ciphertext fail with typed DecryptionErrors.

Composite packages (§4a)

import { StoreDirectory } from '@capsium/packager';

const store = new StoreDirectory(process.env.CAPSIUM_STORE ?? '.capsium-store');
const deps = await store.loadDependencies(model.metadata.dependencies ?? {});
// Map<guid, CapsiumPackage> — newest satisfying version per dependency

A store directory holds <name>-<version>.cap files plus an optional index.json (guid → file). Unsatisfiable dependencies throw DependencyResolutionError.