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

pgmagmig

v0.1.1

Published

PostgreSQL migration tool with integrated schema differ, powered by PGlite

Readme

pgmagmig

A PostgreSQL migration tool with an integrated schema differ, powered by PGlite (PostgreSQL compiled to WASM).

Schema extraction, DDL generation, diffing, and diff validation all run in-process against PGlite. No external PostgreSQL server is required for these operations. A real PostgreSQL server is only needed when applying migrations.

Features

  • Schema extraction: apply SQL to an in-memory PGlite instance, query its system catalogs, produce a JSON representation of the schema.
  • DDL generation: turn a JSON schema back into SQL DDL.
  • Schema diffing: compare two schemas, produce DDL that transforms one into the other. Generates readable CREATE TABLE statements with defaults, constraints, and foreign keys inlined where possible.
  • Automatic diff validation: every diff is verified by applying it to PGlite and comparing the resulting schema to the expected one.
  • Hazard annotations: destructive or lock-heavy statements are tagged with a structured hazard type and human-readable message.
  • Migration drafting: generate a YAML migration file from a schema diff, with up and down SQL and hazard annotations.
  • Migration runner: sequential numbering, up/down, branch switching, per-migration transactions.
  • Ephemeral database: build a PGlite database from any schema source, expose it via Unix socket or TCP, and run a shell command (with DATABASE_URL set in the environment). Works with Prisma, sqlc, pgtyped, psql, or anything that speaks PostgreSQL.

Install

npm install pgmagmig

Requires Node.js 20 or later.

Quick start

Bootstrap a migration directory

pgmagmig bootstrap --migrations-dir ./migrations

Creates 0001.yaml with DDL to set up the management table. The generated YAML file includes a comment with more information on how to switch to pgmagmig for an existing database, or how to start fresh using this migration.

Draft a migration

pgmagmig draft-migration \
  --migrations-dir ./migrations \
  --to-sql schema.sql \
  --title "Add users and orders" \
  --allow-hazards all

Generates a YAML migration file with up/down SQL, validated by roundtripping through PGlite.

Apply migrations

pgmagmig migrate \
  --migrations-dir ./migrations \
  --database-url postgres://localhost/mydb

Diff two schemas

pgmagmig diff --from-sql old.sql --to-sql new.sql

Run a command against an ephemeral PGlite

pgmagmig run \
  --from-migrations-dir ./migrations \
  --command "npx prisma db pull"

Builds a PGlite database from your migrations, exposes it via Unix socket, and runs the given command with DATABASE_URL set to the connection string needed to use this ephemeral database.

CLI commands

| Command | Description | |---------|-------------| | extract | Apply SQL to PGlite, output JSON schema | | generate | Generate DDL from a schema (alias for diff --from-empty) | | diff | Compare two schemas, output DDL | | bootstrap | Write 0001.yaml with management table DDL | | draft-migration | Generate a YAML migration file from a schema diff | | migrate | Apply migrations to a PostgreSQL database | | run | Build PGlite, expose via socket, run a command |

Schema sources

All commands that read schemas accept --from-* and/or --to-* options:

  • --from-sql file1.sql file2.sql: SQL files (order matters)
  • --from-json schema.json: pgmagmig JSON schema file
  • --from-empty: empty schema
  • --from-database postgres://...: live database (read-only)
  • --from-migrations-dir ./migrations: pgmagmig migrations directory (all up-migrations will be applied in order)

Migration files

Migrations are YAML files named 0001.yaml, 0002.yaml, etc. Sequential numbering is enforced: gaps are errors.

title: Create users table
uuid: 7f3b2a1e-8c4d-4e5f-9a6b-1c2d3e4f5a6b
up: |
  CREATE TABLE public.users (
    id SERIAL NOT NULL,
    email text NOT NULL,
    CONSTRAINT users_pkey PRIMARY KEY (id),
    CONSTRAINT users_email_key UNIQUE (email)
  );
down: |
  DROP TABLE public.users;

The down field has three states:

  • SQL string: rollback runs this SQL
  • Empty string: rollback is a no-op (row still removed from management table)
  • Omitted: rollback errors if attempted

Hazards

The differ tags statements with structured hazard types:

| Hazard type | Meaning | |-------------|---------| | DeletesData | Destroys user data (DROP TABLE, DROP COLUMN) | | AcquiresAccessExclusiveLock | Blocks all reads and writes | | RequiresPopulatedTableScan | Scans entire table (SET NOT NULL) | | IndexDropped | May degrade query performance | | IndexBuild | Long-running index build | | Correctness | May break application behaviour | | HasUntrackableDependencies | Drops an object others may depend on |

Use --allow-hazards to acknowledge specific types, or --check-hazards in CI to block on unexpected hazards.

License

ISC