feat: v0.1.0 — sqlite-migrate package extraction from authd #1

Merged
brendan merged 9 commits from feat/initial-package into main 2026-05-12 09:30:50 +00:00
Owner

Summary

v0.1.0 of bchen-sqlite-migrate. Lifted from authd (PR #14 / merge_commit ced21ab4d16c28a6b5fafa9072b0ae8207ba4bfd) into a standalone ESM-only package installable via git+https://gitea.bchen.dev/brendan/sqlite-migrate.git#v0.1.0.

One deliberate API change vs. authd's source: the previously-hardcoded GENESIS_PROBE_TABLE = 'users' is now an ApplyOptions.genesisProbeTable?: string parameter (default 'users', preserving authd back-compat).

What's in v0.1.0

  • applyMigrations(db, dir, opts?) — forward-only runner with checksum guard, idempotent re-apply, transactional per-migration, genesis-stamping for pre-existing prod DBs.
  • listMigrations(dir), readAppliedRows(db), stampMigration(db, dir, version) — introspection + manual stamp helpers.
  • runMigrateCli({ openDb, migrationsDir, command, ... }) — sub-path export bchen-sqlite-migrate/cli; consumers wire a ~5-line shim.
  • Pre-built dist/*.js + dist/*.d.ts (ESM, Node 20+).
  • Peer-dep: better-sqlite3 >=11 <13 (resolved to 12.6.2 in devDeps to match authd).
  • Test runner: vitest@^4.0.0 — installed as 4.1.6 from npm.

Test coverage

  • 9 specs lifted from authd (adapted to write fixtures into a temp dir; the package ships no migrations dir of its own).
  • 3 new specs covering the genesisProbeTable parameterization:
    1. probe-table-not-present + stampGenesis=false -> first migration runs normally.
    2. genesisProbeTable=undefined defaults to 'users' (authd back-compat).
    3. genesisProbeTable='sessions' correctly stamps a buchinese-shaped DB.
  • 3 new CLI specs for runMigrateCli (migrate / status / stamp + missing-version error path).
  • Total: 15 specs, all green via npm test.

Lockfile-verified

npm ci on linux/x64 sandbox after a clean rm -rf node_modules passes typecheck + build + test + git diff --exit-code dist/ (the CI parity flow). No Dockerfile since this is a published-package repo, not a deployed service. Cold install from git+https://gitea.bchen.dev/...#v0.1.0 will be exercised when the first adoption PR lands.

Pack surface

npm pack --dry-run lists exactly: LICENSE, README.md, dist/cli.{d.ts,js}, dist/index.{d.ts,js}, dist/migrate.{d.ts,js}, package.json. No src/ or tests/ leak.

Security

None. This is a server-side library with no HTTP surface, no secret handling, no user input crossing a trust boundary. db.exec(file.body) runs migration SQL verbatim — by design (migrations are trusted, committed-to-repo SQL). README documents the consumer responsibility (don't point migrationsDir at untrusted content).

Environment

None. No new env vars introduced.

## Summary v0.1.0 of `bchen-sqlite-migrate`. Lifted from authd (PR #14 / merge_commit `ced21ab4d16c28a6b5fafa9072b0ae8207ba4bfd`) into a standalone ESM-only package installable via `git+https://gitea.bchen.dev/brendan/sqlite-migrate.git#v0.1.0`. One deliberate API change vs. authd's source: the previously-hardcoded `GENESIS_PROBE_TABLE = 'users'` is now an `ApplyOptions.genesisProbeTable?: string` parameter (default `'users'`, preserving authd back-compat). ## What's in v0.1.0 - `applyMigrations(db, dir, opts?)` — forward-only runner with checksum guard, idempotent re-apply, transactional per-migration, genesis-stamping for pre-existing prod DBs. - `listMigrations(dir)`, `readAppliedRows(db)`, `stampMigration(db, dir, version)` — introspection + manual stamp helpers. - `runMigrateCli({ openDb, migrationsDir, command, ... })` — sub-path export `bchen-sqlite-migrate/cli`; consumers wire a ~5-line shim. - Pre-built `dist/*.js` + `dist/*.d.ts` (ESM, Node 20+). - Peer-dep: `better-sqlite3 >=11 <13` (resolved to 12.6.2 in devDeps to match authd). - Test runner: `vitest@^4.0.0` — installed as 4.1.6 from npm. ## Test coverage - 9 specs lifted from authd (adapted to write fixtures into a temp dir; the package ships no migrations dir of its own). - 3 new specs covering the `genesisProbeTable` parameterization: 1. `probe-table-not-present + stampGenesis=false` -> first migration runs normally. 2. `genesisProbeTable=undefined` defaults to `'users'` (authd back-compat). 3. `genesisProbeTable='sessions'` correctly stamps a buchinese-shaped DB. - 3 new CLI specs for `runMigrateCli` (migrate / status / stamp + missing-version error path). - Total: **15 specs, all green** via `npm test`. ## Lockfile-verified `npm ci` on linux/x64 sandbox after a clean `rm -rf node_modules` passes typecheck + build + test + `git diff --exit-code dist/` (the CI parity flow). No Dockerfile since this is a published-package repo, not a deployed service. Cold install from `git+https://gitea.bchen.dev/...#v0.1.0` will be exercised when the first adoption PR lands. ## Pack surface `npm pack --dry-run` lists exactly: `LICENSE`, `README.md`, `dist/cli.{d.ts,js}`, `dist/index.{d.ts,js}`, `dist/migrate.{d.ts,js}`, `package.json`. No `src/` or `tests/` leak. ## Security None. This is a server-side library with no HTTP surface, no secret handling, no user input crossing a trust boundary. `db.exec(file.body)` runs migration SQL verbatim — **by design** (migrations are trusted, committed-to-repo SQL). README documents the consumer responsibility (don't point `migrationsDir` at untrusted content). ## Environment None. No new env vars introduced.
brendan added 8 commits 2026-05-12 09:21:11 +00:00
Forward-only SQLite migration runner lifted from authd (src/db/migrate.ts,
PR #14 / merge ced21ab) and parameterized for cross-project use. The single
deliberate API change vs. authd's source: the previously-hardcoded
GENESIS_PROBE_TABLE = 'users' is now an ApplyOptions.genesisProbeTable?: string
option (default 'users').
Extracts the union of authd's three CLI scripts (db-migrate.ts,
db-status.ts, db-stamp.ts) into one wrapper. Consumers wire a ~5-line shim
that injects their own openDb / migrationsDir / config-loading logic. The
wrapper returns an exit code rather than calling process.exit, which keeps
it testable via PassThrough stream capture.
15 vitest specs total:
- 9 lifted from authd's tests/db/migrate.test.ts. Specs that referenced
  the on-disk migrations dir now write fixtures into a per-test tmpdir
  (package ships no migrations dir of its own).
- 3 new specs covering the genesisProbeTable parameter (default, custom
  table name, opt-out via stampGenesis=false).
- 3 new specs covering runMigrateCli (migrate / status / stamp) using
  PassThrough stream capture.
ESM-only, Node 20+, ships pre-compiled dist/. Peer dependency on
better-sqlite3 >=11 <13. Dev pins: typescript ^5.5, vitest ^4.0
(resolved to 4.1.6), better-sqlite3 12.6.2 (matches authd).

tsconfig.json (noEmit) is the dev/test config; tsconfig.build.json
extends it and emits .js + .d.ts to dist/. Relative imports inside src/
use .js extensions so the emitted JS resolves correctly at runtime.
Appended '\!/dist/' override to the bottom of .gitignore so the committed
build output is tracked. node_modules and other Nuxt-template-default
entries remain ignored. Verified with 'git check-ignore -v dist/index.js'
(no match, exit 1).
Runs npm ci, typecheck, build, test, and a 'git diff --exit-code dist/'
gate that catches 'forgot to re-run npm run build' before merge. Fires on
PR / push to main / push to v* tags.
Install via git+https with pinned tag, quick-start, API reference for the
4 runtime exports + the CLI sub-path, genesis-stamping explainer, the
per-consumer probe-table table for the six fleet consumers, security note
on the trusted-SQL boundary.
build: regenerate dist/ for v0.1.0
All checks were successful
ci / test (pull_request) Successful in 17s
accd3ca340
Pre-compiled ESM JS + .d.ts from tsconfig.build.json. Consumers install
via 'git+https://gitea.bchen.dev/...#v0.1.0' so the built output must
travel with the source. CI verifies in-sync via 'git diff --exit-code
dist/'.
brendan added 1 commit 2026-05-12 09:25:22 +00:00
refactor: dedupe INSERT SQL and DDL exec in migrate.ts
All checks were successful
ci / test (pull_request) Successful in 12s
93f5d63f26
- Extract INSERT_MIGRATION_SQL constant; was repeated three times.
- Hoist db.exec(SCHEMA_MIGRATIONS_DDL) above the genesis-stamp branch
  so it is no longer duplicated in both arms of the if/else.
- Prepare insertRow once and reuse it for both genesis-stamping and
  the per-file insert in the apply loop.
- Simplify existence probe in stampMigration to SELECT 1 and drop the
  misleading MigrationRow cast (only existence was checked).
brendan merged commit 7dbce6637c into main 2026-05-12 09:30:50 +00:00
Sign in to join this conversation.