@softure-ai/db 0.0.0-stage → 0.1.5

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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +189 -2
  3. package/dist/cli/bin.d.ts +3 -0
  4. package/dist/cli/bin.d.ts.map +1 -0
  5. package/dist/cli/bin.js +5 -0
  6. package/dist/cli/bin.js.map +1 -0
  7. package/dist/cli/command.d.ts +8 -0
  8. package/dist/cli/command.d.ts.map +1 -0
  9. package/dist/cli/command.js +38 -0
  10. package/dist/cli/command.js.map +1 -0
  11. package/dist/cli/index.d.ts +3 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +4 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/cli/run.d.ts +20 -0
  16. package/dist/cli/run.d.ts.map +1 -0
  17. package/dist/cli/run.js +155 -0
  18. package/dist/cli/run.js.map +1 -0
  19. package/dist/client.d.ts +42 -0
  20. package/dist/client.d.ts.map +1 -0
  21. package/dist/client.js +34 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/index.d.ts +11 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +12 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/migrations/adopt.d.ts +26 -0
  28. package/dist/migrations/adopt.d.ts.map +1 -0
  29. package/dist/migrations/adopt.js +131 -0
  30. package/dist/migrations/adopt.js.map +1 -0
  31. package/dist/migrations/export.d.ts +10 -0
  32. package/dist/migrations/export.d.ts.map +1 -0
  33. package/dist/migrations/export.js +58 -0
  34. package/dist/migrations/export.js.map +1 -0
  35. package/dist/migrations/exported.d.ts +20 -0
  36. package/dist/migrations/exported.d.ts.map +1 -0
  37. package/dist/migrations/exported.js +61 -0
  38. package/dist/migrations/exported.js.map +1 -0
  39. package/dist/migrations/files.d.ts +21 -0
  40. package/dist/migrations/files.d.ts.map +1 -0
  41. package/dist/migrations/files.js +112 -0
  42. package/dist/migrations/files.js.map +1 -0
  43. package/dist/migrations/introspect.d.ts +6 -0
  44. package/dist/migrations/introspect.d.ts.map +1 -0
  45. package/dist/migrations/introspect.js +117 -0
  46. package/dist/migrations/introspect.js.map +1 -0
  47. package/dist/migrations/ledger.d.ts +27 -0
  48. package/dist/migrations/ledger.d.ts.map +1 -0
  49. package/dist/migrations/ledger.js +45 -0
  50. package/dist/migrations/ledger.js.map +1 -0
  51. package/dist/migrations/migrator.d.ts +69 -0
  52. package/dist/migrations/migrator.d.ts.map +1 -0
  53. package/dist/migrations/migrator.js +217 -0
  54. package/dist/migrations/migrator.js.map +1 -0
  55. package/dist/migrations/problems.d.ts +84 -0
  56. package/dist/migrations/problems.d.ts.map +1 -0
  57. package/dist/migrations/problems.js +56 -0
  58. package/dist/migrations/problems.js.map +1 -0
  59. package/dist/migrations/session.d.ts +14 -0
  60. package/dist/migrations/session.d.ts.map +1 -0
  61. package/dist/migrations/session.js +39 -0
  62. package/dist/migrations/session.js.map +1 -0
  63. package/dist/shared.d.ts +9 -0
  64. package/dist/shared.d.ts.map +1 -0
  65. package/dist/shared.js +32 -0
  66. package/dist/shared.js.map +1 -0
  67. package/dist/testing.d.ts +14 -0
  68. package/dist/testing.d.ts.map +1 -0
  69. package/dist/testing.js +43 -0
  70. package/dist/testing.js.map +1 -0
  71. package/package.json +56 -4
  72. package/src/cli/bin.ts +5 -0
  73. package/src/cli/command.ts +47 -0
  74. package/src/cli/index.ts +3 -0
  75. package/src/cli/run.ts +189 -0
  76. package/src/client.ts +79 -0
  77. package/src/index.ts +37 -0
  78. package/src/migrations/adopt.ts +171 -0
  79. package/src/migrations/export.ts +66 -0
  80. package/src/migrations/exported.ts +82 -0
  81. package/src/migrations/files.ts +129 -0
  82. package/src/migrations/introspect.ts +165 -0
  83. package/src/migrations/ledger.ts +75 -0
  84. package/src/migrations/migrator.ts +285 -0
  85. package/src/migrations/problems.ts +91 -0
  86. package/src/migrations/session.ts +48 -0
  87. package/src/shared.ts +36 -0
  88. package/src/testing.ts +52 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.js","sourceRoot":"","sources":["../../src/migrations/introspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type MigrationFile } from "./files.js";
