@ingram-tech/nk-db 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/id.d.ts ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The Ingram id codec — a UUIDv7 and its base58 skin. It lives here in nk-db
3
+ * (the lowest package in the graph) behind the `@ingram-tech/nk-db/id` subpath,
4
+ * so it stays `node:crypto`-only — no `pg` / `drizzle` — and any site can mint
5
+ * ids without pulling a heavier slice.
6
+ *
7
+ * The Python twin lives in cloud.ingram.tech's `v1/core.py` (`new_id`); the
8
+ * byte → string vectors in `id.test.ts` and that repo's `tests/test_ids.py` are
9
+ * kept identical, so a stored UUIDv7 and an `agt_` / `smt_` id from the API are
10
+ * the same encoding of the same 16 bytes. That cross-impl contract is the most
11
+ * important property of this file — keep the vectors in lockstep.
12
+ *
13
+ * Store the hyphenated UUIDv7 at rest (uuid columns stay native and time-ordered
14
+ * for index locality) and use {@link toPrefixedId} to skin it as a prefixed
15
+ * base58 id for the wire / display, {@link fromPrefixedId} to recover it.
16
+ * {@link base58Id} mints a fresh one directly; {@link createIdRegistry} builds a
17
+ * typed, prefix-validated set of helpers for a project's entities.
18
+ */
19
+ /**
20
+ * Mint a **UUIDv7** (RFC 9562): a 48-bit Unix-ms timestamp prefix + random tail,
21
+ * version `7`, variant `10`. UUID-shaped (drops straight into a `uuid` column)
22
+ * while staying time-ordered for index locality. Used as Better Auth's
23
+ * `advanced.database.generateId`. Node/Bun's `randomUUID` is v4-only, so we lay
24
+ * the bytes out by hand.
25
+ */
26
+ export declare const uuidGenerateId: () => string;
27
+ /** Skin a stored hyphenated UUIDv7 as a prefixed base58 id, e.g. `team_…`. */
28
+ export declare function toPrefixedId(uuid: string, prefix: string): string;
29
+ /** Inverse of {@link toPrefixedId}: recover the hyphenated UUIDv7. */
30
+ export declare function fromPrefixedId(id: string): string;
31
+ /** Mint a fresh prefixed base58 id (UUIDv7 core), for text-id sites / API parity. */
32
+ export declare function base58Id(prefix: string): string;
33
+ /** Typed helpers for one entity's prefixed ids — built by {@link createIdRegistry}. */
34
+ export interface IdHelper {
35
+ /** This entity's prefix, e.g. `"agt"` (no trailing underscore). */
36
+ readonly prefix: string;
37
+ /** Mint a fresh prefixed id (new UUIDv7 core). */
38
+ mint(): string;
39
+ /** Skin a stored hyphenated UUIDv7 as this entity's prefixed id. */
40
+ encode(uuid: string): string;
41
+ /** Recover the hyphenated UUIDv7; throws if the prefix / shape doesn't match. */
42
+ decode(id: string): string;
43
+ /** Whether `id` is a well-formed prefixed id for this entity. */
44
+ is(id: string): boolean;
45
+ }
46
+ /** The map returned by {@link createIdRegistry}: one {@link IdHelper} per key. */
47
+ export type IdRegistry<K extends string> = Record<K, IdHelper>;
48
+ /**
49
+ * Build a typed, prefix-validated id registry for a project's entities — one
50
+ * place to declare every prefix instead of hand-rolling encode/decode wrappers:
51
+ *
52
+ * ```ts
53
+ * const ids = createIdRegistry({ org: "org", agent: "agt", session: "cs" });
54
+ * ids.org.mint(); // "org_3k9…"
55
+ * ids.org.encode(uuid); // "org_…"
56
+ * ids.org.decode("org_…"); // uuid — throws on a wrong / missing prefix
57
+ * ids.agent.is(someId); // boolean
58
+ * ```
59
+ */
60
+ export declare function createIdRegistry<const T extends Record<string, string>>(prefixes: T): {
61
+ [K in keyof T]: IdHelper;
62
+ };
63
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,QAAO,MAYjC,CAAC;AAuDF,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACxB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,IAAI,IAAI,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,iFAAiF;IACjF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,iEAAiE;IACjE,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,kFAAkF;AAClF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,IAAI,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAiB/D;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtE,QAAQ,EAAE,CAAC,GACT;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,QAAQ;CAAE,CAM9B"}
package/dist/id.js ADDED
@@ -0,0 +1,138 @@
1
+ import { randomBytes } from "node:crypto";
2
+ /**
3
+ * The Ingram id codec — a UUIDv7 and its base58 skin. It lives here in nk-db
4
+ * (the lowest package in the graph) behind the `@ingram-tech/nk-db/id` subpath,
5
+ * so it stays `node:crypto`-only — no `pg` / `drizzle` — and any site can mint
6
+ * ids without pulling a heavier slice.
7
+ *
8
+ * The Python twin lives in cloud.ingram.tech's `v1/core.py` (`new_id`); the
9
+ * byte → string vectors in `id.test.ts` and that repo's `tests/test_ids.py` are
10
+ * kept identical, so a stored UUIDv7 and an `agt_` / `smt_` id from the API are
11
+ * the same encoding of the same 16 bytes. That cross-impl contract is the most
12
+ * important property of this file — keep the vectors in lockstep.
13
+ *
14
+ * Store the hyphenated UUIDv7 at rest (uuid columns stay native and time-ordered
15
+ * for index locality) and use {@link toPrefixedId} to skin it as a prefixed
16
+ * base58 id for the wire / display, {@link fromPrefixedId} to recover it.
17
+ * {@link base58Id} mints a fresh one directly; {@link createIdRegistry} builds a
18
+ * typed, prefix-validated set of helpers for a project's entities.
19
+ */
20
+ /**
21
+ * Mint a **UUIDv7** (RFC 9562): a 48-bit Unix-ms timestamp prefix + random tail,
22
+ * version `7`, variant `10`. UUID-shaped (drops straight into a `uuid` column)
23
+ * while staying time-ordered for index locality. Used as Better Auth's
24
+ * `advanced.database.generateId`. Node/Bun's `randomUUID` is v4-only, so we lay
25
+ * the bytes out by hand.
26
+ */
27
+ export const uuidGenerateId = () => {
28
+ const bytes = randomBytes(16);
29
+ const ts = Date.now();
30
+ bytes[0] = Math.floor(ts / 2 ** 40) & 0xff;
31
+ bytes[1] = Math.floor(ts / 2 ** 32) & 0xff;
32
+ bytes[2] = Math.floor(ts / 2 ** 24) & 0xff;
33
+ bytes[3] = Math.floor(ts / 2 ** 16) & 0xff;
34
+ bytes[4] = Math.floor(ts / 2 ** 8) & 0xff;
35
+ bytes[5] = ts & 0xff;
36
+ bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x70; // version 7
37
+ bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80; // variant 10
38
+ return bytesToUuid(bytes);
39
+ };
40
+ const B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
41
+ // ceil(128 / log2(58)): a 16-byte value never needs more than 22 digits. We
42
+ // left-pad to it so every body is uniform width and sorts lexically ==
43
+ // chronologically (UUIDv7's ms-timestamp prefix lives in the high bytes).
44
+ const WIDTH = 22;
45
+ // A bare base58 body: 22 chars, Bitcoin alphabet (no 0 / I / O / l).
46
+ const BODY = "[1-9A-HJ-NP-Za-km-z]{22}";
47
+ /** Big-endian base58 (Bitcoin alphabet) of 16 bytes, left-padded to `WIDTH`. */
48
+ function encode58(bytes) {
49
+ let n = 0n;
50
+ for (const b of bytes)
51
+ n = (n << 8n) | BigInt(b);
52
+ let out = "";
53
+ while (n > 0n) {
54
+ out = B58.charAt(Number(n % 58n)) + out;
55
+ n /= 58n;
56
+ }
57
+ return out.padStart(WIDTH, B58.charAt(0));
58
+ }
59
+ /** Inverse of {@link encode58}: a base58 body back to 16 bytes. */
60
+ function decode58(body) {
61
+ let n = 0n;
62
+ for (const ch of body) {
63
+ const v = B58.indexOf(ch);
64
+ if (v < 0)
65
+ throw new Error(`invalid base58 char: ${ch}`);
66
+ n = n * 58n + BigInt(v);
67
+ }
68
+ const bytes = new Uint8Array(16);
69
+ for (let i = 15; i >= 0; i--) {
70
+ bytes[i] = Number(n & 0xffn);
71
+ n >>= 8n;
72
+ }
73
+ return bytes;
74
+ }
75
+ /** A hyphenated UUID string → its 16 raw bytes. */
76
+ function uuidToBytes(uuid) {
77
+ const hex = uuid.replace(/-/g, "");
78
+ if (!/^[0-9a-fA-F]{32}$/.test(hex))
79
+ throw new Error(`not a uuid: ${uuid}`);
80
+ const bytes = new Uint8Array(16);
81
+ for (let i = 0; i < 16; i++) {
82
+ bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
83
+ }
84
+ return bytes;
85
+ }
86
+ /** 16 raw bytes → a canonical hyphenated UUID string. */
87
+ function bytesToUuid(bytes) {
88
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
89
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
90
+ }
91
+ /** Skin a stored hyphenated UUIDv7 as a prefixed base58 id, e.g. `team_…`. */
92
+ export function toPrefixedId(uuid, prefix) {
93
+ return `${prefix}_${encode58(uuidToBytes(uuid))}`;
94
+ }
95
+ /** Inverse of {@link toPrefixedId}: recover the hyphenated UUIDv7. */
96
+ export function fromPrefixedId(id) {
97
+ const body = id.slice(id.indexOf("_") + 1);
98
+ return bytesToUuid(decode58(body));
99
+ }
100
+ /** Mint a fresh prefixed base58 id (UUIDv7 core), for text-id sites / API parity. */
101
+ export function base58Id(prefix) {
102
+ return toPrefixedId(uuidGenerateId(), prefix);
103
+ }
104
+ function makeHelper(prefix) {
105
+ // Prefixes are developer-controlled identifier constants, never user input.
106
+ const matcher = new RegExp(`^${prefix}_${BODY}$`);
107
+ return {
108
+ prefix,
109
+ mint: () => base58Id(prefix),
110
+ encode: (uuid) => toPrefixedId(uuid, prefix),
111
+ decode: (id) => {
112
+ if (!matcher.test(id))
113
+ throw new Error(`not a ${prefix}_ id: ${id}`);
114
+ return fromPrefixedId(id);
115
+ },
116
+ is: (id) => matcher.test(id),
117
+ };
118
+ }
119
+ /**
120
+ * Build a typed, prefix-validated id registry for a project's entities — one
121
+ * place to declare every prefix instead of hand-rolling encode/decode wrappers:
122
+ *
123
+ * ```ts
124
+ * const ids = createIdRegistry({ org: "org", agent: "agt", session: "cs" });
125
+ * ids.org.mint(); // "org_3k9…"
126
+ * ids.org.encode(uuid); // "org_…"
127
+ * ids.org.decode("org_…"); // uuid — throws on a wrong / missing prefix
128
+ * ids.agent.is(someId); // boolean
129
+ * ```
130
+ */
131
+ export function createIdRegistry(prefixes) {
132
+ const reg = {};
133
+ for (const [key, prefix] of Object.entries(prefixes)) {
134
+ reg[key] = makeHelper(prefix);
135
+ }
136
+ return reg;
137
+ }
138
+ //# sourceMappingURL=id.js.map
package/dist/id.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.js","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=migrate-bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-bin.d.ts","sourceRoot":"","sources":["../src/migrate-bin.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ // The `nk-pg-migrate` bin — a drop-in replacement for `drizzle-kit migrate` in a
3
+ // site's `db:migrate` script. Unlike drizzle-kit it surfaces the real Postgres
4
+ // error on failure (not an opaque exit 1), refuses to run against a drifted
5
+ // journal with an actionable message, and can reconcile a drifted-but-correct
6
+ // journal with `--baseline`.
7
+ //
8
+ // Connection comes from the env contract (DATABASE_URL [+ DATABASE_CA_CERT], or
9
+ // the nk-db `dbEnv()` vars). Run it via `bun run db:migrate` so the runner loads
10
+ // your `.env` / `.env.local` into the environment first.
11
+ //
12
+ // nk-pg-migrate apply pending migrations
13
+ // nk-pg-migrate --status print journal status, apply nothing
14
+ // nk-pg-migrate --baseline record the current file chain as applied,
15
+ // WITHOUT running DDL (push-built / regenerated
16
+ // baseline whose schema already matches)
17
+ // nk-pg-migrate --migrations <folder> (default: drizzle)
18
+ //
19
+ // Run directly by Node, so the relative import carries a `.js` extension.
20
+ import { baselineMigrations, inspectMigrations, MigrationDriftError, runMigrations, } from "./migrate.js";
21
+ const argv = process.argv.slice(2);
22
+ const flag = (name) => argv.includes(name);
23
+ const value = (name) => {
24
+ const i = argv.indexOf(name);
25
+ return i >= 0 ? argv[i + 1] : undefined;
26
+ };
27
+ const migrationsFolder = value("--migrations") ?? value("--migrations-folder") ?? "drizzle";
28
+ const main = async () => {
29
+ if (flag("--status")) {
30
+ const s = await inspectMigrations({ migrationsFolder });
31
+ console.log(`nk-pg-migrate: ${s.files.length} file(s), ${s.recorded.length} recorded, ${s.pending.length} pending${s.drifted ? " — DRIFTED" : ""}`);
32
+ if (s.drift)
33
+ console.log(` drift: ${s.drift.reason}`);
34
+ if (s.pending.length)
35
+ console.log(` pending: ${s.pending.map((m) => m.tag).join(", ")}`);
36
+ return;
37
+ }
38
+ if (flag("--baseline")) {
39
+ const { recorded } = await baselineMigrations({ migrationsFolder });
40
+ console.log(`nk-pg-migrate: baselined journal to ${recorded.length} migration(s) — recorded as applied, no DDL run.`);
41
+ return;
42
+ }
43
+ const { applied } = await runMigrations({ migrationsFolder });
44
+ console.log(applied.length
45
+ ? `nk-pg-migrate: applied ${applied.length} migration(s) — ${applied.join(", ")}`
46
+ : "nk-pg-migrate: up to date, nothing to apply.");
47
+ };
48
+ main().catch((error) => {
49
+ if (error instanceof MigrationDriftError) {
50
+ console.error(`nk-pg-migrate: ${error.message}`);
51
+ process.exit(2);
52
+ }
53
+ console.error("nk-pg-migrate: migration failed —", error);
54
+ process.exit(1);
55
+ });
56
+ //# sourceMappingURL=migrate-bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-bin.js","sourceRoot":"","sources":["../src/migrate-bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import type { Pool } from "pg";
2
+ import { type CreatePoolConfig } from "./pool.js";
3
+ /** One migration as recorded in `drizzle/meta/_journal.json` + its file hash. */
4
+ export interface MigrationFileMeta {
5
+ /** Journal tag, e.g. `0003_illegal_jack_flag`. */
6
+ tag: string;
7
+ /** `sha256(fileContents)` — the exact value drizzle records, so our journal
8
+ * rows are byte-compatible with `drizzle-kit migrate`. */
9
+ hash: string;
10
+ /** The journal entry's `when` (ms epoch) — drizzle's `created_at`. */
11
+ folderMillis: number;
12
+ }
13
+ export interface MigrationsLocation {
14
+ /** Drizzle migrations folder. Default `drizzle`. */
15
+ migrationsFolder?: string;
16
+ /** Journal table name. Default `__drizzle_migrations`. */
17
+ migrationsTable?: string;
18
+ /** Journal table schema. Default `drizzle`. */
19
+ migrationsSchema?: string;
20
+ }
21
+ export type MigrateConfig = CreatePoolConfig & MigrationsLocation & {
22
+ /** Reuse an existing pool instead of creating one from the connection
23
+ * string. The caller owns its lifecycle — it is not ended here. Pass your
24
+ * app's shared pool to avoid opening a second connection. */
25
+ pool?: Pool;
26
+ };
27
+ /**
28
+ * Read `meta/_journal.json` + each `.sql` and compute the per-file hash the same
29
+ * way drizzle does (`sha256` of the raw file). Decoupled from drizzle's internal
30
+ * `readMigrationFiles` so we also keep the human-readable tag.
31
+ */
32
+ export declare const readJournal: (migrationsFolder?: string) => MigrationFileMeta[];
33
+ /** A row of the drizzle journal table. */
34
+ export interface RecordedMigration {
35
+ hash: string;
36
+ createdAt: number;
37
+ }
38
+ export interface MigrationStatus {
39
+ /** All journal files, in order. */
40
+ files: MigrationFileMeta[];
41
+ /** Rows already in the journal table, oldest first. */
42
+ recorded: RecordedMigration[];
43
+ /** Files drizzle's migrator would apply next (folderMillis > max recorded). */
44
+ pending: MigrationFileMeta[];
45
+ /** True when the journal table doesn't line up with the files (see {@link drift}). */
46
+ drifted: boolean;
47
+ drift?: MigrationDrift;
48
+ }
49
+ export interface MigrationDrift {
50
+ reason: string;
51
+ /** Recorded hashes that match no current file (the regenerated-baseline tell). */
52
+ recordedNotInFiles: string[];
53
+ }
54
+ /**
55
+ * Compare the DB's migration journal to the `drizzle/` files without changing
56
+ * anything. The basis for {@link runMigrations}'s pre-flight; also useful on its
57
+ * own (a `--status` check).
58
+ */
59
+ export declare const inspectMigrations: (config?: MigrateConfig) => Promise<MigrationStatus>;
60
+ /** Thrown by {@link runMigrations} when the journal is out of sync with the
61
+ * files — applying would replay already-present DDL and fail confusingly. */
62
+ export declare class MigrationDriftError extends Error {
63
+ readonly status: MigrationStatus;
64
+ constructor(status: MigrationStatus);
65
+ }
66
+ export interface MigrateResult {
67
+ /** Tags of the migrations applied by this run (empty when up to date). */
68
+ applied: string[];
69
+ }
70
+ /**
71
+ * Apply pending migrations with the real drizzle-orm migrator. Runs a drift
72
+ * pre-flight first and throws {@link MigrationDriftError} (not a confusing
73
+ * `already exists`) when the journal is out of sync. Surfaces the actual
74
+ * Postgres error on a failing statement.
75
+ */
76
+ export declare const runMigrations: (config?: MigrateConfig) => Promise<MigrateResult>;
77
+ /**
78
+ * Reconcile a journal whose schema is ALREADY correct but whose
79
+ * `__drizzle_migrations` rows don't match the files (built via db:push, or after
80
+ * regenerating the baseline). Records the full current file chain as applied —
81
+ * hashes + `when` timestamps, byte-compatible with drizzle — WITHOUT running any
82
+ * migration DDL, so a subsequent `runMigrations` is a clean no-op.
83
+ *
84
+ * Only call this when you've confirmed the live schema matches the migration
85
+ * files; it does not verify that.
86
+ */
87
+ export declare const baselineMigrations: (config?: MigrateConfig) => Promise<{
88
+ recorded: string[];
89
+ }>;
90
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,KAAK,gBAAgB,EAAc,MAAM,WAAW,CAAC;AAE9D,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IACjC,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ;+DAC2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IAClC,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAC3C,kBAAkB,GAAG;IACpB;;kEAE8D;IAC9D,IAAI,CAAC,EAAE,IAAI,CAAC;CACZ,CAAC;AAkBH;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACvB,mBAAkB,MAAkC,KAClD,iBAAiB,EAgBnB,CAAC;AAEF,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC/B,mCAAmC;IACnC,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,+EAA+E;IAC/E,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,sFAAsF;IACtF,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAuDD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC7B,SAAQ,aAAkB,KACxB,OAAO,CAAC,eAAe,CAezB,CAAC;AAEF;8EAC8E;AAC9E,qBAAa,mBAAoB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBACrB,MAAM,EAAE,eAAe;CAgBnC;AAED,MAAM,WAAW,aAAa;IAC7B,0EAA0E;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACzB,SAAQ,aAAkB,KACxB,OAAO,CAAC,aAAa,CAsBvB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAC9B,SAAQ,aAAkB,KACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAmChC,CAAC"}
@@ -0,0 +1,209 @@
1
+ // Migration runner with drift detection — the framework answer to two recurring
2
+ // pains with `drizzle-kit migrate`:
3
+ //
4
+ // 1. It swallows the real database error and exits 1 opaquely ("applying
5
+ // migrations..." then nothing). {@link runMigrations} uses drizzle-orm's
6
+ // own migrator, so a failing statement throws the actual Postgres error.
7
+ // 2. When a DB's migration journal drifts from the `drizzle/` files — the
8
+ // classic "built via db:push, or the 0000 baseline was regenerated" case —
9
+ // the migrator blindly replays 0000 and dies with a confusing
10
+ // `relation "..." already exists`. {@link runMigrations} runs a pre-flight
11
+ // {@link inspectMigrations} check and throws a {@link MigrationDriftError}
12
+ // that explains exactly what happened and how to fix it, and
13
+ // {@link baselineMigrations} reconciles a journal whose schema is already
14
+ // correct without re-running any DDL.
15
+ //
16
+ // This module is node-only (pg + fs + the drizzle migrator); it is NOT exported
17
+ // from the main entry, so a production bundle that only does runtime queries
18
+ // never pulls it. Reached via the "@ingram-tech/nk-db/migrate" subpath and the
19
+ // `nk-pg-migrate` bin.
20
+ import { createHash } from "node:crypto";
21
+ import { existsSync, readFileSync } from "node:fs";
22
+ import { join } from "node:path";
23
+ import { createPool } from "./pool.js";
24
+ /** Resolve the pool to use: a caller-supplied one (left open) or a fresh one we
25
+ * own (ended on release). */
26
+ const acquire = (config) => {
27
+ if (config.pool)
28
+ return { pool: config.pool, release: async () => { } };
29
+ const pool = createPool(config);
30
+ return { pool, release: () => pool.end() };
31
+ };
32
+ const DEFAULTS = {
33
+ migrationsFolder: "drizzle",
34
+ migrationsTable: "__drizzle_migrations",
35
+ migrationsSchema: "drizzle",
36
+ };
37
+ /**
38
+ * Read `meta/_journal.json` + each `.sql` and compute the per-file hash the same
39
+ * way drizzle does (`sha256` of the raw file). Decoupled from drizzle's internal
40
+ * `readMigrationFiles` so we also keep the human-readable tag.
41
+ */
42
+ export const readJournal = (migrationsFolder = DEFAULTS.migrationsFolder) => {
43
+ const journalPath = join(migrationsFolder, "meta", "_journal.json");
44
+ if (!existsSync(journalPath)) {
45
+ throw new Error(`@ingram-tech/nk-db: no migration journal at ${journalPath}`);
46
+ }
47
+ const journal = JSON.parse(readFileSync(journalPath, "utf8"));
48
+ return journal.entries.map((entry) => {
49
+ const sql = readFileSync(join(migrationsFolder, `${entry.tag}.sql`), "utf8");
50
+ return {
51
+ tag: entry.tag,
52
+ hash: createHash("sha256").update(sql).digest("hex"),
53
+ folderMillis: entry.when,
54
+ };
55
+ });
56
+ };
57
+ const qualified = (schema, table) => `"${schema.replace(/"/g, '""')}"."${table.replace(/"/g, '""')}"`;
58
+ /** Read the journal table; returns [] if it doesn't exist yet (fresh DB). */
59
+ const readRecorded = async (pool, schema, table) => {
60
+ try {
61
+ const { rows } = await pool.query(`select hash, created_at from ${qualified(schema, table)} order by created_at asc`);
62
+ // created_at is bigint → pg returns it as a string; coerce to number (ms
63
+ // epochs fit safely in a JS number).
64
+ return rows.map((r) => ({ hash: r.hash, createdAt: Number(r.created_at) }));
65
+ }
66
+ catch (err) {
67
+ // 42P01 = undefined_table → never migrated; not an error.
68
+ if (err.code === "42P01")
69
+ return [];
70
+ throw err;
71
+ }
72
+ };
73
+ const detectDrift = (files, recorded) => {
74
+ const fileHashes = new Set(files.map((f) => f.hash));
75
+ const recordedNotInFiles = recorded
76
+ .map((r) => r.hash)
77
+ .filter((h) => !fileHashes.has(h));
78
+ if (recorded.length > files.length) {
79
+ return {
80
+ reason: `the journal table has ${recorded.length} recorded migration(s) but only ${files.length} file(s) exist`,
81
+ recordedNotInFiles,
82
+ };
83
+ }
84
+ // A healthy journal is exactly the first N files, in order, by hash.
85
+ for (let i = 0; i < recorded.length; i++) {
86
+ if (recorded[i]?.hash !== files[i]?.hash) {
87
+ return {
88
+ reason: recordedNotInFiles.length > 0
89
+ ? `recorded migration #${i + 1} matches no current file — the baseline was likely regenerated, or the schema was built with db:push`
90
+ : `recorded migration #${i + 1} doesn't match file ${files[i]?.tag} (a migration file changed after it was applied)`,
91
+ recordedNotInFiles,
92
+ };
93
+ }
94
+ }
95
+ return undefined;
96
+ };
97
+ /**
98
+ * Compare the DB's migration journal to the `drizzle/` files without changing
99
+ * anything. The basis for {@link runMigrations}'s pre-flight; also useful on its
100
+ * own (a `--status` check).
101
+ */
102
+ export const inspectMigrations = async (config = {}) => {
103
+ const folder = config.migrationsFolder ?? DEFAULTS.migrationsFolder;
104
+ const schema = config.migrationsSchema ?? DEFAULTS.migrationsSchema;
105
+ const table = config.migrationsTable ?? DEFAULTS.migrationsTable;
106
+ const { pool, release } = acquire(config);
107
+ try {
108
+ const files = readJournal(folder);
109
+ const recorded = await readRecorded(pool, schema, table);
110
+ const drift = detectDrift(files, recorded);
111
+ const maxRecorded = recorded.reduce((m, r) => Math.max(m, r.createdAt), 0);
112
+ const pending = files.filter((f) => f.folderMillis > maxRecorded);
113
+ return { files, recorded, pending, drifted: Boolean(drift), drift };
114
+ }
115
+ finally {
116
+ await release();
117
+ }
118
+ };
119
+ /** Thrown by {@link runMigrations} when the journal is out of sync with the
120
+ * files — applying would replay already-present DDL and fail confusingly. */
121
+ export class MigrationDriftError extends Error {
122
+ status;
123
+ constructor(status) {
124
+ const d = status.drift;
125
+ super([
126
+ `migration journal drift: ${d?.reason ?? "journal does not match files"}.`,
127
+ d?.recordedNotInFiles.length
128
+ ? ` Recorded hashes matching no file: ${d.recordedNotInFiles.map((h) => h.slice(0, 12)).join(", ")}.`
129
+ : "",
130
+ " Fix: if this DB's schema already matches the files (e.g. built via db:push, or after regenerating the baseline), reconcile the journal with `baselineMigrations()` / `nk-pg-migrate --baseline` — it records the current file chain WITHOUT re-running DDL. Otherwise rebuild the database.",
131
+ ]
132
+ .filter(Boolean)
133
+ .join("\n"));
134
+ this.name = "MigrationDriftError";
135
+ this.status = status;
136
+ }
137
+ }
138
+ /**
139
+ * Apply pending migrations with the real drizzle-orm migrator. Runs a drift
140
+ * pre-flight first and throws {@link MigrationDriftError} (not a confusing
141
+ * `already exists`) when the journal is out of sync. Surfaces the actual
142
+ * Postgres error on a failing statement.
143
+ */
144
+ export const runMigrations = async (config = {}) => {
145
+ const folder = config.migrationsFolder ?? DEFAULTS.migrationsFolder;
146
+ const schema = config.migrationsSchema ?? DEFAULTS.migrationsSchema;
147
+ const table = config.migrationsTable ?? DEFAULTS.migrationsTable;
148
+ const status = await inspectMigrations(config);
149
+ if (status.drifted)
150
+ throw new MigrationDriftError(status);
151
+ if (status.pending.length === 0)
152
+ return { applied: [] };
153
+ const { pool, release } = acquire(config);
154
+ try {
155
+ const { drizzle } = await import("drizzle-orm/node-postgres");
156
+ const { migrate } = await import("drizzle-orm/node-postgres/migrator");
157
+ await migrate(drizzle(pool), {
158
+ migrationsFolder: folder,
159
+ migrationsTable: table,
160
+ migrationsSchema: schema,
161
+ });
162
+ return { applied: status.pending.map((m) => m.tag) };
163
+ }
164
+ finally {
165
+ await release();
166
+ }
167
+ };
168
+ /**
169
+ * Reconcile a journal whose schema is ALREADY correct but whose
170
+ * `__drizzle_migrations` rows don't match the files (built via db:push, or after
171
+ * regenerating the baseline). Records the full current file chain as applied —
172
+ * hashes + `when` timestamps, byte-compatible with drizzle — WITHOUT running any
173
+ * migration DDL, so a subsequent `runMigrations` is a clean no-op.
174
+ *
175
+ * Only call this when you've confirmed the live schema matches the migration
176
+ * files; it does not verify that.
177
+ */
178
+ export const baselineMigrations = async (config = {}) => {
179
+ const folder = config.migrationsFolder ?? DEFAULTS.migrationsFolder;
180
+ const schema = config.migrationsSchema ?? DEFAULTS.migrationsSchema;
181
+ const table = config.migrationsTable ?? DEFAULTS.migrationsTable;
182
+ const files = readJournal(folder);
183
+ const { pool, release } = acquire(config);
184
+ const client = await pool.connect();
185
+ try {
186
+ await client.query("begin");
187
+ await client.query(`create schema if not exists "${schema.replace(/"/g, '""')}"`);
188
+ await client.query(`create table if not exists ${qualified(schema, table)} (
189
+ id SERIAL PRIMARY KEY,
190
+ hash text NOT NULL,
191
+ created_at bigint
192
+ )`);
193
+ await client.query(`delete from ${qualified(schema, table)}`);
194
+ for (const f of files) {
195
+ await client.query(`insert into ${qualified(schema, table)} ("hash", "created_at") values ($1, $2)`, [f.hash, f.folderMillis]);
196
+ }
197
+ await client.query("commit");
198
+ return { recorded: files.map((f) => f.tag) };
199
+ }
200
+ catch (err) {
201
+ await client.query("rollback").catch(() => { });
202
+ throw err;
203
+ }
204
+ finally {
205
+ client.release();
206
+ await release();
207
+ }
208
+ };
209
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,oCAAoC;AACpC,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,gFAAgF;AAChF,mEAAmE;AACnE,gFAAgF;AAChF,gFAAgF;AAChF,kEAAkE;AAClE,+EAA+E;AAC/E,2CAA2C;AAC3C,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,+EAA+E;AAC/E,uBAAuB;AAEvB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAyB,UAAU,EAAE,MAAM,WAAW,CAAC;AA8B9D;8BAC8B;AAC9B,MAAM,OAAO,GAAG,CACf,MAAqB,EAC0B,EAAE;IACjD,IAAI,MAAM,CAAC,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAC;IACvE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG;IAChB,gBAAgB,EAAE,SAAS;IAC3B,eAAe,EAAE,sBAAsB;IACvC,gBAAgB,EAAE,SAAS;CAClB,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAC1B,mBAA2B,QAAQ,CAAC,gBAAgB,EAC9B,EAAE;IACxB,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IACpE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,+CAA+C,WAAW,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAE3D,CAAC;IACF,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,KAAK,CAAC,GAAG,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7E,OAAO;YACN,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACpD,YAAY,EAAE,KAAK,CAAC,IAAI;SACxB,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AA0BF,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,KAAa,EAAU,EAAE,CAC3D,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAElE,6EAA6E;AAC7E,MAAM,YAAY,GAAG,KAAK,EACzB,IAAU,EACV,MAAc,EACd,KAAa,EACkB,EAAE;IACjC,IAAI,CAAC;QACJ,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAChC,gCAAgC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,0BAA0B,CAClF,CAAC;QACF,yEAAyE;QACzE,qCAAqC;QACrC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,0DAA0D;QAC1D,IAAK,GAAyB,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,EAAE,CAAC;QAC3D,MAAM,GAAG,CAAC;IACX,CAAC;AACF,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CACnB,KAA0B,EAC1B,QAA6B,EACA,EAAE;IAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACrD,MAAM,kBAAkB,GAAG,QAAQ;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpC,IAAI,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACpC,OAAO;YACN,MAAM,EAAE,yBAAyB,QAAQ,CAAC,MAAM,mCAAmC,KAAK,CAAC,MAAM,gBAAgB;YAC/G,kBAAkB;SAClB,CAAC;IACH,CAAC;IACD,qEAAqE;IACrE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAC1C,OAAO;gBACN,MAAM,EACL,kBAAkB,CAAC,MAAM,GAAG,CAAC;oBAC5B,CAAC,CAAC,uBAAuB,CAAC,GAAG,CAAC,sGAAsG;oBACpI,CAAC,CAAC,uBAAuB,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,kDAAkD;gBACtH,kBAAkB;aAClB,CAAC;QACH,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACrC,SAAwB,EAAE,EACC,EAAE;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,IAAI,QAAQ,CAAC,eAAe,CAAC;IACjE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3E,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,WAAW,CAAC,CAAC;QAClE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC;YAAS,CAAC;QACV,MAAM,OAAO,EAAE,CAAC;IACjB,CAAC;AACF,CAAC,CAAC;AAEF;8EAC8E;AAC9E,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACpC,MAAM,CAAkB;IACjC,YAAY,MAAuB;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QACvB,KAAK,CACJ;YACC,4BAA4B,CAAC,EAAE,MAAM,IAAI,8BAA8B,GAAG;YAC1E,CAAC,EAAE,kBAAkB,CAAC,MAAM;gBAC3B,CAAC,CAAC,uCAAuC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBACtG,CAAC,CAAC,EAAE;YACL,+RAA+R;SAC/R;aACC,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAOD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EACjC,SAAwB,EAAE,EACD,EAAE;IAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,IAAI,QAAQ,CAAC,eAAe,CAAC;IAEjE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,OAAO;QAAE,MAAM,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAExD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC;QACJ,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QAC9D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;QACvE,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC5B,gBAAgB,EAAE,MAAM;YACxB,eAAe,EAAE,KAAK;YACtB,gBAAgB,EAAE,MAAM;SACxB,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACtD,CAAC;YAAS,CAAC;QACV,MAAM,OAAO,EAAE,CAAC;IACjB,CAAC;AACF,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACtC,SAAwB,EAAE,EACQ,EAAE;IACpC,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,CAAC,gBAAgB,IAAI,QAAQ,CAAC,gBAAgB,CAAC;IACpE,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,IAAI,QAAQ,CAAC,eAAe,CAAC;IACjE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACpC,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,MAAM,CAAC,KAAK,CACjB,gCAAgC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAC7D,CAAC;QACF,MAAM,MAAM,CAAC,KAAK,CACjB,8BAA8B,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC;;;;KAIpD,CACF,CAAC;QACF,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,MAAM,CAAC,KAAK,CACjB,eAAe,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,yCAAyC,EAChF,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,CACxB,CAAC;QACH,CAAC;QACD,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,GAAG,CAAC;IACX,CAAC;YAAS,CAAC;QACV,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,OAAO,EAAE,CAAC;IACjB,CAAC;AACF,CAAC,CAAC"}
@@ -65,6 +65,13 @@ export interface TestDb {
65
65
  * Both share `resetPublicTables`. If a second in-process consumer appears, the
66
66
  * move is to promote an in-process harness to first-class here, not to bolt one
67
67
  * beside this socket default.
68
+ *
69
+ * Port: unlike `startPgliteDev` (which wants the stable 5432 the app dials),
70
+ * tests reach the db through the returned `pool`/`databaseUrl`, so the socket
71
+ * port is irrelevant — it defaults to an **ephemeral free port** so the harness
72
+ * never collides with a developer's real Postgres on 5432 (the EADDRINUSE that
73
+ * otherwise kills the suite). An explicit `port` option or `PGLITE_PORT` still
74
+ * wins.
68
75
  */
