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

@gate-forge/pack-alembic

v0.18.2

Published

Alembic migration obligations pack: static lineage verification, engine-run roundtrip on disposable database, data-preservation checks, and multi-developer merge safety.

Readme

@gate-forge/pack-alembic

Opt-in Alembic migration obligations. A repository without an alembic key in .gateforge.yml behaves exactly as before; no migration obligations are added.

When enabled, Gateforge parses migration scripts with Python AST only, then runs upgrade → downgrade base → upgrade against an engine-created gf_tmp_<id> database and drops it. The trusted admin URL comes only from this configuration, never from the test environment. Suite claims cannot satisfy these obligations.

alembic:
  chains:
    - name: invoices
      migrations: migrations/versions
      models:
        - models.py
      # Optional; defaults shown:
      alembicIni: alembic.ini
      modelsModule: models
      metadata: Base.metadata
  scratch:
    adminUrl: postgresql://gateforge:[email protected]:5432/postgres
  # Optional: seed existing rows, verify counts/fingerprints, and declare renames.
  seed:
    path: tests/seed.sql
    tables:
      - name: invoices
        columns: [id, number]
        copies:
          - from: legacy_number
            to: number
  # Optional owner-approved irreversible revisions.
  irreversible: []
  # Optional; validates against target branch merge result.
  merge:
    targetRef: origin/main

gateforge init prints an opt-in template when alembic.ini exists; it does not enable the pack. Add the block to .gateforge.yml, provide a disposable Postgres service and a trusted admin URL, then run gateforge check.

The migration runner requires Alembic, SQLAlchemy, and a PostgreSQL driver (psycopg or psycopg2) in its Python environment. It does not import the project's env.py. The runner snapshots tables, columns, constraints, indexes, enums, and sequences, excluding alembic_version. With seed, it compares row counts and declared column fingerprints across the migration. A configured merge target is tested in a temporary Git worktree.

Cause codes (all additive): MIGRATION_MISSING, MIGRATION_LINEAGE_BROKEN, MIGRATION_DOWNGRADE_NOOP, MIGRATION_DRIFT, MIGRATION_ROUNDTRIP_FAILED, MIGRATION_DATA_LOST, MIGRATION_CONFLICT, MIGRATION_SCRATCH_UNSAFE.

Failure matrix

test/scanner.test.ts covers the static cases without a database: duplicate revision ids, dangling parents, and multiple heads, all read with Python AST only.

test/postgres.e2e.test.ts covers the engine-run cases on a disposable PostgreSQL instance. It is skipped, with a printed reason, unless GATEFORGE_ALEMBIC_TEST_ADMIN_URL is set to an admin URL of a throwaway instance (for example a CI postgres service container). GATEFORGE_ALEMBIC_TEST_PYTHON optionally selects an interpreter that already has Alembic, SQLAlchemy, and a PostgreSQL driver; it defaults to python3.

| Case | Cause code | | --- | --- | | model changed with no migration in the same change | MIGRATION_MISSING | | downgrade() is empty or incomplete | MIGRATION_DOWNGRADE_NOOP | | migration chain does not match the models | MIGRATION_DRIFT | | destructive rename after the seed is loaded | MIGRATION_DATA_LOST | | two branches alter the same table, merge result keeps two heads | MIGRATION_CONFLICT | | merge revision breaks a seeded row on the merge result | MIGRATION_DATA_LOST | | failure injected right after the scratch database is created | MIGRATION_ROUNDTRIP_FAILED, database dropped |

The suite also asserts that only the gf_tmp_<id> name recorded during the run is dropped: a similarly named existing database and the configured application database both survive with their data.

packages/cli/test/alembic-first-run.test.ts proves the setup flow end to end: it copies examples/alembic into a fresh repository, runs gateforge init, writes the printed opt-in block verbatim (with the trusted admin URL filled in), and runs check and next. Without the block the run compiles no obligation at all; with it the engine witnesses the chain on a disposable database and the honest example produces no migration finding. Editing the model afterwards makes check and next report MIGRATION_DRIFT. It is skipped, with a printed reason, unless GATEFORGE_ALEMBIC_TEST_ADMIN_URL is set, and it needs python3 to carry Alembic, SQLAlchemy, and a PostgreSQL driver because the engine runs python3 exactly as production does.