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

@cipherstash/stack

v1.1.1

Published

CipherStash Stack for TypeScript and JavaScript

Readme

Encryption-level security without the pain

Field-level encryption is the strongest way to protect data. But if DB functionality or performance suffers, you need to justify the pain. Searchable Encryption nukes the trade-off: encryption-level security without the pain.

  • Searchable Encryption for any Postgres including Supabase, RDS, Aurora, Prisma Postgres and Neon
  • Works with Supabase.js, Prisma Next, Drizzle or plain SQL
  • Built-in key management — automatic rotation, auditing and up to 14x faster than AWS KMS
  • Integrates with Supabase Auth, Clerk, Auth0 and Okta

Quick starts

Use the wizard

Takes 5-10 minutes, starts on the free developer tier (sign up), includes agent handoff.

# Run this to start (or just ask Claude to)
npx stash init

ORM/database-specific guides

| Quick start | Guide | |---|---| | Supabase | Supabase quickstart → | | Prisma Next | Prisma Next quickstart → | | Drizzle ORM | Drizzle quickstart → | | Raw PostgreSQL (pg) | PostgreSQL quickstart → | | DynamoDB | DynamoDB quickstart → |

The Stack also ships a stash CLI for auth, schema, and database setup. See the SDK reference.

What's in the Stack

🔐 Searchable encryption

Encrypt individual fields and still run real queries against them — all on ciphertext, in PostgreSQL:

| Query type | Operations | Docs | |---|---|---| | Equality | =, IN | Equality queries → | | Free-text search | fuzzy matches | Text search → | | Range & ordering | <, >, BETWEEN, ORDER BY, MIN/MAX | Range queries → | | Encrypted JSON | containment (@>), JSONPath selectors | JSON queries → |

With EQL v3, the column type is the configuration. Declare a column with the encrypted type that names its data type and the operations it supports, and it's ready to query — there's no per-column search configuration to maintain in your client:

CREATE TABLE users (
  id          serial PRIMARY KEY,
  username    text,                    -- plaintext — business as usual
  email       eql_v3_text_match,       -- encrypted · free-text search
  ssn         eql_v3_text_eq,          -- encrypted · equality
  salary      eql_v3_integer_ord,      -- encrypted · range + ORDER BY
  preferences eql_v3_json_search       -- encrypted · containment + selectors
);

Encrypted types exist for text, integers, floats, numerics, dates, timestamps, booleans, and JSON, so your schema documents itself — and encrypted data stays indexable with standard Postgres indexes. No special index engine, no SQL rewrites. ORMs pick the types up transparently: declare the column as encrypted in schema.prisma or your Drizzle table and the Stack handles the rest. Only raw pg needs a client-side schema — declared with the same type names:

import { encryptedTable, types } from "@cipherstash/stack/v3";

const users = encryptedTable("users", {
  email: types.TextMatch("email"),       // ↔ eql_v3_text_match
  salary: types.IntegerOrd("salary"),    // ↔ eql_v3_integer_ord
});

Searchable encryption · Schema · Encrypt & decrypt · Bulk & model operations

🔑 Authentication

How you authenticate to ZeroKMS depends on who's asking for keys:

  • Device auth — browser-based login for local development: npx stash auth login opens your browser and saves credentials to your local CipherStash profile. No secrets in your repo or shell.
  • Access key auth — service-level credentials for servers, workers, and CI, supplied via CS_* environment variables.
  • OIDC federation — federate your identity provider's JWT so every key request authenticates as the signed-in user, not as your app. Supported providers: Supabase Auth, Clerk, Okta, and Auth0 (any OIDC-compliant provider works).
// Access key (default) — reads CS_* env vars, no config needed
const client = await Encryption({ schemas: [users] });

// OIDC federation — every ZeroKMS request authenticates as the end user
const client = await Encryption({
  schemas: [users],
  config: { authStrategy: OidcFederationStrategy.create(workspaceCrn, () => getUserJwt()) },
});

Authentication

🗝️ Built-in key management

Key management is built in, powered by ZeroKMS — no AWS KMS to wire up, no key vault to run, no rotation schedule to babysit:

  • A unique key for every value — not one key per table or per database.
  • Automatic key rotation — handled for you, with zero downtime.
  • CipherStash can never see your keys. Keys are derived inside your application; neither plaintext keys nor plaintext data ever leave your infrastructure.
  • Fast at scale — bulk key operations handle up to 10,000 keys in a single call, up to 14× faster than AWS KMS at peak (benchmarks).
  • Every decryption is logged — a built-in audit trail of who decrypted what, and when.

CipherStash never sees your plaintext — or your keys. Data is encrypted in your app with a unique key per value, and keys are derived inside your application via ZeroKMS — so a database breach leaks only ciphertext. See the security architecture →

Advanced features

👤 Identity-locking encryption

Building on OIDC federation, you can bind a record's encryption key to the end user's identity, so only that user can decrypt their data: .withLockContext({ identityClaim }) ties the data key to a claim in the user's JWT, enforced cryptographically by ZeroKMS.

// Bind the data key to a claim — the same claim is required to decrypt
await client
  .encrypt("[email protected]", { table: users, column: users.email })
  .withLockContext({ identityClaim: ["sub"] });