69
76
  export declare const createTestDb: (options?: PgliteServerOptions) => Promise<TestDb>;
70
77
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pglite/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,WAAW,mBAAmB;IACnC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,kBAAkB,CAAC;IAC3B,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAUD;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC9B,UAAS,mBAAwB,KAC/B,OAAO,CAAC,YAAY,CAyBtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAC1B,UAAS,mBAAmB,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,KACzD,OAAO,CAAC,IAAI,CA0Bd,CAAC;AAEF,MAAM,WAAW,MAAM;IACtB,2EAA2E;IAC3E,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,GACxB,UAAS,mBAAwB,KAC/B,OAAO,CAAC,MAAM,CAWhB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pglite/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,WAAW,mBAAmB;IACnC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,kBAAkB,CAAC;IAC3B,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAuBD;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC9B,UAAS,mBAAwB,KAC/B,OAAO,CAAC,YAAY,CAyBtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAC1B,UAAS,mBAAmB,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,KACzD,OAAO,CAAC,IAAI,CA0Bd,CAAC;AAEF,MAAM,WAAW,MAAM;IACtB,2EAA2E;IAC3E,IAAI,EAAE,IAAI,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,YAAY,GACxB,UAAS,mBAAwB,KAC/B,OAAO,CAAC,MAAM,CAiBhB,CAAC"}
@@ -9,9 +9,21 @@
9
9
  // entry, so production bundles stay clean.
