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

@plakboek/db

v0.6.0

Published

Postgres connection factory and migration-lock primitives for Plakboek CMS installations

Readme

@plakboek/db

A Postgres connection factory and a forward-only, lock-safe migration runner for Plakboek CMS installations.

What this package provides

  • createDb -- a Drizzle (drizzle-orm/postgres-js) connection factory over the postgres (porsager) driver.
  • runMigrations -- applies this package's own statically registered migrations, taking a session-scoped Postgres advisory lock internally for the whole run so concurrent migrators can never double-apply (D-03). What Phase 6's deploy step invokes.
  • MigrationLockTimeoutError -- thrown by runMigrations when another migrator still holds that advisory lock after lockWaitMs.
  • The migration authoring convention every migration -- this package's own and every host/host-extension migration -- follows: see MIGRATIONS.md.

Install

pnpm add @plakboek/db drizzle-orm

drizzle-orm is a peer dependency: bring your own version, matching the one this package was built against.

createDb

import { createDb } from '@plakboek/db';

const { db, sql, close } = createDb({
  connectionString: process.env.DATABASE_URL!,
  maxConnections: 10, // optional, default 10
});

// db: a drizzle-orm/postgres-js database instance
// sql: the raw `postgres` tag function, for one-off queries
await close(); // ends the underlying connection pool

createDb validates the connection string's scheme (postgres:// or postgresql://) before connecting, and never echoes the supplied value in an error -- DbConfigError always names the two expected schemes instead.

runMigrations

import { runMigrations } from '@plakboek/db';

const result = await runMigrations({
  connectionString: process.env.DATABASE_URL!,
  lockWaitMs: 60_000, // optional, default 60000
  lockPollIntervalMs: 250, // optional, default 250
  onLockWait: () => console.log('Waiting for the migration lock'), // optional
  onMigrationStart: (name) => console.log(`Applying ${name}`), // optional
});

// result.applied: names of migrations applied by this call
// result.alreadyApplied: names that were already applied before this call

onLockWait fires once, the first time another migrator holds the lock, however long the wait lasts. onMigrationStart(name) fires once per pending migration, just before it applies, and never for an already-applied one. Hooks receive migration names only. A hook that throws is ignored: it never aborts, rolls back or reorders the run.

runMigrations is safe to call from every instance of a rolling deploy: it opens its own connection, holds the advisory lock for the duration of the run, and applies this package's statically registered MIGRATIONS in order. A second overlapping call either observes the first call's migrations as already applied, or throws MigrationLockTimeoutError if it gives up waiting for the lock before the first call finishes.

MIGRATIONS starts with 0001_auth_core, which creates the authentication tables ("user", session, account, verification, two_factor) and the append-only audit_log. 0002_content_engine follows it, creating the content engine tables (content_types, content_type_fields, content_entries, entry_revisions and their history, seed, reference and settings tables) used by @plakboek/content. 0003_page_block_engine creates the page and block-tree tables (pages, page_blocks, block_revisions, page_publications, page_url_history, page_engine_settings) used by @plakboek/pages. See MIGRATIONS.md for how later migrations are added, the transactional-vs-existence-guarded-statement decision, and what each thrown error class means.

Errors

| Class | Meaning | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | DbConfigError | createDb was given an invalid connection string. | | MigrationLockTimeoutError | Another migrator still holds the advisory lock after lockWaitMs. | | MigrationRegistryError | The migration registry itself is structurally invalid. | | MigrationChecksumMismatchError | An already-applied migration's SQL no longer matches its registry entry -- shipped migrations are immutable. | | UnknownAppliedMigrationError | The database has a migration applied that the registry no longer contains. | | MigrationOrderError | A new migration was inserted before one already applied -- migrations must never be reordered. | | MigrationFailedError | A migration's SQL failed to apply; carries the failing statement index (non-transactional) and the original error as cause. |

Full detail, including operator guidance per error, lives in MIGRATIONS.md.