@voltro/database 0.34.0 → 0.35.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/sql.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { It as e, Jt as t, Lt as n, X as r, Z as i, _ as a, a as o, bt as s, c, et as l, i as u, l as d, m as f, mt as p, n as m, o as h, p as g, qt as _, r as v, tt as y } from "./frameworkLiveTables-CeuTYhWm.js";
2
- import { Effect as b } from "effect";
3
- import { createLogger as x } from "@voltro/logger";
4
- import { SqlClient as S } from "@effect/sql";
5
- import { createHash as C } from "node:crypto";
6
- import { promises as ee } from "node:fs";
7
- import { join as te } from "node:path";
8
- import { pathToFileURL as ne } from "node:url";
2
+ import { Effect as b, Schedule as x } from "effect";
3
+ import { createLogger as S } from "@voltro/logger";
4
+ import { SqlClient as C } from "@effect/sql";
5
+ import { createHash as ee } from "node:crypto";
6
+ import { promises as te } from "node:fs";
7
+ import { join as ne } from "node:path";
8
+ import { pathToFileURL as re } from "node:url";
9
9
  //#region src/migrations/ddlError.ts
10
- var re = (e, t, n, r = 400) => {
10
+ var ie = (e, t, n, r = 400) => {
11
11
  let i = n, a = i.cause ?? {}, o = (e) => {
12
12
  let t = a[e];
13
13
  return t == null || t === "" ? void 0 : String(t);
@@ -39,19 +39,19 @@ var re = (e, t, n, r = 400) => {
39
39
  t !== void 0 && s.push(`db.${e}: ${t}`);
40
40
  }
41
41
  return s.push(""), s.join("\n");
42
- }, ie = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, ae = (e) => e.replace(/"/g, "`"), oe = (e) => typeof e == "string" ? e : e.name ?? String(e), se = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ce = (e, t) => {
43
- if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(ie)) return e;
42
+ }, ae = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, oe = (e) => e.replace(/"/g, "`"), se = (e) => typeof e == "string" ? e : e.name ?? String(e), ce = (e, t) => `_ua_${t}_${e}`.slice(0, 64), le = (e, t) => {
43
+ if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(ae)) return e;
44
44
  let n = { ...e.fields }, r = [], i = [];
45
45
  for (let t of e.appliedIndexes) {
46
- if (!ie(t)) {
46
+ if (!ae(t)) {
47
47
  r.push(t);
48
48
  continue;
49
49
  }
50
- let a = ae(t.where), o = [];
50
+ let a = oe(t.where), o = [];
51
51
  for (let r of t.fields) {
52
- let i = oe(r);
52
+ let i = se(r);
53
53
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
54
- let s = se(t.name, i);
54
+ let s = ce(t.name, i);
55
55
  o.push(s), n[s] = {
56
56
  type: "text",
57
57
  nullable: !0,
@@ -74,7 +74,7 @@ var re = (e, t, n, r = 400) => {
74
74
  appliedIndexes: r,
75
75
  appliedUniques: [...e.appliedUniques ?? [], ...i]
76
76
  };
77
- }, w = (e, t) => `${e}::${t}`, le = (e, t) => {
77
+ }, w = (e, t) => `${e}::${t}`, ue = (e, t) => {
78
78
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
79
79
  n.add(e);
80
80
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
@@ -83,45 +83,142 @@ var re = (e, t, n, r = 400) => {
83
83
  };
84
84
  for (let t of [...e].sort()) r.has(t) || a(t);
85
85
  return i;
86
- }, ue = 6322741009312437n, de = 250, fe = () => {
86
+ }, de = 6322741009312437n, fe = (e) => {
87
+ let t = e?.trim();
88
+ return t === void 0 || t === "" || t === "public" ? void 0 : t;
89
+ }, pe = (e) => e?.schema === void 0 ? fe(process.env.DB_SCHEMA) : fe(e.schema), me = 14695981039346656037n, he = 1099511628211n, ge = 18446744073709551615n, _e = (e) => {
90
+ let t = me;
91
+ for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * he & ge;
92
+ return t;
93
+ }, ve = (e) => {
94
+ let t = fe(e);
95
+ return t === void 0 ? de : _e(`voltro_migration_lock:${t}`) & 9223372036854775807n;
96
+ }, ye = (e) => {
97
+ let t = `voltro_migration_${de.toString(36)}`, n = fe(e);
98
+ if (n === void 0) return t;
99
+ let r = `${t}_${n}`;
100
+ return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(_e(`voltro_migration_lock:${n}`) & ge).toString(16)}`;
101
+ }, be = 250, xe = () => {
87
102
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
88
103
  return Number.isFinite(e) && e > 0 ? e : 3e4;
89
- }, pe = (e) => b.gen(function* () {
90
- let t = fe(), n = Date.now();
104
+ }, Se = (e, t) => b.gen(function* () {
105
+ let n = xe(), r = Date.now();
91
106
  for (;;) {
92
107
  if ((yield* e`
93
- SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
94
- Date.now() - n >= t && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* b.sleep(`${de} millis`);
108
+ SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`)[0]?.got) return;
109
+ Date.now() - r >= n && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* b.sleep(`${be} millis`);
95
110
  }
96
- }), me = (e) => b.gen(function* () {
97
- yield* e`SELECT pg_advisory_unlock(${ue.toString()}::bigint)`;
98
- }), he = `voltro_migration_${ue.toString(36)}`, ge = 30, _e = (e) => b.gen(function* () {
111
+ }), Ce = (e, t) => b.gen(function* () {
112
+ yield* e`SELECT pg_advisory_unlock(${t.toString()}::bigint)`;
113
+ }), we = 30, Te = (e, t) => b.gen(function* () {
99
114
  (yield* e`
100
- SELECT GET_LOCK(${he}, ${ge}) AS got`)[0]?.got !== 1 && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${he}' within ${ge}s (another migration is in progress, or a prior one left it held).`)));
101
- }), ve = (e) => b.gen(function* () {
102
- yield* e`SELECT RELEASE_LOCK(${he})`;
103
- }), ye = `voltro_migration_${ue.toString(36)}`, be = 3e4, xe = (e) => b.gen(function* () {
104
- let t = yield* e`
115
+ SELECT GET_LOCK(${t}, ${we}) AS got`)[0]?.got !== 1 && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${we}s (another migration is in progress, or a prior one left it held).`)));
116
+ }), Ee = (e, t) => b.gen(function* () {
117
+ yield* e`SELECT RELEASE_LOCK(${t})`;
118
+ }), De = 3e4, Oe = (e, t) => b.gen(function* () {
119
+ let n = yield* e`
105
120
  DECLARE @res int;
106
- EXEC @res = sp_getapplock @Resource = ${ye}, @LockMode = 'Exclusive',
107
- @LockOwner = 'Session', @LockTimeout = ${be};
121
+ EXEC @res = sp_getapplock @Resource = ${t}, @LockMode = 'Exclusive',
122
+ @LockOwner = 'Session', @LockTimeout = ${De};
108
123
  SELECT @res AS res`;
109
- (t[0]?.res ?? -999) < 0 && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ye}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
- }), Se = (e) => b.gen(function* () {
111
- yield* e`EXEC sp_releaseapplock @Resource = ${ye}, @LockOwner = 'Session'`;
112
- }), Ce = b.void, T = (e) => e.onDialectOrElse({
113
- mysql: () => _e(e),
114
- mssql: () => xe(e),
115
- sqlite: () => Ce,
116
- orElse: () => pe(e)
117
- }), E = (e) => e.onDialectOrElse({
118
- mysql: () => ve(e),
119
- mssql: () => Se(e),
120
- sqlite: () => Ce,
121
- orElse: () => me(e)
122
- }), we = (e, t) => b.acquireUseRelease(T(e), () => t, () => E(e).pipe(b.orDie)), D = "framework_changes", Te = "framework_changes_", Ee = (e, t) => t === "framework_changes" ? `${Te}${e}` : `${Te}${t}_${e}`, De = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Oe = "voltro:notify:v2", ke = x({ scope: "voltro:migrate" }), O = (e) => {
123
- ke.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
124
- }, k = (e, t) => {
124
+ (n[0]?.res ?? -999) < 0 && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
125
+ }), ke = (e, t) => b.gen(function* () {
126
+ yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
127
+ }), Ae = b.void, T = (e, t) => {
128
+ let n = pe(t);
129
+ return e.onDialectOrElse({
130
+ mysql: () => Te(e, ye(n)),
131
+ mssql: () => Oe(e, ye(n)),
132
+ sqlite: () => Ae,
133
+ orElse: () => Se(e, ve(n))
134
+ });
135
+ }, E = (e, t) => {
136
+ let n = pe(t);
137
+ return e.onDialectOrElse({
138
+ mysql: () => Ee(e, ye(n)),
139
+ mssql: () => ke(e, ye(n)),
140
+ sqlite: () => Ae,
141
+ orElse: () => Ce(e, ve(n))
142
+ });
143
+ }, je = (e, t, n) => b.acquireUseRelease(T(e, n), () => t, () => E(e, n).pipe(b.orDie)), Me = (e) => e.onDialectOrElse({
144
+ pg: () => "postgres",
145
+ mysql: () => "mysql",
146
+ mssql: () => "mssql",
147
+ sqlite: () => "sqlite",
148
+ orElse: () => "sqlite"
149
+ }), Ne = {
150
+ postgres: "plan-transactional",
151
+ mssql: "plan-transactional",
152
+ mysql: "per-operation",
153
+ mariadb: "per-operation",
154
+ sqlite: "per-operation",
155
+ turso: "per-operation"
156
+ }, Pe = (e) => Ne[e], D = "_voltro_migration_ops", Fe = l(D, {
157
+ id: e({ prefix: "mop" }),
158
+ runId: _(),
159
+ planFingerprint: _(),
160
+ opIndex: n(),
161
+ opKind: _(),
162
+ opTarget: _(),
163
+ status: _(),
164
+ payload: _(),
165
+ startedAt: t().nullable(),
166
+ appliedAt: t().nullable(),
167
+ durationMs: n().nullable(),
168
+ createdAt: t().default("now")
169
+ }), Ie = (e) => {
170
+ switch (e.kind) {
171
+ case "create-table": return /* @__PURE__ */ new Set([
172
+ `table:${e.table}`,
173
+ ...e.columns.map((t) => `column:${e.table}.${t.name}`),
174
+ ...e.indexes.map((t) => `index:${e.table}.${t.name}`)
175
+ ]);
176
+ case "drop-table": return /* @__PURE__ */ new Set([`table:${e.table}`]);
177
+ case "rename-table": return /* @__PURE__ */ new Set([`table:${e.from}`, `table:${e.to}`]);
178
+ case "add-column": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column.name}`]);
179
+ case "rename-column": return /* @__PURE__ */ new Set([`column:${e.table}.${e.from}`, `column:${e.table}.${e.to}`]);
180
+ case "drop-column":
181
+ case "alter-column-nullability":
182
+ case "alter-column-type":
183
+ case "alter-column-default":
184
+ case "add-unique":
185
+ case "drop-unique":
186
+ case "add-foreign-key":
187
+ case "drop-foreign-key":
188
+ case "add-check":
189
+ case "drop-check": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column}`]);
190
+ case "add-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index.name}`]);
191
+ case "drop-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index}`]);
192
+ case "rename-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.from}`, `index:${e.table}.${e.to}`]);
193
+ case "add-unique-composite":
194
+ case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
195
+ }
196
+ }, Le = (e) => [...Ie(e)].join(" "), Re = (e, t) => {
197
+ let n = Ie(t);
198
+ for (let t of Ie(e)) if (n.has(t)) return !0;
199
+ return !1;
200
+ }, ze = (e, t) => e.operations.some((e) => Re(e.op, t)), Be = "__voltro_rebuild", Ve = "__shadow", He = "__old", Ue = /* @__PURE__ */ new Set([
201
+ "add-unique",
202
+ "drop-unique",
203
+ "add-unique-composite",
204
+ "drop-unique-composite",
205
+ "add-foreign-key",
206
+ "drop-foreign-key",
207
+ "add-check",
208
+ "drop-check",
209
+ "alter-column-nullability",
210
+ "alter-column-type",
211
+ "alter-column-default"
212
+ ]), We = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Ge = (e, t, n) => {
213
+ let r = n === "sqlite" || n === "turso";
214
+ return e.kind === "alter-column-type" && t === "online-required" || r && Ue.has(e.kind) ? "artefact-repair" : We.has(e.kind) ? "idempotent" : "probe-then-replay";
215
+ };
216
+ Object.keys(Ne);
217
+ //#endregion
218
+ //#region src/migrations/reactiveTriggerName.ts
219
+ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "framework_changes" ? `${Ke}${e}` : `${Ke}${t}_${e}`, Je = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Ye = "voltro:notify:v2", Xe = S({ scope: "voltro:migrate" }), k = (e) => {
220
+ Xe.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
221
+ }, A = (e, t) => {
125
222
  let n = e.type;
126
223
  if (e.spatial) {
127
224
  if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
@@ -132,7 +229,7 @@ var re = (e, t, n, r = 400) => {
132
229
  return e.rawDdl;
133
230
  }
134
231
  if (n === "array" && e.arrayElement) {
135
- if (t === "postgres") return `${k({
232
+ if (t === "postgres") return `${A({
136
233
  ...e,
137
234
  type: e.arrayElement,
138
235
  arrayElement: void 0
@@ -232,22 +329,22 @@ var re = (e, t, n, r = 400) => {
232
329
  case "array": return "TEXT[]";
233
330
  case "interval": return "INTERVAL";
234
331
  }
235
- }, Ae = (e, t) => {
332
+ }, Ze = (e, t) => {
236
333
  if (!e.hasDefault || e.defaultFactory !== void 0) return null;
237
334
  let n = e.defaultValue;
238
- return n === "now" ? r(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ? je(n, e, t) : typeof n == "object" && n ? A(n, t) : null;
239
- }, je = (e, t, n) => {
240
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return A(e, n);
241
- let r = k({
335
+ return n === "now" ? r(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ? Qe(n, e, t) : typeof n == "object" && n ? j(n, t) : null;
336
+ }, Qe = (e, t, n) => {
337
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return j(e, n);
338
+ let r = A({
242
339
  ...t,
243
340
  type: t.arrayElement,
244
341
  arrayElement: void 0
245
342
  }, n);
246
343
  return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
247
- }, A = (e, t) => {
344
+ }, j = (e, t) => {
248
345
  let n = JSON.stringify(e).replace(/'/g, "''");
249
346
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
250
- }, j = (e, t) => {
347
+ }, M = (e, t) => {
251
348
  switch (t) {
252
349
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
253
350
  case "mysql":
@@ -256,7 +353,7 @@ var re = (e, t, n, r = 400) => {
256
353
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
257
354
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
258
355
  }
259
- }, Me = (e, t) => {
356
+ }, $e = (e, t) => {
260
357
  if (e === "restrict" && t === "mssql") return "NO ACTION";
261
358
  switch (e) {
262
359
  case "cascade": return "CASCADE";
@@ -264,38 +361,38 @@ var re = (e, t, n, r = 400) => {
264
361
  case "setNull": return "SET NULL";
265
362
  case "noAction": return "NO ACTION";
266
363
  }
267
- }, Ne = (e, t, n) => n === null ? i(e, t) : `${i(n, t)}.${i(e, t)}`, Pe = 191, Fe = (e, t, n) => {
364
+ }, et = (e, t, n) => n === null ? i(e, t) : `${i(n, t)}.${i(e, t)}`, tt = 191, nt = (e, t, n) => {
268
365
  let r = i(e, n);
269
366
  if (n !== "mysql" && n !== "mariadb") return r;
270
367
  let a = t[e];
271
368
  if (!a) return r;
272
- let o = k(a, n).toUpperCase();
273
- return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${r}(${Pe})` : r;
274
- }, Ie = (e, t) => {
369
+ let o = A(a, n).toUpperCase();
370
+ return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${r}(${tt})` : r;
371
+ }, rt = (e, t) => {
275
372
  if (!e.generatedAs) return null;
276
373
  let { expr: n, stored: r } = e.generatedAs;
277
- if (t === "postgres") return r || O("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
374
+ if (t === "postgres") return r || k("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
278
375
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
279
376
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
280
377
  if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
281
378
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
282
- }, Le = (e, t, n, a, o = !1, s = !1) => {
283
- if (t.type === "id" && t.idScheme?.kind === "numeric") return j(e, n);
284
- let c = n === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" : k(t, n), l = [i(e, n), c];
379
+ }, it = (e, t, n, a, o = !1, s = !1) => {
380
+ if (t.type === "id" && t.idScheme?.kind === "numeric") return M(e, n);
381
+ let c = n === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" : A(t, n), l = [i(e, n), c];
285
382
  t.type === "id" && !s && l.push("PRIMARY KEY");
286
- let u = Ie(t, n);
383
+ let u = rt(t, n);
287
384
  if (u) l.push(u);
288
385
  else {
289
386
  t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && l.push("UNIQUE");
290
- let e = Ae(t, n);
387
+ let e = Ze(t, n);
291
388
  e && l.push(e);
292
389
  }
293
390
  if (t.type === "reference" && t.references && !o) {
294
391
  let e = t.references();
295
392
  l.push(`REFERENCES ${i(e.tableName, n)} (${i("id", n)})`);
296
- let r = Me(t.onDelete ?? "restrict", n);
393
+ let r = $e(t.onDelete ?? "restrict", n);
297
394
  l.push(`ON DELETE ${r}`);
298
- let a = Me(t.refOnUpdate ?? "noAction", n);
395
+ let a = $e(t.refOnUpdate ?? "noAction", n);
299
396
  a !== "NO ACTION" && l.push(`ON UPDATE ${a}`);
300
397
  }
301
398
  if (t.oneOf && t.oneOf.length > 0) {
@@ -312,18 +409,18 @@ var re = (e, t, n, r = 400) => {
312
409
  r(n) ? l.push(`CHECK (${t} IS NULL OR json_valid(${t}))`) : n === "mssql" && l.push(`CHECK (${t} IS NULL OR ISJSON(${t}) = 1)`);
313
410
  }
314
411
  return l.join(" ");
315
- }, Re = (e, t, n = null, r) => {
412
+ }, at = (e, t, n = null, r) => {
316
413
  let a = /* @__PURE__ */ new Set();
317
414
  for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
318
415
  for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
319
- let o = e.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${Le(e, n, t, a, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
320
- let r = n.fields.map((n) => Fe(n, e.fields, t)).join(", ");
416
+ let o = e.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${it(e, n, t, a, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
417
+ let r = n.fields.map((n) => nt(n, e.fields, t)).join(", ");
321
418
  return ` CONSTRAINT ${i(n.name, t)} UNIQUE (${r})`;
322
419
  }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${i(e.name, t)} CHECK (${e.expr})`), d = [
323
- ...s ? [` PRIMARY KEY (${o.map((n) => Fe(n, e.fields, t)).join(", ")})`] : [],
420
+ ...s ? [` PRIMARY KEY (${o.map((n) => nt(n, e.fields, t)).join(", ")})`] : [],
324
421
  ...l,
325
422
  ...u
326
- ], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = Ne(e.tableName, t, n);
423
+ ], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = et(e.tableName, t, n);
327
424
  if (t === "mssql") {
328
425
  let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${p} (\n${f}\n)`;
329
426
  return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
@@ -333,10 +430,10 @@ var re = (e, t, n, r = 400) => {
333
430
  f,
334
431
  ");"
335
432
  ].join("\n");
336
- }, ze = (e, t, n) => {
433
+ }, ot = (e, t, n) => {
337
434
  let r = `${e}_${t.name}_fts`, a = (e) => i(e, n), o = t.columns.map(a).join(", "), s = t.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
338
435
  return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(r)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${r}_ai`)} AFTER INSERT ON ${a(e)} BEGIN\n INSERT INTO ${a(r)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${r}_ad`)} AFTER DELETE ON ${a(e)} BEGIN\n DELETE FROM ${a(r)} WHERE row_id = old.${a("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${r}_au`)} AFTER UPDATE ON ${a(e)} BEGIN\n DELETE FROM ${a(r)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(r)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
339
- }, Be = (e, t, n = null) => {
436
+ }, st = (e, t, n = null) => {
340
437
  let r = [], a = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, n, r, i) => {
341
438
  let a = {
342
439
  using: "",
@@ -348,21 +445,21 @@ var re = (e, t, n, r = 400) => {
348
445
  using: " USING GIST",
349
446
  withSuffix: "",
350
447
  skip: !1
351
- } : (O(`[voltro:migrate] index '${e}' on '${n}': ${t} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), a);
448
+ } : (k(`[voltro:migrate] index '${e}' on '${n}': ${t} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), a);
352
449
  if (r === "gin") return t === "postgres" ? {
353
450
  using: " USING GIN",
354
451
  withSuffix: "",
355
452
  skip: !1
356
- } : t === "mysql" || t === "mariadb" ? (O(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
453
+ } : t === "mysql" || t === "mariadb" ? (k(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
357
454
  using: "",
358
455
  withSuffix: "",
359
456
  skip: !0
360
- }) : (O(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), a);
457
+ }) : (k(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), a);
361
458
  if (r === "brin") return t === "postgres" ? {
362
459
  using: " USING BRIN",
363
460
  withSuffix: "",
364
461
  skip: !1
365
- } : (O(`[voltro:migrate] brin index '${e}' on '${n}': ${t} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
462
+ } : (k(`[voltro:migrate] brin index '${e}' on '${n}': ${t} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
366
463
  if (r === "hnsw") {
367
464
  if (t === "postgres") {
368
465
  let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? y(i?.hnsw?.distance);
@@ -373,7 +470,7 @@ var re = (e, t, n, r = 400) => {
373
470
  skip: !1
374
471
  };
375
472
  }
376
- return O(`[voltro:migrate] hnsw index '${e}' on '${n}': ${t} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
473
+ return k(`[voltro:migrate] hnsw index '${e}' on '${n}': ${t} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
377
474
  using: "",
378
475
  withSuffix: "",
379
476
  skip: !0
@@ -382,7 +479,7 @@ var re = (e, t, n, r = 400) => {
382
479
  return a;
383
480
  }, c = (n, r) => {
384
481
  let i = n.map((n) => {
385
- if (typeof n == "string") return Fe(n, e.fields, t);
482
+ if (typeof n == "string") return nt(n, e.fields, t);
386
483
  if ("jsonPath" in n) {
387
484
  let { column: e, path: r, numeric: i } = n.jsonPath;
388
485
  return `(${g(e, r, t, { numeric: i })})`;
@@ -393,7 +490,7 @@ var re = (e, t, n, r = 400) => {
393
490
  }, l = (e, r, a, o, l, u = "", d = !1) => {
394
491
  let f = s(e, r, o, l);
395
492
  if (f.skip) return "";
396
- let p = c(a, f.opclass), m = `${f.withSuffix}${u}`, h = Ne(r, t, n), g = d ? "UNIQUE " : "";
493
+ let p = c(a, f.opclass), m = `${f.withSuffix}${u}`, h = et(r, t, n), g = d ? "UNIQUE " : "";
397
494
  return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${i(e, t)} ON ${h}${f.using} (${p})${m};` : t === "mysql" ? `CREATE ${g}INDEX ${i(e, t)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${i(e, t)} ON ${h}${f.using} (${p})${m};`;
398
495
  };
399
496
  for (let n of e.appliedFullText ?? []) if (t === "postgres") {
@@ -406,15 +503,15 @@ var re = (e, t, n, r = 400) => {
406
503
  let a = n.columns.map((e) => i(e, t)).join(", ");
407
504
  r.push(`CREATE FULLTEXT INDEX ${i(n.name, t)} ON ${i(e.tableName, t)} (${a});`);
408
505
  } else if (t === "turso") throw Error(`@voltro/sql-turso: full-text index '${n.name}' on '${e.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
409
- else t === "sqlite" ? r.push(...ze(e.tableName, n, t)) : O(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
506
+ else t === "sqlite" ? r.push(...ot(e.tableName, n, t)) : k(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
410
507
  for (let n of e.appliedIndexes) {
411
508
  if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
412
- O(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
509
+ k(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
413
510
  continue;
414
511
  }
415
512
  if (n.unique && n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${n.name}' on '${e.tableName}' cannot be expressed on ${t} — it has no partial (WHERE) index support, and a full UNIQUE index would forbid re-creating a soft-deleted row. Use a generated STORED column (text().generatedAs("CASE WHEN \`deletedAt\` IS NULL THEN <key> ELSE NULL END", { stored: true })) + .unique([...]) on ${t}, or move this table to postgres/sqlite/mssql.`);
416
513
  let i = "";
417
- n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? O(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : i = ` WHERE ${n.where}`);
514
+ n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? k(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : i = ` WHERE ${n.where}`);
418
515
  let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, i, n.unique === !0);
419
516
  s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && a.add(o(n.fields));
420
517
  }
@@ -424,17 +521,17 @@ var re = (e, t, n, r = 400) => {
424
521
  r.push(l(i, e.tableName, [t])), a.add(o([t]));
425
522
  }
426
523
  return r.join("\n");
427
- }, Ve = (e, t, n = D) => {
524
+ }, ct = (e, t, n = O) => {
428
525
  if (t !== "postgres") return [];
429
526
  let r = e.filter((e) => e.isReactive !== !1);
430
- return r.length === 0 ? [] : [He(n), ...r.map((e) => We(e, n))];
431
- }, He = (e) => `
432
- CREATE OR REPLACE FUNCTION ${De(e)}() RETURNS trigger AS $$
527
+ return r.length === 0 ? [] : [lt(n), ...r.map((e) => dt(e, n))];
528
+ }, lt = (e) => `
529
+ CREATE OR REPLACE FUNCTION ${Je(e)}() RETURNS trigger AS $$
433
530
  DECLARE
434
531
  payload TEXT;
435
532
  pk JSONB;
436
533
  BEGIN
437
- -- ${Oe}
534
+ -- ${Ye}
438
535
  payload := json_build_object(
439
536
  'table', TG_TABLE_NAME,
440
537
  -- The schema the write landed in. Under namespace isolation this is
@@ -488,22 +585,22 @@ BEGIN
488
585
  RETURN COALESCE(NEW, OLD);
489
586
  END;
490
587
  $$ LANGUAGE plpgsql;
491
- `.trim(), Ue = (e, t) => {
492
- let n = Ee(e.tableName, t);
588
+ `.trim(), ut = (e, t) => {
589
+ let n = qe(e.tableName, t);
493
590
  return [
494
591
  `ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
495
592
  `DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
496
- `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${De(t)}()`
593
+ `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Je(t)}()`
497
594
  ];
498
- }, We = (e, t) => Ue(e, t).map((e) => `${e};`).join("\n"), Ge = (e) => {
595
+ }, dt = (e, t) => ut(e, t).map((e) => `${e};`).join("\n"), ft = (e) => {
499
596
  if (e.dialect !== "postgres") return [];
500
597
  let t = e.channel ?? "framework_changes", n = new Map(e.tables.map((e) => [e.tableName, e])), r = [], i = e.missing.filter((e) => n.has(e));
501
- (i.length > 0 || e.functionOutdated === !0) && r.push(He(t));
502
- for (let e of i) r.push(...Ue(n.get(e), t));
503
- for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Ee(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
598
+ (i.length > 0 || e.functionOutdated === !0) && r.push(lt(t));
599
+ for (let e of i) r.push(...ut(n.get(e), t));
600
+ for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${qe(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
504
601
  return r;
505
- }, Ke = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), qe = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Je = (e) => {
506
- let t = new Map(e.map((e) => [e.tableName, e])), n = le(e.map((e) => e.tableName), (e) => {
602
+ }, pt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), mt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), ht = (e) => {
603
+ let t = new Map(e.map((e) => [e.tableName, e])), n = ue(e.map((e) => e.tableName), (e) => {
507
604
  let n = t.get(e);
508
605
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
509
606
  if (n.type !== "reference" || !n.references) return [];
@@ -539,8 +636,8 @@ $$ LANGUAGE plpgsql;
539
636
  sorted: o,
540
637
  cyclic: r
541
638
  };
542
- }, Ye = (e, t, n = null) => {
543
- let r = (e) => n ? `${i(n, t)}.${i(e, t)}` : i(e, t), a = `${e.table}_${e.column}_fkey`, o = Me(e.onDelete, t), s = Me(e.onUpdate, t), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (n) => `ADD CONSTRAINT ${i(a, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${i(e.column, t)}) REFERENCES ${r(e.targetTable)} (${i("id", t)})${c}`;
639
+ }, gt = (e, t, n = null) => {
640
+ let r = (e) => n ? `${i(n, t)}.${i(e, t)}` : i(e, t), a = `${e.table}_${e.column}_fkey`, o = $e(e.onDelete, t), s = $e(e.onUpdate, t), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (n) => `ADD CONSTRAINT ${i(a, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${i(e.column, t)}) REFERENCES ${r(e.targetTable)} (${i("id", t)})${c}`;
544
641
  switch (t) {
545
642
  case "postgres": return [
546
643
  "DO $$ BEGIN",
@@ -554,7 +651,7 @@ $$ LANGUAGE plpgsql;
554
651
  case "mariadb": return `ALTER TABLE ${r(e.table)} ${l(!0)};`;
555
652
  default: return `ALTER TABLE ${r(e.table)} ${l(!1)};`;
556
653
  }
557
- }, Xe = (e, t) => {
654
+ }, _t = (e, t) => {
558
655
  let n = /* @__PURE__ */ new Map();
559
656
  if (r(t)) return n;
560
657
  for (let t of e) {
@@ -562,7 +659,7 @@ $$ LANGUAGE plpgsql;
562
659
  e.add(t.column), n.set(t.table, e);
563
660
  }
564
661
  return n;
565
- }, Ze = (e, t) => {
662
+ }, vt = (e, t) => {
566
663
  if (t !== "postgres") return "";
567
664
  let n = /* @__PURE__ */ new Map();
568
665
  for (let t of e) for (let e of Object.values(t.fields)) {
@@ -578,7 +675,7 @@ $$ LANGUAGE plpgsql;
578
675
  r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
579
676
  }
580
677
  return r.join("\n\n");
581
- }, Qe = (e, t) => {
678
+ }, yt = (e, t) => {
582
679
  if (t !== "postgres") return "";
583
680
  let n = /* @__PURE__ */ new Set();
584
681
  for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
@@ -592,30 +689,30 @@ BEGIN
592
689
  SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
593
690
  }
594
691
  return r.join("\n\n");
595
- }, $e = (e) => {
692
+ }, bt = (e) => {
596
693
  let t = [], n = [];
597
694
  for (let r of e) f(r) ? n.push(r) : t.push(r);
598
695
  return {
599
696
  tables: t,
600
697
  views: n
601
698
  };
602
- }, et = (e, t, n = D) => {
603
- let { tables: i, views: o } = $e(e), { sorted: s, cyclic: c } = Je(i.map((e) => ce(e, t))), l = Xe(c, t), u = [];
604
- t === "postgres" && Ke(s) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && qe(s) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
605
- let d = Qe(s, t);
699
+ }, xt = (e, t, n = O) => {
700
+ let { tables: i, views: o } = bt(e), { sorted: s, cyclic: c } = ht(i.map((e) => le(e, t))), l = _t(c, t), u = [];
701
+ t === "postgres" && pt(s) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && mt(s) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
702
+ let d = yt(s, t);
606
703
  d && u.push(d);
607
- let f = Ze(s, t);
704
+ let f = vt(s, t);
608
705
  f && u.push(f);
609
- for (let e of s) u.push(Re(e, t, null, l.get(e.tableName)));
610
- if (!r(t)) for (let e of c) u.push(Ye(e, t));
706
+ for (let e of s) u.push(at(e, t, null, l.get(e.tableName)));
707
+ if (!r(t)) for (let e of c) u.push(gt(e, t));
611
708
  for (let e of s) {
612
- let n = Be(e, t);
709
+ let n = st(e, t);
613
710
  n && u.push(n);
614
711
  }
615
- u.push(...Ve(s, t, n));
712
+ u.push(...ct(s, t, n));
616
713
  for (let e of o) u.push(a(e, t));
617
714
  return u.join("\n\n") + "\n";
618
- }, tt = (e, t, n) => {
715
+ }, St = (e, t, n) => {
619
716
  let r = i(e, t);
620
717
  switch (t) {
621
718
  case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
@@ -625,38 +722,62 @@ BEGIN
625
722
  case "turso":
626
723
  case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
627
724
  }
628
- }, nt = (e, t, n, a) => {
629
- let o = tt(n, t, a), s = i(n, t);
630
- if (t === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${et(e, t)}`;
631
- if (t === "mysql" || t === "mariadb") return `${o}\n\nUSE ${s};\n\n${et(e, t)}`;
632
- let { sorted: c, cyclic: l } = Je(e), u = Xe(l, t), d = [o];
633
- for (let e of c) d.push(Re(e, t, n, u.get(e.tableName)));
634
- if (!r(t)) for (let e of l) d.push(Ye(e, t, n));
725
+ }, Ct = (e, t, n, a) => {
726
+ let o = St(n, t, a), s = i(n, t);
727
+ if (t === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${xt(e, t)}`;
728
+ if (t === "mysql" || t === "mariadb") return `${o}\n\nUSE ${s};\n\n${xt(e, t)}`;
729
+ let { sorted: c, cyclic: l } = ht(e), u = _t(l, t), d = [o];
730
+ for (let e of c) d.push(at(e, t, n, u.get(e.tableName)));
731
+ if (!r(t)) for (let e of l) d.push(gt(e, t, n));
635
732
  for (let e of c) {
636
- let r = Be(e, t, n);
733
+ let r = st(e, t, n);
637
734
  r && d.push(r);
638
735
  }
639
736
  return d.join("\n\n") + "\n";
640
- }, rt = (e, t, n = D) => {
641
- let { sorted: r, cyclic: i } = Je(e), a = Xe(i, t), o = [], s = Qe(r, t);
737
+ }, wt = (e, t, n = O) => {
738
+ let { sorted: r, cyclic: i } = ht(e), a = _t(i, t), o = [], s = yt(r, t);
642
739
  s && o.push(s);
643
- let c = Ze(r, t);
740
+ let c = vt(r, t);
644
741
  c && o.push(c);
645
- for (let e of r) o.push(Re(e, t, null, a.get(e.tableName)));
646
- for (let e of i) o.push(Ye(e, t));
647
- return o.push(...Ve(r, t, n)), o.join("\n\n") + "\n";
648
- }, it = (e, t = "postgres", n = D) => b.gen(function* () {
649
- let r = yield* S.SqlClient;
650
- yield* we(r, st(r, et(e, t, n), t)).pipe(b.orDie);
651
- }), at = (e, t) => {
742
+ for (let e of r) o.push(at(e, t, null, a.get(e.tableName)));
743
+ for (let e of i) o.push(gt(e, t));
744
+ return o.push(...ct(r, t, n)), o.join("\n\n") + "\n";
745
+ }, Tt = (e, t = "postgres", n = O, r = {}) => b.gen(function* () {
746
+ let i = yield* C.SqlClient;
747
+ yield* je(i, Mt(i, xt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(b.orDie);
748
+ }), Et = (e, t) => {
652
749
  let n = t.cause ?? {};
653
750
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
654
- }, ot = (e) => b.gen(function* () {
655
- let t = yield* S.SqlClient;
656
- for (let n of ct(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ke.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(b.catchIf((e) => at(n, e), () => b.void), b.tapError((e) => b.sync(() => {
657
- ke.error(re("migrate: statement failed", n, e, 200));
658
- })), b.orDieWith((e) => Error(re("migrate: statement failed", n, e, 400).trim())));
659
- }), st = (e, t, n) => (n === "turso" ? ot(t) : e.withTransaction(ot(t))).pipe(b.orDie), ct = (e) => {
751
+ }, Dt = (e, t) => {
752
+ let n = e.trimStart();
753
+ return !!(/\bIF NOT EXISTS\b/i.test(n) || /^CREATE OR REPLACE\b/i.test(n) || /^DROP\s[\s\S]*?\bIF EXISTS\b/i.test(n) || /^SET search_path\b/i.test(n) || /^USE[\s`"[]/i.test(n) || /^IF\s/i.test(n) || (t === "mysql" || t === "mariadb") && /^CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(n));
754
+ }, Ot = () => {
755
+ let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
756
+ return Number.isInteger(e) && e >= 0 ? e : 4;
757
+ }, kt = (e) => ({
758
+ while: e,
759
+ times: Ot(),
760
+ schedule: x.jittered(x.exponential("50 millis"))
761
+ }), At = class {
762
+ statement;
763
+ error;
764
+ _tag = "DdlStatementFailed";
765
+ constructor(e, t) {
766
+ this.statement = e, this.error = t;
767
+ }
768
+ }, jt = (e, t, n) => b.gen(function* () {
769
+ let r = yield* C.SqlClient, i = n !== void 0 && Pe(t) === "per-operation";
770
+ for (let a of Nt(e)) {
771
+ process.env.VOLTRO_MIGRATE_DEBUG === "1" && Xe.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
772
+ let e = r.unsafe(a).pipe(b.catchIf((e) => Et(a, e), () => b.succeed([])), b.tapError((e) => b.sync(() => {
773
+ Xe.error(ie("migrate: statement failed", a, e, 200));
774
+ })));
775
+ yield* (i && n !== void 0 && Dt(a, t) ? e.pipe(b.retry(kt((e) => n(e) === "retry"))) : e).pipe(b.mapError((e) => new At(a, e)));
776
+ }
777
+ }), Mt = (e, t, n, r) => {
778
+ let i = n === "turso" ? jt(t, n, r) : e.withTransaction(jt(t, n, r)), a = (e) => e instanceof At ? e.error : e;
779
+ return (r !== void 0 && Pe(n) === "plan-transactional" ? i.pipe(b.retry(kt((e) => r(a(e)) === "retry"))) : i).pipe(b.orDieWith((e) => e instanceof At ? Error(ie("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
780
+ }, Nt = (e) => {
660
781
  let t = [], n = "", r = !1;
661
782
  for (let i = 0; i < e.length; i++) {
662
783
  if (e.slice(i, i + 2) === "$$") {
@@ -671,43 +792,43 @@ BEGIN
671
792
  }
672
793
  let i = n.trim();
673
794
  return i.length > 0 && t.push(i), t;
674
- }, lt = async (e, t, n = "postgres") => {
675
- await b.runPromise(it(e, n).pipe(b.provide(t)));
676
- }, ut = (e, t, n = "postgres") => b.gen(function* () {
677
- let r = nt(e, n, t), i = yield* S.SqlClient;
678
- yield* we(i, st(i, r, n)).pipe(b.orDie);
679
- }), dt = async (e, t, n, r = "postgres") => {
680
- await b.runPromise(ut(e, t, r).pipe(b.provide(n))), await d({
795
+ }, Pt = async (e, t, n = "postgres", r = {}) => {
796
+ await b.runPromise(Tt(e, n, void 0, r).pipe(b.provide(t)));
797
+ }, Ft = (e, t, n = "postgres", r = {}) => b.gen(function* () {
798
+ let i = Ct(e, n, t), a = yield* C.SqlClient;
799
+ yield* je(a, Mt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(b.orDie);
800
+ }), It = async (e, t, n, r = "postgres", i = {}) => {
801
+ await b.runPromise(Ft(e, t, r, i).pipe(b.provide(n))), await d({
681
802
  namespace: t,
682
803
  dialect: r
683
804
  });
684
- }, ft = async (e, t, n = "postgres") => {
805
+ }, Lt = async (e, t, n = "postgres", r = {}) => {
685
806
  await b.runPromise(b.gen(function* () {
686
- let t = rt(e, n), r = yield* S.SqlClient;
687
- yield* we(r, st(r, t, n)).pipe(b.orDie);
807
+ let t = wt(e, n), i = yield* C.SqlClient;
808
+ yield* je(i, Mt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(b.orDie);
688
809
  }).pipe(b.provide(t)));
689
- }, pt = (e) => {
810
+ }, Rt = (e) => {
690
811
  if (e == null) return e;
691
- if (Array.isArray(e)) return e.map(pt);
812
+ if (Array.isArray(e)) return e.map(Rt);
692
813
  if (typeof e != "object") return e;
693
814
  let t = {};
694
815
  for (let n of Object.keys(e).sort()) {
695
816
  let r = e[n];
696
- r !== void 0 && (t[n] = pt(r));
817
+ r !== void 0 && (t[n] = Rt(r));
697
818
  }
698
819
  return t;
699
- }, mt = (e) => {
820
+ }, zt = (e) => {
700
821
  if (!e.idScheme && !e.sensitive && !e.safe) return e;
701
822
  let { idScheme: t, sensitive: n, safe: r, ...i } = e;
702
823
  return i;
703
- }, ht = (e) => [...e].map(mt).sort((e, t) => e.name.localeCompare(t.name)), gt = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), _t = (e) => [...e].map((e) => ({
824
+ }, Bt = (e) => [...e].map(zt).sort((e, t) => e.name.localeCompare(t.name)), Vt = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), Ht = (e) => [...e].map((e) => ({
704
825
  name: e.name,
705
- columns: ht(e.columns),
706
- indexes: gt(e.indexes)
707
- })).sort((e, t) => e.name.localeCompare(t.name)), M = (e) => {
708
- let t = { tables: _t(e.tables) }, n = JSON.stringify(pt(t));
709
- return C("sha256").update(n).digest("hex");
710
- }, N = (e) => e.slice(0, 16), vt = (e, t) => {
826
+ columns: Bt(e.columns),
827
+ indexes: Vt(e.indexes)
828
+ })).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
829
+ let t = { tables: Ht(e.tables) }, n = JSON.stringify(Rt(t));
830
+ return ee("sha256").update(n).digest("hex");
831
+ }, P = (e) => e.slice(0, 16), Ut = (e, t) => {
711
832
  let n = t.references ? {
712
833
  table: t.references().tableName,
713
834
  column: "id",
@@ -746,7 +867,7 @@ BEGIN
746
867
  ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
747
868
  ...t.spatial === void 0 ? {} : { spatial: t.spatial }
748
869
  };
749
- }, yt = (e) => {
870
+ }, Wt = (e) => {
750
871
  let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
751
872
  n.has(e.name) || (n.add(e.name), t.push(e));
752
873
  }, i = e.appliedPrimaryKey ?? [];
@@ -794,11 +915,11 @@ BEGIN
794
915
  });
795
916
  }
796
917
  return t;
797
- }, bt = (e) => {
918
+ }, Gt = (e) => {
798
919
  let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
799
920
  for (let [r, i] of Object.entries(e.fields)) {
800
921
  if (i.dropped) continue;
801
- let e = vt(r, i);
922
+ let e = Ut(r, i);
802
923
  n.push(t.has(r) ? {
803
924
  ...e,
804
925
  unique: !0
@@ -808,27 +929,27 @@ BEGIN
808
929
  return {
809
930
  name: e.tableName,
810
931
  columns: n,
811
- indexes: yt(e),
932
+ indexes: Wt(e),
812
933
  ...r.length > 0 ? { primaryKey: [...r] } : {},
813
934
  ...i === void 0 ? {} : { renamedFrom: i }
814
935
  };
815
- }, xt = (e) => {
936
+ }, Kt = (e) => {
816
937
  let t = /* @__PURE__ */ new Map();
817
938
  for (let n of e) for (let e of n.indexes) {
818
939
  let r = t.get(e.name);
819
940
  if (r !== void 0 && r !== n.name) throw Error(`duplicate index name '${e.name}' across tables '${r}' and '${n.name}'. Index names must be unique per SCHEMA, not just per table — the DB creates only one, so the other never applies and 'db plan' re-emits it forever. Give each an explicit, table-prefixed name (e.g. '${n.name}_${e.name}').`);
820
941
  t.set(e.name, n.name);
821
942
  }
822
- }, P = (e, t) => {
823
- let n = e.map((e) => bt(ce(e, t)));
824
- return xt(n), { tables: n };
825
- }, St = (e, t, n = D) => b.gen(function* () {
943
+ }, F = (e, t) => {
944
+ let n = e.map((e) => Gt(le(e, t)));
945
+ return Kt(n), { tables: n };
946
+ }, qt = (e, t, n = O) => b.gen(function* () {
826
947
  let r = (yield* e`
827
948
  SELECT p.prosrc
828
949
  FROM pg_proc p
829
950
  JOIN pg_namespace n ON n.oid = p.pronamespace
830
951
  WHERE n.nspname = current_schema()
831
- AND p.proname = ${De(n)}
952
+ AND p.proname = ${Je(n)}
832
953
  `)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
833
954
  if (a.length === 0) return {
834
955
  missing: [],
@@ -842,10 +963,10 @@ BEGIN
842
963
  JOIN pg_namespace n ON n.oid = c.relnamespace
843
964
  WHERE NOT t.tgisinternal
844
965
  AND n.nspname = current_schema()
845
- AND t.tgname LIKE ${`${Te}%`}
966
+ AND t.tgname LIKE ${`${Ke}%`}
846
967
  `, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
847
968
  for (let e of a) {
848
- let t = s.has(Ee(e.tableName, n)), r = e.isReactive !== !1;
969
+ let t = s.has(qe(e.tableName, n)), r = e.isReactive !== !1;
849
970
  r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
850
971
  }
851
972
  return {
@@ -853,7 +974,7 @@ BEGIN
853
974
  stale: l.sort(),
854
975
  functionOutdated: i
855
976
  };
856
- }), Ct = (e) => {
977
+ }), Jt = (e) => {
857
978
  let t = [];
858
979
  if (e.missing.length > 0) {
859
980
  let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
@@ -864,19 +985,19 @@ BEGIN
864
985
  t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
865
986
  }
866
987
  return e.functionOutdated && t.push("The change-notify function in this database is OLDER than the framework installed here. Its triggers fire, so nothing looks wrong — but a row too large for a NOTIFY payload (postgres caps it at 8000 bytes) is emitted without its primary key, and a change that carries no key cannot be re-read: it reaches subscriptions as a re-query and reaches every TAP — search index, analytics mirror, cdc-out, row history — as nothing at all. Run `voltro db apply` to replace it."), t.length > 0 ? t.join("\n") : void 0;
867
- }, wt = {
988
+ }, Yt = {
868
989
  postgres: !0,
869
990
  mysql: !0,
870
991
  mariadb: !0,
871
992
  mssql: !0,
872
993
  sqlite: !0
873
- }, Tt = {
994
+ }, Xt = {
874
995
  postgres: !0,
875
996
  mysql: !1,
876
997
  mariadb: !1,
877
998
  mssql: !0,
878
999
  sqlite: !0
879
- }, Et = (e) => {
1000
+ }, Zt = (e) => {
880
1001
  switch (e) {
881
1002
  case "add-column":
882
1003
  case "drop-column":
@@ -886,47 +1007,47 @@ BEGIN
886
1007
  case "add-foreign-key":
887
1008
  case "add-unique":
888
1009
  case "add-unique-composite":
889
- case "add-check": return Tt;
890
- default: return wt;
1010
+ case "add-check": return Xt;
1011
+ default: return Yt;
891
1012
  }
892
- }, Dt = (e, t) => {
1013
+ }, Qt = (e, t) => {
893
1014
  let n = new Map(t.tables.map((e) => [e.name, e]));
894
1015
  return new Map(e.map((e) => [e.tableName, {
895
1016
  table: e,
896
1017
  snapshot: n.get(e.tableName),
897
1018
  columnDefs: e.fields
898
1019
  }]));
899
- }, F = (e) => {
1020
+ }, I = (e) => {
900
1021
  if (typeof e != "object" || !e) return JSON.stringify(e);
901
- if (Array.isArray(e)) return `[${e.map(F).join(",")}]`;
1022
+ if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
902
1023
  let t = e;
903
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${F(t[e])}`).join(",")}}`;
904
- }, Ot = (e) => {
1024
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
1025
+ }, $t = (e) => {
905
1026
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
906
1027
  let t = e.defaultValue;
907
1028
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
908
1029
  if (typeof t == "number") return String(t);
909
- if (typeof t != "string") return F(t);
1030
+ if (typeof t != "string") return I(t);
910
1031
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
911
1032
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
912
1033
  let i = n.replace(/::[a-zA-Z0-9_ "]+$/, "").trim(), a = /^'(.*)'$/.test(i) ? i.slice(1, -1).replace(/''/g, "'") : i, o = /^cast\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+as\s+json\s*\)$/i.exec(a);
913
1034
  if (o) try {
914
- return F(JSON.parse(o[1]));
1035
+ return I(JSON.parse(o[1]));
915
1036
  } catch {}
916
1037
  let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
917
1038
  if (s) try {
918
- return F(JSON.parse(s[1]));
1039
+ return I(JSON.parse(s[1]));
919
1040
  } catch {}
920
1041
  if (a.startsWith("{") || a.startsWith("[")) try {
921
- return F(JSON.parse(a));
1042
+ return I(JSON.parse(a));
922
1043
  } catch {}
923
1044
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
924
- }, kt = (e, t) => {
925
- let n = Ot(e), r = Ot(t);
1045
+ }, en = (e, t) => {
1046
+ let n = $t(e), r = $t(t);
926
1047
  if (n === r) return !0;
927
1048
  let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
928
1049
  return i(n) === i(r);
929
- }, At = (e) => {
1050
+ }, tn = (e) => {
930
1051
  if (!e) return null;
931
1052
  let t = (e) => e === "restrict" ? "noAction" : e;
932
1053
  return {
@@ -935,25 +1056,25 @@ BEGIN
935
1056
  onDelete: t(e.onDelete),
936
1057
  onUpdate: t(e.onUpdate)
937
1058
  };
938
- }, jt = (e, t) => {
1059
+ }, nn = (e, t) => {
939
1060
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
940
1061
  if (!n && !r) return !0;
941
1062
  if (!n || !r || n.length !== r.length) return !1;
942
1063
  let i = [...n].sort(), a = [...r].sort();
943
1064
  return i.every((e, t) => e === a[t]);
944
- }, Mt = (e, t) => {
1065
+ }, rn = (e, t) => {
945
1066
  try {
946
- let n = /\((\d+)\)/.exec(k(e, t));
1067
+ let n = /\((\d+)\)/.exec(A(e, t));
947
1068
  return n ? Number(n[1]) : void 0;
948
1069
  } catch {
949
1070
  return;
950
1071
  }
951
- }, Nt = (e, t, n) => n === void 0 || r(n) ? !0 : e.type !== "text" || t.type !== "text" || Mt(e, n) === t.maxLength, Pt = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && kt(e, t) && Nt(e, t, n) && JSON.stringify(At(e.references)) === JSON.stringify(At(t.references)) && jt(e.oneOf, t.oneOf), Ft = (e, t) => t.oneOf && t.oneOf.length > 0 ? I({
1072
+ }, an = (e, t, n) => n === void 0 || r(n) ? !0 : e.type !== "text" || t.type !== "text" || rn(e, n) === t.maxLength, on = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && en(e, t) && an(e, t, n) && JSON.stringify(tn(e.references)) === JSON.stringify(tn(t.references)) && nn(e.oneOf, t.oneOf), sn = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
952
1073
  kind: "add-check",
953
1074
  table: e,
954
1075
  column: t.name,
955
1076
  values: t.oneOf
956
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, It = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Lt = (e, t, n) => {
1077
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, cn = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), ln = (e, t, n) => {
957
1078
  let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
958
1079
  for (let t of e.columns) {
959
1080
  let e = r.get(t.name);
@@ -961,7 +1082,7 @@ BEGIN
961
1082
  a.push(t);
962
1083
  continue;
963
1084
  }
964
- Pt(t, e, n) || s.push({
1085
+ on(t, e, n) || s.push({
965
1086
  declared: t,
966
1087
  live: e
967
1088
  });
@@ -972,47 +1093,47 @@ BEGIN
972
1093
  removed: o,
973
1094
  changed: s
974
1095
  };
975
- }, Rt = (e, t) => {
1096
+ }, un = (e, t) => {
976
1097
  let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
977
1098
  for (let t of e.indexes) {
978
1099
  let e = n.get(t.name);
979
- (!e || !It(t, e)) && i.push(t);
1100
+ (!e || !cn(t, e)) && i.push(t);
980
1101
  }
981
1102
  for (let e of t.indexes) r.has(e.name) || a.push(e);
982
1103
  return {
983
1104
  added: i,
984
1105
  removed: a
985
1106
  };
986
- }, I = (e, t, n, r) => ({
1107
+ }, L = (e, t, n, r) => ({
987
1108
  op: e,
988
1109
  classification: t,
989
- atomicByDialect: Et(e.kind),
1110
+ atomicByDialect: Zt(e.kind),
990
1111
  ...n ? { reason: n } : {},
991
1112
  ...r ? { blocked: r } : {}
992
- }), zt = (e, t, n) => {
1113
+ }), dn = (e, t, n) => {
993
1114
  let r = {
994
1115
  kind: "add-column",
995
1116
  table: e,
996
1117
  column: t
997
1118
  };
998
- return t.nullable ? I(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? I(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? I(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : I(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
999
- }, Bt = (e, t, n) => {
1119
+ return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
1120
+ }, fn = (e, t, n) => {
1000
1121
  let r = {
1001
1122
  kind: "drop-column",
1002
1123
  table: e,
1003
1124
  column: t.name
1004
1125
  };
1005
- return n?.dropped ? I(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : I(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1006
- }, Vt = (e, t, n, r, i) => I({
1126
+ return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1127
+ }, pn = (e, t, n, r, i) => L({
1007
1128
  kind: "create-table",
1008
1129
  table: e,
1009
1130
  columns: t,
1010
1131
  indexes: n,
1011
1132
  ...r && r.length > 0 ? { primaryKey: r } : {}
1012
- }, "safe", i ?? "new table — no data to preserve"), Ht = (e) => I({
1133
+ }, "safe", i ?? "new table — no data to preserve"), mn = (e) => L({
1013
1134
  kind: "drop-table",
1014
1135
  table: e
1015
- }, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }), Ut = 5e4, Wt = (e, t, n, r) => {
1136
+ }, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }), hn = 5e4, gn = (e, t, n, r) => {
1016
1137
  let i = (n ?? 0) >= r, a;
1017
1138
  return a = t.unique ? t.columns.length === 1 ? {
1018
1139
  kind: "add-unique",
@@ -1027,16 +1148,16 @@ BEGIN
1027
1148
  kind: "add-index",
1028
1149
  table: e,
1029
1150
  index: t
1030
- }, i ? I(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : I(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
1031
- }, Gt = (e, t) => t.unique && t.columns.length > 1 ? I({
1151
+ }, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
1152
+ }, _n = (e, t) => t.unique && t.columns.length > 1 ? L({
1032
1153
  kind: "drop-unique-composite",
1033
1154
  table: e,
1034
1155
  name: t.name
1035
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : I({
1156
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
1036
1157
  kind: "drop-index",
1037
1158
  table: e,
1038
1159
  index: t.name
1039
- }, "safe", "drop index (no data loss — index is derived data)"), Kt = (e, t) => {
1160
+ }, "safe", "drop index (no data loss — index is derived data)"), vn = (e, t) => {
1040
1161
  if (e === "reference") return "text";
1041
1162
  switch (t) {
1042
1163
  case "sqlite":
@@ -1044,7 +1165,7 @@ BEGIN
1044
1165
  case "mssql": return e === "json" ? "text" : e;
1045
1166
  default: return e;
1046
1167
  }
1047
- }, qt = (e, t, n, i, a, o) => {
1168
+ }, yn = (e, t, n, i, a, o) => {
1048
1169
  let s = [];
1049
1170
  if (t.nullable !== n.nullable) {
1050
1171
  let n = {
@@ -1053,7 +1174,7 @@ BEGIN
1053
1174
  column: t.name,
1054
1175
  toNullable: t.nullable
1055
1176
  };
1056
- s.push(t.nullable ? I(n, "safe", `loosen ${e}.${t.name} to nullable`) : I(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1177
+ s.push(t.nullable ? L(n, "safe", `loosen ${e}.${t.name} to nullable`) : L(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1057
1178
  }
1058
1179
  if (t.unique !== n.unique) if (t.unique) {
1059
1180
  let n = {
@@ -1061,13 +1182,13 @@ BEGIN
1061
1182
  table: e,
1062
1183
  column: t.name
1063
1184
  }, r = (a ?? 0) >= o;
1064
- s.push(r ? I(n, "online-required", `online unique build on ${a} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : I(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1065
- } else s.push(I({
1185
+ s.push(r ? L(n, "online-required", `online unique build on ${a} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1186
+ } else s.push(L({
1066
1187
  kind: "drop-unique",
1067
1188
  table: e,
1068
1189
  column: t.name
1069
1190
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
1070
- if (Kt(t.type, i) !== Kt(n.type, i)) {
1191
+ if (vn(t.type, i) !== vn(n.type, i)) {
1071
1192
  let r = t.narrowedFrom;
1072
1193
  if (r && r.from === n.type) {
1073
1194
  let i = {
@@ -1078,7 +1199,7 @@ BEGIN
1078
1199
  to: t.type,
1079
1200
  ...r.using === void 0 ? {} : { using: r.using }
1080
1201
  };
1081
- s.push(I(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
1202
+ s.push(L(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
1082
1203
  } else {
1083
1204
  let r = {
1084
1205
  kind: "alter-column-type",
@@ -1087,12 +1208,12 @@ BEGIN
1087
1208
  from: n.type,
1088
1209
  to: t.type
1089
1210
  };
1090
- s.push(I(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
1211
+ s.push(L(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
1091
1212
  }
1092
1213
  }
1093
1214
  if (t.type === "text" && n.type === "text" && !r(i ?? "postgres") && t.maxLength !== n.maxLength) {
1094
1215
  let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
1095
- s.push(I({
1216
+ s.push(L({
1096
1217
  kind: "alter-column-type",
1097
1218
  table: e,
1098
1219
  column: t.name,
@@ -1100,7 +1221,7 @@ BEGIN
1100
1221
  to: "text"
1101
1222
  }, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
1102
1223
  }
1103
- if (!kt(t, n)) {
1224
+ if (!en(t, n)) {
1104
1225
  let n = {
1105
1226
  kind: "alter-column-default",
1106
1227
  table: e,
@@ -1108,23 +1229,23 @@ BEGIN
1108
1229
  hasDefault: t.hasDefault,
1109
1230
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
1110
1231
  };
1111
- s.push(I(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1232
+ s.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1112
1233
  }
1113
- if (!jt(t.oneOf, n.oneOf)) {
1114
- n.oneOf && n.oneOf.length > 0 && s.push(I({
1234
+ if (!nn(t.oneOf, n.oneOf)) {
1235
+ n.oneOf && n.oneOf.length > 0 && s.push(L({
1115
1236
  kind: "drop-check",
1116
1237
  table: e,
1117
1238
  column: t.name
1118
1239
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
1119
- let r = Ft(e, t);
1240
+ let r = sn(e, t);
1120
1241
  r && s.push(r);
1121
1242
  }
1122
- return JSON.stringify(At(t.references)) !== JSON.stringify(At(n.references)) && (n.references && s.push(I({
1243
+ return JSON.stringify(tn(t.references)) !== JSON.stringify(tn(n.references)) && (n.references && s.push(L({
1123
1244
  kind: "drop-foreign-key",
1124
1245
  table: e,
1125
1246
  column: t.name
1126
- }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), s.push(...Jt(e, t))), s;
1127
- }, Jt = (e, t) => {
1247
+ }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), s.push(...bn(e, t))), s;
1248
+ }, bn = (e, t) => {
1128
1249
  let n = [];
1129
1250
  if (!t.references) return n;
1130
1251
  let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
@@ -1136,15 +1257,15 @@ BEGIN
1136
1257
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1137
1258
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1138
1259
  };
1139
- return i === "null" && !t.nullable ? n.push(I(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(I({
1260
+ return i === "null" && !t.nullable ? n.push(L(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(L({
1140
1261
  ...a,
1141
1262
  orphanPolicy: i
1142
- }, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(I(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1143
- }, Yt = (e, t, n) => {
1263
+ }, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(L(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1264
+ }, xn = (e, t, n) => {
1144
1265
  let r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = new Set(n.removed.map((e) => e.name)), s = new Set(n.added.map((e) => e.name));
1145
1266
  for (let [n, c] of Object.entries(t)) {
1146
1267
  let t = c.renamedFrom;
1147
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(I({
1268
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
1148
1269
  kind: "rename-column",
1149
1270
  table: e.tableName,
1150
1271
  from: t,
@@ -1156,26 +1277,26 @@ BEGIN
1156
1277
  consumedAddedNames: i,
1157
1278
  consumedRemovedNames: a
1158
1279
  };
1159
- }, Xt = /* @__PURE__ */ new Set([
1280
+ }, Sn = /* @__PURE__ */ new Set([
1160
1281
  "postgres",
1161
1282
  "mysql",
1162
1283
  "mariadb",
1163
1284
  "mssql"
1164
- ]), Zt = {
1285
+ ]), Cn = {
1165
1286
  ops: [],
1166
1287
  consumedAddedNames: /* @__PURE__ */ new Set(),
1167
1288
  consumedRemovedNames: /* @__PURE__ */ new Set()
1168
- }, Qt = (e) => !e.unique && !e.expression, $t = (e, t, n, r, i) => {
1169
- if (i === void 0 || !Xt.has(i)) return Zt;
1170
- let a = t.added.filter((e) => Qt(e) && !r.has(e.name));
1171
- if (a.length === 0) return Zt;
1289
+ }, wn = (e) => !e.unique && !e.expression, Tn = (e, t, n, r, i) => {
1290
+ if (i === void 0 || !Sn.has(i)) return Cn;
1291
+ let a = t.added.filter((e) => wn(e) && !r.has(e.name));
1292
+ if (a.length === 0) return Cn;
1172
1293
  let o = (e) => e.columns.map((e) => n.get(e) ?? e).join("\0"), s = (e) => e.columns.join("\0"), c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set();
1173
1294
  for (let n of t.removed) {
1174
- if (!Qt(n)) continue;
1295
+ if (!wn(n)) continue;
1175
1296
  let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
1176
1297
  if (r.length !== 1) continue;
1177
1298
  let i = r[0];
1178
- i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(I({
1299
+ i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(L({
1179
1300
  kind: "rename-index",
1180
1301
  table: e,
1181
1302
  from: n.name,
@@ -1187,7 +1308,7 @@ BEGIN
1187
1308
  consumedAddedNames: l,
1188
1309
  consumedRemovedNames: u
1189
1310
  };
1190
- }, en = (e, t, n) => {
1311
+ }, En = (e, t, n) => {
1191
1312
  let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
1192
1313
  for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
1193
1314
  for (let c of e.tables) {
@@ -1198,7 +1319,7 @@ BEGIN
1198
1319
  continue;
1199
1320
  }
1200
1321
  if (t.has(c.name)) {
1201
- r.push(I({
1322
+ r.push(L({
1202
1323
  kind: "rename-table",
1203
1324
  from: e,
1204
1325
  to: c.name
@@ -1206,14 +1327,14 @@ BEGIN
1206
1327
  continue;
1207
1328
  }
1208
1329
  if ((s.get(e) ?? 0) !== 1) {
1209
- r.push(I({
1330
+ r.push(L({
1210
1331
  kind: "rename-table",
1211
1332
  from: e,
1212
1333
  to: c.name
1213
1334
  }, "needs-rename-annotation", `.renamedFrom('${e}') is claimed by ${s.get(e)} tables — nothing says which receives its rows`, { fix: `remove the \`.renamedFrom('${e}')\` marker from all but one of them.` }));
1214
1335
  continue;
1215
1336
  }
1216
- i.set(c.name, e), a.add(e), r.push(I({
1337
+ i.set(c.name, e), a.add(e), r.push(L({
1217
1338
  kind: "rename-table",
1218
1339
  from: e,
1219
1340
  to: c.name
@@ -1227,19 +1348,19 @@ BEGIN
1227
1348
  claimedOldNames: c,
1228
1349
  refusals: o
1229
1350
  };
1230
- }, tn = (e, t, n, r) => {
1351
+ }, Dn = (e, t, n, r) => {
1231
1352
  if (t === void 0) return {
1232
1353
  live: e,
1233
1354
  ops: []
1234
1355
  };
1235
- let i = r !== void 0 && Xt.has(r), a = [], o = e.indexes.map((e) => {
1356
+ let i = r !== void 0 && Sn.has(r), a = [], o = e.indexes.map((e) => {
1236
1357
  if (!e.name.startsWith(t)) return e;
1237
1358
  let r = `${n}${e.name.slice(t.length)}`;
1238
1359
  return r === e.name ? e : e.name === `${t}_pkey` ? {
1239
1360
  ...e,
1240
1361
  name: r,
1241
1362
  table: n
1242
- } : i ? (a.push(I({
1363
+ } : i ? (a.push(L({
1243
1364
  kind: "rename-index",
1244
1365
  table: n,
1245
1366
  from: e.name,
@@ -1258,7 +1379,7 @@ BEGIN
1258
1379
  },
1259
1380
  ops: a
1260
1381
  };
1261
- }, nn = (e) => {
1382
+ }, On = (e) => {
1262
1383
  let t = {
1263
1384
  safe: 0,
1264
1385
  needsDefault: 0,
@@ -1293,42 +1414,42 @@ BEGIN
1293
1414
  break;
1294
1415
  }
1295
1416
  return t;
1296
- }, rn = (e) => {
1297
- let t = P(e.declared, e.dialect), n = Dt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Ut, a = [], o = en(t, r, n);
1417
+ }, kn = (e) => {
1418
+ let t = F(e.declared, e.dialect), n = Qt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? hn, a = [], o = En(t, r, n);
1298
1419
  a.push(...o.ops);
1299
1420
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1300
- a.push(Vt(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1421
+ a.push(pn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1301
1422
  for (let t of e.columns) {
1302
- let n = Ft(e.name, t);
1423
+ let n = sn(e.name, t);
1303
1424
  n && a.push(n);
1304
1425
  }
1305
1426
  }
1306
1427
  let s = new Set(e.ignoreTables ?? []);
1307
- for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || m(t.name) || v(t.name) || s.has(t.name) || a.push(Ht(t.name));
1428
+ for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || m(t.name) || v(t.name) || s.has(t.name) || a.push(mn(t.name));
1308
1429
  for (let s of t.tables) {
1309
1430
  let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
1310
1431
  if (!c) continue;
1311
- let l = tn(c, t, s.name, e.dialect);
1432
+ let l = Dn(c, t, s.name, e.dialect);
1312
1433
  a.push(...l.ops);
1313
- let u = l.live, d = n.get(s.name), f = Lt(s, u, e.dialect), p = Rt(s, u), m = Yt(d.table, d.columnDefs, f);
1434
+ let u = l.live, d = n.get(s.name), f = ln(s, u, e.dialect), p = un(s, u), m = xn(d.table, d.columnDefs, f);
1314
1435
  a.push(...m.ops);
1315
1436
  for (let e of f.removed) {
1316
1437
  if (m.consumedRemovedNames.has(e.name) || v(e.name)) continue;
1317
1438
  let t = d.columnDefs[e.name];
1318
- a.push(Bt(s.name, e, t));
1439
+ a.push(fn(s.name, e, t));
1319
1440
  }
1320
1441
  for (let e of f.added) {
1321
1442
  if (m.consumedAddedNames.has(e.name)) continue;
1322
1443
  let t = d.columnDefs[e.name];
1323
- a.push(zt(s.name, e, t));
1324
- let n = Ft(s.name, e);
1325
- n && a.push(n), a.push(...Jt(s.name, e));
1444
+ a.push(dn(s.name, e, t));
1445
+ let n = sn(s.name, e);
1446
+ n && a.push(n), a.push(...bn(s.name, e));
1326
1447
  }
1327
- let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = $t(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1448
+ let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Tn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1328
1449
  a.push(...g.ops);
1329
- for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(Wt(s.name, e, u.rowCount, i));
1330
- for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(Gt(s.name, e));
1331
- for (let { declared: t, live: n } of f.changed) a.push(...qt(s.name, t, n, e.dialect, u.rowCount, i));
1450
+ for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(gn(s.name, e, u.rowCount, i));
1451
+ for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(_n(s.name, e));
1452
+ for (let { declared: t, live: n } of f.changed) a.push(...yn(s.name, t, n, e.dialect, u.rowCount, i));
1332
1453
  }
1333
1454
  let c = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), l = new Map(t.tables.map((e) => [e.name, e])), u = (e) => {
1334
1455
  let t = l.get(e);
@@ -1336,8 +1457,8 @@ BEGIN
1336
1457
  column: e.name,
1337
1458
  target: e.references.table
1338
1459
  }] : []) : [];
1339
- }, d = le([...c], u), f = [];
1340
- for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(w(e.name, t.name)) || f.push(I({
1460
+ }, d = ue([...c], u), f = [];
1461
+ for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(w(e.name, t.name)) || f.push(L({
1341
1462
  kind: "add-foreign-key",
1342
1463
  table: e.name,
1343
1464
  column: t.name,
@@ -1409,87 +1530,11 @@ BEGIN
1409
1530
  });
1410
1531
  return {
1411
1532
  operations: S,
1412
- fromFingerprint: M(e.live),
1413
- toFingerprint: M(t),
1414
- summary: nn(S)
1533
+ fromFingerprint: N(e.live),
1534
+ toFingerprint: N(t),
1535
+ summary: On(S)
1415
1536
  };
1416
- }, an = (e) => e.onDialectOrElse({
1417
- pg: () => "postgres",
1418
- mysql: () => "mysql",
1419
- mssql: () => "mssql",
1420
- sqlite: () => "sqlite",
1421
- orElse: () => "sqlite"
1422
- }), on = {
1423
- postgres: "plan-transactional",
1424
- mssql: "plan-transactional",
1425
- mysql: "per-operation",
1426
- mariadb: "per-operation",
1427
- sqlite: "per-operation",
1428
- turso: "per-operation"
1429
- }, sn = (e) => on[e], L = "_voltro_migration_ops", cn = l(L, {
1430
- id: e({ prefix: "mop" }),
1431
- runId: _(),
1432
- planFingerprint: _(),
1433
- opIndex: n(),
1434
- opKind: _(),
1435
- opTarget: _(),
1436
- status: _(),
1437
- payload: _(),
1438
- startedAt: t().nullable(),
1439
- appliedAt: t().nullable(),
1440
- durationMs: n().nullable(),
1441
- createdAt: t().default("now")
1442
- }), ln = (e) => {
1443
- switch (e.kind) {
1444
- case "create-table": return /* @__PURE__ */ new Set([
1445
- `table:${e.table}`,
1446
- ...e.columns.map((t) => `column:${e.table}.${t.name}`),
1447
- ...e.indexes.map((t) => `index:${e.table}.${t.name}`)
1448
- ]);
1449
- case "drop-table": return /* @__PURE__ */ new Set([`table:${e.table}`]);
1450
- case "rename-table": return /* @__PURE__ */ new Set([`table:${e.from}`, `table:${e.to}`]);
1451
- case "add-column": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column.name}`]);
1452
- case "rename-column": return /* @__PURE__ */ new Set([`column:${e.table}.${e.from}`, `column:${e.table}.${e.to}`]);
1453
- case "drop-column":
1454
- case "alter-column-nullability":
1455
- case "alter-column-type":
1456
- case "alter-column-default":
1457
- case "add-unique":
1458
- case "drop-unique":
1459
- case "add-foreign-key":
1460
- case "drop-foreign-key":
1461
- case "add-check":
1462
- case "drop-check": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column}`]);
1463
- case "add-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index.name}`]);
1464
- case "drop-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index}`]);
1465
- case "rename-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.from}`, `index:${e.table}.${e.to}`]);
1466
- case "add-unique-composite":
1467
- case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
1468
- }
1469
- }, un = (e) => [...ln(e)].join(" "), dn = (e, t) => {
1470
- let n = ln(t);
1471
- for (let t of ln(e)) if (n.has(t)) return !0;
1472
- return !1;
1473
- }, fn = (e, t) => e.operations.some((e) => dn(e.op, t)), pn = "__voltro_rebuild", mn = "__shadow", hn = "__old", gn = /* @__PURE__ */ new Set([
1474
- "add-unique",
1475
- "drop-unique",
1476
- "add-unique-composite",
1477
- "drop-unique-composite",
1478
- "add-foreign-key",
1479
- "drop-foreign-key",
1480
- "add-check",
1481
- "drop-check",
1482
- "alter-column-nullability",
1483
- "alter-column-type",
1484
- "alter-column-default"
1485
- ]), _n = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), vn = (e, t, n) => {
1486
- let r = n === "sqlite" || n === "turso";
1487
- return e.kind === "alter-column-type" && t === "online-required" || r && gn.has(e.kind) ? "artefact-repair" : _n.has(e.kind) ? "idempotent" : "probe-then-replay";
1488
- };
1489
- Object.keys(on);
1490
- //#endregion
1491
- //#region src/migrations/introspect.ts
1492
- var yn = (e) => {
1537
+ }, An = (e) => {
1493
1538
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1494
1539
  if (!t) return null;
1495
1540
  let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
@@ -1497,7 +1542,7 @@ var yn = (e) => {
1497
1542
  column: t[1],
1498
1543
  values: n
1499
1544
  };
1500
- }, bn = (e, t) => {
1545
+ }, jn = (e, t) => {
1501
1546
  if (t === "vector") return "vector";
1502
1547
  switch (e) {
1503
1548
  case "text":
@@ -1532,25 +1577,25 @@ var yn = (e) => {
1532
1577
  case "SET DEFAULT": return "noAction";
1533
1578
  default: return "noAction";
1534
1579
  }
1535
- }, xn = (e, t) => {
1580
+ }, Mn = (e, t) => {
1536
1581
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1537
1582
  return Number.isInteger(n) && n > 0 ? n : t;
1538
- }, Sn = () => xn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Cn = 300, wn = () => {
1583
+ }, Nn = () => Mn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Pn = 300, Fn = () => {
1539
1584
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1540
- return e !== void 0 && e.trim() === "0" ? 0 : xn(e, 3e4);
1541
- }, Tn = (e, t) => {
1585
+ return e !== void 0 && e.trim() === "0" ? 0 : Mn(e, 3e4);
1586
+ }, In = (e, t) => {
1542
1587
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1543
1588
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1544
1589
  return r;
1545
- }, En = (e) => {
1546
- let t = wn(), n = b.gen(function* () {
1590
+ }, Ln = (e) => {
1591
+ let t = Fn(), n = b.gen(function* () {
1547
1592
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1548
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Sn(), a = (e, t) => b.gen(function* () {
1593
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Nn(), a = (e, t) => b.gen(function* () {
1549
1594
  let r = [];
1550
- for (let a of Tn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1595
+ for (let a of In(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1551
1596
  return r;
1552
1597
  }), o = [];
1553
- for (let t = 0;; t += Cn) {
1598
+ for (let t = 0;; t += Pn) {
1554
1599
  let n = yield* e`
1555
1600
  SELECT c.relname AS table_name,
1556
1601
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1558,9 +1603,9 @@ var yn = (e) => {
1558
1603
  JOIN pg_namespace n ON n.oid = c.relnamespace
1559
1604
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1560
1605
  ORDER BY c.relname
1561
- LIMIT ${r(Cn)} OFFSET ${r(t)}
1606
+ LIMIT ${r(Pn)} OFFSET ${r(t)}
1562
1607
  `;
1563
- if (o.push(...n), n.length < Cn) break;
1608
+ if (o.push(...n), n.length < Pn) break;
1564
1609
  }
1565
1610
  let s = /* @__PURE__ */ new Set(), c = [];
1566
1611
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
@@ -1694,7 +1739,7 @@ var yn = (e) => {
1694
1739
  let te = [];
1695
1740
  for (let e of c) {
1696
1741
  let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = S.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
1697
- let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : bn(t.data_type, t.udt_name), c = a ? {
1742
+ let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : jn(t.data_type, t.udt_name), c = a ? {
1698
1743
  table: a.target_table,
1699
1744
  column: a.target_column,
1700
1745
  onDelete: R(a.delete_rule),
@@ -1748,7 +1793,7 @@ var yn = (e) => {
1748
1793
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1749
1794
  return n.includes("statement timeout") || n.includes("57014") ? b.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : b.fail(e);
1750
1795
  }));
1751
- }, Dn = (e, t) => {
1796
+ }, Rn = (e, t) => {
1752
1797
  switch (e.toLowerCase()) {
1753
1798
  case "varchar":
1754
1799
  case "char":
@@ -1784,7 +1829,7 @@ var yn = (e) => {
1784
1829
  let t = e, n = {};
1785
1830
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1786
1831
  return n;
1787
- }), On = (e) => b.gen(function* () {
1832
+ }), zn = (e) => b.gen(function* () {
1788
1833
  let t = z(yield* e`
1789
1834
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1790
1835
  FROM information_schema.tables
@@ -1818,7 +1863,7 @@ var yn = (e) => {
1818
1863
  o.add(`${e.table_name}.${t[1]}`);
1819
1864
  continue;
1820
1865
  }
1821
- let n = yn(e.check_clause);
1866
+ let n = An(e.check_clause);
1822
1867
  n && s.set(`${e.table_name}.${n.column}`, n.values);
1823
1868
  }
1824
1869
  let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
@@ -1841,7 +1886,7 @@ var yn = (e) => {
1841
1886
  let t = c.get(e.table_name) ?? [], n = l.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), f = u.get(e.table_name);
1842
1887
  if (f) for (let e of f.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1843
1888
  let p = t.map((t) => {
1844
- let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : Dn(t.data_type, t.column_type), u = c ? {
1889
+ let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : Rn(t.data_type, t.column_type), u = c ? {
1845
1890
  table: c.target_table,
1846
1891
  column: c.target_column,
1847
1892
  onDelete: R(c.delete_rule),
@@ -1883,10 +1928,10 @@ var yn = (e) => {
1883
1928
  });
1884
1929
  }
1885
1930
  return { tables: d };
1886
- }), kn = (e) => {
1931
+ }), Bn = (e) => {
1887
1932
  let t = e.toUpperCase();
1888
1933
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1889
- }, An = (e) => b.gen(function* () {
1934
+ }, Vn = (e) => b.gen(function* () {
1890
1935
  let t = yield* e`
1891
1936
  SELECT name, sql FROM sqlite_master
1892
1937
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1903,7 +1948,7 @@ var yn = (e) => {
1903
1948
  d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1904
1949
  }
1905
1950
  let p = o.map((e) => {
1906
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : kn(e.type), a = r ? {
1951
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Bn(e.type), a = r ? {
1907
1952
  table: r.table,
1908
1953
  column: r.to,
1909
1954
  onDelete: R(r.on_delete),
@@ -1942,7 +1987,7 @@ var yn = (e) => {
1942
1987
  });
1943
1988
  }
1944
1989
  return { tables: r };
1945
- }), jn = (e) => {
1990
+ }), Hn = (e) => {
1946
1991
  switch (e.toLowerCase()) {
1947
1992
  case "int":
1948
1993
  case "smallint":
@@ -1964,7 +2009,7 @@ var yn = (e) => {
1964
2009
  case "image": return "bytes";
1965
2010
  default: return "text";
1966
2011
  }
1967
- }, B = (e) => e === !0 || e === 1, Mn = (e) => b.gen(function* () {
2012
+ }, B = (e) => e === !0 || e === 1, Un = (e) => b.gen(function* () {
1968
2013
  let t = yield* e`
1969
2014
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
1970
2015
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
@@ -2025,12 +2070,12 @@ var yn = (e) => {
2025
2070
  else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
2026
2071
  }
2027
2072
  let p = t.map((t) => {
2028
- let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : jn(t.data_type), s = i ? {
2073
+ let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Hn(t.data_type), s = i ? {
2029
2074
  table: i.target_table,
2030
2075
  column: i.target_column,
2031
- onDelete: Nn(i.delete_rule),
2032
- onUpdate: Nn(i.update_rule)
2033
- } : void 0, c = t.column_default === null ? null : Pn(t.column_default), l = o.get(`${e}.${t.column_name}`);
2076
+ onDelete: Wn(i.delete_rule),
2077
+ onUpdate: Wn(i.update_rule)
2078
+ } : void 0, c = t.column_default === null ? null : Gn(t.column_default), l = o.get(`${e}.${t.column_name}`);
2034
2079
  return {
2035
2080
  name: t.column_name,
2036
2081
  type: a,
@@ -2064,18 +2109,18 @@ var yn = (e) => {
2064
2109
  });
2065
2110
  }
2066
2111
  return { tables: u };
2067
- }), Nn = (e) => {
2112
+ }), Wn = (e) => {
2068
2113
  switch (e.toUpperCase().replace(/_/g, " ")) {
2069
2114
  case "CASCADE": return "cascade";
2070
2115
  case "SET NULL": return "setNull";
2071
2116
  case "SET DEFAULT": return "noAction";
2072
2117
  default: return "noAction";
2073
2118
  }
2074
- }, Pn = (e) => {
2119
+ }, Gn = (e) => {
2075
2120
  let t = e.trim();
2076
2121
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
2077
2122
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
2078
- }, Fn = /* @__PURE__ */ new Set([
2123
+ }, Kn = /* @__PURE__ */ new Set([
2079
2124
  "character varying",
2080
2125
  "varchar",
2081
2126
  "nvarchar",
@@ -2083,35 +2128,35 @@ var yn = (e) => {
2083
2128
  "character",
2084
2129
  "nchar"
2085
2130
  ]), V = (e, t) => {
2086
- if (!Fn.has(e.toLowerCase())) return;
2131
+ if (!Kn.has(e.toLowerCase())) return;
2087
2132
  let n = Number(t);
2088
2133
  if (!(!Number.isFinite(n) || n <= 0)) return n;
2089
- }, In = /* @__PURE__ */ new Set([L]), Ln = (e) => e.onDialectOrElse({
2090
- mysql: () => On(e),
2091
- mssql: () => Mn(e),
2092
- sqlite: () => An(e),
2093
- orElse: () => En(e)
2134
+ }, qn = /* @__PURE__ */ new Set([D]), Jn = (e) => e.onDialectOrElse({
2135
+ mysql: () => zn(e),
2136
+ mssql: () => Un(e),
2137
+ sqlite: () => Vn(e),
2138
+ orElse: () => Ln(e)
2094
2139
  }).pipe(b.map((e) => ({
2095
2140
  ...e,
2096
- tables: e.tables.filter((e) => !In.has(e.name))
2141
+ tables: e.tables.filter((e) => !qn.has(e.name))
2097
2142
  }))), H = (e, t) => e.onDialectOrElse({
2098
2143
  mysql: () => b.succeed(t.replace("T", " ").replace("Z", "")),
2099
2144
  orElse: () => b.succeed(t)
2100
- }), Rn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, zn = (e, t) => {
2145
+ }), Yn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Xn = (e, t) => {
2101
2146
  if (!(e.type === "text" && e.maxLength !== void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2102
2147
  let n = e.type === "vector" && e.vectorDim === void 0 ? "vector dimension" : e.type === "array" && e.arrayElement === void 0 ? "array element type" : e.type === "enum" && e.enumName === void 0 && e.enumValues === void 0 ? "enum name/values" : void 0;
2103
2148
  if (n !== void 0) throw Error(`migration applier: cannot render '${e.name}' (${e.type}) — the schema snapshot carries no ${n}. Rendering it as 'text' would emit DDL that applies successfully and changes nothing, so this fails instead. This is a framework bug: declaredSchema.ts must carry the parameter into the ColumnSnapshot.`);
2104
- return k(e, t);
2105
- }, Bn = (e) => {
2106
- let t = zn(e, "postgres");
2107
- return t === void 0 ? Vn(e) : t;
2108
- }, Vn = (e) => {
2149
+ return A(e, t);
2150
+ }, Zn = (e) => {
2151
+ let t = Xn(e, "postgres");
2152
+ return t === void 0 ? Qn(e) : t;
2153
+ }, Qn = (e) => {
2109
2154
  switch (e.type) {
2110
2155
  case "id": return "text";
2111
2156
  case "text": return "text";
2112
2157
  case "integer": return "integer";
2113
2158
  case "real": return "double precision";
2114
- case "decimal": return Rn(e, "NUMERIC");
2159
+ case "decimal": return Yn(e, "NUMERIC");
2115
2160
  case "bigint": return "bigint";
2116
2161
  case "boolean": return "boolean";
2117
2162
  case "timestamp": return "timestamptz";
@@ -2125,15 +2170,15 @@ var yn = (e) => {
2125
2170
  case "interval": return "interval";
2126
2171
  case "raw": return e.rawDdl ?? "text";
2127
2172
  }
2128
- }, Hn = (e) => {
2129
- let t = zn(e, "mariadb");
2173
+ }, $n = (e) => {
2174
+ let t = Xn(e, "mariadb");
2130
2175
  if (t !== void 0) return t;
2131
2176
  switch (e.type) {
2132
2177
  case "id": return "VARCHAR(64)";
2133
2178
  case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
2134
2179
  case "integer": return "INT";
2135
2180
  case "real": return "DOUBLE";
2136
- case "decimal": return Rn(e, "DECIMAL");
2181
+ case "decimal": return Yn(e, "DECIMAL");
2137
2182
  case "bigint": return "BIGINT";
2138
2183
  case "boolean": return "TINYINT(1)";
2139
2184
  case "timestamp": return "DATETIME(6)";
@@ -2147,32 +2192,32 @@ var yn = (e) => {
2147
2192
  case "interval": return "BIGINT";
2148
2193
  case "raw": return e.rawDdl ?? "LONGTEXT";
2149
2194
  }
2150
- }, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``, Un = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, Wn = (e) => `ALTER TABLE ${W(e.table)} DROP COLUMN IF EXISTS ${W(e.column)}, ALGORITHM=COPY;`, Gn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Kn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${_r(t)}`)};`, qn = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Jn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Jn = (e, t) => {
2195
+ }, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``, er = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, tr = (e) => `ALTER TABLE ${W(e.table)} DROP COLUMN IF EXISTS ${W(e.column)}, ALGORITHM=COPY;`, nr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, rr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Or(t)}`)};`, ir = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${ar(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, ar = (e, t) => {
2151
2196
  let n = t(e.defaultValue);
2152
2197
  if (n === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${e.column}' (${JSON.stringify(e.defaultValue)}). Emitting 'DEFAULT NULL' would apply cleanly and drop the default silently, so this fails instead. This is a framework bug — report the column type + default.`);
2153
2198
  return n;
2154
- }, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Yn = (e, t, n) => {
2199
+ }, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], or = (e, t, n) => {
2155
2200
  let r = G(e, t, n);
2156
- return r ? vt(n, r) : void 0;
2157
- }, Xn = (e, t, n) => {
2158
- let r = n ?? e.nullable, i = Ae(e, "mariadb");
2201
+ return r ? Ut(n, r) : void 0;
2202
+ }, sr = (e, t, n) => {
2203
+ let r = n ?? e.nullable, i = Ze(e, "mariadb");
2159
2204
  return [
2160
2205
  W(t),
2161
- k(e, "mariadb"),
2206
+ A(e, "mariadb"),
2162
2207
  r ? null : "NOT NULL",
2163
2208
  i
2164
2209
  ].filter(Boolean).join(" ");
2165
- }, Zn = (e, t) => e == null ? null : Array.isArray(e) ? Qn(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? A(e, "mariadb") : null, Qn = (e, t, n) => je(e, t ?? { type: "json" }, n), $n = (e, t) => e == null ? null : Array.isArray(e) ? Qn(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? A(e, "postgres") : null, K = (e, t) => {
2210
+ }, cr = (e, t) => e == null ? null : Array.isArray(e) ? lr(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? j(e, "mariadb") : null, lr = (e, t, n) => Qe(e, t ?? { type: "json" }, n), ur = (e, t) => e == null ? null : Array.isArray(e) ? lr(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? j(e, "postgres") : null, K = (e, t) => {
2166
2211
  if (!e.generatedAs) return null;
2167
2212
  let { expr: n, stored: r } = e.generatedAs;
2168
2213
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2169
- }, er = (e) => {
2170
- if (e.type === "id" && e.idScheme?.kind === "numeric") return j(e.name, "postgres");
2214
+ }, dr = (e) => {
2215
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "postgres");
2171
2216
  let t = K(e, "postgres");
2172
- if (t) return `${U(e.name)} ${Bn(e)} ${t}`;
2173
- let n = [U(e.name), Bn(e)];
2217
+ if (t) return `${U(e.name)} ${Zn(e)} ${t}`;
2218
+ let n = [U(e.name), Zn(e)];
2174
2219
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2175
- let t = $n(e.defaultValue, e);
2220
+ let t = ur(e.defaultValue, e);
2176
2221
  t && n.push(t);
2177
2222
  }
2178
2223
  return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
@@ -2181,20 +2226,20 @@ var yn = (e) => {
2181
2226
  setNull: "SET NULL",
2182
2227
  noAction: "NO ACTION"
2183
2228
  }[e.references.onDelete]}`)), n.join(" ");
2184
- }, tr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", nr = (e) => {
2185
- let t = e.columns.map((e) => ` ${er(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${tr(e, U)}\n)`];
2186
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(Sr).join(", ")})`);
2229
+ }, fr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", pr = (e) => {
2230
+ let t = e.columns.map((e) => ` ${dr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${fr(e, U)}\n)`];
2231
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(Nr).join(", ")})`);
2187
2232
  return n;
2188
- }, rr = 191, ir = (e) => {
2189
- let t = Hn(e).toUpperCase();
2233
+ }, mr = 191, hr = (e) => {
2234
+ let t = $n(e).toUpperCase();
2190
2235
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2191
- }, ar = (e) => {
2192
- if (e.type === "id" && e.idScheme?.kind === "numeric") return j(e.name, "mariadb");
2236
+ }, gr = (e) => {
2237
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "mariadb");
2193
2238
  let t = K(e, "mariadb");
2194
- if (t) return `${W(e.name)} ${Hn(e)} ${t}`;
2195
- let n = [W(e.name), Hn(e)];
2196
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !ir(e) && n.push("UNIQUE"), e.hasDefault) {
2197
- let t = Zn(e.defaultValue, e);
2239
+ if (t) return `${W(e.name)} ${$n(e)} ${t}`;
2240
+ let n = [W(e.name), $n(e)];
2241
+ if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !hr(e) && n.push("UNIQUE"), e.hasDefault) {
2242
+ let t = cr(e.defaultValue, e);
2198
2243
  t && n.push(t);
2199
2244
  }
2200
2245
  return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
@@ -2203,26 +2248,26 @@ var yn = (e) => {
2203
2248
  setNull: "SET NULL",
2204
2249
  noAction: "NO ACTION"
2205
2250
  }[e.references.onDelete]}`)), n.join(" ");
2206
- }, or = (e) => {
2251
+ }, _r = (e) => {
2207
2252
  let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
2208
- let n = br(t.get(e));
2253
+ let n = jr(t.get(e));
2209
2254
  return n === void 0 ? W(e) : `${W(e)}(${n})`;
2210
- }, r = e.columns.map((e) => ` ${ar(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${r}${tr(e, n)}\n)`];
2211
- for (let t of e.columns) t.unique && t.type !== "id" && ir(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${W(`${e.table}_${t.name}_key`)} ON ${W(e.table)} (${n(t.name)})`);
2255
+ }, r = e.columns.map((e) => ` ${gr(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${r}${fr(e, n)}\n)`];
2256
+ for (let t of e.columns) t.unique && t.type !== "id" && hr(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${W(`${e.table}_${t.name}_key`)} ON ${W(e.table)} (${n(t.name)})`);
2212
2257
  for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(n).join(", ")})`);
2213
2258
  return i;
2214
- }, sr = {
2259
+ }, vr = {
2215
2260
  cascade: "CASCADE",
2216
2261
  restrict: "RESTRICT",
2217
2262
  setNull: "SET NULL",
2218
2263
  noAction: "NO ACTION"
2219
- }, cr = {
2264
+ }, yr = {
2220
2265
  cascade: "CASCADE",
2221
2266
  restrict: "NO ACTION",
2222
2267
  setNull: "SET NULL",
2223
2268
  noAction: "NO ACTION"
2224
- }, lr = (e) => {
2225
- let t = zn(e, "sqlite");
2269
+ }, br = (e) => {
2270
+ let t = Xn(e, "sqlite");
2226
2271
  if (t !== void 0) return t;
2227
2272
  switch (e.type) {
2228
2273
  case "integer":
@@ -2233,29 +2278,29 @@ var yn = (e) => {
2233
2278
  case "bytes": return "BLOB";
2234
2279
  default: return "TEXT";
2235
2280
  }
2236
- }, q = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? A(e, "sqlite") : null, ur = (e) => {
2237
- if (e.type === "id" && e.idScheme?.kind === "numeric") return j(e.name, "sqlite");
2281
+ }, q = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? j(e, "sqlite") : null, xr = (e) => {
2282
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "sqlite");
2238
2283
  let t = K(e, "sqlite");
2239
- if (t) return `${U(e.name)} ${lr(e)} ${t}`;
2240
- let n = [U(e.name), lr(e)];
2284
+ if (t) return `${U(e.name)} ${br(e)} ${t}`;
2285
+ let n = [U(e.name), br(e)];
2241
2286
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2242
2287
  let t = q(e.defaultValue, "CURRENT_TIMESTAMP");
2243
2288
  t && n.push(t);
2244
2289
  }
2245
- if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${sr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2290
+ if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${vr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2246
2291
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2247
2292
  n.push(`CHECK (${U(e.name)} IN (${t}))`);
2248
2293
  }
2249
2294
  return n.join(" ");
2250
- }, dr = (e) => {
2251
- let t = e.columns.map((e) => ` ${ur(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${tr(e, U)}\n)`];
2295
+ }, Sr = (e) => {
2296
+ let t = e.columns.map((e) => ` ${xr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${fr(e, U)}\n)`];
2252
2297
  for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(U).join(", ")})`);
2253
2298
  return n;
2254
2299
  }, J = (e, t) => {
2255
2300
  let n = t.find((t) => t.tableName === e);
2256
2301
  if (!n) return [];
2257
- let r = P([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
2258
- ...dr({
2302
+ let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
2303
+ ...Sr({
2259
2304
  kind: "create-table",
2260
2305
  table: i,
2261
2306
  columns: r.columns,
@@ -2268,25 +2313,25 @@ var yn = (e) => {
2268
2313
  ];
2269
2314
  for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e)} (${t.columns.map(U).join(", ")})`);
2270
2315
  return o;
2271
- }, fr = (e, t, n, r) => {
2316
+ }, Cr = (e, t, n, r) => {
2272
2317
  let i = r ?? e.nullable;
2273
- return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${k(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2274
- }, pr = (e) => {
2318
+ return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${A(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2319
+ }, wr = (e) => {
2275
2320
  let t = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Y(e.table)} DROP CONSTRAINT [' + @dc + ']');`;
2276
2321
  if (!e.hasDefault) return t;
2277
2322
  let n = q(e.defaultValue, "SYSUTCDATETIME()");
2278
2323
  if (!n) return t;
2279
2324
  let r = n.replace(/^DEFAULT\s+/i, "");
2280
2325
  return `${t} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${r} FOR ${Y(e.column)};`;
2281
- }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, mr = (e) => {
2282
- let t = zn(e, "mssql");
2326
+ }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Tr = (e) => {
2327
+ let t = Xn(e, "mssql");
2283
2328
  if (t !== void 0) return t;
2284
2329
  switch (e.type) {
2285
2330
  case "id":
2286
2331
  case "reference": return "NVARCHAR(64)";
2287
2332
  case "integer": return "INT";
2288
2333
  case "real": return "FLOAT";
2289
- case "decimal": return Rn(e, "DECIMAL");
2334
+ case "decimal": return Yn(e, "DECIMAL");
2290
2335
  case "bigint": return "BIGINT";
2291
2336
  case "boolean": return "BIT";
2292
2337
  case "timestamp": return "DATETIME2(6)";
@@ -2294,44 +2339,44 @@ var yn = (e) => {
2294
2339
  case "bytes": return "VARBINARY(MAX)";
2295
2340
  default: return "NVARCHAR(MAX)";
2296
2341
  }
2297
- }, hr = (e, t) => {
2298
- if (e.type === "id" && e.idScheme?.kind === "numeric") return j(e.name, "mssql");
2299
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : mr(e), r = K(e, "mssql");
2342
+ }, Er = (e, t) => {
2343
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "mssql");
2344
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Tr(e), r = K(e, "mssql");
2300
2345
  if (r) return `${Y(e.name)} ${r}`;
2301
2346
  let i = [Y(e.name), n];
2302
2347
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2303
2348
  let t = q(e.defaultValue, "SYSUTCDATETIME()");
2304
2349
  t && i.push(t);
2305
2350
  }
2306
- return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${cr[e.references.onDelete]}`)), i.join(" ");
2307
- }, gr = (e) => {
2308
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${hr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${tr(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2351
+ return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${yr[e.references.onDelete]}`)), i.join(" ");
2352
+ }, Dr = (e) => {
2353
+ let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Er(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${fr(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2309
2354
  for (let n of e.indexes) {
2310
2355
  if (n.name === `${e.table}_pkey`) continue;
2311
2356
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})`;
2312
2357
  a.push(`IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(n.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(r)}')`);
2313
2358
  }
2314
2359
  return a;
2315
- }, _r = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, vr = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, yr = (e, t, n) => {
2316
- let r = `${e.table}${_r(t)}`;
2360
+ }, Or = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, kr = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Ar = (e, t, n) => {
2361
+ let r = `${e.table}${Or(t)}`;
2317
2362
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2318
- }, br = (e) => {
2319
- if (e === void 0 || !ir(e)) return;
2363
+ }, jr = (e) => {
2364
+ if (e === void 0 || !hr(e)) return;
2320
2365
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
2321
- return t === void 0 ? rr : Math.min(rr, t);
2322
- }, xr = (e, t, n) => {
2323
- let r = br(Yn(e, t, n));
2366
+ return t === void 0 ? mr : Math.min(mr, t);
2367
+ }, Mr = (e, t, n) => {
2368
+ let r = jr(or(e, t, n));
2324
2369
  return r === void 0 ? W(n) : `${W(n)}(${r})`;
2325
- }, Sr = (e) => e.startsWith("(") ? e : U(e), Cr = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${U(e.index.name)} ON ${U(e.table)} (${e.index.columns.map(Sr).join(", ")});`, wr = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map((n) => xr(t, e.table, n)).join(", ")});`, Tr = (e) => `DROP INDEX IF EXISTS ${U(e.index)};`, Er = (e) => `DROP INDEX ${W(e.index)} ON ${W(e.table)};`, Dr = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, Or = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, kr = (e) => {
2370
+ }, Nr = (e) => e.startsWith("(") ? e : U(e), Pr = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${U(e.index.name)} ON ${U(e.table)} (${e.index.columns.map(Nr).join(", ")});`, Fr = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map((n) => Mr(t, e.table, n)).join(", ")});`, Ir = (e) => `DROP INDEX IF EXISTS ${U(e.index)};`, Lr = (e) => `DROP INDEX ${W(e.index)} ON ${W(e.table)};`, Rr = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, zr = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Br = (e) => {
2326
2371
  let t = (e) => e.replace(/'/g, "''");
2327
2372
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
2328
- }, Ar = (e) => `ALTER INDEX ${U(e.from)} RENAME TO ${U(e.to)};`, jr = (e) => `ALTER TABLE ${W(e.table)} RENAME INDEX ${W(e.from)} TO ${W(e.to)};`, Mr = (e) => {
2373
+ }, Vr = (e) => `ALTER INDEX ${U(e.from)} RENAME TO ${U(e.to)};`, Hr = (e) => `ALTER TABLE ${W(e.table)} RENAME INDEX ${W(e.from)} TO ${W(e.to)};`, Ur = (e) => {
2329
2374
  let t = (e) => e.replace(/'/g, "''");
2330
2375
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2331
- }, Nr = (e) => {
2376
+ }, Wr = (e) => {
2332
2377
  let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Y(e.index.name)} ON ${Y(e.table)} (${e.index.columns.map(Y).join(", ")})`;
2333
2378
  return `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(e.index.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(n)}');`;
2334
- }, Pr = (e, t, n) => {
2379
+ }, Gr = (e, t, n) => {
2335
2380
  let r = n.find((t) => t.tableName === e);
2336
2381
  if (!r) return [];
2337
2382
  let i = [];
@@ -2340,13 +2385,13 @@ var yn = (e) => {
2340
2385
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2341
2386
  }
2342
2387
  return i;
2343
- }, Fr = (e) => `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(`${e.table}_${e.column}_key`)} UNIQUE (${U(e.column)});`, Ir = (e, t) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${xr(t, e.table, e.column)});`, Lr = (e) => {
2388
+ }, Kr = (e) => `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(`${e.table}_${e.column}_key`)} UNIQUE (${U(e.column)});`, qr = (e, t) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${Mr(t, e.table, e.column)});`, Jr = (e) => {
2344
2389
  let t = e.fields.map((e) => U(e)).join(", ");
2345
2390
  return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
2346
- }, Rr = (e, t) => {
2347
- let n = e.fields.map((n) => xr(t, e.table, n)).join(", ");
2391
+ }, Yr = (e, t) => {
2392
+ let n = e.fields.map((n) => Mr(t, e.table, n)).join(", ");
2348
2393
  return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
2349
- }, zr = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(e.name)};`, Br = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(e.name)};`, Vr = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_key`)};`, Hr = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(`${e.table}_${e.column}_key`)};`, Ur = (e, t) => {
2394
+ }, Xr = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(e.name)};`, Zr = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(e.name)};`, Qr = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_key`)};`, $r = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(`${e.table}_${e.column}_key`)};`, ei = (e, t) => {
2350
2395
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2351
2396
  if (e.orphanPolicy) {
2352
2397
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2364,11 +2409,11 @@ var yn = (e) => {
2364
2409
  setNull: "SET NULL",
2365
2410
  noAction: "NO ACTION"
2366
2411
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2367
- }, Wr = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_fkey`)};`, Gr = (e) => `ALTER TABLE ${W(e.table)} DROP FOREIGN KEY ${W(`${e.table}_${e.column}_fkey`)};`, Kr = (e, t) => {
2412
+ }, ti = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_fkey`)};`, ni = (e) => `ALTER TABLE ${W(e.table)} DROP FOREIGN KEY ${W(`${e.table}_${e.column}_fkey`)};`, ri = (e, t) => {
2368
2413
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2369
2414
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2370
- }, qr = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_check`)};`, Jr = (e) => `ALTER TABLE ${W(e.table)} DROP CHECK ${W(`${e.table}_${e.column}_check`)};`, Yr = (e, t, n, r) => {
2371
- let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Y : U, s = a ? Hn(i) : r === "mssql" ? mr(i) : r === "sqlite" ? lr(i) : Bn(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? Zn(e, i) : r === "mssql" ? q(e, "SYSUTCDATETIME()") : r === "sqlite" ? q(e, "CURRENT_TIMESTAMP") : $n(e, i), u = K(i, r);
2415
+ }, ii = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_check`)};`, ai = (e) => `ALTER TABLE ${W(e.table)} DROP CHECK ${W(`${e.table}_${e.column}_check`)};`, oi = (e, t, n, r) => {
2416
+ let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Y : U, s = a ? $n(i) : r === "mssql" ? Tr(i) : r === "sqlite" ? br(i) : Zn(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? cr(e, i) : r === "mssql" ? q(e, "SYSUTCDATETIME()") : r === "sqlite" ? q(e, "CURRENT_TIMESTAMP") : ur(e, i), u = K(i, r);
2372
2417
  if (u) {
2373
2418
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2374
2419
  return {
@@ -2396,7 +2441,7 @@ var yn = (e) => {
2396
2441
  post: f ? [f] : []
2397
2442
  };
2398
2443
  return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
2399
- }, Xr = (e) => {
2444
+ }, si = (e) => {
2400
2445
  let t = new Map(e.map((e) => [e.tableName, e]));
2401
2446
  return (e, n) => {
2402
2447
  let r = t.get(e);
@@ -2417,46 +2462,46 @@ var yn = (e) => {
2417
2462
  };
2418
2463
  };
2419
2464
  }, X = (e, t, n) => e.unsafe(t).pipe(b.tapError((e) => b.sync(() => {
2420
- process.stderr.write(re(`applier: statement failed (op=${n})`, t, e, 400));
2465
+ process.stderr.write(ie(`applier: statement failed (op=${n})`, t, e, 400));
2421
2466
  })), b.mapError((e) => {
2422
- let r = re(`applier: statement failed (op=${n})`, t, e, 400).trim();
2467
+ let r = ie(`applier: statement failed (op=${n})`, t, e, 400).trim();
2423
2468
  return Object.assign(e, { message: r });
2424
- }), b.map(() => void 0)), Z = (e, t, n) => b.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : i(r, t)} FROM ${i(n, t)} WHERE 1=0`).pipe(b.as(!0), b.catchAll(() => b.succeed(!1))), Zr = (e, t) => b.gen(function* () {
2425
- let n = P([cn], t).tables[0];
2469
+ }), b.map(() => void 0)), Z = (e, t, n) => b.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : i(r, t)} FROM ${i(n, t)} WHERE 1=0`).pipe(b.as(!0), b.catchAll(() => b.succeed(!1))), ci = (e, t) => b.gen(function* () {
2470
+ let n = F([Fe], t).tables[0];
2426
2471
  if (!n) return yield* b.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2427
2472
  let r = {
2428
2473
  kind: "create-table",
2429
- table: L,
2474
+ table: D,
2430
2475
  columns: n.columns,
2431
2476
  indexes: []
2432
2477
  }, i = yield* e.onDialectOrElse({
2433
- mysql: () => b.succeed(or(r)),
2434
- mssql: () => b.succeed(gr(r)),
2435
- sqlite: () => b.succeed(dr(r)),
2436
- orElse: () => b.succeed(nr(r))
2478
+ mysql: () => b.succeed(_r(r)),
2479
+ mssql: () => b.succeed(Dr(r)),
2480
+ sqlite: () => b.succeed(Sr(r)),
2481
+ orElse: () => b.succeed(pr(r))
2437
2482
  });
2438
2483
  yield* b.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2439
- }), Qr = (e) => e`
2484
+ }), li = (e) => e`
2440
2485
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2441
2486
  ${e("status")}, ${e("payload")}
2442
- FROM ${e(L)}
2443
- `, $r = (e, t, n, r) => b.gen(function* () {
2487
+ FROM ${e(D)}
2488
+ `, ui = (e, t, n, r) => b.gen(function* () {
2444
2489
  let i = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2445
2490
  yield* b.forEach(r, ({ index: r, planned: a }) => e`
2446
- INSERT INTO ${e(L)}
2491
+ INSERT INTO ${e(D)}
2447
2492
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2448
2493
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
2449
2494
  ${e("createdAt")})
2450
2495
  VALUES
2451
2496
  (${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
2452
- ${a.op.kind}, ${un(a.op)}, ${"pending"},
2497
+ ${a.op.kind}, ${Le(a.op)}, ${"pending"},
2453
2498
  ${JSON.stringify(a)}, ${i})
2454
2499
  `, { discard: !0 });
2455
- }), ei = (e, t, n, r, i) => b.gen(function* () {
2500
+ }), di = (e, t, n, r, i) => b.gen(function* () {
2456
2501
  let a = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2457
2502
  if (r === "applied") {
2458
2503
  yield* e`
2459
- UPDATE ${e(L)}
2504
+ UPDATE ${e(D)}
2460
2505
  SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
2461
2506
  ${e("durationMs")} = ${i ?? null}
2462
2507
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
@@ -2464,47 +2509,47 @@ var yn = (e) => {
2464
2509
  return;
2465
2510
  }
2466
2511
  yield* e`
2467
- UPDATE ${e(L)}
2512
+ UPDATE ${e(D)}
2468
2513
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
2469
2514
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
2470
2515
  `;
2471
- }), ti = (e, t, n, r) => b.gen(function* () {
2516
+ }), fi = (e, t, n, r) => b.gen(function* () {
2472
2517
  let i = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2473
2518
  r.length > 0 && (yield* e`
2474
- UPDATE ${e(L)}
2519
+ UPDATE ${e(D)}
2475
2520
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
2476
2521
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
2477
2522
  `), n.length > 0 && (yield* e`
2478
- UPDATE ${e(L)}
2523
+ UPDATE ${e(D)}
2479
2524
  SET ${e("status")} = ${"pending"}
2480
2525
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
2481
2526
  `);
2482
- }), ni = (e, t) => t === void 0 ? e`DELETE FROM ${e(L)}`.pipe(b.asVoid) : e`DELETE FROM ${e(L)} WHERE ${e("runId")} = ${t}`.pipe(b.asVoid), ri = (e, t, n) => b.gen(function* () {
2483
- if (vn(n.op, n.classification, t) !== "artefact-repair") return "clean";
2527
+ }), pi = (e, t) => t === void 0 ? e`DELETE FROM ${e(D)}`.pipe(b.asVoid) : e`DELETE FROM ${e(D)} WHERE ${e("runId")} = ${t}`.pipe(b.asVoid), mi = (e, t, n) => b.gen(function* () {
2528
+ if (Ge(n.op, n.classification, t) !== "artefact-repair") return "clean";
2484
2529
  let r = n.op, a = (e) => i(e, t);
2485
2530
  if (t === "sqlite" || t === "turso") {
2486
2531
  if (!("table" in r)) return "clean";
2487
- let n = `${r.table}${pn}`;
2532
+ let n = `${r.table}${Be}`;
2488
2533
  return (yield* $(e, t, n)) ? ((yield* $(e, t, r.table)) ? yield* X(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* X(e, `ALTER TABLE ${a(n)} RENAME TO ${a(r.table)}`, "resume-repair"), yield* b.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
2489
2534
  }
2490
2535
  if (r.kind !== "alter-column-type") return "clean";
2491
- let o = `${r.column}${mn}`, s = `${r.column}${hn}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, o), u = yield* $(e, t, r.table, s), d = (e) => b.logWarning(`migration resume: ${e}`).pipe(b.annotateLogs({ scope: "voltro:migrate" }));
2536
+ let o = `${r.column}${Ve}`, s = `${r.column}${He}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, o), u = yield* $(e, t, r.table, s), d = (e) => b.logWarning(`migration resume: ${e}`).pipe(b.annotateLogs({ scope: "voltro:migrate" }));
2492
2537
  return !l && !u ? "clean" : c && l && !u ? (yield* X(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${r.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* X(e, `ALTER TABLE ${a(r.table)} RENAME COLUMN ${a(o)} TO ${a(r.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : c && !l && u ? (yield* X(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${r.table}.${s}'`), "applied") : yield* b.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${r.table}.${r.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${o}=${l}, ${s}=${u}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
2493
- }), ii = (e, t, n, r = "fresh") => b.gen(function* () {
2494
- let i = process.hrtime.bigint(), a = Xr(n.declared), o = t.op;
2538
+ }), hi = (e, t, n, r = "fresh") => b.gen(function* () {
2539
+ let i = process.hrtime.bigint(), a = si(n.declared), o = t.op;
2495
2540
  switch (o.kind) {
2496
2541
  case "create-table": {
2497
2542
  let t = yield* e.onDialectOrElse({
2498
- mysql: () => b.succeed(or(o)),
2499
- mssql: () => b.succeed(gr(o)),
2500
- sqlite: () => b.succeed(dr(o)),
2501
- orElse: () => b.succeed(nr(o))
2543
+ mysql: () => b.succeed(_r(o)),
2544
+ mssql: () => b.succeed(Dr(o)),
2545
+ sqlite: () => b.succeed(Sr(o)),
2546
+ orElse: () => b.succeed(pr(o))
2502
2547
  });
2503
2548
  for (let n of t) yield* X(e, n, o.kind);
2504
2549
  break;
2505
2550
  }
2506
2551
  case "drop-table": {
2507
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? yr(o, n, e) : vr(o, e);
2552
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Ar(o, n, e) : kr(o, e);
2508
2553
  yield* e.onDialectOrElse({
2509
2554
  mysql: () => X(e, r(W), o.kind),
2510
2555
  orElse: () => X(e, r(U), o.kind)
@@ -2514,91 +2559,91 @@ var yn = (e) => {
2514
2559
  case "drop-column": {
2515
2560
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2516
2561
  yield* e.onDialectOrElse({
2517
- mysql: () => X(e, t ? Kn(o, n, W) : Wn(o), o.kind),
2518
- orElse: () => X(e, t ? Kn(o, n, U) : Un(o, U), o.kind)
2562
+ mysql: () => X(e, t ? rr(o, n, W) : tr(o), o.kind),
2563
+ orElse: () => X(e, t ? rr(o, n, U) : er(o, U), o.kind)
2519
2564
  });
2520
2565
  break;
2521
2566
  }
2522
2567
  case "rename-column":
2523
2568
  yield* e.onDialectOrElse({
2524
- mysql: () => X(e, Gn(o, W), o.kind),
2569
+ mysql: () => X(e, nr(o, W), o.kind),
2525
2570
  mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
2526
- orElse: () => X(e, Gn(o, U), o.kind)
2571
+ orElse: () => X(e, nr(o, U), o.kind)
2527
2572
  });
2528
2573
  break;
2529
2574
  case "add-index":
2530
2575
  yield* e.onDialectOrElse({
2531
- mysql: () => X(e, wr(o, n.declared), o.kind),
2532
- mssql: () => Z(e, [...Pr(o.table, o.index.columns, n.declared), Nr(o)], o.kind),
2533
- orElse: () => X(e, Cr(o, t.classification === "online-required"), o.kind)
2576
+ mysql: () => X(e, Fr(o, n.declared), o.kind),
2577
+ mssql: () => Z(e, [...Gr(o.table, o.index.columns, n.declared), Wr(o)], o.kind),
2578
+ orElse: () => X(e, Pr(o, t.classification === "online-required"), o.kind)
2534
2579
  });
2535
2580
  break;
2536
2581
  case "drop-index":
2537
2582
  yield* e.onDialectOrElse({
2538
- mysql: () => X(e, Er(o), o.kind),
2539
- mssql: () => X(e, Dr(o), o.kind),
2540
- orElse: () => X(e, Tr(o), o.kind)
2583
+ mysql: () => X(e, Lr(o), o.kind),
2584
+ mssql: () => X(e, Rr(o), o.kind),
2585
+ orElse: () => X(e, Ir(o), o.kind)
2541
2586
  });
2542
2587
  break;
2543
2588
  case "rename-table":
2544
2589
  yield* e.onDialectOrElse({
2545
- mysql: () => X(e, Or(o, W), o.kind),
2546
- mssql: () => X(e, kr(o), o.kind),
2547
- orElse: () => X(e, Or(o, U), o.kind)
2590
+ mysql: () => X(e, zr(o, W), o.kind),
2591
+ mssql: () => X(e, Br(o), o.kind),
2592
+ orElse: () => X(e, zr(o, U), o.kind)
2548
2593
  });
2549
2594
  break;
2550
2595
  case "rename-index":
2551
2596
  yield* e.onDialectOrElse({
2552
- mysql: () => X(e, jr(o), o.kind),
2553
- mssql: () => X(e, Mr(o), o.kind),
2554
- orElse: () => X(e, Ar(o), o.kind)
2597
+ mysql: () => X(e, Hr(o), o.kind),
2598
+ mssql: () => X(e, Ur(o), o.kind),
2599
+ orElse: () => X(e, Vr(o), o.kind)
2555
2600
  });
2556
2601
  break;
2557
2602
  case "add-unique":
2558
2603
  yield* e.onDialectOrElse({
2559
- mysql: () => X(e, Ir(o, n.declared), o.kind),
2604
+ mysql: () => X(e, qr(o, n.declared), o.kind),
2560
2605
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2561
- mssql: () => Z(e, [...Pr(o.table, [o.column], n.declared), Fr(o)], o.kind),
2562
- orElse: () => X(e, Fr(o), o.kind)
2606
+ mssql: () => Z(e, [...Gr(o.table, [o.column], n.declared), Kr(o)], o.kind),
2607
+ orElse: () => X(e, Kr(o), o.kind)
2563
2608
  });
2564
2609
  break;
2565
2610
  case "drop-unique":
2566
2611
  yield* e.onDialectOrElse({
2567
- mysql: () => X(e, Hr(o), o.kind),
2612
+ mysql: () => X(e, $r(o), o.kind),
2568
2613
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2569
- orElse: () => X(e, Vr(o), o.kind)
2614
+ orElse: () => X(e, Qr(o), o.kind)
2570
2615
  });
2571
2616
  break;
2572
2617
  case "add-unique-composite":
2573
2618
  yield* e.onDialectOrElse({
2574
- mysql: () => X(e, Rr(o, n.declared), o.kind),
2619
+ mysql: () => X(e, Yr(o, n.declared), o.kind),
2575
2620
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2576
- mssql: () => Z(e, [...Pr(o.table, o.fields, n.declared), Lr(o)], o.kind),
2577
- orElse: () => X(e, Lr(o), o.kind)
2621
+ mssql: () => Z(e, [...Gr(o.table, o.fields, n.declared), Jr(o)], o.kind),
2622
+ orElse: () => X(e, Jr(o), o.kind)
2578
2623
  });
2579
2624
  break;
2580
2625
  case "drop-unique-composite":
2581
2626
  yield* e.onDialectOrElse({
2582
- mysql: () => X(e, Br(o), o.kind),
2627
+ mysql: () => X(e, Zr(o), o.kind),
2583
2628
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2584
- orElse: () => X(e, zr(o), o.kind)
2629
+ orElse: () => X(e, Xr(o), o.kind)
2585
2630
  });
2586
2631
  break;
2587
2632
  case "add-foreign-key":
2588
2633
  yield* e.onDialectOrElse({
2589
- mysql: () => Z(e, Ur(o, W), o.kind),
2634
+ mysql: () => Z(e, ei(o, W), o.kind),
2590
2635
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2591
- orElse: () => Z(e, Ur(o, U), o.kind)
2636
+ orElse: () => Z(e, ei(o, U), o.kind)
2592
2637
  });
2593
2638
  break;
2594
2639
  case "add-column": {
2595
- let n = Yr(o, t, a, yield* e.onDialectOrElse({
2640
+ let n = oi(o, t, a, yield* e.onDialectOrElse({
2596
2641
  mysql: () => b.succeed("mariadb"),
2597
2642
  mssql: () => b.succeed("mssql"),
2598
2643
  sqlite: () => b.succeed("sqlite"),
2599
2644
  orElse: () => b.succeed("postgres")
2600
2645
  }));
2601
- if (!(r === "resume" && (yield* $(e, an(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
2646
+ if (!(r === "resume" && (yield* $(e, Me(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
2602
2647
  if (n.backfillKind === "sql" && n.backfillSql) if (!(t.classification === "online-required" || n.batchSize !== void 0)) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
2603
2648
  else {
2604
2649
  let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
@@ -2638,37 +2683,37 @@ var yn = (e) => {
2638
2683
  yield* e.onDialectOrElse({
2639
2684
  mysql: () => {
2640
2685
  let t = G(n.declared, o.table, o.column);
2641
- return t ? X(e, `ALTER TABLE ${W(o.table)} MODIFY COLUMN ${Xn(t, o.column, o.toNullable)};`, o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2686
+ return t ? X(e, `ALTER TABLE ${W(o.table)} MODIFY COLUMN ${sr(t, o.column, o.toNullable)};`, o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2642
2687
  },
2643
2688
  mssql: () => {
2644
2689
  let t = G(n.declared, o.table, o.column);
2645
- return t ? X(e, fr(t, o.column, o.table, o.toNullable), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
2690
+ return t ? X(e, Cr(t, o.column, o.table, o.toNullable), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
2646
2691
  },
2647
2692
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2648
2693
  orElse: () => X(e, `ALTER TABLE ${U(o.table)} ALTER COLUMN ${U(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2649
2694
  });
2650
2695
  break;
2651
2696
  case "alter-column-default": {
2652
- let t = Yn(n.declared, o.table, o.column);
2697
+ let t = or(n.declared, o.table, o.column);
2653
2698
  yield* e.onDialectOrElse({
2654
- mysql: () => X(e, qn(o, W, (e) => Zn(e, t)), o.kind),
2655
- mssql: () => X(e, pr(o), o.kind),
2699
+ mysql: () => X(e, ir(o, W, (e) => cr(e, t)), o.kind),
2700
+ mssql: () => X(e, wr(o), o.kind),
2656
2701
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2657
- orElse: () => X(e, qn(o, U, (e) => $n(e, t)), o.kind)
2702
+ orElse: () => X(e, ir(o, U, (e) => ur(e, t)), o.kind)
2658
2703
  });
2659
2704
  break;
2660
2705
  }
2661
2706
  case "alter-column-type": {
2662
- let r = Bn(Yn(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
2707
+ let r = Zn(or(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
2663
2708
  if (t.classification !== "online-required") {
2664
2709
  yield* e.onDialectOrElse({
2665
2710
  mysql: () => {
2666
2711
  let t = G(n.declared, o.table, o.column);
2667
- return t ? X(e, `ALTER TABLE ${W(o.table)} MODIFY COLUMN ${Xn(t, o.column)};`, o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2712
+ return t ? X(e, `ALTER TABLE ${W(o.table)} MODIFY COLUMN ${sr(t, o.column)};`, o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2668
2713
  },
2669
2714
  mssql: () => {
2670
2715
  let t = G(n.declared, o.table, o.column);
2671
- return t ? X(e, fr(t, o.column, o.table), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2716
+ return t ? X(e, Cr(t, o.column, o.table), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2672
2717
  },
2673
2718
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2674
2719
  orElse: () => X(e, `ALTER TABLE ${U(o.table)} ALTER COLUMN ${U(o.column)} TYPE ${r}${i};`, o.kind)
@@ -2692,23 +2737,23 @@ var yn = (e) => {
2692
2737
  }
2693
2738
  case "drop-foreign-key":
2694
2739
  yield* e.onDialectOrElse({
2695
- mysql: () => X(e, Gr(o), o.kind),
2740
+ mysql: () => X(e, ni(o), o.kind),
2696
2741
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2697
- orElse: () => X(e, Wr(o), o.kind)
2742
+ orElse: () => X(e, ti(o), o.kind)
2698
2743
  });
2699
2744
  break;
2700
2745
  case "add-check":
2701
2746
  yield* e.onDialectOrElse({
2702
- mysql: () => X(e, Kr(o, W), o.kind),
2747
+ mysql: () => X(e, ri(o, W), o.kind),
2703
2748
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2704
- orElse: () => X(e, Kr(o, U), o.kind)
2749
+ orElse: () => X(e, ri(o, U), o.kind)
2705
2750
  });
2706
2751
  break;
2707
2752
  case "drop-check":
2708
2753
  yield* e.onDialectOrElse({
2709
- mysql: () => X(e, Jr(o), o.kind),
2754
+ mysql: () => X(e, ai(o), o.kind),
2710
2755
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2711
- orElse: () => X(e, qr(o), o.kind)
2756
+ orElse: () => X(e, ii(o), o.kind)
2712
2757
  });
2713
2758
  break;
2714
2759
  }
@@ -2717,32 +2762,32 @@ var yn = (e) => {
2717
2762
  status: "applied",
2718
2763
  durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
2719
2764
  };
2720
- }), ai = (e, t, n, r) => b.gen(function* () {
2765
+ }), gi = (e, t, n, r) => b.gen(function* () {
2721
2766
  let i = [...new Set(r.map((e) => e.runId))];
2722
- if (i.length > 1) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${i.length} unfinished runs (${i.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${L}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
2767
+ if (i.length > 1) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${i.length} unfinished runs (${i.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${D}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
2723
2768
  let a = i[0], o = [...r].map((e) => ({
2724
2769
  index: Number(e.opIndex),
2725
2770
  status: e.status,
2726
2771
  planned: JSON.parse(e.payload)
2727
2772
  })).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
2728
- if (c > 1) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${c} operations as in-flight for run ${a}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${L}\` by hand before re-running.`));
2729
- if (yield* b.logWarning(`migration resume: found an interrupted run (${a}) — ${o.filter((e) => e.status === "applied").length} of ${o.length} operation(s) completed${s ? `, in flight: ${s.planned.op.kind} ${un(s.planned.op)}` : ""}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
2773
+ if (c > 1) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${c} operations as in-flight for run ${a}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${D}\` by hand before re-running.`));
2774
+ if (yield* b.logWarning(`migration resume: found an interrupted run (${a}) — ${o.filter((e) => e.status === "applied").length} of ${o.length} operation(s) completed${s ? `, in flight: ${s.planned.op.kind} ${Le(s.planned.op)}` : ""}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
2730
2775
  kind: "discard",
2731
2776
  runId: a,
2732
2777
  why: "no operation had started — no DDL ran"
2733
2778
  };
2734
- let l = s ? yield* ri(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2779
+ let l = s ? yield* mi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2735
2780
  if (u !== n.toFingerprint) return {
2736
2781
  kind: "discard",
2737
2782
  runId: a,
2738
2783
  why: `the declared schema changed since the interruption (recorded target ${u.slice(0, 12)}…, current ${n.toFingerprint.slice(0, 12)}…) — applying the freshly-diffed plan instead`
2739
2784
  };
2740
- let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : fn(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
2785
+ let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : ze(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
2741
2786
  return f.length === 0 ? {
2742
2787
  kind: "discard",
2743
2788
  runId: a,
2744
2789
  why: "every recorded operation had already taken effect"
2745
- } : (yield* ti(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* b.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), {
2790
+ } : (yield* fi(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* b.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), {
2746
2791
  kind: "resume",
2747
2792
  runId: a,
2748
2793
  ops: f.map((e) => ({
@@ -2750,32 +2795,32 @@ var yn = (e) => {
2750
2795
  planned: e.planned
2751
2796
  }))
2752
2797
  });
2753
- }), oi = (e, t, n) => b.gen(function* () {
2798
+ }), _i = (e, t, n) => b.gen(function* () {
2754
2799
  let r = t.operations.filter((e) => e.blocked);
2755
2800
  if (r.length > 0) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
2756
- yield* T(e);
2757
- let i = Date.now(), a = [], o = an(e), s = sn(o) === "plan-transactional", l = s ? t.operations.filter((e) => e.classification !== "online-required") : [], u = s ? t.operations.filter((e) => e.classification === "online-required") : t.operations, d = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, f = u.map((e, t) => ({
2801
+ yield* T(e, { schema: n.lockSchema });
2802
+ let i = Date.now(), a = [], o = Me(e), s = Pe(o) === "plan-transactional", l = s ? t.operations.filter((e) => e.classification !== "online-required") : [], u = s ? t.operations.filter((e) => e.classification === "online-required") : t.operations, d = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, f = u.map((e, t) => ({
2758
2803
  index: t,
2759
2804
  planned: e
2760
2805
  })), p = "fresh";
2761
2806
  try {
2762
- yield* Zr(e, o);
2763
- let r = yield* Qr(e);
2807
+ yield* ci(e, o);
2808
+ let r = yield* li(e);
2764
2809
  if (r.length > 0) {
2765
- let n = yield* ai(e, o, t, r);
2766
- n.kind === "resume" ? (d = n.runId, f = n.ops, p = "resume") : (yield* b.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield* ni(e, n.runId));
2810
+ let n = yield* gi(e, o, t, r);
2811
+ n.kind === "resume" ? (d = n.runId, f = n.ops, p = "resume") : (yield* b.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield* pi(e, n.runId));
2767
2812
  }
2768
- p === "fresh" && f.length > 0 && (yield* $r(e, d, t.toFingerprint, f)), l.length > 0 && (yield* e.withTransaction(b.gen(function* () {
2769
- let e = yield* S.SqlClient;
2770
- for (let t of l) a.push(yield* ii(e, t, n));
2813
+ p === "fresh" && f.length > 0 && (yield* ui(e, d, t.toFingerprint, f)), l.length > 0 && (yield* e.withTransaction(b.gen(function* () {
2814
+ let e = yield* C.SqlClient;
2815
+ for (let t of l) a.push(yield* hi(e, t, n));
2771
2816
  })));
2772
2817
  for (let { index: t, planned: r } of f) {
2773
- yield* ei(e, d, t, "started");
2774
- let i = yield* ii(e, r, n, p);
2775
- a.push(i), yield* ei(e, d, t, "applied", i.durationMs);
2818
+ yield* di(e, d, t, "started");
2819
+ let i = yield* hi(e, r, n, p);
2820
+ a.push(i), yield* di(e, d, t, "applied", i.durationMs);
2776
2821
  }
2777
2822
  } finally {
2778
- yield* E(e).pipe(b.orDie);
2823
+ yield* E(e, { schema: n.lockSchema }).pipe(b.orDie);
2779
2824
  }
2780
2825
  let m = yield* n.replan(e);
2781
2826
  if (m.operations.length > 0) {
@@ -2792,9 +2837,9 @@ var yn = (e) => {
2792
2837
  (${_}, ${t.toFingerprint}, ${m.fromFingerprint}, ${JSON.stringify(x)},
2793
2838
  ${n.appliedBy}, ${n.environment}, ${n.source},
2794
2839
  ${g}, ${y}, ${n.notes ?? null})
2795
- `, yield* ni(e, d);
2796
- let C = [...new Set(x.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
2797
- return yield* b.promise(() => c({ changedTables: C }).catch(() => {})), {
2840
+ `, yield* pi(e, d);
2841
+ let S = [...new Set(x.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
2842
+ return yield* b.promise(() => c({ changedTables: S }).catch(() => {})), {
2798
2843
  id: _,
2799
2844
  appliedAt: v,
2800
2845
  fingerprint: t.toFingerprint,
@@ -2806,13 +2851,13 @@ var yn = (e) => {
2806
2851
  source: n.source,
2807
2852
  ...n.notes ? { notes: n.notes } : {}
2808
2853
  };
2809
- }), si = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), ci = (e) => e`
2854
+ }), vi = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), yi = (e) => e`
2810
2855
  SELECT fingerprint
2811
2856
  FROM _voltro_migration_plans
2812
2857
  ORDER BY ${e("appliedAt")} DESC
2813
2858
  LIMIT 1
2814
- `.pipe(b.map((e) => e.length > 0 ? e[0].fingerprint : void 0), b.catchAll(() => b.succeed(void 0))), li = (e, t, n) => b.gen(function* () {
2815
- if ((yield* ci(e)) === t.toFingerprint) return "already-current";
2859
+ `.pipe(b.map((e) => e.length > 0 ? e[0].fingerprint : void 0), b.catchAll(() => b.succeed(void 0))), bi = (e, t, n) => b.gen(function* () {
2860
+ if ((yield* yi(e)) === t.toFingerprint) return "already-current";
2816
2861
  let r = `plan_${Date.now().toString(36)}`, i = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2817
2862
  return yield* e`
2818
2863
  INSERT INTO ${e("_voltro_migration_plans")}
@@ -2824,8 +2869,8 @@ var yn = (e) => {
2824
2869
  ${n.appliedBy}, ${n.environment}, ${n.source},
2825
2870
  ${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
2826
2871
  `, "recorded";
2827
- }).pipe(b.catchAll(() => b.succeed("already-current"))), ui = (e, t) => b.gen(function* () {
2828
- let n = M(P(t, an(e))), r = yield* ci(e);
2872
+ }).pipe(b.catchAll(() => b.succeed("already-current"))), xi = (e, t) => b.gen(function* () {
2873
+ let n = N(F(t, Me(e))), r = yield* yi(e);
2829
2874
  return r === n ? {
2830
2875
  kind: "up-to-date",
2831
2876
  fingerprint: n
@@ -2834,23 +2879,23 @@ var yn = (e) => {
2834
2879
  expected: n,
2835
2880
  ...r === void 0 ? {} : { actual: r }
2836
2881
  };
2837
- }), di = [
2882
+ }), Si = [
2838
2883
  "pgeagertest_",
2839
2884
  "mig_e2e_",
2840
2885
  "mig_test_",
2841
2886
  "mysqleagertest_",
2842
2887
  "mssqleagertest_",
2843
2888
  "sqliteeagertest_"
2844
- ], fi = (e) => di.some((t) => e.startsWith(t)), pi = (e, t) => b.gen(function* () {
2889
+ ], Ci = (e) => Si.some((t) => e.startsWith(t)), wi = (e, t) => b.gen(function* () {
2845
2890
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2846
- let n = t.filter((e) => fi(e.name)).map((e) => e.name);
2891
+ let n = t.filter((e) => Ci(e.name)).map((e) => e.name);
2847
2892
  if (n.length === 0) return [];
2848
2893
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(b.catchAll(() => b.void));
2849
2894
  return n;
2850
- }), mi = () => {
2895
+ }), Ti = () => {
2851
2896
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2852
2897
  return e.length > 0 ? { ignoreTables: e } : {};
2853
- }, hi = (e) => {
2898
+ }, Ei = (e) => {
2854
2899
  if (e === void 0) return;
2855
2900
  let t = e.trim();
2856
2901
  if (t === "") return;
@@ -2860,48 +2905,48 @@ var yn = (e) => {
2860
2905
  kind: "tables",
2861
2906
  tables: new Set(n)
2862
2907
  } : void 0;
2863
- }, gi = (e) => typeof e.table == "string" ? e.table : void 0, _i = (e, t = { kind: "all" }) => ({
2908
+ }, Di = (e) => typeof e.table == "string" ? e.table : void 0, Oi = (e, t = { kind: "all" }) => ({
2864
2909
  ...e,
2865
2910
  operations: e.operations.map((e) => {
2866
2911
  if (!e.blocked || e.classification !== "lossy") return e;
2867
2912
  if (t?.kind === "tables") {
2868
- let n = gi(e.op);
2913
+ let n = Di(e.op);
2869
2914
  if (n === void 0 || !t.tables.has(n)) return e;
2870
2915
  }
2871
2916
  let { blocked: n, ...r } = e;
2872
2917
  return r;
2873
2918
  })
2874
- }), vi = (e, t, n) => t === "postgres" ? St(e, n).pipe(b.flatMap((e) => {
2875
- let t = Ct(e);
2919
+ }), ki = (e, t, n) => t === "postgres" ? qt(e, n).pipe(b.flatMap((e) => {
2920
+ let t = Jt(e);
2876
2921
  return t === void 0 ? b.void : b.logWarning(`auto-migrate: ${t}`).pipe(b.annotateLogs({ scope: "voltro:migrate" }));
2877
- }), b.catchAll(() => b.void)) : b.void, yi = (e, t, n) => b.gen(function* () {
2878
- let r = an(e), i = t;
2922
+ }), b.catchAll(() => b.void)) : b.void, Ai = (e, t, n) => b.gen(function* () {
2923
+ let r = Me(e), i = t;
2879
2924
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2880
- let t = M(P(i, r));
2881
- if ((yield* ci(e)) === t) return yield* vi(e, r, i), {
2925
+ let t = N(F(i, r));
2926
+ if ((yield* yi(e)) === t) return yield* ki(e, r, i), {
2882
2927
  kind: "up-to-date",
2883
2928
  fingerprint: t
2884
2929
  };
2885
2930
  }
2886
- let a = yield* Ln(e), o = yield* pi(e, a.tables);
2931
+ let a = yield* Jn(e), o = yield* wi(e, a.tables);
2887
2932
  o.length > 0 && (yield* b.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(b.annotateLogs({
2888
2933
  scope: "voltro:migrate",
2889
2934
  count: o.length
2890
- })), a = yield* Ln(e));
2891
- let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !m(e.name) || s.has(e.name)), l = rn({
2935
+ })), a = yield* Jn(e));
2936
+ let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !m(e.name) || s.has(e.name)), l = kn({
2892
2937
  declared: i,
2893
2938
  live: { tables: c(a.tables) },
2894
2939
  dialect: r,
2895
- ...mi()
2940
+ ...Ti()
2896
2941
  });
2897
2942
  if (l.summary.blocked > 0) {
2898
- let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = hi(process.env.VOLTRO_DESTRUCTIVE_OK);
2899
- if (t === void 0 || !e || (l = _i(l, t), l.operations.some((e) => e.blocked))) return {
2943
+ let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Ei(process.env.VOLTRO_DESTRUCTIVE_OK);
2944
+ if (t === void 0 || !e || (l = Oi(l, t), l.operations.some((e) => e.blocked))) return {
2900
2945
  kind: "refused-blocked",
2901
2946
  plan: l
2902
2947
  };
2903
2948
  }
2904
- return l.operations.length === 0 ? (yield* li(e, l, {
2949
+ return l.operations.length === 0 ? (yield* bi(e, l, {
2905
2950
  appliedBy: n.appliedBy,
2906
2951
  environment: n.environment === "prod" ? "dev" : n.environment,
2907
2952
  source: "auto-diff"
@@ -2910,37 +2955,37 @@ var yn = (e) => {
2910
2955
  fingerprint: l.toFingerprint
2911
2956
  }) : {
2912
2957
  kind: "applied",
2913
- applied: yield* oi(e, l, {
2958
+ applied: yield* _i(e, l, {
2914
2959
  declared: t,
2915
2960
  appliedBy: n.appliedBy,
2916
2961
  environment: n.environment === "prod" ? "dev" : n.environment,
2917
2962
  source: "auto-diff",
2918
2963
  replan: (e) => b.gen(function* () {
2919
- let t = yield* Ln(e);
2920
- return rn({
2964
+ let t = yield* Jn(e);
2965
+ return kn({
2921
2966
  declared: i,
2922
2967
  live: { tables: c(t.tables) },
2923
2968
  dialect: r,
2924
- ...mi()
2969
+ ...Ti()
2925
2970
  });
2926
2971
  })
2927
2972
  }),
2928
2973
  plan: l
2929
2974
  };
2930
- }), bi = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? b.succeed({
2975
+ }), ji = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? b.succeed({
2931
2976
  kind: "skipped",
2932
2977
  reason: "VOLTRO_AUTO_MIGRATE=0"
2933
- }) : n.environment === "prod" ? ui(e, t) : yi(e, t, n), xi = (e, t) => {
2978
+ }) : n.environment === "prod" ? xi(e, t) : Ai(e, t, n), Mi = (e, t) => {
2934
2979
  switch (e.kind) {
2935
2980
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
2936
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${N(e.fingerprint)})`;
2981
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
2937
2982
  case "applied": {
2938
2983
  let t = e.plan.summary;
2939
- return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${N(e.applied.fingerprint)}`;
2984
+ return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${P(e.applied.fingerprint)}`;
2940
2985
  }
2941
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${N(e.expected)}` + (e.actual ? ` live=${N(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2986
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${P(e.expected)}` + (e.actual ? ` live=${P(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2942
2987
  case "refused-blocked": {
2943
- let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + si(e.plan), c = [""];
2988
+ let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + vi(e.plan), c = [""];
2944
2989
  if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", ` → Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing — the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
2945
2990
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2946
2991
  for (let r of e.plan.operations) {
@@ -2957,7 +3002,7 @@ var yn = (e) => {
2957
3002
  return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
2958
3003
  }
2959
3004
  }
2960
- }, Si = /* @__PURE__ */ new Set([
3005
+ }, Ni = /* @__PURE__ */ new Set([
2961
3006
  "node_modules",
2962
3007
  "dist",
2963
3008
  "build",
@@ -2966,12 +3011,12 @@ var yn = (e) => {
2966
3011
  ".next",
2967
3012
  ".git",
2968
3013
  ".framework"
2969
- ]), Ci = async (e) => {
3014
+ ]), Pi = async (e) => {
2970
3015
  let t = [], n = async (e) => {
2971
- let r = await ee.readdir(e, { withFileTypes: !0 }).catch(() => []);
3016
+ let r = await te.readdir(e, { withFileTypes: !0 }).catch(() => []);
2972
3017
  for (let i of r) {
2973
- if (Si.has(i.name)) continue;
2974
- let r = te(e, i.name);
3018
+ if (Ni.has(i.name)) continue;
3019
+ let r = ne(e, i.name);
2975
3020
  i.isDirectory() ? await n(r) : i.isFile() && u.test(i.name) && t.push(r);
2976
3021
  }
2977
3022
  };
@@ -2979,10 +3024,10 @@ var yn = (e) => {
2979
3024
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
2980
3025
  return n.localeCompare(r);
2981
3026
  });
2982
- }, wi = async (e) => {
3027
+ }, Fi = async (e) => {
2983
3028
  let t = [];
2984
3029
  for (let n of e) {
2985
- let e = (await import(ne(n).href)).default;
3030
+ let e = (await import(re(n).href)).default;
2986
3031
  if (!o(e)) {
2987
3032
  process.stderr.write(`[voltro:migrate] ${n} has no default-exported \`migration(...)\` — skipped\n`);
2988
3033
  continue;
@@ -2993,11 +3038,11 @@ var yn = (e) => {
2993
3038
  });
2994
3039
  }
2995
3040
  return t;
2996
- }, Ti = (e) => e`
3041
+ }, Ii = (e) => e`
2997
3042
  SELECT ${e("id")}
2998
3043
  FROM ${e("_voltro_migration_plans")}
2999
3044
  WHERE ${e("source")} = 'file'
3000
- `.pipe(b.map((e) => e.map((e) => e.id)), b.catchAll(() => b.succeed([]))), Ei = class extends Error {
3045
+ `.pipe(b.map((e) => e.map((e) => e.id)), b.catchAll(() => b.succeed([]))), Li = class extends Error {
3001
3046
  migrationId;
3002
3047
  file;
3003
3048
  cause;
@@ -3005,7 +3050,7 @@ var yn = (e) => {
3005
3050
  constructor(e, t, n) {
3006
3051
  super(`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";
3007
3052
  }
3008
- }, Di = (e, t, n, r) => b.gen(function* () {
3053
+ }, Ri = (e, t, n, r) => b.gen(function* () {
3009
3054
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
3010
3055
  sql: e,
3011
3056
  log: {
@@ -3039,10 +3084,10 @@ var yn = (e) => {
3039
3084
  }])},
3040
3085
  ${r}, ${n}, ${"file"},
3041
3086
  ${c}, ${l}, ${t.migration.description})
3042
- `.pipe(b.mapError((e) => new Ei(t.migration.id, t.file, e))), { durationMs: c };
3043
- }), Oi = (e, t) => b.gen(function* () {
3087
+ `.pipe(b.mapError((e) => new Li(t.migration.id, t.file, e))), { durationMs: c };
3088
+ }), zi = (e, t) => b.gen(function* () {
3044
3089
  let n = yield* b.tryPromise({
3045
- try: () => Ci(te(t, "migrations")),
3090
+ try: () => Pi(ne(t, "migrations")),
3046
3091
  catch: (e) => e
3047
3092
  });
3048
3093
  if (n.length === 0) return {
@@ -3050,25 +3095,25 @@ var yn = (e) => {
3050
3095
  skipped: []
3051
3096
  };
3052
3097
  let r = yield* b.tryPromise({
3053
- try: () => wi(n),
3098
+ try: () => Fi(n),
3054
3099
  catch: (e) => e
3055
3100
  });
3056
3101
  if (r.length === 0) return {
3057
3102
  pending: [],
3058
3103
  skipped: []
3059
3104
  };
3060
- let i = new Set(yield* Ti(e));
3105
+ let i = new Set(yield* Ii(e));
3061
3106
  return {
3062
3107
  pending: r.filter((e) => !i.has(e.migration.id)),
3063
3108
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
3064
3109
  };
3065
- }), ki = (e, t) => Oi(e, t).pipe(b.map((e) => e.pending.map((e) => e.migration.id))), Ai = (e, t) => b.gen(function* () {
3066
- let { pending: n, skipped: r } = yield* Oi(e, t.projectRoot);
3110
+ }), Bi = (e, t) => zi(e, t).pipe(b.map((e) => e.pending.map((e) => e.migration.id))), Vi = (e, t) => b.gen(function* () {
3111
+ let { pending: n, skipped: r } = yield* zi(e, t.projectRoot);
3067
3112
  if (n.length === 0) return {
3068
3113
  applied: [],
3069
3114
  skipped: r
3070
3115
  };
3071
- yield* T(e);
3116
+ yield* T(e, { schema: t.lockSchema });
3072
3117
  let i = [];
3073
3118
  try {
3074
3119
  for (let r of n) {
@@ -3077,7 +3122,7 @@ var yn = (e) => {
3077
3122
  id: r.migration.id,
3078
3123
  file: r.file
3079
3124
  }));
3080
- let { durationMs: n } = yield* Di(e, r, t.env, t.appliedBy);
3125
+ let { durationMs: n } = yield* Ri(e, r, t.env, t.appliedBy);
3081
3126
  i.push({
3082
3127
  id: r.migration.id,
3083
3128
  durationMs: n
@@ -3088,28 +3133,28 @@ var yn = (e) => {
3088
3133
  }));
3089
3134
  }
3090
3135
  } finally {
3091
- yield* E(e).pipe(b.orDie);
3136
+ yield* E(e, { schema: t.lockSchema }).pipe(b.orDie);
3092
3137
  }
3093
3138
  return {
3094
3139
  applied: i,
3095
3140
  skipped: r
3096
3141
  };
3097
- }), ji = (e, t) => e`
3142
+ }), Hi = (e, t) => e`
3098
3143
  SELECT ${e("id")}
3099
3144
  FROM ${e("_voltro_migration_plans")}
3100
3145
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
3101
3146
  LIMIT 1
3102
- `, Mi = (e, t) => b.gen(function* () {
3103
- if (!(yield* ji(e, t.id))[0]) return yield* b.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3147
+ `, Ui = (e, t) => b.gen(function* () {
3148
+ if (!(yield* Hi(e, t.id))[0]) return yield* b.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3104
3149
  let n = yield* b.tryPromise({
3105
- try: () => Ci(te(t.projectRoot, "migrations")),
3150
+ try: () => Pi(ne(t.projectRoot, "migrations")),
3106
3151
  catch: (e) => e
3107
3152
  }), r = (yield* b.tryPromise({
3108
- try: () => wi(n),
3153
+ try: () => Fi(n),
3109
3154
  catch: (e) => e
3110
3155
  })).find((e) => e.migration.id === t.id);
3111
3156
  if (!r) return yield* b.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3112
- yield* T(e);
3157
+ yield* T(e, { schema: t.lockSchema });
3113
3158
  let i = Date.now();
3114
3159
  try {
3115
3160
  let n = {
@@ -3136,10 +3181,10 @@ var yn = (e) => {
3136
3181
  durationMs: o
3137
3182
  };
3138
3183
  } finally {
3139
- yield* E(e).pipe(b.orDie);
3184
+ yield* E(e, { schema: t.lockSchema }).pipe(b.orDie);
3140
3185
  }
3141
- }), Ni = (e) => b.gen(function* () {
3142
- let t = yield* S.SqlClient, n = yield* t`
3186
+ }), Wi = (e) => b.gen(function* () {
3187
+ let t = yield* C.SqlClient, n = yield* t`
3143
3188
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
3144
3189
  WHERE source = 'auto-diff'
3145
3190
  AND squashedAt IS NULL
@@ -3183,7 +3228,7 @@ var yn = (e) => {
3183
3228
  snapshotFingerprint: e.fingerprint,
3184
3229
  snapshotId: i
3185
3230
  };
3186
- }), Pi = { safe: !0 }, Fi = (e) => {
3231
+ }), Gi = { safe: !0 }, Ki = (e) => {
3187
3232
  switch (e.kind) {
3188
3233
  case "drop-column": return {
3189
3234
  safe: !1,
@@ -3210,7 +3255,7 @@ var yn = (e) => {
3210
3255
  reason: `old instances read/write "${e.table}"."${e.column}" as ${e.from}; the new ${e.to} type can reject their writes or fail to decode their reads`,
3211
3256
  remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
3212
3257
  };
3213
- case "alter-column-nullability": return e.toNullable ? Pi : {
3258
+ case "alter-column-nullability": return e.toNullable ? Gi : {
3214
3259
  safe: !1,
3215
3260
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
3216
3261
  remedy: `make code always write "${e.column}" and deploy that first; add NOT NULL in a LATER deploy (with a default to cover the gap)`
@@ -3240,12 +3285,12 @@ var yn = (e) => {
3240
3285
  case "drop-unique":
3241
3286
  case "drop-unique-composite":
3242
3287
  case "drop-foreign-key":
3243
- case "drop-check": return Pi;
3288
+ case "drop-check": return Gi;
3244
3289
  }
3245
- }, Ii = (e) => {
3290
+ }, qi = (e) => {
3246
3291
  let t = [];
3247
3292
  for (let n of e) {
3248
- let e = Fi(n.op);
3293
+ let e = Ki(n.op);
3249
3294
  e.safe || t.push({
3250
3295
  op: n,
3251
3296
  reason: e.reason,
@@ -3253,7 +3298,7 @@ var yn = (e) => {
3253
3298
  });
3254
3299
  }
3255
3300
  return t;
3256
- }, Li = (e) => {
3301
+ }, Ji = (e) => {
3257
3302
  if (!e.enabled || e.unsafeCount === 0) return {
3258
3303
  refuse: !1,
3259
3304
  warnForced: !1,
@@ -3269,18 +3314,18 @@ var yn = (e) => {
3269
3314
  warnForced: !1,
3270
3315
  message: `${t}. Old instances would break against the new schema mid-rollout. Split into expand → deploy → contract (see the ⚠ list above), deploy with no overlap (maintenance window / scale-to-zero), or pass --force to override.`
3271
3316
  };
3272
- }, Ri = (e) => {
3317
+ }, Yi = (e) => {
3273
3318
  let t = e.table;
3274
3319
  if (typeof t == "string") return t;
3275
3320
  let n = e.from;
3276
3321
  return typeof n == "string" ? n : void 0;
3277
- }, zi = (e) => ({
3322
+ }, Xi = (e) => ({
3278
3323
  kind: e.op.kind,
3279
- table: Ri(e.op),
3324
+ table: Yi(e.op),
3280
3325
  classification: e.classification,
3281
3326
  reason: e.reason,
3282
3327
  blockedFix: e.blocked?.fix
3283
- }), Bi = (e) => e.operations.map(zi), Vi = async (e) => {
3328
+ }), Zi = (e) => e.operations.map(Xi), Qi = async (e) => {
3284
3329
  let t = e.log ?? (() => {}), n = {
3285
3330
  branchId: e.branchId,
3286
3331
  mechanism: e.mechanism,
@@ -3299,10 +3344,10 @@ var yn = (e) => {
3299
3344
  applied: !1,
3300
3345
  converged: !1,
3301
3346
  residual: r,
3302
- infidelity: Bi(o)
3347
+ infidelity: Zi(o)
3303
3348
  };
3304
3349
  else {
3305
- let i = await e.plan(), o = Bi(i), s = o.filter((e) => e.classification === "lossy"), c = _i(i), l = c.operations.filter((e) => e.blocked !== void 0).map(zi);
3350
+ let i = await e.plan(), o = Zi(i), s = o.filter((e) => e.classification === "lossy"), c = Oi(i), l = c.operations.filter((e) => e.blocked !== void 0).map(Xi);
3306
3351
  if (l.length > 0) a = {
3307
3352
  ...n,
3308
3353
  outcome: "blocked",
@@ -3327,7 +3372,7 @@ var yn = (e) => {
3327
3372
  };
3328
3373
  else {
3329
3374
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
3330
- let i = Bi(await e.replan());
3375
+ let i = Zi(await e.replan());
3331
3376
  a = {
3332
3377
  ...n,
3333
3378
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -3365,7 +3410,7 @@ var yn = (e) => {
3365
3410
  ...a,
3366
3411
  tornDown: o
3367
3412
  };
3368
- }, Hi = (e) => {
3413
+ }, $i = (e) => {
3369
3414
  switch (e.outcome) {
3370
3415
  case "clean": return 0;
3371
3416
  case "lossy": return 2;
@@ -3374,22 +3419,22 @@ var yn = (e) => {
3374
3419
  case "infidelity": return 1;
3375
3420
  case "failed": return 1;
3376
3421
  }
3377
- }, Ui = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Wi = (e) => {
3422
+ }, ea = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ta = (e) => {
3378
3423
  let t = [];
3379
3424
  if (t.push(`branch rehearsal · ${e.branchId} · mechanism ${e.mechanism}`), t.push(` branched ${e.branchedTables} table(s), replayed ${e.replayedForeignKeys} foreign key(s)`), e.outcome === "failed") t.push(` FAILED: ${e.error ?? "unknown error"}`);
3380
3425
  else if (e.outcome === "infidelity") {
3381
3426
  t.push(" BRANCH IS NOT A FAITHFUL COPY of the parent — the rehearsal proves nothing about your migration."), t.push(" The parent's own schema still differs from the branch by:");
3382
- for (let n of e.infidelity) t.push(Ui(n));
3427
+ for (let n of e.infidelity) t.push(ea(n));
3383
3428
  } else {
3384
3429
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
3385
- for (let n of e.operations) t.push(Ui(n));
3386
- if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(Ui(n));
3430
+ for (let n of e.operations) t.push(ea(n));
3431
+ if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(ea(n));
3387
3432
  }
3388
3433
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
3389
- }, Gi = (e, ...t) => ({
3434
+ }, na = (e, ...t) => ({
3390
3435
  _tag: "RawSqlFragment",
3391
3436
  strings: [...e],
3392
3437
  values: [...t]
3393
- }), Ki = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3438
+ }), ra = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3394
3439
  //#endregion
3395
- export { D as DEFAULT_CDC_CHANNEL, u as FILE_MIGRATION_PATTERN, Ei as FileMigrationLedgerError, Te as REACTIVE_TRIGGER_PREFIX, ue as VOLTRO_MIGRATION_LOCK_KEY, T as acquireMigrationLock, ut as applyNamespacedSchema, oi as applyPlan, it as applySchema, Li as assessRollingDeployGate, Hi as branchRehearsalExitCode, Tn as chunkTables, Fi as classifyRollingDeploySafety, P as declaredSnapshot, je as defaultArrayClause, Ae as defaultClause, A as defaultJsonClause, xi as describeOutcome, hi as destructiveScope, St as detectReactiveTriggerDrift, wr as emitAddIndexMysql, or as emitCreateTableMysql, Un as emitDropColumnDdl, Wn as emitDropColumnDdlMysql, rt as emitFrameworkBootstrapSql, tt as emitNamespaceProvisionDdl, nt as emitNamespacedSchemaSql, et as emitSchemaSql, M as fingerprintSchema, Wi as formatBranchRehearsal, Ct as formatReactiveTriggerDrift, mi as ignoreTablesFromEnv, Ln as introspectSchema, o as isFileMigration, Ki as isRawSqlFragment, bn as mapPgType, h as migration, br as mysqlIndexPrefixFor, j as numericIdSql, yn as parseEnumCheck, ki as pendingFileMigrationIds, rn as planMigrations, dt as provisionTenantNamespace, Ge as reactiveTriggerRepairSql, li as recordUpToDate, Vi as rehearseMigrationOnBranch, zi as rehearsedOperation, E as releaseMigrationLock, ar as renderColumnMysql, er as renderColumnPg, Mi as rollbackFileBasedMigration, Ii as rollingDeployUnsafeOps, Ai as runFileBasedMigrations, ft as runFrameworkBootstrap, lt as runMigrate, bi as runPlannedMigrations, N as shortFingerprint, vt as snapshotColumn, Gi as sql, k as sqlType, Ni as squashMigrationPlans, _i as unblockLossy, we as withMigrationLock };
3440
+ export { O as DEFAULT_CDC_CHANNEL, u as FILE_MIGRATION_PATTERN, Li as FileMigrationLedgerError, Ke as REACTIVE_TRIGGER_PREFIX, de as VOLTRO_MIGRATION_LOCK_KEY, T as acquireMigrationLock, H as appliedAtValue, Ft as applyNamespacedSchema, _i as applyPlan, Tt as applySchema, Ji as assessRollingDeployGate, $i as branchRehearsalExitCode, In as chunkTables, Ki as classifyRollingDeploySafety, F as declaredSnapshot, Qe as defaultArrayClause, Ze as defaultClause, j as defaultJsonClause, Mi as describeOutcome, Ei as destructiveScope, qt as detectReactiveTriggerDrift, Fr as emitAddIndexMysql, _r as emitCreateTableMysql, er as emitDropColumnDdl, tr as emitDropColumnDdlMysql, wt as emitFrameworkBootstrapSql, St as emitNamespaceProvisionDdl, Ct as emitNamespacedSchemaSql, xt as emitSchemaSql, N as fingerprintSchema, _e as fnv1a64, ta as formatBranchRehearsal, Jt as formatReactiveTriggerDrift, Ti as ignoreTablesFromEnv, Jn as introspectSchema, o as isFileMigration, ra as isRawSqlFragment, Dt as isReRunSafeDdl, jn as mapPgType, h as migration, ve as migrationLockKeyForSchema, ye as migrationLockNameForSchema, jr as mysqlIndexPrefixFor, Je as notifyFunctionName, M as numericIdSql, An as parseEnumCheck, Bi as pendingFileMigrationIds, kn as planMigrations, It as provisionTenantNamespace, qe as reactiveTriggerName, ft as reactiveTriggerRepairSql, bi as recordUpToDate, Qi as rehearseMigrationOnBranch, Xi as rehearsedOperation, E as releaseMigrationLock, gr as renderColumnMysql, dr as renderColumnPg, pe as resolveMigrationLockSchema, Ui as rollbackFileBasedMigration, qi as rollingDeployUnsafeOps, Vi as runFileBasedMigrations, Lt as runFrameworkBootstrap, Pt as runMigrate, ji as runPlannedMigrations, P as shortFingerprint, Ut as snapshotColumn, na as sql, A as sqlType, Wi as squashMigrationPlans, Oi as unblockLossy, je as withMigrationLock };