10
10
  import { existsSync } from "node:fs";
11
11
  import { rm } from "node:fs/promises";
12
+ import { createServer } from "node:net";
12
13
  import { PGlite } from "@electric-sql/pglite";
13
14
  import { PGLiteSocketServer } from "@electric-sql/pglite-socket";
14
15
  import { resetPublicTables } from "./reset.js";
16
+ /** Ask the OS for a currently-free TCP port (bind :0, read it back, release).
17
+ * Used so the test harness never collides with a dev Postgres on 5432. */
18
+ const freePort = (host) => new Promise((resolve, reject) => {
19
+ const srv = createServer();
20
+ srv.once("error", reject);
21
+ srv.listen(0, host, () => {
22
+ const addr = srv.address();
23
+ const port = typeof addr === "object" && addr ? addr.port : 0;
24
+ srv.close((err) => (err ? reject(err) : resolve(port)));
25
+ });
26
+ });
15
27
  const defaultMigrate = (migrationsFolder) => async (db) => {
16
28
  const { drizzle } = await import("drizzle-orm/pglite");
17
29
  const { migrate } = await import("drizzle-orm/pglite/migrator");
@@ -84,10 +96,22 @@ export const startPgliteDev = async (options = {}) => {
84
96
  * Both share `resetPublicTables`. If a second in-process consumer appears, the
85
97
  * move is to promote an in-process harness to first-class here, not to bolt one
86
98
  * beside this socket default.
99
+ *
100
+ * Port: unlike `startPgliteDev` (which wants the stable 5432 the app dials),
101
+ * tests reach the db through the returned `pool`/`databaseUrl`, so the socket
102
+ * port is irrelevant — it defaults to an **ephemeral free port** so the harness
103
+ * never collides with a developer's real Postgres on 5432 (the EADDRINUSE that
104
+ * otherwise kills the suite). An explicit `port` option or `PGLITE_PORT` still
105
+ * wins.
87
106
  */
88
107
  export const createTestDb = async (options = {}) => {
89
108
  const { Pool } = await import("pg");
90
- const { databaseUrl, stop } = await createPgliteServer(options);
109
+ const host = options.host ?? "127.0.0.1";
110
+ const port = options.port ??
111
+ (process.env.PGLITE_PORT
112
+ ? Number(process.env.PGLITE_PORT)
113
+ : await freePort(host));
114
+ const { databaseUrl, stop } = await createPgliteServer({ ...options, host, port });
91
115
  const pool = new Pool({ connectionString: databaseUrl, max: 1 });
92
116
  const reset = () => resetPublicTables((sql) => pool.query(sql));
93
117
  const close = async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pglite/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pglite/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingram-tech/nk-db",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "The Ingram Postgres data layer: one TLS-aware pg pool, raw-SQL helpers, Drizzle wiring, and a PGlite (no-Docker) dev/test harness for Next.js sites.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -16,13 +16,22 @@
16
16
  "dist"
17
17
  ],
18
18
  "bin": {
19
- "nk-pglite-dev": "./dist/pglite/dev.js"
19
+ "nk-pglite-dev": "./dist/pglite/dev.js",
20
+ "nk-pg-migrate": "./dist/migrate-bin.js"
20
21
  },
21
22
  "exports": {
22
23
  ".": {
23
24
  "types": "./dist/index.d.ts",
24
25
  "import": "./dist/index.js"
25
26
  },
27
+ "./id": {
28
+ "types": "./dist/id.d.ts",
29
+ "import": "./dist/id.js"
30
+ },
31
+ "./migrate": {
32
+ "types": "./dist/migrate.d.ts",
33
+ "import": "./dist/migrate.js"
34
+ },
26
35
  "./pglite": {
27
36
  "types": "./dist/pglite/index.d.ts",
28
37
  "import": "./dist/pglite/index.js"
@@ -57,7 +66,7 @@
57
66
  "devDependencies": {
58
67
  "@electric-sql/pglite": "^0.5.0",
59
68
  "@electric-sql/pglite-socket": "^0.2.4",
60
- "@ingram-tech/typescript-config": "0.1.0",
69
+ "@ingram-tech/nk-dev": "workspace:*",
61
70
  "@types/node": "^25.0.0",
62
71
  "@types/pg": "^8.11.0",
63
72
  "drizzle-orm": "^0.45.0",