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

@better-iam/adapter-postgres

v0.2.0

Published

PostgreSQL storage adapter for Better IAM, built on Kysely and node-postgres.

Readme

@better-iam/adapter-postgres

PostgreSQL persistence for Better IAM, using Kysely and node-postgres. Requires Node.js 22.12 or later. Install better-iam to receive this adapter with the complete distribution, or install this package directly.

import { postgresAdapter } from '@better-iam/adapter-postgres';

const database = postgresAdapter({ connectionString: process.env.DATABASE_URL! });
await database.migrate();
// Pass database to betterIam({ database, ... }).

poolSize defaults to 10 (allowed range: 1–100). lockTimeoutMs defaults to 5000 (allowed range: 1–60000). Configure transport encryption in the PostgreSQL connection string for your deployment. Keep connection strings and credentials on the server.

Every write must execute inside database.transaction(async tx => ...). Application transactions acquire a database-wide transaction advisory lock before reading data. This serializes write decisions across pools and processes. PostgreSQL READ COMMITTED is intentional: each data read obtains its snapshot after the advisory lock is acquired. An early SERIALIZABLE snapshot could become stale while waiting for the lock. This implementation provides serialized application transactions while favoring clear revocation semantics over concurrent write throughput.

All clients writing Better IAM records must honor the adapter's advisory lock. Never write directly to its tables in application code. Do not perform network requests or long-running work inside transactions. Nested transactions on one adapter join the outer callback; a failed nested operation forces rollback. Do not nest a second adapter's transaction inside the first on the same database. A completed transaction handle rejects later use.

Records use the same schema and strict JSON filter semantics as SQLite. Natural keys are unique within collection and tenant. put updates existing rows and forbids changing tenant ownership. ID sorting and pagination are independent of database locale. Tenant and ID predicates use indexes; remaining JSON filters execute in application code. Large collections with complex JSON filters may require a future indexed adapter implementation.

migrate() checks the schema version and is idempotent. Back up production data before upgrades. close() drains and closes the pool. Database uniqueness conflicts expose IamError code CONFLICT; lock timeouts expose STORAGE_BUSY. Retry the complete operation after a busy response.

The shared generic record schema has no application foreign keys. Better IAM services validate references, tenant boundaries, and hierarchy within transactions. A raw adapter is privileged persistence access, not an authorization boundary.

Integration tests use a dedicated database configured through BETTER_IAM_POSTGRES_URL. They skip explicitly when this environment variable is absent and clean only their randomly named test collection.

License: Apache-2.0.