@voltro/database 0.86.0 → 0.87.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.
@@ -0,0 +1,9 @@
1
+ import { splitStatements as e } from "../migrate.js";
2
+ //#region src/migrations/ddlStatements.ts
3
+ var t = (t, n) => {
4
+ if (t !== "postgres") return [n];
5
+ let r = e(n);
6
+ return r.length <= 1 ? [n] : r;
7
+ };
8
+ //#endregion
9
+ export { t as ddlStatementsFor };
@@ -1,22 +1,23 @@
1
1
  import { causeBranches as e, classifyConstraintViolation as t, extractDbCause as n } from "../dbCause.js";
2
- import { FILE_MIGRATION_PATTERN as r, IrreversibleMigrationError as i, MigrationExpectationFailed as a, MigrationSkipped as o, TransactionBrokenByBodyError as s, irreversibleReason as c, isFileMigration as l } from "./fileBased.js";
3
- import { acquireMigrationLock as u } from "./lock.js";
4
- import { MIGRATION_OPS_TABLE as d, dialectOf as f } from "./resumeLedger.js";
5
- import { migrationTableExists as p } from "./migrationTableExists.js";
6
- import { appliedAtValue as m } from "./appliedAtValue.js";
7
- import { ensureLedgerTable as h, ensurePlanLedgerTable as g } from "./applier.js";
8
- import { isFileMigrationRow as _ } from "./ledgerRows.js";
9
- import { failedExpectations as v, makeFileMigrationContext as y } from "./fileContext.js";
10
- import { withSchemaProbeRecorder as b } from "./fileSkipProbes.js";
11
- import { Effect as x } from "effect";
12
- import { createHash as S } from "node:crypto";
13
- import { SqlClient as C } from "effect/sql";
14
- import { createLogger as w } from "@voltro/logger";
15
- import { promises as T } from "node:fs";
16
- import { join as E } from "node:path";
17
- import { pathToFileURL as D } from "node:url";
2
+ import { derivedRowId as r } from "../derivedRowId.js";
3
+ import { FILE_MIGRATION_PATTERN as i, IrreversibleMigrationError as a, MigrationExpectationFailed as o, MigrationSkipped as s, TransactionBrokenByBodyError as c, irreversibleReason as l, isFileMigration as u } from "./fileBased.js";
4
+ import { acquireMigrationLock as d } from "./lock.js";
5
+ import { MIGRATION_OPS_TABLE as f, dialectOf as p } from "./resumeLedger.js";
6
+ import { migrationTableExists as m } from "./migrationTableExists.js";
7
+ import { appliedAtValue as h } from "./appliedAtValue.js";
8
+ import { ensureLedgerTable as g, ensurePlanLedgerTable as _ } from "./applier.js";
9
+ import { isFileMigrationRow as v } from "./ledgerRows.js";
10
+ import { failedExpectations as y, makeFileMigrationContext as b } from "./fileContext.js";
11
+ import { withSchemaProbeRecorder as x } from "./fileSkipProbes.js";
12
+ import { Effect as S } from "effect";
13
+ import { createHash as C } from "node:crypto";
14
+ import { SqlClient as w } from "effect/sql";
15
+ import { createLogger as T } from "@voltro/logger";
16
+ import { promises as E } from "node:fs";
17
+ import { join as D } from "node:path";
18
+ import { pathToFileURL as O } from "node:url";
18
19
  //#region src/migrations/fileDiscovery.ts