2
+ import type { MigrationSession } from "./session.js";
3
+ export declare const LEDGER_MODULE_ID = "softure";
4
+ export declare const LEDGER_SCHEMA = "softure";
5
+ /** The ledger's own format version, recorded as `module_version` of its rows. */
6
+ export declare const LEDGER_VERSION = "1.0.0";
7
+ export declare const LEDGER_FILES: readonly MigrationFile[];
8
+ export type MigrationMethod = "applied" | "adopted";
9
+ export interface JournalRow {
10
+ readonly module: string;
11
+ readonly version: number;
12
+ readonly name: string;
13
+ readonly checksum: string;
14
+ readonly method: MigrationMethod;
15
+ }
16
+ export interface LedgerEntry {
17
+ readonly module: string;
18
+ readonly version: number;
19
+ readonly name: string;
20
+ readonly checksum: string;
21
+ readonly moduleVersion: string;
22
+ readonly method: MigrationMethod;
23
+ }
24
+ /** Every ledger row, or none while the ledger table does not exist yet. */
25
+ export declare function readJournal(session: MigrationSession): Promise<JournalRow[]>;
26
+ export declare function recordMigration(session: MigrationSession, entry: LedgerEntry): Promise<void>;
27
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/migrations/ledger.ts"],"names":[],"mappings":"AAOA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,iFAAiF;AACjF,eAAO,MAAM,cAAc,UAAU,CAAC;AAwBtC,eAAO,MAAM,YAAY,EAAE,SAAS,aAAa,EAAwB,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;CAClC;AAED,2EAA2E;AAC3E,wBAAsB,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAQlF;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAKlG"}
@@ -0,0 +1,45 @@
1
+ // The migration ledger `softure.migrations` (docs/02-module-standard.md §4). It is owned by the
2
+ // pseudo-module `softure` and created by its own migration, which ships as code so a bundled
3
+ // runner needs no file for it. While the table does not exist the journal reads as empty, so the
4
+ // first run bootstraps through the normal path.
5
+ //
6
+ // NEVER edit LEDGER_MIGRATION: deployed databases hold its checksum (a test pins it). A change to
7
+ // the ledger is a new file, `0002_…`, appended to LEDGER_FILES.
8
+ import { createMigrationFile } from "./files.js";
9
+ export const LEDGER_MODULE_ID = "softure";
10
+ export const LEDGER_SCHEMA = "softure";
11
+ /** The ledger's own format version, recorded as `module_version` of its rows. */
12
+ export const LEDGER_VERSION = "1.0.0";
13
+ const LEDGER_MIGRATION = `-- Rollback: DROP SCHEMA softure CASCADE; this forgets which module migrations ran, the module schemas and their data stay.
14
+ CREATE TABLE softure.migrations (
15
+ id bigint GENERATED ALWAYS AS IDENTITY UNIQUE,
16
+ module text NOT NULL CHECK (module ~ '^[a-z][a-z0-9]*(-[a-z0-9]+)*$'),
17
+ version integer NOT NULL CHECK (version > 0),
18
+ name text NOT NULL CHECK (name ~ '^[a-z0-9]+(_[a-z0-9]+)*$'),
19
+ checksum text NOT NULL CHECK (checksum ~ '^[0-9a-f]{64}$'),
20
+ module_version text NOT NULL,
21
+ method text NOT NULL CHECK (method IN ('applied', 'adopted')),
22
+ applied_at timestamptz NOT NULL DEFAULT now(),
23
+ PRIMARY KEY (module, version)
24
+ );
25
+ `;
26
+ function createLedgerFiles() {
27
+ const file = createMigrationFile("0001_ledger.sql", LEDGER_MIGRATION);
28
+ if (typeof file === "string") {
29
+ throw new Error(`ledger: the built-in migration is invalid: ${file}`);
30
+ }
31
+ return [file];
32
+ }
33
+ export const LEDGER_FILES = createLedgerFiles();
34
+ /** Every ledger row, or none while the ledger table does not exist yet. */
35
+ export async function readJournal(session) {
36
+ const [table] = await session.query("SELECT to_regclass('softure.migrations') IS NOT NULL AS exists");
37
+ if (table?.exists !== true) {
38
+ return [];
39
+ }
40
+ return session.query("SELECT module, version, name, checksum, method FROM softure.migrations ORDER BY id");
41
+ }
42
+ export async function recordMigration(session, entry) {
43
+ await session.query("INSERT INTO softure.migrations (module, version, name, checksum, module_version, method) VALUES ($1, $2, $3, $4, $5, $6)", [entry.module, entry.version, entry.name, entry.checksum, entry.moduleVersion, entry.method]);
44
+ }
45
+ //# sourceMappingURL=ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/migrations/ledger.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,6FAA6F;AAC7F,iGAAiG;AACjG,gDAAgD;AAChD,EAAE;AACF,kGAAkG;AAClG,gEAAgE;AAChE,OAAO,EAAE,mBAAmB,EAAsB,MAAM,YAAY,CAAC;AAGrE,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,CAAC;AAC1C,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AACvC,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;CAYxB,CAAC;AAEF,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAG,mBAAmB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;IACtE,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,8CAA8C,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAA6B,iBAAiB,EAAE,CAAC;AAqB1E,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAyB;IACzD,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,KAAK,CAAsB,gEAAgE,CAAC,CAAC;IAC3H,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAClB,oFAAoF,CACrF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAyB,EAAE,KAAkB;IACjF,MAAM,OAAO,CAAC,KAAK,CACjB,0HAA0H,EAC1H,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAC7F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { type AnySoftureModule } from "@softure-ai/core";
2
+ import type { DatabaseHandle } from "../client.js";
3
+ import { type MigrationFile } from "./files.js";
4
+ import { type JournalRow, type MigrationMethod } from "./ledger.js";
5
+ import { type MigrationProblem, type MigrationResult } from "./problems.js";
6
+ import { type MigrationSession } from "./session.js";
7
+ export interface MigrateOptions {
8
+ /** The enabled modules, in any order; dependencies are applied first. */
9
+ readonly modules: readonly AnySoftureModule[];
10
+ /**
11
+ * Read each module's files from `<migrationsDir>/<module id>/` instead of the module's own
12
+ * folder: the container path, where a bundle cannot locate package folders.
13
+ */
14
+ readonly migrationsDir?: URL;
15
+ /** Called after each file is committed, e.g. to print progress. */
16
+ readonly onApplied?: (step: MigrationStep) => void;
17
+ }
18
+ export interface MigrationStep {
19
+ readonly module: string;
20
+ readonly schema: string;
21
+ readonly version: number;
22
+ readonly name: string;
23
+ readonly checksum: string;
24
+ }
25
+ export interface MigrationPlan {
26
+ /** What `migrate` would apply, in order. */
27
+ readonly pending: readonly MigrationStep[];
28
+ }
29
+ export interface MigrationReport {
30
+ readonly applied: readonly MigrationStep[];
31
+ }
32
+ /** One migration owner: the ledger itself or an enabled module with a schema. */
33
+ export interface MigrationUnit {
34
+ readonly module: string;
35
+ readonly schema: string;
36
+ readonly moduleVersion: string;
37
+ readonly files: readonly MigrationFile[];
38
+ }
39
+ /** The dry run: what `migrate` would apply. Takes no lock and writes nothing. */
40
+ export declare function planMigrations(handle: DatabaseHandle, options: MigrateOptions): Promise<MigrationResult<MigrationPlan>>;
41
+ /** Applies every pending migration under the advisory lock. */
42
+ export declare function migrate(handle: DatabaseHandle, options: MigrateOptions): Promise<MigrationResult<MigrationReport>>;
43
+ /**
44
+ * Validates the module list and reads every file: the ledger first, then the modules with a
45
+ * schema in dependency order. Fails with every problem found.
46
+ */
47
+ export declare function prepareUnits(modules: readonly AnySoftureModule[], migrationsDir: URL | undefined): Promise<MigrationResult<MigrationUnit[]>>;
48
+ /** Checks applied files against the folder and lists the pending ones in run order. */
49
+ export declare function compareJournal(units: readonly MigrationUnit[], journal: readonly JournalRow[]): {
50
+ problems: MigrationProblem[];
51
+ pending: MigrationStep[];
52
+ };
53
+ /**
54
+ * Runs one file and its ledger row in one transaction, inside the unit's schema. Returns the
55
+ * problem when the SQL fails; the transaction is rolled back first.
56
+ */
57
+ export declare function applyFile(session: MigrationSession, input: {
58
+ unit: MigrationUnit;
59
+ file: MigrationFile;
60
+ method: MigrationMethod;
61
+ }): Promise<MigrationProblem | null>;
62
+ /**
63
+ * Rolls the open transaction back and returns the reason to report. A failing ROLLBACK (a lost
64
+ * connection) is added to the reason instead of hiding the original error.
65
+ */
66
+ export declare function rollBack(session: MigrationSession, error: unknown): Promise<string>;
67
+ /** Holds the session-level advisory lock while `run` runs; a second runner waits for it. */
68
+ export declare function withMigrationLock<T>(session: MigrationSession, run: () => Promise<T>): Promise<T>;
69
+ //# sourceMappingURL=migrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../../src/migrations/migrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,217 @@
1
+ // The module migrator (docs/02-module-standard.md §4). Every enabled module's SQL files run in the
2
+ // module's own schema, dependencies first, one transaction per file together with its ledger row.
3
+ // Everything that can be checked (names, numbering, checksums, order) is checked for all modules
4
+ // before the first file runs, so a problem in one module never leaves another half-migrated.
5
+ import { ok, sortModulesByDependencies } from "@softure-ai/core";
6
+ import { readMigrationFiles } from "./files.js";
7
+ import { LEDGER_FILES, LEDGER_MODULE_ID, LEDGER_SCHEMA, LEDGER_VERSION, readJournal, recordMigration, } from "./ledger.js";
8
+ import { failWith } from "./problems.js";
9
+ import { withSession } from "./session.js";
10
+ // Any constant works; it only has to be the same for every runner of every app.
11
+ const MIGRATION_LOCK_KEY = "73012026";
12
+ const RESERVED_SCHEMAS = new Set([LEDGER_SCHEMA, "public", "information_schema"]);
13
+ const MAX_IDENTIFIER_BYTES = 63;
14
+ /** The dry run: what `migrate` would apply. Takes no lock and writes nothing. */
15
+ export async function planMigrations(handle, options) {
16
+ const units = await prepareUnits(options.modules, options.migrationsDir);
17
+ if (!units.ok) {
18
+ return units;
19
+ }
20
+ const journal = await withSession(handle, readJournal);
21
+ const comparison = compareJournal(units.value, journal);
22
+ return comparison.problems.length > 0 ? failWith(comparison.problems) : ok({ pending: comparison.pending });
23
+ }
24
+ /** Applies every pending migration under the advisory lock. */
25
+ export async function migrate(handle, options) {
26
+ const units = await prepareUnits(options.modules, options.migrationsDir);
27
+ if (!units.ok) {
28
+ return units;
29
+ }
30
+ return withSession(handle, (session) => withMigrationLock(session, async () => {
31
+ // Read after the lock: a runner that waited sees what the first one applied.
32
+ const comparison = compareJournal(units.value, await readJournal(session));
33
+ if (comparison.problems.length > 0) {
34
+ return failWith(comparison.problems);
35
+ }
36
+ const applied = [];
37
+ for (const step of comparison.pending) {
38
+ const unit = units.value.find((candidate) => candidate.module === step.module);
39
+ const file = unit?.files.find((candidate) => candidate.version === step.version);
40
+ if (unit === undefined || file === undefined) {
41
+ throw new Error(`migrate: step ${step.module} ${step.version} has no file; compareJournal is broken`);
42
+ }
43
+ const failure = await applyFile(session, { unit, file, method: "applied" });
44
+ if (failure !== null) {
45
+ return failWith([failure]);
46
+ }
47
+ applied.push(step);
48
+ options.onApplied?.(step);
49
+ }
50
+ return ok({ applied });
51
+ }));
52
+ }
53
+ /**
54
+ * Validates the module list and reads every file: the ledger first, then the modules with a
55
+ * schema in dependency order. Fails with every problem found.
56
+ */
57
+ export async function prepareUnits(modules, migrationsDir) {
58
+ const problems = modules.flatMap(checkModule);
59
+ const sorted = sortModulesByDependencies(modules);
60
+ if (!sorted.ok) {
61
+ problems.push({ code: "db.dependency_cycle", modules: modules.map((module) => module.id) });
62
+ }
63
+ if (problems.length > 0 || !sorted.ok) {
64
+ return failWith(problems);
65
+ }
66
+ const units = [
67
+ { module: LEDGER_MODULE_ID, schema: LEDGER_SCHEMA, moduleVersion: LEDGER_VERSION, files: LEDGER_FILES },
68
+ ];
69
+ for (const module of sorted.value) {
70
+ const schema = module.manifest.dbSchema;
71
+ if (schema === null || module.migrations === null) {
72
+ continue;
73
+ }
74
+ const dir = migrationsDir === undefined ? module.migrations.dir : new URL(`${module.id}/`, ensureFolderUrl(migrationsDir));
75
+ const files = await readMigrationFiles(module.id, dir);
76
+ if (files.ok) {
77
+ units.push({ module: module.id, schema, moduleVersion: module.manifest.version, files: files.value });
78
+ }
79
+ else {
80
+ problems.push(...files.problems);
81
+ }
82
+ }
83
+ return problems.length > 0 ? failWith(problems) : ok(units);
84
+ }
85
+ /** Checks applied files against the folder and lists the pending ones in run order. */
86
+ export function compareJournal(units, journal) {
87
+ const problems = [];
88
+ const pending = [];
89
+ for (const unit of units) {
90
+ const rows = journal.filter((row) => row.module === unit.module);
91
+ const appliedVersions = new Set(rows.map((row) => row.version));
92
+ const lastApplied = Math.max(0, ...rows.map((row) => row.version));
93
+ for (const row of rows) {
94
+ const file = unit.files.find((candidate) => candidate.version === row.version);
95
+ if (file === undefined) {
96
+ problems.push({ code: "db.migration_missing", module: unit.module, version: row.version, name: row.name });
97
+ }
98
+ else if (file.checksum !== row.checksum || file.name !== row.name) {
99
+ problems.push({ code: "db.migration_changed", module: unit.module, version: row.version, name: row.name });
100
+ }
101
+ }
102
+ for (const file of unit.files) {
103
+ if (appliedVersions.has(file.version)) {
104
+ continue;
105
+ }
106
+ if (file.version < lastApplied) {
107
+ problems.push({ code: "db.migration_out_of_order", module: unit.module, version: file.version, appliedVersion: lastApplied });
108
+ }
109
+ else {
110
+ pending.push({ module: unit.module, schema: unit.schema, version: file.version, name: file.name, checksum: file.checksum });
111
+ }
112
+ }
113
+ }
114
+ return { problems, pending };
115
+ }
116
+ /**
117
+ * Runs one file and its ledger row in one transaction, inside the unit's schema. Returns the
118
+ * problem when the SQL fails; the transaction is rolled back first.
119
+ */
120
+ export async function applyFile(session, input) {
121
+ const { unit, file, method } = input;
122
+ // The schema passed the manifest's lower_snake_case rule and checkModule; quoting is a second line.
123
+ const schema = quoteIdentifier(unit.schema);
124
+ try {
125
+ await session.exec(`BEGIN; CREATE SCHEMA IF NOT EXISTS ${schema}; SET LOCAL search_path TO ${schema}, public;`);
126
+ const transactionId = await readTransactionId(session);
127
+ if (method === "applied") {
128
+ await session.exec(file.sql);
129
+ }
130
+ // Second line behind findTransactionControl: a file that still ended the transaction left
131
+ // part of itself committed, so it must not be reported as cleanly rolled back.
132
+ if ((await readTransactionId(session)) !== transactionId) {
133
+ throw new TransactionEndedError();
134
+ }
135
+ await recordMigration(session, {
136
+ module: unit.module,
137
+ version: file.version,
138
+ name: file.name,
139
+ checksum: file.checksum,
140
+ moduleVersion: unit.moduleVersion,
141
+ method,
142
+ });
143
+ await session.exec("COMMIT");
144
+ return null;
145
+ }
146
+ catch (error) {
147
+ const reason = await rollBack(session, error);
148
+ return { code: "db.migration_failed", module: unit.module, version: file.version, name: file.name, reason };
149
+ }
150
+ }
151
+ class TransactionEndedError extends Error {
152
+ constructor() {
153
+ super("the file ended the migrator's transaction, so the statements before that point may be committed; check the schema by hand");
154
+ }
155
+ }
156
+ // The transaction id, not now(): two transactions can share a start time (PGlite's clock ticks in
157
+ // milliseconds), but never an id.
158
+ async function readTransactionId(session) {
159
+ const [row] = await session.query("SELECT pg_current_xact_id()::text AS id");
160
+ return row?.id ?? "";
161
+ }
162
+ /**
163
+ * Rolls the open transaction back and returns the reason to report. A failing ROLLBACK (a lost
164
+ * connection) is added to the reason instead of hiding the original error.
165
+ */
166
+ export async function rollBack(session, error) {
167
+ const reason = describeError(error);
168
+ try {
169
+ await session.exec("ROLLBACK");
170
+ return reason;
171
+ }
172
+ catch (rollbackError) {
173
+ return `${reason} (and ROLLBACK failed: ${describeError(rollbackError)})`;
174
+ }
175
+ }
176
+ /** Holds the session-level advisory lock while `run` runs; a second runner waits for it. */
177
+ export async function withMigrationLock(session, run) {
178
+ await session.query("SELECT pg_advisory_lock($1)", [MIGRATION_LOCK_KEY]);
179
+ let result;
180
+ try {
181
+ result = await run();
182
+ }
183
+ catch (error) {
184
+ // The run's own error wins; an unlock failure here is secondary (the session is discarded).
185
+ await session.query("SELECT pg_advisory_unlock($1)", [MIGRATION_LOCK_KEY]).catch((unlockError) => {
186
+ throw new Error(`migration run failed (${describeError(error)}) and releasing the lock failed: ${describeError(unlockError)}`, {
187
+ cause: error,
188
+ });
189
+ });
190
+ throw error;
191
+ }
192
+ await session.query("SELECT pg_advisory_unlock($1)", [MIGRATION_LOCK_KEY]);
193
+ return result;
194
+ }
195
+ function checkModule(module) {
196
+ const schema = module.manifest.dbSchema;
197
+ if (module.id === LEDGER_MODULE_ID || (schema !== null && isReservedSchema(schema))) {
198
+ return [{ code: "db.reserved_module", module: module.id }];
199
+ }
200
+ if (schema === null && module.migrations !== null) {
201
+ return [{ code: "db.migrations_without_schema", module: module.id }];
202
+ }
203
+ return [];
204
+ }
205
+ function isReservedSchema(schema) {
206
+ return RESERVED_SCHEMAS.has(schema) || schema.startsWith("pg_") || Buffer.byteLength(schema, "utf8") > MAX_IDENTIFIER_BYTES;
207
+ }
208
+ function quoteIdentifier(name) {
209
+ return `"${name.replace(/"/g, '""')}"`;
210
+ }
211
+ function ensureFolderUrl(url) {
212
+ return url.href.endsWith("/") ? url : new URL(`${url.href}/`);
213
+ }
214
+ function describeError(error) {
215
+ return error instanceof Error ? error.message : String(error);
216
+ }
217
+ //# sourceMappingURL=migrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrator.js","sourceRoot":"","sources":["../../src/migrations/migrator.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,kGAAkG;AAClG,iGAAiG;AACjG,6FAA6F;AAC7F,OAAO,EAAE,EAAE,EAAE,yBAAyB,EAAyB,MAAM,kBAAkB,CAAC;AAExF,OAAO,EAAE,kBAAkB,EAAsB,MAAM,YAAY,CAAC;AACpE,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,WAAW,EACX,eAAe,GAGhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAA+C,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,WAAW,EAAyB,MAAM,cAAc,CAAC;AAuClE,gFAAgF;AAChF,MAAM,kBAAkB,GAAG,UAAU,CAAC;AACtC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAClF,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAsB,EAAE,OAAuB;IAClF,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxD,OAAO,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9G,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,MAAsB,EAAE,OAAuB;IAC3E,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CACrC,iBAAiB,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QACpC,6EAA6E;QAC7E,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3E,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,OAAO,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/E,MAAM,IAAI,GAAG,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC;YACjF,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7C,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,wCAAwC,CAAC,CAAC;YACxG,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YAC5E,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACzB,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAoC,EACpC,aAA8B;IAE9B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACtC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,KAAK,GAAoB;QAC7B,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE;KACxG,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACxC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAClD,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC;QAC3H,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QACxG,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,cAAc,CAC5B,KAA+B,EAC/B,OAA8B;IAE9B,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAEnE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;YAC/E,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7G,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;gBACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7G,CAAC;QACH,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtC,SAAS;YACX,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,GAAG,WAAW,EAAE,CAAC;gBAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,2BAA2B,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YAChI,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC9H,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAyB,EACzB,KAA4E;IAE5E,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACrC,oGAAoG;IACpG,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,sCAAsC,MAAM,8BAA8B,MAAM,WAAW,CAAC,CAAC;QAChH,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;QACD,0FAA0F;QAC1F,+EAA+E;QAC/E,IAAI,CAAC,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC,KAAK,aAAa,EAAE,CAAC;YACzD,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,CAAC;QACD,MAAM,eAAe,CAAC,OAAO,EAAE;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,MAAM;SACP,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC9C,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAC9G,CAAC;AACH,CAAC;AAED,MAAM,qBAAsB,SAAQ,KAAK;IACvC;QACE,KAAK,CAAC,2HAA2H,CAAC,CAAC;IACrI,CAAC;CACF;AAED,kGAAkG;AAClG,kCAAkC;AAClC,KAAK,UAAU,iBAAiB,CAAC,OAAyB;IACxD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,KAAK,CAAiB,yCAAyC,CAAC,CAAC;IAC7F,OAAO,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAyB,EAAE,KAAc;IACtE,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,aAAa,EAAE,CAAC;QACvB,OAAO,GAAG,MAAM,0BAA0B,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAI,OAAyB,EAAE,GAAqB;IACzF,MAAM,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACzE,IAAI,MAAS,CAAC;IACd,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4FAA4F;QAC5F,MAAM,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAoB,EAAE,EAAE;YACxG,MAAM,IAAI,KAAK,CAAC,yBAAyB,aAAa,CAAC,KAAK,CAAC,oCAAoC,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE;gBAC7H,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,MAAwB;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACxC,IAAI,MAAM,CAAC,EAAE,KAAK,gBAAgB,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACpF,OAAO,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAClD,OAAO,CAAC,EAAE,IAAI,EAAE,8BAA8B,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc;IACtC,OAAO,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,oBAAoB,CAAC;AAC9H,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACzC,CAAC;AAED,SAAS,eAAe,CAAC,GAAQ;IAC/B,OAAO,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,84 @@
1
+ import type { Err, Ok } from "@softure-ai/core";
2
+ export type MigrationProblem = {
3
+ readonly code: "db.invalid_migration_file";
4
+ readonly module: string;
5
+ readonly file: string;
6
+ readonly reason: string;
7
+ } | {
8
+ readonly code: "db.migrations_unreadable";
9
+ readonly module: string;
10
+ readonly dir: string;
11
+ readonly reason: string;
12
+ } | {
13
+ readonly code: "db.migration_changed";
14
+ readonly module: string;
15
+ readonly version: number;
16
+ readonly name: string;
17
+ } | {
18
+ readonly code: "db.migration_missing";
19
+ readonly module: string;
20
+ readonly version: number;
21
+ readonly name: string;
22
+ } | {
23
+ readonly code: "db.migration_out_of_order";
24
+ readonly module: string;
25
+ readonly version: number;
26
+ readonly appliedVersion: number;
27
+ } | {
28
+ readonly code: "db.migration_failed";
29
+ readonly module: string;
30
+ readonly version: number;
31
+ readonly name: string;
32
+ readonly reason: string;
33
+ } | {
34
+ readonly code: "db.reserved_module";
35
+ readonly module: string;
36
+ } | {
37
+ readonly code: "db.migrations_without_schema";
38
+ readonly module: string;
39
+ } | {
40
+ readonly code: "db.dependency_cycle";
41
+ readonly modules: readonly string[];
42
+ } | {
43
+ readonly code: "db.adopt_unknown_module";
44
+ readonly module: string;
45
+ } | {
46
+ readonly code: "db.adopt_version_mismatch";
47
+ readonly module: string;
48
+ readonly requested: string;
49
+ readonly enabled: string;
50
+ } | {
51
+ readonly code: "db.adopt_already_applied";
52
+ readonly module: string;
53
+ } | {
54
+ readonly code: "db.adopt_dependency_pending";
55
+ readonly module: string;
56
+ readonly dependency: string;
57
+ } | {
58
+ readonly code: "db.adopt_no_schema";
59
+ readonly module: string;
60
+ } | {
61
+ readonly code: "db.adopt_reference_failed";
62
+ readonly module: string;
63
+ readonly reason: string;
64
+ } | {
65
+ readonly code: "db.export_target_not_empty";
66
+ readonly module: string;
67
+ readonly dir: string;
68
+ readonly entries: readonly string[];
69
+ } | {
70
+ readonly code: "db.schema_mismatch";
71
+ readonly module: string;
72
+ readonly schema: string;
73
+ readonly differences: readonly string[];
74
+ };
75
+ export type MigrationErrorCode = MigrationProblem["code"];
76
+ /** A failed migration operation: the code of its first problem, and every problem found. */
77
+ export interface MigrationFailure extends Err<MigrationErrorCode> {
78
+ readonly problems: readonly MigrationProblem[];
79
+ }
80
+ export type MigrationResult<T> = Ok<T> | MigrationFailure;
81
+ export declare function failWith(problems: readonly MigrationProblem[]): MigrationFailure;
82
+ /** One English line per problem, naming the module and the file or object involved. */
83
+ export declare function describeProblem(problem: MigrationProblem): string;
84
+ //# sourceMappingURL=problems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"problems.d.ts","sourceRoot":"","sources":["../../src/migrations/problems.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ export function failWith(problems) {
2
+ const [first] = problems;
3
+ if (first === undefined) {
4
+ throw new Error("failWith: a migration failure needs at least one problem");
5
+ }
6
+ return { ok: false, error: first.code, problems };
7
+ }
8
+ /** One English line per problem, naming the module and the file or object involved. */
9
+ export function describeProblem(problem) {
10
+ switch (problem.code) {
11
+ case "db.invalid_migration_file":
12
+ return `${problem.module}: migration file ${problem.file} is invalid: ${problem.reason}`;
13
+ case "db.migrations_unreadable":
14
+ return `${problem.module}: cannot read the migrations folder ${problem.dir}: ${problem.reason}`;
15
+ case "db.migration_changed":
16
+ return `${problem.module}: applied migration ${formatFile(problem.version, problem.name)} was edited (checksum differs); add a new migration instead`;
17
+ case "db.migration_missing":
18
+ return `${problem.module}: applied migration ${formatFile(problem.version, problem.name)} is missing from the module`;
19
+ case "db.migration_out_of_order":
20
+ return `${problem.module}: migration ${formatVersion(problem.version)} is pending but ${formatVersion(problem.appliedVersion)} is already applied`;
21
+ case "db.migration_failed":
22
+ return `${problem.module}: migration ${formatFile(problem.version, problem.name)} failed and was rolled back: ${problem.reason}`;
23
+ case "db.reserved_module":
24
+ return `${problem.module}: uses a reserved id or schema (the id "softure"; the schemas softure, public, information_schema, pg_* and names over 63 bytes)`;
25
+ case "db.migrations_without_schema":
26
+ return `${problem.module}: has migrations but no dbSchema in its manifest`;
27
+ case "db.dependency_cycle":
28
+ return `modules ${problem.modules.join(", ")} depend on each other in a cycle`;
29
+ case "db.adopt_unknown_module":
30
+ return `${problem.module}: cannot adopt a module that is not enabled in the config`;
31
+ case "db.adopt_version_mismatch":
32
+ return `${problem.module}: --adopt asks for ${problem.requested} but ${problem.enabled} is enabled`;
33
+ case "db.adopt_already_applied":
34
+ return `${problem.module}: already has migrations in the ledger; adopt only works on a module the ledger has never seen`;
35
+ case "db.adopt_dependency_pending":
36
+ return `${problem.module}: depends on ${problem.dependency}, which has migrations still pending; migrate or adopt ${problem.dependency} first`;
37
+ case "db.adopt_no_schema":
38
+ return `${problem.module}: has no dbSchema, so there is nothing to adopt`;
39
+ case "db.adopt_reference_failed":
40
+ return `${problem.module}: could not build the reference schema: ${problem.reason}`;
41
+ case "db.export_target_not_empty":
42
+ return `${problem.module}: ${problem.dir} holds other files (${problem.entries.join(", ")}); export into an empty folder`;
43
+ case "db.schema_mismatch":
44
+ return [
45
+ `${problem.module}: schema "${problem.schema}" differs from what its migrations create:`,
46
+ ...problem.differences.map((difference) => ` ${difference}`),
47
+ ].join("\n");
48
+ }
49
+ }
50
+ function formatVersion(version) {
51
+ return String(version).padStart(4, "0");
52
+ }
53
+ function formatFile(version, name) {
54
+ return `${formatVersion(version)}_${name}.sql`;
55
+ }
56
+ //# sourceMappingURL=problems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"problems.js","sourceRoot":"","sources":["../../src/migrations/problems.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { DatabaseHandle } from "../client.js";
2
+ export interface MigrationSession {
3
+ /** A parameterised statement; returns its rows. */
4
+ readonly query: <T>(text: string, params?: readonly unknown[]) => Promise<T[]>;
5
+ /** One or more statements without parameters (a migration file). */
6
+ readonly exec: (sql: string) => Promise<void>;
7
+ }
8
+ /**
9
+ * Runs `run` on one dedicated connection. A pg client is destroyed afterwards instead of going
10
+ * back to the pool, so a `SET` inside a migration file or a lock that failed to release cannot
11
+ * leak into the app's queries. PGlite has one connection, so its settings are reset instead.
12
+ */
13
+ export declare function withSession<T>(handle: DatabaseHandle, run: (session: MigrationSession) => Promise<T>): Promise<T>;
14
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/migrations/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/E,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA+BvH"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Runs `run` on one dedicated connection. A pg client is destroyed afterwards instead of going
3
+ * back to the pool, so a `SET` inside a migration file or a lock that failed to release cannot
4
+ * leak into the app's queries. PGlite has one connection, so its settings are reset instead.
5
+ */
6
+ export async function withSession(handle, run) {
7
+ if (handle.kind === "pglite") {
8
+ const { client } = handle;
9
+ try {
10
+ return await run({
11
+ query: async (text, params) => (await client.query(text, params ? [...params] : undefined)).rows,
12
+ exec: async (sql) => {
13
+ await client.exec(sql);
14
+ },
15
+ });
16
+ }
17
+ finally {
18
+ await client.exec("RESET ALL");
19
+ }
20
+ }
21
+ const client = await handle.pool.connect();
22
+ // A dropped connection makes pg emit 'error' on the client; without a listener Node crashes the
23
+ // process. The pending query rejects on its own, so the listener only has to exist.
24
+ const ignoreClientError = () => undefined;
25
+ client.on("error", ignoreClientError);
26
+ try {
27
+ return await run({
28
+ query: async (text, params) => (await client.query(text, params ? [...params] : undefined)).rows,
29
+ exec: async (sql) => {
30
+ await client.query(sql);
31
+ },
32
+ });
33
+ }
34
+ finally {
35
+ client.release(true);
36
+ client.off("error", ignoreClientError);
37
+ }
38
+ }
39
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/migrations/session.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAI,MAAsB,EAAE,GAA8C;IACzG,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QAC1B,IAAI,CAAC;YACH,OAAO,MAAM,GAAG,CAAC;gBACf,KAAK,EAAE,KAAK,EAAK,IAAY,EAAE,MAA2B,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAI,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;gBACnI,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;oBAClB,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACzB,CAAC;aACF,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IAC3C,gGAAgG;IAChG,oFAAoF;IACpF,MAAM,iBAAiB,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;IAChD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC;YACf,KAAK,EAAE,KAAK,EAAK,IAAY,EAAE,MAA2B,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAW;YACvI,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBAClB,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;SACF,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACzC,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type CreateDatabaseOptions, type DatabaseHandle } from "./client.js";
2
+ /**
3
+ * The process-wide handle for `url`, opened on first use. `options` apply only to that first call.
4
+ * A failed open is not kept, so the next call tries again.
5
+ */
6
+ export declare function getSharedDatabase(url: string, options?: CreateDatabaseOptions): Promise<DatabaseHandle>;
7
+ /** Closes and forgets every shared handle. For tests and graceful shutdown. */
8
+ export declare function closeSharedDatabases(): Promise<void>;
9
+ //# sourceMappingURL=shared.d.ts.map