/** * Tool-discriminated boot-time gate: verify a relational database's * latest-by-name applied migration matches the expected version baked into * the deployed image. Companion to {@link pickLatestPrismaMigration} (which * resolves the expected version FROM disk at synth/runner time); this * helper closes the loop by reading what the DB actually has APPLIED. * * "Latest" MUST mean lexicographic max of migration_name, mirroring * pickLatestPrismaMigration — NOT most recently finished. Prisma's * `migrate deploy` applies a pending migration even when it name-sorts * before already-applied ones (parallel branches landing interleaved * timestamps), so latest-by-finished_at can be an OLDER name than what the * schema actually satisfies, false-failing the gate against a complete DB. * * Consumer supplies the driver via the {@link MigrationsSqlClient} shim so * the package stays driver-agnostic (pg, mysql2, postgres.js, Drizzle * session, raw Prisma `$queryRawUnsafe`, …). The shim's single `query(sql)` * surface is intentionally narrower than any real driver — callers wrap. * * Two tool branches today: * - `tool: "prisma"` reads `_prisma_migrations.migration_name` (max name * among `finished_at IS NOT NULL`). Stable across all Prisma DB engines. * - `tool: "custom"` lets a caller pass a `{ sql, column }` pair when the * migration tool's metadata table doesn't match the Prisma shape (e.g. * Drizzle's `__drizzle_migrations.hash`, Knex's `knex_migrations.name`). * * Returns `{ matches, expected, actual }` rather than throwing on mismatch: * the boot gate's caller owns the exit-code / log shape so the helper can * be reused by integration tests, dashboards, and CLI checks alike. * * `matches` tolerates expand-only rollback: an old image booting against a * NEWER applied schema passes (`actual >= expected`), while the forward * direction (new code against an older schema) still fails. The comparison is * delegated to `isSchemaVersionSatisfied` — see it for the orderability rules. */ /** * Minimal SQL-driver shim. Compatible with `pg.Client.query`, `mysql2.query`, * `postgres()(sql)`, and Drizzle's `db.session.execute()` via a thin adapter. */ export interface MigrationsSqlClient { query(sql: string): Promise<{ rows: ReadonlyArray>; }>; } export interface VerifyExpectedSchemaVersionOpts { /** Migration tool whose metadata table to inspect. */ tool: "prisma" | "custom"; /** Expected version (typically read from an env var baked into the image). */ expected: string; /** SQL driver shim. Consumer owns connection lifecycle. */ client: MigrationsSqlClient; /** Abort signal honoured before the query is issued. */ signal?: AbortSignal; /** * Required when `tool: "custom"`. `sql` MUST return a single row whose * `column` holds the latest applied migration's name/hash. */ customQuery?: { sql: string; column: string; }; } export interface VerifyExpectedSchemaVersionResult { matches: boolean; expected: string; /** `null` when no migrations have been applied (empty result set). */ actual: string | null; } export declare function verifyExpectedSchemaVersion(opts: VerifyExpectedSchemaVersionOpts): Promise;