19
- var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest("hex").slice(0, 16), A = [{
20
+ var k = T({ scope: "voltro:migrate" }), A = (e) => C("sha256").update(e).digest("hex").slice(0, 16), j = [{
20
21
  codemod: "0.78.0/01_file-migration-phase",
21
22
  inverse: (e) => {
22
23
  let t = /\n {2}phase: 'before-schema',\n {2}/g, n = /\n {2}phase: 'before-schema'(?=\r?\n[ \t]*\})/g, r = e.includes("\r\n") ? "\r\n" : "\n", i = (t) => {
@@ -25,7 +26,7 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
25
26
  };
26
27
  return [e.replace(t, (e, t) => r + i(t)).replace(n, ""), e.replace(t, " ").replace(n, "")];
27
28
  }
28
- }], j = (e) => new Set([e, ...A.flatMap((t) => t.inverse(e))].map(k)), M = /* @__PURE__ */ new Set([
29
+ }], M = (e) => new Set([e, ...j.flatMap((t) => t.inverse(e))].map(A)), N = /* @__PURE__ */ new Set([
29
30
  "node_modules",
30
31
  "dist",
31
32
  "build",
@@ -34,56 +35,67 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
34
35
  ".next",
35
36
  ".git",
36
37
  ".framework"
37
- ]), N = async (e) => {
38
+ ]), P = async (e) => {
38
39
  let t = [], n = async (e) => {
39
- let i = await T.readdir(e, { withFileTypes: !0 }).catch(() => []);
40
- for (let a of i) {
41
- if (M.has(a.name)) continue;
42
- let i = E(e, a.name);
43
- a.isDirectory() ? await n(i) : a.isFile() && r.test(a.name) && t.push(i);
40
+ let r = await E.readdir(e, { withFileTypes: !0 }).catch(() => []);
41
+ for (let a of r) {
42
+ if (N.has(a.name)) continue;
43
+ let r = D(e, a.name);
44
+ a.isDirectory() ? await n(r) : a.isFile() && i.test(a.name) && t.push(r);
44
45
  }
45
46
  };
46
47
  return await n(e), t.sort((e, t) => {
47
48
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
48
49
  return n.localeCompare(r);
49
50
  });
50
- }, P = async (e) => await import(D(e).href), F = async (e, t = P) => {
51
+ }, F = async (e) => await import(O(e).href), I = async (e, t = F) => {
51
52
  let n = [];
52
53
  for (let r of e) {
53
54
  let e = (await t(r)).default;
54
- if (!l(e)) {
55
- O.warn("migration file has no default-exported `migration(...)` — skipped", { file: r });
55
+ if (!u(e)) {
56
+ k.warn("migration file has no default-exported `migration(...)` — skipped", { file: r });
56
57
  continue;
57
58
  }
58
- let i = await T.readFile(r, "utf8").catch(() => "");
59
+ let i = await E.readFile(r, "utf8").catch(() => "");
59
60
  n.push({
60
61
  file: r,
61
62
  migration: e,
62
- hash: k(i),
63
- accepted: j(i)
63
+ hash: A(i),
64
+ accepted: M(i)
64
65
  });
65
66
  }
66
67
  return n;
67
- }, I = "_voltro_migration_plans", L = (e) => R(e).pipe(x.map((e) => e.map((e) => e.id))), R = (e) => p(e, I).pipe(x.flatMap((t) => t ? e`
68
+ }, L = "_voltro_migration_plans", R = (e) => z(e).pipe(S.map((e) => e.map((e) => e.id))), z = (e) => m(e, L).pipe(S.flatMap((t) => t ? e`
68
69
  SELECT ${e("id")}, ${e("fingerprint")}
69
- FROM ${e(I)}
70
- WHERE ${_(e)}
71
- `.pipe(x.map((e) => e.map((e) => ({
70
+ FROM ${e(L)}
71
+ WHERE ${v(e)}
72
+ `.pipe(S.map((e) => e.map((e) => ({
72
73
  id: e.id,
73
74
  hash: e.fingerprint ?? ""
74
- })))) : x.succeed([]))), z = (e, t) => t.filter((t) => {
75
+ })))) : S.succeed([]))), B = (e, t) => t.filter((t) => {
75
76
  let n = e.get(t.migration.id);
76
77
  return n !== void 0 && n !== "" && !t.accepted.has(n);
77
- }).map((e) => e.migration.id), B = /* @__PURE__ */ new Set(), V = (e) => t(n(e))?.kind === "unique", H = class extends Error {
78
+ }).map((e) => e.migration.id), V = /* @__PURE__ */ new Set(), H = (e) => t(n(e))?.kind === "unique", U = class extends Error {
78
79
  migrationId;
79
80
  file;
80
81
  cause;
81
82
  _tag = "FileMigrationLedgerError";
82
83
  constructor(e, t, n) {
83
- super(V(n) ? `migration ${e}: up() SUCCEEDED here, and ANOTHER process had already recorded the same migration.\n The body has run TWICE. The ledger row is correct — do not delete it; the next run will not apply ${t} again.\n Two processes applied it without being serialised by the migration lock: check that both reach the same database and lock schema.\n Cause: ${n instanceof Error ? n.message : String(n)}` : `migration ${e}: up() SUCCEEDED but the ledger row could not be written.\n The change IS in the database. It is NOT recorded, so the next run would apply it AGAIN.\n Do not re-run ${t} until this is resolved.\n Cause: ${n instanceof Error ? n.message : String(n)}`), this.migrationId = e, this.file = t, this.cause = n, this.name = "FileMigrationLedgerError";
84
+ super(H(n) ? `migration ${e}: up() SUCCEEDED here, and ANOTHER process had already recorded the same migration.\n The body has run TWICE. The ledger row is correct — do not delete it; the next run will not apply ${t} again.\n Two processes applied it without being serialised by the migration lock: check that both reach the same database and lock schema.\n Cause: ${n instanceof Error ? n.message : String(n)}` : `migration ${e}: up() SUCCEEDED but the ledger row could not be written.\n The change IS in the database. It is NOT recorded, so the next run would apply it AGAIN.\n Do not re-run ${t} until this is resolved.\n Cause: ${n instanceof Error ? n.message : String(n)}`), this.migrationId = e, this.file = t, this.cause = n, this.name = "FileMigrationLedgerError";
84
85
  }
85
- }, U = (e, t, n) => x.gen(function* () {
86
- let r = yield* m(e, n.appliedAtIso);
86
+ }, W = /* @__PURE__ */ new Set([
87
+ "mysql",
88
+ "mariadb",
89
+ "mssql"
90
+ ]), G = (e, t) => W.has(e) ? t.filter((e) => e.length > 64) : [], K = class extends Error {
91
+ dialect;
92
+ migrationIds;
93
+ _tag = "MigrationIdTooLongError";
94
+ constructor(e, t) {
95
+ super(`migration id(s) longer than 64 characters cannot be recorded on ${e}: ` + t.map((e) => `${e} (${e.length})`).join(", ") + ". Nothing was applied. Rename the migration file and its `id` to at most 64 characters."), this.dialect = e, this.migrationIds = t, this.name = "MigrationIdTooLongError";
96
+ }
97
+ }, q = (e, t, n) => S.gen(function* () {
98
+ let r = yield* h(e, n.appliedAtIso);
87
99
  yield* e`
88
100
  INSERT INTO ${e("_voltro_migration_plans")}
89
101
  (${e("id")}, ${e("fingerprint")}, ${e("operations")},
@@ -97,93 +109,93 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
97
109
  }])},
98
110
  ${n.appliedBy}, ${n.env}, ${"file"},
99
111
  ${n.durationMs}, ${r}, ${n.notes})
100
- `.pipe(x.mapError((e) => new H(t.migration.id, t.file, e)));
101
- }), W = (t) => {
102
- for (let n of e(t)) if (n instanceof o) return n.reason;
103
- }, G = (e, t, n) => x.gen(function* () {
104
- let r = b(t), i = r.ctx, o = e.migration.up(i), s = !x.isEffect(o), c = yield* (x.isEffect(o) ? o : x.tryPromise({
105
- try: () => o,
112
+ `.pipe(S.mapError((e) => new U(t.migration.id, t.file, e)));
113
+ }), J = (t) => {
114
+ for (let n of e(t)) if (n instanceof s) return n.reason;
115
+ }, Y = (e, t, n) => S.gen(function* () {
116
+ let r = x(t), i = r.ctx, a = e.migration.up(i), s = !S.isEffect(a), c = yield* (S.isEffect(a) ? a : S.tryPromise({
117
+ try: () => a,
106
118
  catch: (e) => e
107
- })).pipe(x.as(void 0), x.catch((e) => {
108
- let t = W(e);
109
- return t === void 0 ? x.fail(e) : x.succeed(t);
119
+ })).pipe(S.as(void 0), S.catch((e) => {
120
+ let t = J(e);
121
+ return t === void 0 ? S.fail(e) : S.succeed(t);
110
122
  }));
111
123
  if (c === void 0) {
112
- let t = yield* v(n);
113
- if (t.length > 0) return yield* x.fail(new a(e.migration.id, t));
124
+ let t = yield* y(n);
125
+ if (t.length > 0) return yield* S.fail(new o(e.migration.id, t));
114
126
  }
115
127
  return {
116
128
  skipped: c,
117
129
  promiseForm: s,
118
130
  absent: r.absent()
119
131
  };
120
- }), K = (e, t, n, r, i, a, o, c) => x.gen(function* () {
121
- let l = Date.now(), u = (/* @__PURE__ */ new Date()).toISOString(), p = f(e), m = `migrations:file:${n.migration.id}`, g = (e) => ({
122
- durationMs: Date.now() - l,
132
+ }), X = (e, t, n, i, a, o, s, l) => S.gen(function* () {
133
+ let u = Date.now(), d = (/* @__PURE__ */ new Date()).toISOString(), m = p(e), h = `migrations:file:${n.migration.id}`, _ = (e) => ({
134
+ durationMs: Date.now() - u,
123
135
  notes: e.skipped === void 0 ? n.migration.description : `skipped: ${e.skipped}`
124
136
  });
125
- if (n.migration.transactional !== !1 && !a) {
126
- if (t.run === void 0) return yield* x.fail(/* @__PURE__ */ Error(`migration ${n.migration.id}: transactional: true needs a SQL-backed store`));
127
- let a = p === "mysql" || p === "mariadb", l = `probe_${n.migration.id}_${Date.now().toString(36)}`;
128
- a && (yield* h(e, p, o));
129
- let f = (e) => e.executeUnprepared(`SELECT COUNT(*) AS n FROM \`${d}\` WHERE \`runId\` = ?`, [l], void 0), _ = () => (c === void 0 ? x.scoped(x.flatMap(e.reserve, f)) : f(c)).pipe(x.map((e) => Number(e[0]?.n ?? 0) > 0)), v = yield* x.tryPromise({
137
+ if (n.migration.transactional !== !1 && !o) {
138
+ if (t.run === void 0) return yield* S.fail(/* @__PURE__ */ Error(`migration ${n.migration.id}: transactional: true needs a SQL-backed store`));
139
+ let o = m === "mysql" || m === "mariadb", u = `probe_${n.migration.id}_${Date.now().toString(36)}`;
140
+ o && (yield* g(e, m, s));
141
+ let p = (e) => e.executeUnprepared(`SELECT COUNT(*) AS n FROM \`${f}\` WHERE \`runId\` = ?`, [u], void 0), v = () => (l === void 0 ? S.scoped(S.flatMap(e.reserve, p)) : p(l)).pipe(S.map((e) => Number(e[0]?.n ?? 0) > 0)), y = yield* S.tryPromise({
130
142
  try: () => t.transactional(async (t) => {
131
- a && await t.run(e`INSERT INTO ${e(d)} (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")}, ${e("status")}, ${e("opKind")}, ${e("opTarget")}, ${e("payload")})
132
- VALUES (${`mop_${l}`}, ${l}, ${""}, ${0}, ${"pending"}, ${"probe"}, ${""}, ${"{}"})`);
133
- let { ctx: o, expectations: s } = y({
143
+ o && await t.run(e`INSERT INTO ${e(f)} (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")}, ${e("status")}, ${e("opKind")}, ${e("opTarget")}, ${e("payload")})
144
+ VALUES (${r("mop", u)}, ${u}, ${""}, ${0}, ${"pending"}, ${"probe"}, ${""}, ${"{}"})`);
145
+ let { ctx: s, expectations: c } = b({
134
146
  sql: e,
135
147
  store: t,
136
- dialect: p,
148
+ dialect: m,
137
149
  migrationId: n.migration.id,
138
- appliedAt: u
139
- }), c = await t.run(G(n, o, s)), f = a && await x.runPromise(_().pipe(x.provideService(C.SqlClient, e))), { durationMs: m, notes: h } = g(c);
140
- return await t.run(U(e, n, {
141
- env: r,
142
- appliedBy: i,
143
- durationMs: m,
144
- appliedAtIso: u,
145
- notes: f ? `${h} — transactional guarantee broken by the body (DDL on ${p})` : h
146
- })), a && await t.run(e`DELETE FROM ${e(d)} WHERE ${e("runId")} = ${l}`), {
147
- ...c,
148
- durationMs: m,
149
- broken: f
150
+ appliedAt: d
151
+ }), l = await t.run(Y(n, s, c)), p = o && await S.runPromise(v().pipe(S.provideService(w.SqlClient, e))), { durationMs: h, notes: g } = _(l);
152
+ return await t.run(q(e, n, {
153
+ env: i,
154
+ appliedBy: a,
155
+ durationMs: h,
156
+ appliedAtIso: d,
157
+ notes: p ? `${g} — transactional guarantee broken by the body (DDL on ${m})` : g
158
+ })), o && await t.run(e`DELETE FROM ${e(f)} WHERE ${e("runId")} = ${u}`), {
159
+ ...l,
160
+ durationMs: h,
161
+ broken: p
150
162
  };
151
163
  }),
152
164
  catch: (e) => e
153
165
  });
154
- return v.broken ? yield* x.fail(new s(n.migration.id, p)) : (v.skipped !== void 0 && (yield* x.logInfo(`migration ${n.migration.id} skipped: ${v.skipped}`).pipe(x.annotateLogs({ scope: m }))), {
155
- durationMs: v.durationMs,
156
- skip: v.skipped === void 0 ? void 0 : {
166
+ return y.broken ? yield* S.fail(new c(n.migration.id, m)) : (y.skipped !== void 0 && (yield* S.logInfo(`migration ${n.migration.id} skipped: ${y.skipped}`).pipe(S.annotateLogs({ scope: h }))), {
167
+ durationMs: y.durationMs,
168
+ skip: y.skipped === void 0 ? void 0 : {
157
169
  id: n.migration.id,
158
- reason: v.skipped,
159
- absent: v.absent
170
+ reason: y.skipped,
171
+ absent: y.absent
160
172
  }
161
173
  });
162
174
  }
163
- let { ctx: _, expectations: v } = y({
175
+ let { ctx: v, expectations: y } = b({
164
176
  sql: e,
165
177
  store: t,
166
- dialect: p,
178
+ dialect: m,
167
179
  migrationId: n.migration.id,
168
- appliedAt: u
169
- }), b = yield* G(n, _, v), { durationMs: S, notes: w } = g(b);
170
- return b.promiseForm && b.skipped === void 0 && S < 2 && (yield* x.logWarning(`migration ${n.migration.id}: up() resolved in ${S}ms — did the body \`await\` an \`effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(x.annotateLogs({ scope: m }))), b.skipped !== void 0 && (yield* x.logInfo(`migration ${n.migration.id} skipped: ${b.skipped}`).pipe(x.annotateLogs({ scope: m }))), yield* U(e, n, {
171
- env: r,
172
- appliedBy: i,
173
- durationMs: S,
174
- appliedAtIso: u,
175
- notes: w
180
+ appliedAt: d
181
+ }), x = yield* Y(n, v, y), { durationMs: C, notes: T } = _(x);
182
+ return x.promiseForm && x.skipped === void 0 && C < 2 && (yield* S.logWarning(`migration ${n.migration.id}: up() resolved in ${C}ms — did the body \`await\` an \`effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(S.annotateLogs({ scope: h }))), x.skipped !== void 0 && (yield* S.logInfo(`migration ${n.migration.id} skipped: ${x.skipped}`).pipe(S.annotateLogs({ scope: h }))), yield* q(e, n, {
183
+ env: i,
184
+ appliedBy: a,
185
+ durationMs: C,
186
+ appliedAtIso: d,
187
+ notes: T
176
188
  }), {
177
- durationMs: S,
178
- skip: b.skipped === void 0 ? void 0 : {
189
+ durationMs: C,
190
+ skip: x.skipped === void 0 ? void 0 : {
179
191
  id: n.migration.id,
180
- reason: b.skipped,
181
- absent: b.absent
192
+ reason: x.skipped,
193
+ absent: x.absent
182
194
  }
183
195
  };
184
- }), q = (e, t, n, r) => x.gen(function* () {
185
- let i = yield* x.tryPromise({
186
- try: () => N(E(t, "migrations")),
196
+ }), Z = (e, t, n, r) => S.gen(function* () {
197
+ let i = yield* S.tryPromise({
198
+ try: () => P(D(t, "migrations")),
187
199
  catch: (e) => e
188
200
  });
189
201
  if (i.length === 0) return {
@@ -191,8 +203,8 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
191
203
  alreadyApplied: [],
192
204
  drifted: []
193
205
  };
194
- let a = yield* x.tryPromise({
195
- try: () => F(i, r),
206
+ let a = yield* S.tryPromise({
207
+ try: () => I(i, r),
196
208
  catch: (e) => e
197
209
  });
198
210
  if (a.length === 0) return {
@@ -200,11 +212,11 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
200
212
  alreadyApplied: [],
201
213
  drifted: []
202
214
  };
203
- let o = new Map((yield* R(e)).map((e) => [e.id, e.hash])), s = z(o, a), c = s.length >= 32 ? /* @__PURE__ */ new Map() : void 0;
215
+ let o = new Map((yield* z(e)).map((e) => [e.id, e.hash])), s = B(o, a), c = s.length >= 32 ? /* @__PURE__ */ new Map() : void 0;
204
216
  if (c !== void 0) for (let e of a) c.has(e.migration.id) || c.set(e.migration.id, e);
205
217
  for (let e of s) {
206
218
  let t = c === void 0 ? a.find((t) => t.migration.id === e) : c.get(e), n = `${t?.file ?? e}:${t?.hash ?? ""}`;
207
- B.has(n) || (B.add(n), O.warn("file migration: the body on disk is not the one that was applied — the file no longer describes this database", {
219
+ V.has(n) || (V.add(n), k.warn("file migration: the body on disk is not the one that was applied — the file no longer describes this database", {
208
220
  id: e,
209
221
  file: t?.file
210
222
  }));
@@ -215,11 +227,11 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
215
227
  alreadyApplied: l.filter((e) => o.has(e.migration.id)),
216
228
  drifted: s
217
229
  };
218
- }), J = (e, t, n, r) => q(e, t, n, r).pipe(x.map((e) => e.pending.map((e) => e.migration.id))), Y = (e, t, n) => q(e, t, n).pipe(x.map((e) => e.pending.map((e) => ({
230
+ }), Q = (e, t, n, r) => Z(e, t, n, r).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), ee = (e, t, n) => Z(e, t, n).pipe(S.map((e) => e.pending.map((e) => ({
219
231
  id: e.migration.id,
220
232
  phase: e.migration.phase,
221
- irreversible: c(e.migration.down)
222
- })))), X = (e, t) => q(e, t).pipe(x.map((e) => {
233
+ irreversible: l(e.migration.down)
234
+ })))), te = (e, t) => Z(e, t).pipe(S.map((e) => {
223
235
  let t = new Set(e.drifted);
224
236
  return [...e.alreadyApplied.map((e) => ({
225
237
  id: e.migration.id,
@@ -232,17 +244,19 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
232
244
  applied: !1,
233
245
  bodyChanged: !1
234
246
  }))].sort((e, t) => e.id < t.id ? -1 : 1);
235
- })), Z = (e, t) => x.gen(function* () {
236
- let { pending: n, alreadyApplied: r } = yield* q(e, t.projectRoot, t.phase), i = r.map((e) => e.migration.id);
247
+ })), ne = (e, t) => S.gen(function* () {
248
+ let { pending: n, alreadyApplied: r } = yield* Z(e, t.projectRoot, t.phase), i = r.map((e) => e.migration.id);
237
249
  if (n.length === 0) return {
238
250
  applied: [],
239
251
  skipped: i,
240
252
  skips: []
241
253
  };
242
- yield* g(e, f(e), t.charset);
243
- let a = yield* x.acquireUseRelease(u(e, { schema: t.lockSchema }), (r) => x.gen(function* () {
244
- let i = new Set((yield* R(e)).map((e) => e.id)), a = n.filter((e) => !i.has(e.migration.id));
245
- a.length < n.length && (yield* x.logInfo("file-based migrations applied by another process while this one waited for the migration lock").pipe(x.annotateLogs({
254
+ let a = G(p(e), n.map((e) => e.migration.id));
255
+ if (a.length > 0) return yield* S.fail(new K(p(e), a));
256
+ yield* _(e, p(e), t.charset);
257
+ let o = yield* S.acquireUseRelease(d(e, { schema: t.lockSchema }), (r) => S.gen(function* () {
258
+ let i = new Set((yield* z(e)).map((e) => e.id)), a = n.filter((e) => !i.has(e.migration.id));
259
+ a.length < n.length && (yield* S.logInfo("file-based migrations applied by another process while this one waited for the migration lock").pipe(S.annotateLogs({
246
260
  scope: "voltro:migrate",
247
261
  ids: n.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id).join(",")
248
262
  })));
@@ -250,17 +264,17 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
250
264
  a.length > 0 && t.beforeExecute !== void 0 && (yield* t.beforeExecute);
251
265
  let s = [];
252
266
  for (let n of a) {
253
- yield* x.logInfo("file-based migration applying").pipe(x.annotateLogs({
267
+ yield* S.logInfo("file-based migration applying").pipe(S.annotateLogs({
254
268
  scope: "voltro:migrate",
255
269
  id: n.migration.id,
256
270
  file: n.file,
257
271
  phase: n.migration.phase
258
272
  }));
259
- let { durationMs: i, skip: a } = yield* K(e, t.store, n, t.env, t.appliedBy, t.enclosed === !0, t.charset, r.connection);
273
+ let { durationMs: i, skip: a } = yield* X(e, t.store, n, t.env, t.appliedBy, t.enclosed === !0, t.charset, r.connection);
260
274
  o.push({
261
275
  id: n.migration.id,
262
276
  durationMs: i
263
- }), a !== void 0 && s.push(a), yield* x.logInfo("file-based migration applied").pipe(x.annotateLogs({
277
+ }), a !== void 0 && s.push(a), yield* S.logInfo("file-based migration applied").pipe(S.annotateLogs({
264
278
  scope: "voltro:migrate",
265
279
  id: n.migration.id,
266
280
  durationMs: i,
@@ -271,39 +285,39 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
271
285
  done: o,
272
286
  skips: s
273
287
  };
274
- }), (e) => e.release.pipe(x.orDie));
288
+ }), (e) => e.release.pipe(S.orDie));
275
289
  return {
276
- applied: a.done,
290
+ applied: o.done,
277
291
  skipped: i,
278
- skips: a.skips
292
+ skips: o.skips
279
293
  };
280
- }), Q = (e, t) => e`
294
+ }), $ = (e, t) => e`
281
295
  SELECT ${e("id")}
282
296
  FROM ${e("_voltro_migration_plans")}
283
297
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
284
- `, $ = (e, t) => x.gen(function* () {
285
- if (!(yield* Q(e, t.id))[0]) return yield* x.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
286
- let n = yield* x.tryPromise({
287
- try: () => N(E(t.projectRoot, "migrations")),
298
+ `, re = (e, t) => S.gen(function* () {
299
+ if (!(yield* $(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
300
+ let n = yield* S.tryPromise({
301
+ try: () => P(D(t.projectRoot, "migrations")),
288
302
  catch: (e) => e
289
- }), r = (yield* x.tryPromise({
290
- try: () => F(n),
303
+ }), r = (yield* S.tryPromise({
304
+ try: () => I(n),
291
305
  catch: (e) => e
292
306
  })).find((e) => e.migration.id === t.id);
293
- if (!r) return yield* x.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
294
- let a = c(r.migration.down);
295
- return a === void 0 ? yield* x.acquireUseRelease(u(e, { schema: t.lockSchema }), () => x.gen(function* () {
296
- if ((yield* Q(e, t.id))[0] === void 0) return yield* x.fail(/* @__PURE__ */ Error(`rollback: ${t.id} was rolled back by another process while this one waited for the migration lock — nothing to do`));
297
- let n = Date.now(), { ctx: i } = y({
307
+ if (!r) return yield* S.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
308
+ let i = l(r.migration.down);
309
+ return i === void 0 ? yield* S.acquireUseRelease(d(e, { schema: t.lockSchema }), () => S.gen(function* () {
310
+ if ((yield* $(e, t.id))[0] === void 0) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} was rolled back by another process while this one waited for the migration lock — nothing to do`));
311
+ let n = Date.now(), { ctx: i } = b({
298
312
  sql: e,
299
313
  store: t.store,
300
- dialect: f(e),
314
+ dialect: p(e),
301
315
  migrationId: t.id,
302
316
  appliedAt: (/* @__PURE__ */ new Date()).toISOString()
303
317
  });
304
318
  t.beforeExecute !== void 0 && (yield* t.beforeExecute);
305
319
  let a = r.migration.down(i);
306
- x.isEffect(a) ? yield* a : yield* x.tryPromise({
320
+ S.isEffect(a) ? yield* a : yield* S.tryPromise({
307
321
  try: () => a,
308
322
  catch: (e) => e
309
323
  });
@@ -312,7 +326,7 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
312
326
  id: t.id,
313
327
  durationMs: o
314
328
  };
315
- }), (e) => e.release.pipe(x.orDie)) : yield* x.fail(new i(t.id, a));
329
+ }), (e) => e.release.pipe(S.orDie)) : yield* S.fail(new a(t.id, i));
316
330
  });
317
331
  //#endregion
318
- export { r as FILE_MIGRATION_PATTERN, A as FRAMEWORK_MIGRATION_EDITS, H as FileMigrationLedgerError, j as acceptedBodyHashes, L as appliedFileMigrationIds, R as appliedFileMigrations, X as fileMigrationStatus, k as migrationBodyHash, J as pendingFileMigrationIds, Y as pendingFileMigrationSummary, $ as rollbackFileBasedMigration, Z as runFileBasedMigrations, N as walkMigrationFiles };
332
+ export { i as FILE_MIGRATION_PATTERN, j as FRAMEWORK_MIGRATION_EDITS, U as FileMigrationLedgerError, K as MigrationIdTooLongError, M as acceptedBodyHashes, R as appliedFileMigrationIds, z as appliedFileMigrations, te as fileMigrationStatus, A as migrationBodyHash, Q as pendingFileMigrationIds, ee as pendingFileMigrationSummary, re as rollbackFileBasedMigration, ne as runFileBasedMigrations, G as unrecordableMigrationIds, P as walkMigrationFiles };