Identity-locking encryption

🗂️ Keysets for multitenancy & sovereignty

Partition your keys into keysets — independent key hierarchies within a single workspace. Give each tenant its own keyset (config.keyset) for cryptographic tenant isolation: every encrypt, decrypt, and query is scoped to a keyset, so revoking a client's access to a keyset makes that tenant's data unreadable until the grant is restored — without re-architecting your app. Keysets →

Encrypted fields. Real queries. Your tools.

The email column below is stored as ciphertext with a unique key per row — and the search still works, because the query runs on the ciphertext. No decrypt-and-scan, no query rewrites.

Supabase — same Supabase.js calls; the wrapper introspects your schema, encrypts filters on the way in, and decrypts results on the way out:

const db = await encryptedSupabase(supabaseUrl, supabaseKey);

const { data } = await db.from("users")
  .select("id, name, email")
  .eq("email", "[email protected]"); // encrypted equality — runs on ciphertext

Prisma Next — declare encrypted columns in schema.prisma, query with type-safe operators:

model User {
  id    String @id
  email cipherstash.TextSearch()
}
const rows = await db.orm.public.User
  .where((u) => u.email.eqlMatch("acme.com"))
  .all();

Drizzle — encrypted column types in your table, auto-encrypting operators in your queries:

export const usersTable = pgTable("users", {
  id: integer("id").primaryKey(),
  email: types.TextSearch("email"), // → eql_v3_text_search — the type is the config
});

const results = await db.select().from(usersTable)
  .where(await ops.matches(usersTable.email, "acme.com"));

How it works

Encryption happens in your application. Ciphertext is stored as an EQL payload in your database; plaintext and keys never reach CipherStash. Per-value keys are issued in bulk by ZeroKMS (so millions of unique keys stay fast), and every decryption is logged for compliance.

Security architecture · ZeroKMS

Performance

Encrypted queries stay fast — latency is flat from 10k to 10M rows. Measured on EQL v3 in cipherstash/benches:

| Operation | Median latency (up to 10M rows) | |---|---| | Equality lookup | ~0.1 ms | | Range query | ~0.5 ms | | JSON field equality | ~0.1 ms |

Why CipherStash

  • Trusted data access — only your end-users can access their sensitive data, enforced cryptographically.
  • Shrink the blast radius — a breached vulnerability exposes only what one user can decrypt, not your whole table.
  • Audit trail built in — every decryption event is recorded, no extra tooling to bolt on.
  • Meet compliance faster — exceed the encryption requirements of SOC 2 and ISO 27001, with FIPS-compliant cryptography and BYOK for teams that need it.

FAQ

No, never. Encryption and decryption happen in your application, and keys are derived within your own environment. Plaintext and keys never leave your control and never reach CipherStash.

Latency stays flat as data grows — exact-match lookups hold at ~0.1 ms and range queries at ~0.5 ms from 10k up to 10M rows (cipherstash/benches). ZeroKMS handles keys in bulk (up to 10,000 per call), so key management isn't the bottleneck.

Install EQL on your Postgres database (npx stash init and the quick starts handle this), declare the columns you want protected with the encrypted type that fits each one (for example eql_v3_text_match for searchable text or eql_v3_integer_ord for range queries), and encrypt values in your app before writing. You can adopt it column-by-column — no big-bang rewrite — and your existing Postgres indexes keep working.

Barely. You keep your query builder: Supabase.js filters work unchanged, and Drizzle and Prisma Next add encrypted-aware operators (ops.eq, ops.matches, eqlMatch, …) that take plaintext and encrypt it for you. There are no SQL rewrites.

No. Key management is built in through ZeroKMS. If you want to control the root key, Bring Your Own Key lets you root it in your own KMS.

Yes. It integrates with Supabase Auth and runs alongside RLS — it complements them, it doesn't replace them.

RLS and CipherStash solve different problems, and they're strongest together. RLS decides which rows a role may query, but the data underneath is plaintext — so anything that bypasses RLS reveals it in the clear: a leaked service_role key, a misconfigured policy, a SQL injection running as an elevated role, a stolen backup, or the database host itself. CipherStash stores only ciphertext and keeps the keys outside the database, so those same bypasses reveal nothing readable. Keep RLS for authorization; add CipherStash so a bypass never becomes a breach.

Yes — a free developer tier, so you can build encryption in from day one.

Start free

Encryption is far cheaper to design in than to retrofit — and it's what unlocks regulated and enterprise customers. The developer tier is free, so you can add encryption from your very first migration:

npx stash init

Signing up is the wizard's first step if you don't have an account yet — or create your free account in the browser first, and stash init will pick it up.

Install

npm install @cipherstash/stack   # or: yarn / pnpm / bun add @cipherstash/stack

[!IMPORTANT] Opt out of bundling @cipherstash/stack. It uses native Node.js features (a Rust FFI module) and the native require. For edge and serverless runtimes (Cloudflare Workers, Deno, Bun), use the bundler-friendly @cipherstash/stack/wasm-inline entry instead. Bundling guide →

Requirements: Node.js ≥ 22.

Documentation & community

Contributing · Security · License

Contributions are welcome — see CONTRIBUTING.md. For our security policy and responsible disclosure, see SECURITY.md. MIT licensed.