@voltro/database 0.37.0 → 0.39.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,4 +1,4 @@
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";
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-BS6FuivX.js";
2
2
  import { Effect as b, Schedule as x } from "effect";
3
3
  import { createLogger as S } from "@voltro/logger";
4
4
  import { SqlClient as C } from "@effect/sql";
@@ -38,20 +38,21 @@ var ie = (e, t, n, r = 400) => {
38
38
  let t = o(e);
39
39
  t !== void 0 && s.push(`db.${e}: ${t}`);
40
40
  }
41
- return s.push(""), s.join("\n");
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;
41
+ let c = ae(o("code"));
42
+ return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
43
+ }, ae = (e) => e === "3F000" ? "remedy: the connection's search_path names a schema that does not exist. Voltro sets it from DB_SCHEMA — create the schema (`CREATE SCHEMA \"<name>\"`) or unset DB_SCHEMA to use the connection default. Voltro creates TABLES, never the schema itself: that is a namespace decision, and inventing one from a typo is how a migration lands somewhere nobody is looking." : void 0, oe = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, se = (e) => e.replace(/"/g, "`"), ce = (e) => typeof e == "string" ? e : e.name ?? String(e), le = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ue = (e, t) => {
44
+ if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(oe)) return e;
44
45
  let n = { ...e.fields }, r = [], i = [];
45
46
  for (let t of e.appliedIndexes) {
46
- if (!ae(t)) {
47
+ if (!oe(t)) {
47
48
  r.push(t);
48
49
  continue;
49
50
  }
50
- let a = oe(t.where), o = [];
51
+ let a = se(t.where), o = [];
51
52
  for (let r of t.fields) {
52
- let i = se(r);
53
+ let i = ce(r);
53
54
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
54
- let s = ce(t.name, i);
55
+ let s = le(t.name, i);
55
56
  o.push(s), n[s] = {
56
57
  type: "text",
57
58
  nullable: !0,
@@ -74,7 +75,7 @@ var ie = (e, t, n, r = 400) => {
74
75
  appliedIndexes: r,
75
76
  appliedUniques: [...e.appliedUniques ?? [], ...i]
76
77
  };
77
- }, w = (e, t) => `${e}::${t}`, ue = (e, t) => {
78
+ }, w = (e, t) => `${e}::${t}`, de = (e, t) => {
78
79
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
79
80
  n.add(e);
80
81
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
@@ -83,21 +84,21 @@ var ie = (e, t, n, r = 400) => {
83
84
  };
84
85
  for (let t of [...e].sort()) r.has(t) || a(t);
85
86
  return i;
86
- }, de = 6322741009312437n, fe = (e) => {
87
+ }, fe = 6322741009312437n, pe = (e) => {
87
88
  let t = e?.trim();
88
89
  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;
90
+ }, me = (e) => e?.schema === void 0 ? pe(process.env.DB_SCHEMA) : pe(e.schema), he = 14695981039346656037n, ge = 1099511628211n, _e = 18446744073709551615n, ve = (e) => {
91
+ let t = he;
92
+ for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * ge & _e;
92
93
  return t;
93
- }, ve = (e) => {
94
- let t = fe(e);
95
- return t === void 0 ? de : _e(`voltro_migration_lock:${t}`) & 9223372036854775807n;
96
94
  }, ye = (e) => {
97
- let t = `voltro_migration_${de.toString(36)}`, n = fe(e);
95
+ let t = pe(e);
96
+ return t === void 0 ? fe : ve(`voltro_migration_lock:${t}`) & 9223372036854775807n;
97
+ }, T = (e) => {
98
+ let t = `voltro_migration_${fe.toString(36)}`, n = pe(e);
98
99
  if (n === void 0) return t;
99
100
  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
+ return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(ve(`voltro_migration_lock:${n}`) & _e).toString(16)}`;
101
102
  }, be = 250, xe = () => {
102
103
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
103
104
  return Number.isFinite(e) && e > 0 ? e : 3e4;
@@ -124,23 +125,23 @@ var ie = (e, t, n, r = 400) => {
124
125
  (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
126
  }), ke = (e, t) => b.gen(function* () {
126
127
  yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
127
- }), Ae = b.void, T = (e, t) => {
128
- let n = pe(t);
128
+ }), Ae = b.void, E = (e, t) => {
129
+ let n = me(t);
129
130
  return e.onDialectOrElse({
130
- mysql: () => Te(e, ye(n)),
131
- mssql: () => Oe(e, ye(n)),
131
+ mysql: () => Te(e, T(n)),
132
+ mssql: () => Oe(e, T(n)),
132
133
  sqlite: () => Ae,
133
- orElse: () => Se(e, ve(n))
134
+ orElse: () => Se(e, ye(n))
134
135
  });
135
- }, E = (e, t) => {
136
- let n = pe(t);
136
+ }, D = (e, t) => {
137
+ let n = me(t);
137
138
  return e.onDialectOrElse({
138
- mysql: () => Ee(e, ye(n)),
139
- mssql: () => ke(e, ye(n)),
139
+ mysql: () => Ee(e, T(n)),
140
+ mssql: () => ke(e, T(n)),
140
141
  sqlite: () => Ae,
141
- orElse: () => Ce(e, ve(n))
142
+ orElse: () => Ce(e, ye(n))
142
143
  });
143
- }, je = (e, t, n) => b.acquireUseRelease(T(e, n), () => t, () => E(e, n).pipe(b.orDie)), Me = (e) => e.onDialectOrElse({
144
+ }, je = (e, t, n) => b.acquireUseRelease(E(e, n), () => t, () => D(e, n).pipe(b.orDie)), Me = (e) => e.onDialectOrElse({
144
145
  pg: () => "postgres",
145
146
  mysql: () => "mysql",
146
147
  mssql: () => "mssql",
@@ -153,7 +154,7 @@ var ie = (e, t, n, r = 400) => {
153
154
  mariadb: "per-operation",
154
155
  sqlite: "per-operation",
155
156
  turso: "per-operation"
156
- }, Pe = (e) => Ne[e], D = "_voltro_migration_ops", Fe = l(D, {
157
+ }, Pe = (e) => Ne[e], O = "_voltro_migration_ops", Fe = l(O, {
157
158
  id: e({ prefix: "mop" }),
158
159
  runId: _(),
159
160
  planFingerprint: _(),
@@ -216,9 +217,9 @@ var ie = (e, t, n, r = 400) => {
216
217
  Object.keys(Ne);
217
218
  //#endregion
218
219
  //#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
+ var k = "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" }), A = (e) => {
220
221
  Xe.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
221
- }, A = (e, t) => {
222
+ }, j = (e, t) => {
222
223
  let n = e.type;
223
224
  if (e.spatial) {
224
225
  if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
@@ -229,7 +230,7 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
229
230
  return e.rawDdl;
230
231
  }
231
232
  if (n === "array" && e.arrayElement) {
232
- if (t === "postgres") return `${A({
233
+ if (t === "postgres") return `${j({
233
234
  ...e,
234
235
  type: e.arrayElement,
235
236
  arrayElement: void 0
@@ -332,19 +333,19 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
332
333
  }, Ze = (e, t) => {
333
334
  if (!e.hasDefault || e.defaultFactory !== void 0) return null;
334
335
  let n = e.defaultValue;
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
+ 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 ? M(n, t) : null;
336
337
  }, Qe = (e, t, n) => {
337
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return j(e, n);
338
- let r = A({
338
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return M(e, n);
339
+ let r = j({
339
340
  ...t,
340
341
  type: t.arrayElement,
341
342
  arrayElement: void 0
342
343
  }, n);
343
344
  return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
344
- }, j = (e, t) => {
345
+ }, M = (e, t) => {
345
346
  let n = JSON.stringify(e).replace(/'/g, "''");
346
347
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
347
- }, M = (e, t) => {
348
+ }, N = (e, t) => {
348
349
  switch (t) {
349
350
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
350
351
  case "mysql":
@@ -366,19 +367,19 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
366
367
  if (n !== "mysql" && n !== "mariadb") return r;
367
368
  let a = t[e];
368
369
  if (!a) return r;
369
- let o = A(a, n).toUpperCase();
370
+ let o = j(a, n).toUpperCase();
370
371
  return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${r}(${tt})` : r;
371
372
  }, rt = (e, t) => {
372
373
  if (!e.generatedAs) return null;
373
374
  let { expr: n, stored: r } = e.generatedAs;
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`;
375
+ if (t === "postgres") return r || A("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
375
376
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
376
377
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
377
378
  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.");
378
379
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
379
380
  }, 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];
381
+ if (t.type === "id" && t.idScheme?.kind === "numeric") return N(e, n);
382
+ let c = n === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" : j(t, n), l = [i(e, n), c];
382
383
  t.type === "id" && !s && l.push("PRIMARY KEY");
383
384
  let u = rt(t, n);
384
385
  if (u) l.push(u);
@@ -445,21 +446,21 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
445
446
  using: " USING GIST",
446
447
  withSuffix: "",
447
448
  skip: !1
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);
449
+ } : (A(`[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);
449
450
  if (r === "gin") return t === "postgres" ? {
450
451
  using: " USING GIN",
451
452
  withSuffix: "",
452
453
  skip: !1
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(...).`), {
454
+ } : t === "mysql" || t === "mariadb" ? (A(`[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(...).`), {
454
455
  using: "",
455
456
  withSuffix: "",
456
457
  skip: !0
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);
458
+ }) : (A(`[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);
458
459
  if (r === "brin") return t === "postgres" ? {
459
460
  using: " USING BRIN",
460
461
  withSuffix: "",
461
462
  skip: !1
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);
463
+ } : (A(`[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);
463
464
  if (r === "hnsw") {
464
465
  if (t === "postgres") {
465
466
  let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? y(i?.hnsw?.distance);
@@ -470,7 +471,7 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
470
471
  skip: !1
471
472
  };
472
473
  }
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.`), {
474
+ return A(`[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.`), {
474
475
  using: "",
475
476
  withSuffix: "",
476
477
  skip: !0
@@ -503,15 +504,15 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
503
504
  let a = n.columns.map((e) => i(e, t)).join(", ");
504
505
  r.push(`CREATE FULLTEXT INDEX ${i(n.name, t)} ON ${i(e.tableName, t)} (${a});`);
505
506
  } 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.`);
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).`);
507
+ else t === "sqlite" ? r.push(...ot(e.tableName, n, t)) : A(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
507
508
  for (let n of e.appliedIndexes) {
508
509
  if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
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(...).`);
510
+ A(`[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(...).`);
510
511
  continue;
511
512
  }
512
513
  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.`);
513
514
  let i = "";
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}`);
515
+ n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? A(`[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}`);
515
516
  let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, i, n.unique === !0);
516
517
  s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && a.add(o(n.fields));
517
518
  }
@@ -521,7 +522,7 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
521
522
  r.push(l(i, e.tableName, [t])), a.add(o([t]));
522
523
  }
523
524
  return r.join("\n");
524
- }, ct = (e, t, n = O) => {
525
+ }, ct = (e, t, n = k) => {
525
526
  if (t !== "postgres") return [];
526
527
  let r = e.filter((e) => e.isReactive !== !1);
527
528
  return r.length === 0 ? [] : [lt(n), ...r.map((e) => dt(e, n))];
@@ -600,7 +601,7 @@ $$ LANGUAGE plpgsql;
600
601
  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`);
601
602
  return r;
602
603
  }, 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) => {
604
+ let t = new Map(e.map((e) => [e.tableName, e])), n = de(e.map((e) => e.tableName), (e) => {
604
605
  let n = t.get(e);
605
606
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
606
607
  if (n.type !== "reference" || !n.references) return [];
@@ -696,8 +697,8 @@ BEGIN
696
697
  tables: t,
697
698
  views: n
698
699
  };
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 = [];
700
+ }, xt = (e, t, n = k) => {
701
+ let { tables: i, views: o } = bt(e), { sorted: s, cyclic: c } = ht(i.map((e) => ue(e, t))), l = _t(c, t), u = [];
701
702
  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
703
  let d = yt(s, t);
703
704
  d && u.push(d);
@@ -734,7 +735,7 @@ BEGIN
734
735
  r && d.push(r);
735
736
  }
736
737
  return d.join("\n\n") + "\n";
737
- }, wt = (e, t, n = O) => {
738
+ }, wt = (e, t, n = k) => {
738
739
  let { sorted: r, cyclic: i } = ht(e), a = _t(i, t), o = [], s = yt(r, t);
739
740
  s && o.push(s);
740
741
  let c = vt(r, t);
@@ -742,7 +743,7 @@ BEGIN
742
743
  for (let e of r) o.push(at(e, t, null, a.get(e.tableName)));
743
744
  for (let e of i) o.push(gt(e, t));
744
745
  return o.push(...ct(r, t, n)), o.join("\n\n") + "\n";
745
- }, Tt = (e, t = "postgres", n = O, r = {}) => b.gen(function* () {
746
+ }, Tt = (e, t = "postgres", n = k, r = {}) => b.gen(function* () {
746
747
  let i = yield* C.SqlClient;
747
748
  yield* je(i, Mt(i, xt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(b.orDie);
748
749
  }), Et = (e, t) => {
@@ -825,10 +826,10 @@ BEGIN
825
826
  name: e.name,
826
827
  columns: Bt(e.columns),
827
828
  indexes: Vt(e.indexes)
828
- })).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
829
+ })).sort((e, t) => e.name.localeCompare(t.name)), P = (e) => {
829
830
  let t = { tables: Ht(e.tables) }, n = JSON.stringify(Rt(t));
830
831
  return ee("sha256").update(n).digest("hex");
831
- }, P = (e) => e.slice(0, 16), Ut = (e, t) => {
832
+ }, F = (e) => e.slice(0, 16), Ut = (e, t) => {
832
833
  let n = t.references ? {
833
834
  table: t.references().tableName,
834
835
  column: "id",
@@ -940,10 +941,10 @@ BEGIN
940
941
  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}').`);
941
942
  t.set(e.name, n.name);
942
943
  }
943
- }, F = (e, t) => {
944
- let n = e.map((e) => Gt(le(e, t)));
944
+ }, I = (e, t) => {
945
+ let n = e.map((e) => Gt(ue(e, t)));
945
946
  return Kt(n), { tables: n };
946
- }, qt = (e, t, n = O) => b.gen(function* () {
947
+ }, qt = (e, t, n = k) => b.gen(function* () {
947
948
  let r = (yield* e`
948
949
  SELECT p.prosrc
949
950
  FROM pg_proc p
@@ -1017,29 +1018,29 @@ BEGIN
1017
1018
  snapshot: n.get(e.tableName),
1018
1019
  columnDefs: e.fields
1019
1020
  }]));
1020
- }, I = (e) => {
1021
+ }, L = (e) => {
1021
1022
  if (typeof e != "object" || !e) return JSON.stringify(e);
1022
- if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
1023
+ if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
1023
1024
  let t = e;
1024
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
1025
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
1025
1026
  }, $t = (e) => {
1026
1027
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
1027
1028
  let t = e.defaultValue;
1028
1029
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
1029
1030
  if (typeof t == "number") return String(t);
1030
- if (typeof t != "string") return I(t);
1031
+ if (typeof t != "string") return L(t);
1031
1032
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
1032
1033
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
1033
1034
  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);
1034
1035
  if (o) try {
1035
- return I(JSON.parse(o[1]));
1036
+ return L(JSON.parse(o[1]));
1036
1037
  } catch {}
1037
1038
  let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
1038
1039
  if (s) try {
1039
- return I(JSON.parse(s[1]));
1040
+ return L(JSON.parse(s[1]));
1040
1041
  } catch {}
1041
1042
  if (a.startsWith("{") || a.startsWith("[")) try {
1042
- return I(JSON.parse(a));
1043
+ return L(JSON.parse(a));
1043
1044
  } catch {}
1044
1045
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
1045
1046
  }, en = (e, t) => {
@@ -1064,12 +1065,12 @@ BEGIN
1064
1065
  return i.every((e, t) => e === a[t]);
1065
1066
  }, rn = (e, t) => {
1066
1067
  try {
1067
- let n = /\((\d+)\)/.exec(A(e, t));
1068
+ let n = /\((\d+)\)/.exec(j(e, t));
1068
1069
  return n ? Number(n[1]) : void 0;
1069
1070
  } catch {
1070
1071
  return;
1071
1072
  }
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({
1073
+ }, 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 ? R({
1073
1074
  kind: "add-check",
1074
1075
  table: e,
1075
1076
  column: t.name,
@@ -1104,7 +1105,7 @@ BEGIN
1104
1105
  added: i,
1105
1106
  removed: a
1106
1107
  };
1107
- }, L = (e, t, n, r) => ({
1108
+ }, R = (e, t, n, r) => ({
1108
1109
  op: e,
1109
1110
  classification: t,
1110
1111
  atomicByDialect: Zt(e.kind),
@@ -1116,21 +1117,21 @@ BEGIN
1116
1117
  table: e,
1117
1118
  column: t
1118
1119
  };
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
+ return t.nullable ? R(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? R(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? R(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : R(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
1121
  }, fn = (e, t, n) => {
1121
1122
  let r = {
1122
1123
  kind: "drop-column",
1123
1124
  table: e,
1124
1125
  column: t.name
1125
1126
  };
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({
1127
+ return n?.dropped ? R(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : R(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1128
+ }, pn = (e, t, n, r, i) => R({
1128
1129
  kind: "create-table",
1129
1130
  table: e,
1130
1131
  columns: t,
1131
1132
  indexes: n,
1132
1133
  ...r && r.length > 0 ? { primaryKey: r } : {}
1133
- }, "safe", i ?? "new table — no data to preserve"), mn = (e) => L({
1134
+ }, "safe", i ?? "new table — no data to preserve"), mn = (e) => R({
1134
1135
  kind: "drop-table",
1135
1136
  table: e
1136
1137
  }, "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) => {
@@ -1148,12 +1149,12 @@ BEGIN
1148
1149
  kind: "add-index",
1149
1150
  table: e,
1150
1151
  index: t
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({
1152
+ }, i ? R(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
1153
+ }, _n = (e, t) => t.unique && t.columns.length > 1 ? R({
1153
1154
  kind: "drop-unique-composite",
1154
1155
  table: e,
1155
1156
  name: t.name
1156
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
1157
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : R({
1157
1158
  kind: "drop-index",
1158
1159
  table: e,
1159
1160
  index: t.name
@@ -1174,20 +1175,22 @@ BEGIN
1174
1175
  column: t.name,
1175
1176
  toNullable: t.nullable
1176
1177
  };
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`));
1178
+ s.push(t.nullable ? R(n, "safe", `loosen ${e}.${t.name} to nullable`) : R(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1178
1179
  }
1179
- if (t.unique !== n.unique) if (t.unique) {
1180
- let n = {
1181
- kind: "add-unique",
1180
+ if (t.unique !== n.unique) {
1181
+ if (t.unique) {
1182
+ let n = {
1183
+ kind: "add-unique",
1184
+ table: e,
1185
+ column: t.name
1186
+ }, r = (a ?? 0) >= o;
1187
+ s.push(r ? R(n, "online-required", `online unique build on ${a} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1188
+ } else s.push(R({
1189
+ kind: "drop-unique",
1182
1190
  table: e,
1183
1191
  column: t.name
1184
- }, r = (a ?? 0) >= o;
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({
1187
- kind: "drop-unique",
1188
- table: e,
1189
- column: t.name
1190
- }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
1192
+ }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
1193
+ }
1191
1194
  if (vn(t.type, i) !== vn(n.type, i)) {
1192
1195
  let r = t.narrowedFrom;
1193
1196
  if (r && r.from === n.type) {
@@ -1199,7 +1202,7 @@ BEGIN
1199
1202
  to: t.type,
1200
1203
  ...r.using === void 0 ? {} : { using: r.using }
1201
1204
  };
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)")));
1205
+ s.push(R(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)")));
1203
1206
  } else {
1204
1207
  let r = {
1205
1208
  kind: "alter-column-type",
@@ -1208,12 +1211,12 @@ BEGIN
1208
1211
  from: n.type,
1209
1212
  to: t.type
1210
1213
  };
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` }));
1214
+ s.push(R(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` }));
1212
1215
  }
1213
1216
  }
1214
1217
  if (t.type === "text" && n.type === "text" && !r(i ?? "postgres") && t.maxLength !== n.maxLength) {
1215
1218
  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})`;
1216
- s.push(L({
1219
+ s.push(R({
1217
1220
  kind: "alter-column-type",
1218
1221
  table: e,
1219
1222
  column: t.name,
@@ -1229,10 +1232,10 @@ BEGIN
1229
1232
  hasDefault: t.hasDefault,
1230
1233
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
1231
1234
  };
1232
- s.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1235
+ s.push(R(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1233
1236
  }
1234
1237
  if (!nn(t.oneOf, n.oneOf)) {
1235
- n.oneOf && n.oneOf.length > 0 && s.push(L({
1238
+ n.oneOf && n.oneOf.length > 0 && s.push(R({
1236
1239
  kind: "drop-check",
1237
1240
  table: e,
1238
1241
  column: t.name
@@ -1240,7 +1243,7 @@ BEGIN
1240
1243
  let r = sn(e, t);
1241
1244
  r && s.push(r);
1242
1245
  }
1243
- return JSON.stringify(tn(t.references)) !== JSON.stringify(tn(n.references)) && (n.references && s.push(L({
1246
+ return JSON.stringify(tn(t.references)) !== JSON.stringify(tn(n.references)) && (n.references && s.push(R({
1244
1247
  kind: "drop-foreign-key",
1245
1248
  table: e,
1246
1249
  column: t.name
@@ -1257,15 +1260,15 @@ BEGIN
1257
1260
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1258
1261
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1259
1262
  };
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({
1263
+ return i === "null" && !t.nullable ? n.push(R(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(R({
1261
1264
  ...a,
1262
1265
  orphanPolicy: i
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;
1266
+ }, "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(R(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1264
1267
  }, xn = (e, t, n) => {
1265
1268
  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));
1266
1269
  for (let [n, c] of Object.entries(t)) {
1267
1270
  let t = c.renamedFrom;
1268
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
1271
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(R({
1269
1272
  kind: "rename-column",
1270
1273
  table: e.tableName,
1271
1274
  from: t,
@@ -1296,7 +1299,7 @@ BEGIN
1296
1299
  let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
1297
1300
  if (r.length !== 1) continue;
1298
1301
  let i = r[0];
1299
- i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(L({
1302
+ i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(R({
1300
1303
  kind: "rename-index",
1301
1304
  table: e,
1302
1305
  from: n.name,
@@ -1319,7 +1322,7 @@ BEGIN
1319
1322
  continue;
1320
1323
  }
1321
1324
  if (t.has(c.name)) {
1322
- r.push(L({
1325
+ r.push(R({
1323
1326
  kind: "rename-table",
1324
1327
  from: e,
1325
1328
  to: c.name
@@ -1327,14 +1330,14 @@ BEGIN
1327
1330
  continue;
1328
1331
  }
1329
1332
  if ((s.get(e) ?? 0) !== 1) {
1330
- r.push(L({
1333
+ r.push(R({
1331
1334
  kind: "rename-table",
1332
1335
  from: e,
1333
1336
  to: c.name
1334
1337
  }, "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.` }));
1335
1338
  continue;
1336
1339
  }
1337
- i.set(c.name, e), a.add(e), r.push(L({
1340
+ i.set(c.name, e), a.add(e), r.push(R({
1338
1341
  kind: "rename-table",
1339
1342
  from: e,
1340
1343
  to: c.name
@@ -1360,7 +1363,7 @@ BEGIN
1360
1363
  ...e,
1361
1364
  name: r,
1362
1365
  table: n
1363
- } : i ? (a.push(L({
1366
+ } : i ? (a.push(R({
1364
1367
  kind: "rename-index",
1365
1368
  table: n,
1366
1369
  from: e.name,
@@ -1409,13 +1412,11 @@ BEGIN
1409
1412
  case "online-required":
1410
1413
  t.onlineRequired++;
1411
1414
  break;
1412
- case "multi-step":
1413
- t.multiStep++;
1414
- break;
1415
+ case "multi-step": t.multiStep++;
1415
1416
  }
1416
1417
  return t;
1417
1418
  }, 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);
1419
+ let t = I(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);
1419
1420
  a.push(...o.ops);
1420
1421
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1421
1422
  a.push(pn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
@@ -1457,8 +1458,8 @@ BEGIN
1457
1458
  column: e.name,
1458
1459
  target: e.references.table
1459
1460
  }] : []) : [];
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({
1461
+ }, d = de([...c], u), f = [];
1462
+ 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(R({
1462
1463
  kind: "add-foreign-key",
1463
1464
  table: e.name,
1464
1465
  column: t.name,
@@ -1530,8 +1531,8 @@ BEGIN
1530
1531
  });
1531
1532
  return {
1532
1533
  operations: S,
1533
- fromFingerprint: N(e.live),
1534
- toFingerprint: N(t),
1534
+ fromFingerprint: P(e.live),
1535
+ toFingerprint: P(t),
1535
1536
  summary: On(S)
1536
1537
  };
1537
1538
  }, An = (e) => {
@@ -1569,7 +1570,7 @@ BEGIN
1569
1570
  case "USER-DEFINED": return "text";
1570
1571
  default: return "text";
1571
1572
  }
1572
- }, R = (e) => {
1573
+ }, z = (e) => {
1573
1574
  switch (e.toUpperCase()) {
1574
1575
  case "CASCADE": return "cascade";
1575
1576
  case "RESTRICT": return "restrict";
@@ -1738,17 +1739,17 @@ BEGIN
1738
1739
  }
1739
1740
  let te = [];
1740
1741
  for (let e of c) {
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) => {
1742
+ let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (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) => {
1742
1743
  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 ? {
1743
1744
  table: a.target_table,
1744
1745
  column: a.target_column,
1745
- onDelete: R(a.delete_rule),
1746
- onUpdate: R(a.update_rule)
1746
+ onDelete: z(a.delete_rule),
1747
+ onUpdate: z(a.update_rule)
1747
1748
  } : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
1748
1749
  return {
1749
1750
  name: t.column_name,
1750
1751
  type: s,
1751
- ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1752
+ ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
1752
1753
  nullable: t.is_nullable === "YES",
1753
1754
  unique: i.has(t.column_name) || n && t.column_name === "id",
1754
1755
  hasDefault: t.column_default !== null,
@@ -1760,7 +1761,7 @@ BEGIN
1760
1761
  if (u) for (let [t, n] of u) {
1761
1762
  let r = /* @__PURE__ */ new Set(), i = [...n].filter((e) => e.column_name !== null && e.position !== null).sort((e, t) => (e.position ?? 0) - (t.position ?? 0)).filter((e) => {
1762
1763
  let t = e.position;
1763
- return r.has(t) ? !1 : (r.add(t), !0);
1764
+ return !r.has(t) && (r.add(t), !0);
1764
1765
  });
1765
1766
  if (i.some((e) => s.has(e.column_name))) continue;
1766
1767
  let a = n.some((e) => e.has_expression);
@@ -1825,21 +1826,21 @@ BEGIN
1825
1826
  case "json": return "json";
1826
1827
  default: return "text";
1827
1828
  }
1828
- }, z = (e) => e.map((e) => {
1829
+ }, B = (e) => e.map((e) => {
1829
1830
  let t = e, n = {};
1830
1831
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1831
1832
  return n;
1832
1833
  }), zn = (e) => b.gen(function* () {
1833
- let t = z(yield* e`
1834
+ let t = B(yield* e`
1834
1835
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1835
1836
  FROM information_schema.tables
1836
1837
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1837
- ORDER BY table_name`), n = z(yield* e`
1838
+ ORDER BY table_name`), n = B(yield* e`
1838
1839
  SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
1839
1840
  character_maximum_length
1840
1841
  FROM information_schema.columns
1841
1842
  WHERE table_schema = DATABASE()
1842
- ORDER BY table_name, ordinal_position`), r = z(yield* e`
1843
+ ORDER BY table_name, ordinal_position`), r = B(yield* e`
1843
1844
  SELECT k.table_name AS source_table,
1844
1845
  k.column_name AS source_column,
1845
1846
  k.referenced_table_name AS target_table,
@@ -1849,11 +1850,11 @@ BEGIN
1849
1850
  JOIN information_schema.referential_constraints r
1850
1851
  ON k.constraint_name = r.constraint_name
1851
1852
  AND k.table_schema = r.constraint_schema
1852
- WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = z(yield* e`
1853
+ WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = B(yield* e`
1853
1854
  SELECT table_name, index_name, non_unique, column_name, seq_in_index
1854
1855
  FROM information_schema.statistics
1855
1856
  WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
1856
- ORDER BY table_name, index_name, seq_in_index`), a = z(yield* e`
1857
+ ORDER BY table_name, index_name, seq_in_index`), a = B(yield* e`
1857
1858
  SELECT table_name, check_clause
1858
1859
  FROM information_schema.check_constraints
1859
1860
  WHERE constraint_schema = DATABASE()`.unprepared.pipe(b.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
@@ -1889,14 +1890,14 @@ BEGIN
1889
1890
  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 ? {
1890
1891
  table: c.target_table,
1891
1892
  column: c.target_column,
1892
- onDelete: R(c.delete_rule),
1893
- onUpdate: R(c.update_rule)
1893
+ onDelete: z(c.delete_rule),
1894
+ onUpdate: z(c.update_rule)
1894
1895
  } : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = s.get(`${e.table_name}.${t.column_name}`);
1895
1896
  return {
1896
1897
  name: t.column_name,
1897
1898
  type: l,
1898
1899
  nullable: t.is_nullable === "YES",
1899
- ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1900
+ ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
1900
1901
  unique: d,
1901
1902
  hasDefault: f !== null,
1902
1903
  ...f === null ? {} : { defaultValue: f },
@@ -1906,12 +1907,12 @@ BEGIN
1906
1907
  }), m = new Set(n.map((e) => e.source_column)), h = [];
1907
1908
  if (f) for (let [t, n] of f) {
1908
1909
  let r = [...n].sort((e, t) => e.seq_in_index - t.seq_in_index);
1909
- r.length === 1 && r[0].non_unique === 0 || r.length === 1 && r[0].non_unique !== 0 && m.has(r[0].column_name) && t !== `${e.table_name}_${r[0].column_name}_idx` || h.push({
1910
+ (r.length !== 1 || r[0].non_unique !== 0) && (r.length === 1 && r[0].non_unique !== 0 && m.has(r[0].column_name) && t !== `${e.table_name}_${r[0].column_name}_idx` || h.push({
1910
1911
  name: t,
1911
1912
  table: e.table_name,
1912
1913
  columns: r.map((e) => e.column_name),
1913
1914
  unique: r[0].non_unique === 0
1914
- });
1915
+ }));
1915
1916
  }
1916
1917
  i.length > 0 && h.push({
1917
1918
  name: `${e.table_name}_pkey`,
@@ -1951,8 +1952,8 @@ BEGIN
1951
1952
  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 ? {
1952
1953
  table: r.table,
1953
1954
  column: r.to,
1954
- onDelete: R(r.on_delete),
1955
- onUpdate: R(r.on_update)
1955
+ onDelete: z(r.on_delete),
1956
+ onUpdate: z(r.on_update)
1956
1957
  } : void 0, o = t.get(e.name);
1957
1958
  return {
1958
1959
  name: e.name,
@@ -1968,12 +1969,12 @@ BEGIN
1968
1969
  for (let e of c) {
1969
1970
  if (e.origin === "pk") continue;
1970
1971
  let t = d.get(e.name) ?? [];
1971
- t.length === 1 && e.unique === 1 || t.length === 1 && e.unique !== 1 && m.has(t[0]) && e.name !== `${i}_${t[0]}_idx` || h.push({
1972
+ (t.length !== 1 || e.unique !== 1) && (t.length === 1 && e.unique !== 1 && m.has(t[0]) && e.name !== `${i}_${t[0]}_idx` || h.push({
1972
1973
  name: e.name,
1973
1974
  table: i,
1974
1975
  columns: t,
1975
1976
  unique: e.unique === 1
1976
- });
1977
+ }));
1977
1978
  }
1978
1979
  u.length > 0 && h.push({
1979
1980
  name: `${i}_pkey`,
@@ -2009,7 +2010,7 @@ BEGIN
2009
2010
  case "image": return "bytes";
2010
2011
  default: return "text";
2011
2012
  }
2012
- }, B = (e) => e === !0 || e === 1, Un = (e) => b.gen(function* () {
2013
+ }, V = (e) => e === !0 || e === 1, Un = (e) => b.gen(function* () {
2013
2014
  let t = yield* e`
2014
2015
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
2015
2016
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
@@ -2066,8 +2067,8 @@ BEGIN
2066
2067
  let t = s.get(e) ?? [], n = c.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = new Set(n.map((e) => e.source_column)), a = l.get(e), d = [], f = /* @__PURE__ */ new Set();
2067
2068
  if (a) for (let [, e] of a) {
2068
2069
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
2069
- if (B(t[0].is_primary)) for (let e of t) d.push(e.column_name);
2070
- else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
2070
+ if (V(t[0].is_primary)) for (let e of t) d.push(e.column_name);
2071
+ else V(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
2071
2072
  }
2072
2073
  let p = t.map((t) => {
2073
2074
  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 ? {
@@ -2080,7 +2081,7 @@ BEGIN
2080
2081
  name: t.column_name,
2081
2082
  type: a,
2082
2083
  nullable: t.is_nullable === "YES",
2083
- ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
2084
+ ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
2084
2085
  unique: f.has(t.column_name) || n && t.column_name === "id",
2085
2086
  hasDefault: c !== null,
2086
2087
  ...c === null ? {} : { defaultValue: c },
@@ -2090,11 +2091,11 @@ BEGIN
2090
2091
  }), m = [];
2091
2092
  if (a) for (let [t, n] of a) {
2092
2093
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
2093
- B(r[0].is_primary) || r.length === 1 && B(r[0].is_unique) || r.length === 1 && !B(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
2094
+ V(r[0].is_primary) || r.length === 1 && V(r[0].is_unique) || r.length === 1 && !V(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
2094
2095
  name: t,
2095
2096
  table: e,
2096
2097
  columns: r.map((e) => e.column_name),
2097
- unique: B(r[0].is_unique)
2098
+ unique: V(r[0].is_unique)
2098
2099
  });
2099
2100
  }
2100
2101
  d.length > 0 && m.push({
@@ -2127,11 +2128,11 @@ BEGIN
2127
2128
  "char",
2128
2129
  "character",
2129
2130
  "nchar"
2130
- ]), V = (e, t) => {
2131
+ ]), H = (e, t) => {
2131
2132
  if (!Kn.has(e.toLowerCase())) return;
2132
2133
  let n = Number(t);
2133
2134
  if (!(!Number.isFinite(n) || n <= 0)) return n;
2134
- }, qn = /* @__PURE__ */ new Set([D]), Jn = (e) => e.onDialectOrElse({
2135
+ }, qn = /* @__PURE__ */ new Set([O]), Jn = (e) => e.onDialectOrElse({
2135
2136
  mysql: () => zn(e),
2136
2137
  mssql: () => Un(e),
2137
2138
  sqlite: () => Vn(e),
@@ -2139,14 +2140,14 @@ BEGIN
2139
2140
  }).pipe(b.map((e) => ({
2140
2141
  ...e,
2141
2142
  tables: e.tables.filter((e) => !qn.has(e.name))
2142
- }))), H = (e, t) => e.onDialectOrElse({
2143
+ }))), U = (e, t) => e.onDialectOrElse({
2143
2144
  mysql: () => b.succeed(t.replace("T", " ").replace("Z", "")),
2144
2145
  orElse: () => b.succeed(t)
2145
2146
  }), Yn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Xn = (e, t) => {
2146
- if (!(e.type === "text" && e.maxLength !== void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2147
+ if ((e.type !== "text" || e.maxLength === void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2147
2148
  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;
2148
2149
  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.`);
2149
- return A(e, t);
2150
+ return j(e, t);
2150
2151
  }, Zn = (e) => {
2151
2152
  let t = Xn(e, "postgres");
2152
2153
  return t === void 0 ? Qn(e) : t;
@@ -2192,57 +2193,57 @@ BEGIN
2192
2193
  case "interval": return "BIGINT";
2193
2194
  case "raw": return e.rawDdl ?? "LONGTEXT";
2194
2195
  }
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) => {
2196
+ }, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, er = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, tr = (e) => `ALTER TABLE ${G(e.table)} DROP COLUMN IF EXISTS ${G(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}${kr(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) => {
2196
2197
  let n = t(e.defaultValue);
2197
2198
  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.`);
2198
2199
  return n;
2199
- }, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], or = (e, t, n) => {
2200
- let r = G(e, t, n);
2200
+ }, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], or = (e, t, n) => {
2201
+ let r = K(e, t, n);
2201
2202
  return r ? Ut(n, r) : void 0;
2202
2203
  }, sr = (e, t, n) => {
2203
2204
  let r = n ?? e.nullable, i = Ze(e, "mariadb");
2204
2205
  return [
2205
- W(t),
2206
- A(e, "mariadb"),
2206
+ G(t),
2207
+ j(e, "mariadb"),
2207
2208
  r ? null : "NOT NULL",
2208
2209
  i
2209
2210
  ].filter(Boolean).join(" ");
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) => {
2211
+ }, 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" ? M(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" ? M(e, "postgres") : null, q = (e, t) => {
2211
2212
  if (!e.generatedAs) return null;
2212
2213
  let { expr: n, stored: r } = e.generatedAs;
2213
2214
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2214
2215
  }, dr = (e) => {
2215
- if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "postgres");
2216
- let t = K(e, "postgres");
2217
- if (t) return `${U(e.name)} ${Zn(e)} ${t}`;
2218
- let n = [U(e.name), Zn(e)];
2216
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "postgres");
2217
+ let t = q(e, "postgres");
2218
+ if (t) return `${W(e.name)} ${Zn(e)} ${t}`;
2219
+ let n = [W(e.name), Zn(e)];
2219
2220
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2220
2221
  let t = ur(e.defaultValue, e);
2221
2222
  t && n.push(t);
2222
2223
  }
2223
- return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2224
+ return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2224
2225
  cascade: "CASCADE",
2225
2226
  restrict: "RESTRICT",
2226
2227
  setNull: "SET NULL",
2227
2228
  noAction: "NO ACTION"
2228
2229
  }[e.references.onDelete]}`)), n.join(" ");
2229
2230
  }, 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(", ")})`);
2231
+ let t = e.columns.map((e) => ` ${dr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${fr(e, W)}\n)`];
2232
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(Pr).join(", ")})`);
2232
2233
  return n;
2233
2234
  }, mr = 191, hr = (e) => {
2234
2235
  let t = $n(e).toUpperCase();
2235
2236
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2236
2237
  }, gr = (e) => {
2237
- if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "mariadb");
2238
- let t = K(e, "mariadb");
2239
- if (t) return `${W(e.name)} ${$n(e)} ${t}`;
2240
- let n = [W(e.name), $n(e)];
2238
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mariadb");
2239
+ let t = q(e, "mariadb");
2240
+ if (t) return `${G(e.name)} ${$n(e)} ${t}`;
2241
+ let n = [G(e.name), $n(e)];
2241
2242
  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
2243
  let t = cr(e.defaultValue, e);
2243
2244
  t && n.push(t);
2244
2245
  }
2245
- return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2246
+ return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2246
2247
  cascade: "CASCADE",
2247
2248
  restrict: "RESTRICT",
2248
2249
  setNull: "SET NULL",
@@ -2250,11 +2251,11 @@ BEGIN
2250
2251
  }[e.references.onDelete]}`)), n.join(" ");
2251
2252
  }, _r = (e) => {
2252
2253
  let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
2253
- let n = jr(t.get(e));
2254
- return n === void 0 ? W(e) : `${W(e)}(${n})`;
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)})`);
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(", ")})`);
2254
+ let n = Mr(t.get(e));
2255
+ return n === void 0 ? G(e) : `${G(e)}(${n})`;
2256
+ }, r = e.columns.map((e) => ` ${gr(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${r}${fr(e, n)}\n)`];
2257
+ for (let t of e.columns) t.unique && t.type !== "id" && hr(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${G(`${e.table}_${t.name}_key`)} ON ${G(e.table)} (${n(t.name)})`);
2258
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(n).join(", ")})`);
2258
2259
  return i;
2259
2260
  }, vr = {
2260
2261
  cascade: "CASCADE",
@@ -2278,52 +2279,52 @@ BEGIN
2278
2279
  case "bytes": return "BLOB";
2279
2280
  default: return "TEXT";
2280
2281
  }
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");
2283
- let t = K(e, "sqlite");
2284
- if (t) return `${U(e.name)} ${br(e)} ${t}`;
2285
- let n = [U(e.name), br(e)];
2282
+ }, xr = (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" ? M(e, "sqlite") : null, Sr = (e) => {
2283
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "sqlite");
2284
+ let t = q(e, "sqlite");
2285
+ if (t) return `${W(e.name)} ${br(e)} ${t}`;
2286
+ let n = [W(e.name), br(e)];
2286
2287
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2287
- let t = q(e.defaultValue, "CURRENT_TIMESTAMP");
2288
+ let t = xr(e.defaultValue, "CURRENT_TIMESTAMP");
2288
2289
  t && n.push(t);
2289
2290
  }
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) {
2291
+ if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${vr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2291
2292
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2292
- n.push(`CHECK (${U(e.name)} IN (${t}))`);
2293
+ n.push(`CHECK (${W(e.name)} IN (${t}))`);
2293
2294
  }
2294
2295
  return n.join(" ");
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)`];
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(", ")})`);
2296
+ }, Cr = (e) => {
2297
+ let t = e.columns.map((e) => ` ${Sr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${fr(e, W)}\n)`];
2298
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(W).join(", ")})`);
2298
2299
  return n;
2299
2300
  }, J = (e, t) => {
2300
2301
  let n = t.find((t) => t.tableName === e);
2301
2302
  if (!n) return [];
2302
- let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
2303
- ...Sr({
2303
+ let r = I([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
2304
+ ...Cr({
2304
2305
  kind: "create-table",
2305
2306
  table: i,
2306
2307
  columns: r.columns,
2307
2308
  indexes: [],
2308
2309
  ...r.primaryKey ? { primaryKey: r.primaryKey } : {}
2309
2310
  }),
2310
- `INSERT INTO ${U(i)} (${a}) SELECT ${a} FROM ${U(e)}`,
2311
- `DROP TABLE ${U(e)}`,
2312
- `ALTER TABLE ${U(i)} RENAME TO ${U(e)}`
2311
+ `INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
2312
+ `DROP TABLE ${W(e)}`,
2313
+ `ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
2313
2314
  ];
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(", ")})`);
2315
+ for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e)} (${t.columns.map(W).join(", ")})`);
2315
2316
  return o;
2316
- }, Cr = (e, t, n, r) => {
2317
+ }, wr = (e, t, n, r) => {
2317
2318
  let i = r ?? e.nullable;
2318
- return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${A(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2319
- }, wr = (e) => {
2319
+ return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${j(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2320
+ }, Tr = (e) => {
2320
2321
  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 + ']');`;
2321
2322
  if (!e.hasDefault) return t;
2322
- let n = q(e.defaultValue, "SYSUTCDATETIME()");
2323
+ let n = xr(e.defaultValue, "SYSUTCDATETIME()");
2323
2324
  if (!n) return t;
2324
2325
  let r = n.replace(/^DEFAULT\s+/i, "");
2325
2326
  return `${t} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${r} FOR ${Y(e.column)};`;
2326
- }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Tr = (e) => {
2327
+ }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Er = (e) => {
2327
2328
  let t = Xn(e, "mssql");
2328
2329
  if (t !== void 0) return t;
2329
2330
  switch (e.type) {
@@ -2339,44 +2340,44 @@ BEGIN
2339
2340
  case "bytes": return "VARBINARY(MAX)";
2340
2341
  default: return "NVARCHAR(MAX)";
2341
2342
  }
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");
2343
+ }, Dr = (e, t) => {
2344
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mssql");
2345
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Er(e), r = q(e, "mssql");
2345
2346
  if (r) return `${Y(e.name)} ${r}`;
2346
2347
  let i = [Y(e.name), n];
2347
2348
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2348
- let t = q(e.defaultValue, "SYSUTCDATETIME()");
2349
+ let t = xr(e.defaultValue, "SYSUTCDATETIME()");
2349
2350
  t && i.push(t);
2350
2351
  }
2351
2352
  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)}')`];
2353
+ }, Or = (e) => {
2354
+ let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Dr(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)}')`];
2354
2355
  for (let n of e.indexes) {
2355
2356
  if (n.name === `${e.table}_pkey`) continue;
2356
2357
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})`;
2357
2358
  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)}')`);
2358
2359
  }
2359
2360
  return a;
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)}`;
2361
+ }, kr = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Ar = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, jr = (e, t, n) => {
2362
+ let r = `${e.table}${kr(t)}`;
2362
2363
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2363
- }, jr = (e) => {
2364
+ }, Mr = (e) => {
2364
2365
  if (e === void 0 || !hr(e)) return;
2365
2366
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
2366
2367
  return t === void 0 ? mr : Math.min(mr, t);
2367
- }, Mr = (e, t, n) => {
2368
- let r = jr(or(e, t, n));
2369
- return r === void 0 ? W(n) : `${W(n)}(${r})`;
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) => {
2368
+ }, Nr = (e, t, n) => {
2369
+ let r = Mr(or(e, t, n));
2370
+ return r === void 0 ? G(n) : `${G(n)}(${r})`;
2371
+ }, Pr = (e) => e.startsWith("(") ? e : W(e), Fr = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map(Pr).join(", ")});`, Ir = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => Nr(t, e.table, n)).join(", ")});`, Lr = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, Rr = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, zr = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, Br = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Vr = (e) => {
2371
2372
  let t = (e) => e.replace(/'/g, "''");
2372
2373
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
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) => {
2374
+ }, Hr = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, Ur = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, Wr = (e) => {
2374
2375
  let t = (e) => e.replace(/'/g, "''");
2375
2376
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2376
- }, Wr = (e) => {
2377
+ }, Gr = (e) => {
2377
2378
  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(", ")})`;
2378
2379
  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)}');`;
2379
- }, Gr = (e, t, n) => {
2380
+ }, Kr = (e, t, n) => {
2380
2381
  let r = n.find((t) => t.tableName === e);
2381
2382
  if (!r) return [];
2382
2383
  let i = [];
@@ -2385,13 +2386,13 @@ BEGIN
2385
2386
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2386
2387
  }
2387
2388
  return i;
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) => {
2389
- let t = e.fields.map((e) => U(e)).join(", ");
2390
- return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
2391
- }, Yr = (e, t) => {
2392
- let n = e.fields.map((n) => Mr(t, e.table, n)).join(", ");
2393
- return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
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) => {
2389
+ }, qr = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, Jr = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${Nr(t, e.table, e.column)});`, Yr = (e) => {
2390
+ let t = e.fields.map((e) => W(e)).join(", ");
2391
+ return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
2392
+ }, Xr = (e, t) => {
2393
+ let n = e.fields.map((n) => Nr(t, e.table, n)).join(", ");
2394
+ return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
2395
+ }, Zr = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, Qr = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, $r = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, ei = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, ti = (e, t) => {
2395
2396
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2396
2397
  if (e.orphanPolicy) {
2397
2398
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2409,11 +2410,11 @@ BEGIN
2409
2410
  setNull: "SET NULL",
2410
2411
  noAction: "NO ACTION"
2411
2412
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
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) => {
2413
+ }, ni = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, ri = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, ii = (e, t) => {
2413
2414
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2414
2415
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
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);
2416
+ }, ai = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, oi = (e) => `ALTER TABLE ${G(e.table)} DROP CHECK ${G(`${e.table}_${e.column}_check`)};`, si = (e, t, n, r) => {
2417
+ let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? Y : W, s = a ? $n(i) : r === "mssql" ? Er(i) : r === "sqlite" ? br(i) : Zn(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? cr(e, i) : r === "mssql" ? xr(e, "SYSUTCDATETIME()") : r === "sqlite" ? xr(e, "CURRENT_TIMESTAMP") : ur(e, i), u = q(i, r);
2417
2418
  if (u) {
2418
2419
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2419
2420
  return {
@@ -2441,7 +2442,7 @@ BEGIN
2441
2442
  post: f ? [f] : []
2442
2443
  };
2443
2444
  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;
2444
- }, si = (e) => {
2445
+ }, ci = (e) => {
2445
2446
  let t = new Map(e.map((e) => [e.tableName, e]));
2446
2447
  return (e, n) => {
2447
2448
  let r = t.get(e);
@@ -2466,29 +2467,29 @@ BEGIN
2466
2467
  })), b.mapError((e) => {
2467
2468
  let r = ie(`applier: statement failed (op=${n})`, t, e, 400).trim();
2468
2469
  return Object.assign(e, { message: r });
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];
2470
+ }), 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))), li = (e, t) => b.gen(function* () {
2471
+ let n = I([Fe], t).tables[0];
2471
2472
  if (!n) return yield* b.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2472
2473
  let r = {
2473
2474
  kind: "create-table",
2474
- table: D,
2475
+ table: O,
2475
2476
  columns: n.columns,
2476
2477
  indexes: []
2477
2478
  }, i = yield* e.onDialectOrElse({
2478
2479
  mysql: () => b.succeed(_r(r)),
2479
- mssql: () => b.succeed(Dr(r)),
2480
- sqlite: () => b.succeed(Sr(r)),
2480
+ mssql: () => b.succeed(Or(r)),
2481
+ sqlite: () => b.succeed(Cr(r)),
2481
2482
  orElse: () => b.succeed(pr(r))
2482
2483
  });
2483
2484
  yield* b.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2484
- }), li = (e) => e`
2485
+ }), ui = (e) => e`
2485
2486
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2486
2487
  ${e("status")}, ${e("payload")}
2487
- FROM ${e(D)}
2488
- `, ui = (e, t, n, r) => b.gen(function* () {
2489
- let i = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2488
+ FROM ${e(O)}
2489
+ `, di = (e, t, n, r) => b.gen(function* () {
2490
+ let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2490
2491
  yield* b.forEach(r, ({ index: r, planned: a }) => e`
2491
- INSERT INTO ${e(D)}
2492
+ INSERT INTO ${e(O)}
2492
2493
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2493
2494
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
2494
2495
  ${e("createdAt")})
@@ -2497,11 +2498,11 @@ BEGIN
2497
2498
  ${a.op.kind}, ${Le(a.op)}, ${"pending"},
2498
2499
  ${JSON.stringify(a)}, ${i})
2499
2500
  `, { discard: !0 });
2500
- }), di = (e, t, n, r, i) => b.gen(function* () {
2501
- let a = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2501
+ }), fi = (e, t, n, r, i) => b.gen(function* () {
2502
+ let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2502
2503
  if (r === "applied") {
2503
2504
  yield* e`
2504
- UPDATE ${e(D)}
2505
+ UPDATE ${e(O)}
2505
2506
  SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
2506
2507
  ${e("durationMs")} = ${i ?? null}
2507
2508
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
@@ -2509,22 +2510,22 @@ BEGIN
2509
2510
  return;
2510
2511
  }
2511
2512
  yield* e`
2512
- UPDATE ${e(D)}
2513
+ UPDATE ${e(O)}
2513
2514
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
2514
2515
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
2515
2516
  `;
2516
- }), fi = (e, t, n, r) => b.gen(function* () {
2517
- let i = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2517
+ }), pi = (e, t, n, r) => b.gen(function* () {
2518
+ let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2518
2519
  r.length > 0 && (yield* e`
2519
- UPDATE ${e(D)}
2520
+ UPDATE ${e(O)}
2520
2521
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
2521
2522
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
2522
2523
  `), n.length > 0 && (yield* e`
2523
- UPDATE ${e(D)}
2524
+ UPDATE ${e(O)}
2524
2525
  SET ${e("status")} = ${"pending"}
2525
2526
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
2526
2527
  `);
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
+ }), mi = (e, t) => t === void 0 ? e`DELETE FROM ${e(O)}`.pipe(b.asVoid) : e`DELETE FROM ${e(O)} WHERE ${e("runId")} = ${t}`.pipe(b.asVoid), hi = (e, t, n) => b.gen(function* () {
2528
2529
  if (Ge(n.op, n.classification, t) !== "artefact-repair") return "clean";
2529
2530
  let r = n.op, a = (e) => i(e, t);
2530
2531
  if (t === "sqlite" || t === "turso") {
@@ -2535,129 +2536,130 @@ BEGIN
2535
2536
  if (r.kind !== "alter-column-type") return "clean";
2536
2537
  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" }));
2537
2538
  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.`));
2538
- }), hi = (e, t, n, r = "fresh") => b.gen(function* () {
2539
- let i = process.hrtime.bigint(), a = si(n.declared), o = t.op;
2539
+ }), gi = (e, t, n, r = "fresh") => b.gen(function* () {
2540
+ let i = process.hrtime.bigint(), a = ci(n.declared), o = t.op;
2540
2541
  switch (o.kind) {
2541
2542
  case "create-table": {
2542
2543
  let t = yield* e.onDialectOrElse({
2543
2544
  mysql: () => b.succeed(_r(o)),
2544
- mssql: () => b.succeed(Dr(o)),
2545
- sqlite: () => b.succeed(Sr(o)),
2545
+ mssql: () => b.succeed(Or(o)),
2546
+ sqlite: () => b.succeed(Cr(o)),
2546
2547
  orElse: () => b.succeed(pr(o))
2547
2548
  });
2548
2549
  for (let n of t) yield* X(e, n, o.kind);
2549
2550
  break;
2550
2551
  }
2551
2552
  case "drop-table": {
2552
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Ar(o, n, e) : kr(o, e);
2553
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? jr(o, n, e) : Ar(o, e);
2553
2554
  yield* e.onDialectOrElse({
2554
- mysql: () => X(e, r(W), o.kind),
2555
- orElse: () => X(e, r(U), o.kind)
2555
+ mysql: () => X(e, r(G), o.kind),
2556
+ orElse: () => X(e, r(W), o.kind)
2556
2557
  });
2557
2558
  break;
2558
2559
  }
2559
2560
  case "drop-column": {
2560
2561
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2561
2562
  yield* e.onDialectOrElse({
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)
2563
+ mysql: () => X(e, t ? rr(o, n, G) : tr(o), o.kind),
2564
+ orElse: () => X(e, t ? rr(o, n, W) : er(o, W), o.kind)
2564
2565
  });
2565
2566
  break;
2566
2567
  }
2567
2568
  case "rename-column":
2568
2569
  yield* e.onDialectOrElse({
2569
- mysql: () => X(e, nr(o, W), o.kind),
2570
+ mysql: () => X(e, nr(o, G), o.kind),
2570
2571
  mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
2571
- orElse: () => X(e, nr(o, U), o.kind)
2572
+ orElse: () => X(e, nr(o, W), o.kind)
2572
2573
  });
2573
2574
  break;
2574
2575
  case "add-index":
2575
2576
  yield* e.onDialectOrElse({
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)
2577
+ mysql: () => X(e, Ir(o, n.declared), o.kind),
2578
+ mssql: () => Z(e, [...Kr(o.table, o.index.columns, n.declared), Gr(o)], o.kind),
2579
+ orElse: () => X(e, Fr(o, t.classification === "online-required"), o.kind)
2579
2580
  });
2580
2581
  break;
2581
2582
  case "drop-index":
2582
2583
  yield* e.onDialectOrElse({
2583
- mysql: () => X(e, Lr(o), o.kind),
2584
- mssql: () => X(e, Rr(o), o.kind),
2585
- orElse: () => X(e, Ir(o), o.kind)
2584
+ mysql: () => X(e, Rr(o), o.kind),
2585
+ mssql: () => X(e, zr(o), o.kind),
2586
+ orElse: () => X(e, Lr(o), o.kind)
2586
2587
  });
2587
2588
  break;
2588
2589
  case "rename-table":
2589
2590
  yield* e.onDialectOrElse({
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)
2591
+ mysql: () => X(e, Br(o, G), o.kind),
2592
+ mssql: () => X(e, Vr(o), o.kind),
2593
+ orElse: () => X(e, Br(o, W), o.kind)
2593
2594
  });
2594
2595
  break;
2595
2596
  case "rename-index":
2596
2597
  yield* e.onDialectOrElse({
2597
- mysql: () => X(e, Hr(o), o.kind),
2598
- mssql: () => X(e, Ur(o), o.kind),
2599
- orElse: () => X(e, Vr(o), o.kind)
2598
+ mysql: () => X(e, Ur(o), o.kind),
2599
+ mssql: () => X(e, Wr(o), o.kind),
2600
+ orElse: () => X(e, Hr(o), o.kind)
2600
2601
  });
2601
2602
  break;
2602
2603
  case "add-unique":
2603
2604
  yield* e.onDialectOrElse({
2604
- mysql: () => X(e, qr(o, n.declared), o.kind),
2605
+ mysql: () => X(e, Jr(o, n.declared), o.kind),
2605
2606
  sqlite: () => Z(e, J(o.table, n.declared), 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)
2607
+ mssql: () => Z(e, [...Kr(o.table, [o.column], n.declared), qr(o)], o.kind),
2608
+ orElse: () => X(e, qr(o), o.kind)
2608
2609
  });
2609
2610
  break;
2610
2611
  case "drop-unique":
2611
2612
  yield* e.onDialectOrElse({
2612
- mysql: () => X(e, $r(o), o.kind),
2613
+ mysql: () => X(e, ei(o), o.kind),
2613
2614
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2614
- orElse: () => X(e, Qr(o), o.kind)
2615
+ orElse: () => X(e, $r(o), o.kind)
2615
2616
  });
2616
2617
  break;
2617
2618
  case "add-unique-composite":
2618
2619
  yield* e.onDialectOrElse({
2619
- mysql: () => X(e, Yr(o, n.declared), o.kind),
2620
+ mysql: () => X(e, Xr(o, n.declared), o.kind),
2620
2621
  sqlite: () => Z(e, J(o.table, n.declared), 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)
2622
+ mssql: () => Z(e, [...Kr(o.table, o.fields, n.declared), Yr(o)], o.kind),
2623
+ orElse: () => X(e, Yr(o), o.kind)
2623
2624
  });
2624
2625
  break;
2625
2626
  case "drop-unique-composite":
2626
2627
  yield* e.onDialectOrElse({
2627
- mysql: () => X(e, Zr(o), o.kind),
2628
+ mysql: () => X(e, Qr(o), o.kind),
2628
2629
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2629
- orElse: () => X(e, Xr(o), o.kind)
2630
+ orElse: () => X(e, Zr(o), o.kind)
2630
2631
  });
2631
2632
  break;
2632
2633
  case "add-foreign-key":
2633
2634
  yield* e.onDialectOrElse({
2634
- mysql: () => Z(e, ei(o, W), o.kind),
2635
+ mysql: () => Z(e, ti(o, G), o.kind),
2635
2636
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2636
- orElse: () => Z(e, ei(o, U), o.kind)
2637
+ orElse: () => Z(e, ti(o, W), o.kind)
2637
2638
  });
2638
2639
  break;
2639
2640
  case "add-column": {
2640
- let n = oi(o, t, a, yield* e.onDialectOrElse({
2641
+ let n = si(o, t, a, yield* e.onDialectOrElse({
2641
2642
  mysql: () => b.succeed("mariadb"),
2642
2643
  mssql: () => b.succeed("mssql"),
2643
2644
  sqlite: () => b.succeed("sqlite"),
2644
2645
  orElse: () => b.succeed("postgres")
2645
2646
  }));
2646
2647
  if (!(r === "resume" && (yield* $(e, Me(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
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}`;
2648
- else {
2649
- let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
2650
- for (;;) {
2651
- let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
2652
- if (s.length === 0) break;
2653
- let c = s.map((e) => e.id);
2654
- yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += s.length, yield* b.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows`).pipe(b.annotateLogs({
2655
- scope: "voltro:migrate",
2656
- mode: "sql-batched"
2657
- })), i = s[s.length - 1].id, r > 0 && (yield* b.sleep(`${r} millis`));
2648
+ if (n.backfillKind === "sql" && n.backfillSql) {
2649
+ if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
2650
+ else {
2651
+ let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
2652
+ for (;;) {
2653
+ let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
2654
+ if (s.length === 0) break;
2655
+ let c = s.map((e) => e.id);
2656
+ yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += s.length, yield* b.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows`).pipe(b.annotateLogs({
2657
+ scope: "voltro:migrate",
2658
+ mode: "sql-batched"
2659
+ })), i = s[s.length - 1].id, r > 0 && (yield* b.sleep(`${r} millis`));
2660
+ }
2658
2661
  }
2659
- }
2660
- else if (n.backfillKind === "js" && n.backfillJs) {
2662
+ } else if (n.backfillKind === "js" && n.backfillJs) {
2661
2663
  let t = n.batchSize ?? 1e3, r = n.sleepMs ?? 0, i, a = 0;
2662
2664
  for (;;) {
2663
2665
  let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
@@ -2682,24 +2684,24 @@ BEGIN
2682
2684
  case "alter-column-nullability":
2683
2685
  yield* e.onDialectOrElse({
2684
2686
  mysql: () => {
2685
- let t = G(n.declared, o.table, o.column);
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.`));
2687
+ let t = K(n.declared, o.table, o.column);
2688
+ return t ? X(e, `ALTER TABLE ${G(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.`));
2687
2689
  },
2688
2690
  mssql: () => {
2689
- let t = G(n.declared, 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}'.`));
2691
+ let t = K(n.declared, o.table, o.column);
2692
+ return t ? X(e, wr(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}'.`));
2691
2693
  },
2692
2694
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2693
- orElse: () => X(e, `ALTER TABLE ${U(o.table)} ALTER COLUMN ${U(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2695
+ orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2694
2696
  });
2695
2697
  break;
2696
2698
  case "alter-column-default": {
2697
2699
  let t = or(n.declared, o.table, o.column);
2698
2700
  yield* e.onDialectOrElse({
2699
- mysql: () => X(e, ir(o, W, (e) => cr(e, t)), o.kind),
2700
- mssql: () => X(e, wr(o), o.kind),
2701
+ mysql: () => X(e, ir(o, G, (e) => cr(e, t)), o.kind),
2702
+ mssql: () => X(e, Tr(o), o.kind),
2701
2703
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2702
- orElse: () => X(e, ir(o, U, (e) => ur(e, t)), o.kind)
2704
+ orElse: () => X(e, ir(o, W, (e) => ur(e, t)), o.kind)
2703
2705
  });
2704
2706
  break;
2705
2707
  }
@@ -2708,15 +2710,15 @@ BEGIN
2708
2710
  if (t.classification !== "online-required") {
2709
2711
  yield* e.onDialectOrElse({
2710
2712
  mysql: () => {
2711
- let t = G(n.declared, o.table, o.column);
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.`));
2713
+ let t = K(n.declared, o.table, o.column);
2714
+ return t ? X(e, `ALTER TABLE ${G(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.`));
2713
2715
  },
2714
2716
  mssql: () => {
2715
- let t = G(n.declared, 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}'.`));
2717
+ let t = K(n.declared, o.table, o.column);
2718
+ return t ? X(e, wr(t, o.column, o.table), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2717
2719
  },
2718
2720
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2719
- orElse: () => X(e, `ALTER TABLE ${U(o.table)} ALTER COLUMN ${U(o.column)} TYPE ${r}${i};`, o.kind)
2721
+ orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
2720
2722
  });
2721
2723
  break;
2722
2724
  }
@@ -2725,58 +2727,56 @@ BEGIN
2725
2727
  orElse: () => b.void
2726
2728
  });
2727
2729
  let a = `${o.column}__shadow`, s = `${o.column}__old`;
2728
- yield* e.unsafe(`ALTER TABLE ${U(o.table)} ADD COLUMN ${U(a)} ${r}`);
2729
- let c = o.using ?? U(o.column), l;
2730
+ yield* e.unsafe(`ALTER TABLE ${W(o.table)} ADD COLUMN ${W(a)} ${r}`);
2731
+ let c = o.using ?? W(o.column), l;
2730
2732
  for (;;) {
2731
2733
  let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Q(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Q(e, 5e3)}`;
2732
2734
  if (t.length === 0) break;
2733
- yield* e.unsafe(`UPDATE ${U(o.table)} SET ${U(a)} = ${c} WHERE ${U(o.column)} IS NOT NULL AND ${U(a)} IS NULL AND ${U("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2735
+ yield* e.unsafe(`UPDATE ${W(o.table)} SET ${W(a)} = ${c} WHERE ${W(o.column)} IS NOT NULL AND ${W(a)} IS NULL AND ${W("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2734
2736
  }
2735
- yield* b.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${U(o.table)} RENAME COLUMN ${U(o.column)} TO ${U(s)}`), yield* e.unsafe(`ALTER TABLE ${U(o.table)} RENAME COLUMN ${U(a)} TO ${U(o.column)}`), yield* e.unsafe(`ALTER TABLE ${U(o.table)} DROP COLUMN ${U(s)}`);
2737
+ yield* b.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${W(o.table)} RENAME COLUMN ${W(o.column)} TO ${W(s)}`), yield* e.unsafe(`ALTER TABLE ${W(o.table)} RENAME COLUMN ${W(a)} TO ${W(o.column)}`), yield* e.unsafe(`ALTER TABLE ${W(o.table)} DROP COLUMN ${W(s)}`);
2736
2738
  break;
2737
2739
  }
2738
2740
  case "drop-foreign-key":
2739
2741
  yield* e.onDialectOrElse({
2740
- mysql: () => X(e, ni(o), o.kind),
2742
+ mysql: () => X(e, ri(o), o.kind),
2741
2743
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2742
- orElse: () => X(e, ti(o), o.kind)
2744
+ orElse: () => X(e, ni(o), o.kind)
2743
2745
  });
2744
2746
  break;
2745
2747
  case "add-check":
2746
2748
  yield* e.onDialectOrElse({
2747
- mysql: () => X(e, ri(o, W), o.kind),
2748
- sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2749
- orElse: () => X(e, ri(o, U), o.kind)
2750
- });
2751
- break;
2752
- case "drop-check":
2753
- yield* e.onDialectOrElse({
2754
- mysql: () => X(e, ai(o), o.kind),
2749
+ mysql: () => X(e, ii(o, G), o.kind),
2755
2750
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2756
- orElse: () => X(e, ii(o), o.kind)
2751
+ orElse: () => X(e, ii(o, W), o.kind)
2757
2752
  });
2758
2753
  break;
2754
+ case "drop-check": yield* e.onDialectOrElse({
2755
+ mysql: () => X(e, oi(o), o.kind),
2756
+ sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2757
+ orElse: () => X(e, ai(o), o.kind)
2758
+ });
2759
2759
  }
2760
2760
  return {
2761
2761
  op: o,
2762
2762
  status: "applied",
2763
2763
  durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
2764
2764
  };
2765
- }), gi = (e, t, n, r) => b.gen(function* () {
2765
+ }), _i = (e, t, n, r) => b.gen(function* () {
2766
2766
  let i = [...new Set(r.map((e) => e.runId))];
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.`));
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 \`${O}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
2768
2768
  let a = i[0], o = [...r].map((e) => ({
2769
2769
  index: Number(e.opIndex),
2770
2770
  status: e.status,
2771
2771
  planned: JSON.parse(e.payload)
2772
2772
  })).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
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.`));
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 \`${O}\` by hand before re-running.`));
2774
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 {
2775
2775
  kind: "discard",
2776
2776
  runId: a,
2777
2777
  why: "no operation had started — no DDL ran"
2778
2778
  };
2779
- let l = s ? yield* mi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2779
+ let l = s ? yield* hi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2780
2780
  if (u !== n.toFingerprint) return {
2781
2781
  kind: "discard",
2782
2782
  runId: a,
@@ -2787,7 +2787,7 @@ BEGIN
2787
2787
  kind: "discard",
2788
2788
  runId: a,
2789
2789
  why: "every recorded operation had already taken effect"
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" })), {
2790
+ } : (yield* pi(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" })), {
2791
2791
  kind: "resume",
2792
2792
  runId: a,
2793
2793
  ops: f.map((e) => ({
@@ -2795,39 +2795,39 @@ BEGIN
2795
2795
  planned: e.planned
2796
2796
  }))
2797
2797
  });
2798
- }), _i = (e, t, n) => b.gen(function* () {
2798
+ }), vi = (e, t, n) => b.gen(function* () {
2799
2799
  let r = t.operations.filter((e) => e.blocked);
2800
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.`));
2801
- yield* T(e, { schema: n.lockSchema });
2801
+ yield* E(e, { schema: n.lockSchema });
2802
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) => ({
2803
2803
  index: t,
2804
2804
  planned: e
2805
2805
  })), p = "fresh";
2806
2806
  try {
2807
- yield* ci(e, o);
2808
- let r = yield* li(e);
2807
+ yield* li(e, o);
2808
+ let r = yield* ui(e);
2809
2809
  if (r.length > 0) {
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));
2810
+ let n = yield* _i(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* mi(e, n.runId));
2812
2812
  }
2813
- p === "fresh" && f.length > 0 && (yield* ui(e, d, t.toFingerprint, f)), l.length > 0 && (yield* e.withTransaction(b.gen(function* () {
2813
+ p === "fresh" && f.length > 0 && (yield* di(e, d, t.toFingerprint, f)), l.length > 0 && (yield* e.withTransaction(b.gen(function* () {
2814
2814
  let e = yield* C.SqlClient;
2815
- for (let t of l) a.push(yield* hi(e, t, n));
2815
+ for (let t of l) a.push(yield* gi(e, t, n));
2816
2816
  })));
2817
2817
  for (let { index: t, planned: r } of f) {
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);
2818
+ yield* fi(e, d, t, "started");
2819
+ let i = yield* gi(e, r, n, p);
2820
+ a.push(i), yield* fi(e, d, t, "applied", i.durationMs);
2821
2821
  }
2822
2822
  } finally {
2823
- yield* E(e, { schema: n.lockSchema }).pipe(b.orDie);
2823
+ yield* D(e, { schema: n.lockSchema }).pipe(b.orDie);
2824
2824
  }
2825
2825
  let m = yield* n.replan(e);
2826
2826
  if (m.operations.length > 0) {
2827
2827
  let e = m.operations.slice(0, 10).map((e) => ` - ${e.op.kind} ${"table" in e.op ? e.op.table : ""}${"column" in e.op ? `.${String(e.op.column)}` : ""}`).join("\n");
2828
2828
  return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${t.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${m.operations.length}:\n${e}${m.operations.length > 10 ? `\n … and ${m.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug; the schema is unchanged and safe.\nTwo causes look identical from here, so read the list before assuming either:\n - the DDL for those operations is a no-op (it succeeded and changed nothing), or\n - the planner cannot see what the DDL did, so it proposes the same work again — which is what an\n operation naming an object a PREVIOUS operation created or renamed usually means.\nReport the operation kinds above with the column types involved.`));
2829
2829
  }
2830
- let h = a.filter((e) => e.status === "applied").length, g = Date.now() - i, _ = d, v = (/* @__PURE__ */ new Date()).toISOString(), y = yield* H(e, v), x = [...l, ...f.map((e) => e.planned)];
2830
+ let h = a.filter((e) => e.status === "applied").length, g = Date.now() - i, _ = d, v = (/* @__PURE__ */ new Date()).toISOString(), y = yield* U(e, v), x = [...l, ...f.map((e) => e.planned)];
2831
2831
  yield* e`
2832
2832
  INSERT INTO ${e("_voltro_migration_plans")}
2833
2833
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -2837,7 +2837,7 @@ BEGIN
2837
2837
  (${_}, ${t.toFingerprint}, ${m.fromFingerprint}, ${JSON.stringify(x)},
2838
2838
  ${n.appliedBy}, ${n.environment}, ${n.source},
2839
2839
  ${g}, ${y}, ${n.notes ?? null})
2840
- `, yield* pi(e, d);
2840
+ `, yield* mi(e, d);
2841
2841
  let S = [...new Set(x.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
2842
2842
  return yield* b.promise(() => c({ changedTables: S }).catch(() => {})), {
2843
2843
  id: _,
@@ -2851,14 +2851,14 @@ BEGIN
2851
2851
  source: n.source,
2852
2852
  ...n.notes ? { notes: n.notes } : {}
2853
2853
  };
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`
2854
+ }), yi = (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"), bi = (e) => e`
2855
2855
  SELECT fingerprint
2856
2856
  FROM _voltro_migration_plans
2857
2857
  ORDER BY ${e("appliedAt")} DESC
2858
2858
  LIMIT 1
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";
2861
- let r = `plan_${Date.now().toString(36)}`, i = yield* H(e, (/* @__PURE__ */ new Date()).toISOString());
2859
+ `.pipe(b.map((e) => e.length > 0 ? e[0].fingerprint : void 0), b.catchAll(() => b.succeed(void 0))), xi = (e, t, n) => b.gen(function* () {
2860
+ if ((yield* bi(e)) === t.toFingerprint) return "already-current";
2861
+ let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2862
2862
  return yield* e`
2863
2863
  INSERT INTO ${e("_voltro_migration_plans")}
2864
2864
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -2869,8 +2869,8 @@ BEGIN
2869
2869
  ${n.appliedBy}, ${n.environment}, ${n.source},
2870
2870
  ${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
2871
2871
  `, "recorded";
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);
2872
+ }).pipe(b.catchAll(() => b.succeed("already-current"))), Si = (e, t) => b.gen(function* () {
2873
+ let n = P(I(t, Me(e))), r = yield* bi(e);
2874
2874
  return r === n ? {
2875
2875
  kind: "up-to-date",
2876
2876
  fingerprint: n
@@ -2879,23 +2879,23 @@ BEGIN
2879
2879
  expected: n,
2880
2880
  ...r === void 0 ? {} : { actual: r }
2881
2881
  };
2882
- }), Si = [
2882
+ }), Ci = [
2883
2883
  "pgeagertest_",
2884
2884
  "mig_e2e_",
2885
2885
  "mig_test_",
2886
2886
  "mysqleagertest_",
2887
2887
  "mssqleagertest_",
2888
2888
  "sqliteeagertest_"
2889
- ], Ci = (e) => Si.some((t) => e.startsWith(t)), wi = (e, t) => b.gen(function* () {
2889
+ ], wi = (e) => Ci.some((t) => e.startsWith(t)), Ti = (e, t) => b.gen(function* () {
2890
2890
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2891
- let n = t.filter((e) => Ci(e.name)).map((e) => e.name);
2891
+ let n = t.filter((e) => wi(e.name)).map((e) => e.name);
2892
2892
  if (n.length === 0) return [];
2893
2893
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(b.catchAll(() => b.void));
2894
2894
  return n;
2895
- }), Ti = () => {
2895
+ }), Ei = () => {
2896
2896
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2897
2897
  return e.length > 0 ? { ignoreTables: e } : {};
2898
- }, Ei = (e) => {
2898
+ }, Di = (e) => {
2899
2899
  if (e === void 0) return;
2900
2900
  let t = e.trim();
2901
2901
  if (t === "") return;
@@ -2905,30 +2905,30 @@ BEGIN
2905
2905
  kind: "tables",
2906
2906
  tables: new Set(n)
2907
2907
  } : void 0;
2908
- }, Di = (e) => typeof e.table == "string" ? e.table : void 0, Oi = (e, t = { kind: "all" }) => ({
2908
+ }, Oi = (e) => typeof e.table == "string" ? e.table : void 0, ki = (e, t = { kind: "all" }) => ({
2909
2909
  ...e,
2910
2910
  operations: e.operations.map((e) => {
2911
2911
  if (!e.blocked || e.classification !== "lossy") return e;
2912
2912
  if (t?.kind === "tables") {
2913
- let n = Di(e.op);
2913
+ let n = Oi(e.op);
2914
2914
  if (n === void 0 || !t.tables.has(n)) return e;
2915
2915
  }
2916
2916
  let { blocked: n, ...r } = e;
2917
2917
  return r;
2918
2918
  })
2919
- }), ki = (e, t, n) => t === "postgres" ? qt(e, n).pipe(b.flatMap((e) => {
2919
+ }), Ai = (e, t, n) => t === "postgres" ? qt(e, n).pipe(b.flatMap((e) => {
2920
2920
  let t = Jt(e);
2921
2921
  return t === void 0 ? b.void : b.logWarning(`auto-migrate: ${t}`).pipe(b.annotateLogs({ scope: "voltro:migrate" }));
2922
- }), b.catchAll(() => b.void)) : b.void, Ai = (e, t, n) => b.gen(function* () {
2922
+ }), b.catchAll(() => b.void)) : b.void, ji = (e, t, n) => b.gen(function* () {
2923
2923
  let r = Me(e), i = t;
2924
2924
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2925
- let t = N(F(i, r));
2926
- if ((yield* yi(e)) === t) return yield* ki(e, r, i), {
2925
+ let t = P(I(i, r));
2926
+ if ((yield* bi(e)) === t) return yield* Ai(e, r, i), {
2927
2927
  kind: "up-to-date",
2928
2928
  fingerprint: t
2929
2929
  };
2930
2930
  }
2931
- let a = yield* Jn(e), o = yield* wi(e, a.tables);
2931
+ let a = yield* Jn(e), o = yield* Ti(e, a.tables);
2932
2932
  o.length > 0 && (yield* b.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(b.annotateLogs({
2933
2933
  scope: "voltro:migrate",
2934
2934
  count: o.length
@@ -2937,16 +2937,16 @@ BEGIN
2937
2937
  declared: i,
2938
2938
  live: { tables: c(a.tables) },
2939
2939
  dialect: r,
2940
- ...Ti()
2940
+ ...Ei()
2941
2941
  });
2942
2942
  if (l.summary.blocked > 0) {
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 {
2943
+ let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Di(process.env.VOLTRO_DESTRUCTIVE_OK);
2944
+ if (t === void 0 || !e || (l = ki(l, t), l.operations.some((e) => e.blocked))) return {
2945
2945
  kind: "refused-blocked",
2946
2946
  plan: l
2947
2947
  };
2948
2948
  }
2949
- return l.operations.length === 0 ? (yield* bi(e, l, {
2949
+ return l.operations.length === 0 ? (yield* xi(e, l, {
2950
2950
  appliedBy: n.appliedBy,
2951
2951
  environment: n.environment === "prod" ? "dev" : n.environment,
2952
2952
  source: "auto-diff"
@@ -2955,7 +2955,7 @@ BEGIN
2955
2955
  fingerprint: l.toFingerprint
2956
2956
  }) : {
2957
2957
  kind: "applied",
2958
- applied: yield* _i(e, l, {
2958
+ applied: yield* vi(e, l, {
2959
2959
  declared: t,
2960
2960
  appliedBy: n.appliedBy,
2961
2961
  environment: n.environment === "prod" ? "dev" : n.environment,
@@ -2966,26 +2966,26 @@ BEGIN
2966
2966
  declared: i,
2967
2967
  live: { tables: c(t.tables) },
2968
2968
  dialect: r,
2969
- ...Ti()
2969
+ ...Ei()
2970
2970
  });
2971
2971
  })
2972
2972
  }),
2973
2973
  plan: l
2974
2974
  };
2975
- }), ji = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? b.succeed({
2975
+ }), Mi = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? b.succeed({
2976
2976
  kind: "skipped",
2977
2977
  reason: "VOLTRO_AUTO_MIGRATE=0"
2978
- }) : n.environment === "prod" ? xi(e, t) : Ai(e, t, n), Mi = (e, t) => {
2978
+ }) : n.environment === "prod" ? Si(e, t) : ji(e, t, n), Ni = (e, t) => {
2979
2979
  switch (e.kind) {
2980
2980
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
2981
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
2981
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${F(e.fingerprint)})`;
2982
2982
  case "applied": {
2983
2983
  let t = e.plan.summary;
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)}`;
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=${F(e.applied.fingerprint)}`;
2985
2985
  }
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.";
2986
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${F(e.expected)}` + (e.actual ? ` live=${F(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2987
2987
  case "refused-blocked": {
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 = [""];
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` + yi(e.plan), c = [""];
2989
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) {
2990
2990
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2991
2991
  for (let r of e.plan.operations) {
@@ -3002,7 +3002,7 @@ BEGIN
3002
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");
3003
3003
  }
3004
3004
  }
3005
- }, Ni = /* @__PURE__ */ new Set([
3005
+ }, Pi = /* @__PURE__ */ new Set([
3006
3006
  "node_modules",
3007
3007
  "dist",
3008
3008
  "build",
@@ -3011,11 +3011,11 @@ BEGIN
3011
3011
  ".next",
3012
3012
  ".git",
3013
3013
  ".framework"
3014
- ]), Pi = async (e) => {
3014
+ ]), Fi = async (e) => {
3015
3015
  let t = [], n = async (e) => {
3016
3016
  let r = await te.readdir(e, { withFileTypes: !0 }).catch(() => []);
3017
3017
  for (let i of r) {
3018
- if (Ni.has(i.name)) continue;
3018
+ if (Pi.has(i.name)) continue;
3019
3019
  let r = ne(e, i.name);
3020
3020
  i.isDirectory() ? await n(r) : i.isFile() && u.test(i.name) && t.push(r);
3021
3021
  }
@@ -3024,7 +3024,7 @@ BEGIN
3024
3024
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
3025
3025
  return n.localeCompare(r);
3026
3026
  });
3027
- }, Fi = async (e) => {
3027
+ }, Ii = async (e) => {
3028
3028
  let t = [];
3029
3029
  for (let n of e) {
3030
3030
  let e = (await import(re(n).href)).default;
@@ -3038,11 +3038,11 @@ BEGIN
3038
3038
  });
3039
3039
  }
3040
3040
  return t;
3041
- }, Ii = (e) => e`
3041
+ }, Li = (e) => e`
3042
3042
  SELECT ${e("id")}
3043
3043
  FROM ${e("_voltro_migration_plans")}
3044
3044
  WHERE ${e("source")} = 'file'
3045
- `.pipe(b.map((e) => e.map((e) => e.id)), b.catchAll(() => b.succeed([]))), Li = class extends Error {
3045
+ `.pipe(b.map((e) => e.map((e) => e.id)), b.catchAll(() => b.succeed([]))), Ri = class extends Error {
3046
3046
  migrationId;
3047
3047
  file;
3048
3048
  cause;
@@ -3050,7 +3050,7 @@ BEGIN
3050
3050
  constructor(e, t, n) {
3051
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";
3052
3052
  }
3053
- }, Ri = (e, t, n, r) => b.gen(function* () {
3053
+ }, zi = (e, t, n, r) => b.gen(function* () {
3054
3054
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
3055
3055
  sql: e,
3056
3056
  log: {
@@ -3071,7 +3071,7 @@ BEGIN
3071
3071
  });
3072
3072
  let c = Date.now() - i;
3073
3073
  !b.isEffect(s) && c < 2 && (yield* b.logWarning(`migration ${t.migration.id}: up() resolved in ${c}ms — did the body \`await\` an \`@effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(b.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
3074
- let l = yield* H(e, a);
3074
+ let l = yield* U(e, a);
3075
3075
  return yield* e`
3076
3076
  INSERT INTO ${e("_voltro_migration_plans")}
3077
3077
  (${e("id")}, ${e("fingerprint")}, ${e("operations")},
@@ -3084,10 +3084,10 @@ BEGIN
3084
3084
  }])},
3085
3085
  ${r}, ${n}, ${"file"},
3086
3086
  ${c}, ${l}, ${t.migration.description})
3087
- `.pipe(b.mapError((e) => new Li(t.migration.id, t.file, e))), { durationMs: c };
3088
- }), zi = (e, t) => b.gen(function* () {
3087
+ `.pipe(b.mapError((e) => new Ri(t.migration.id, t.file, e))), { durationMs: c };
3088
+ }), Bi = (e, t) => b.gen(function* () {
3089
3089
  let n = yield* b.tryPromise({
3090
- try: () => Pi(ne(t, "migrations")),
3090
+ try: () => Fi(ne(t, "migrations")),
3091
3091
  catch: (e) => e
3092
3092
  });
3093
3093
  if (n.length === 0) return {
@@ -3095,25 +3095,25 @@ BEGIN
3095
3095
  skipped: []
3096
3096
  };
3097
3097
  let r = yield* b.tryPromise({
3098
- try: () => Fi(n),
3098
+ try: () => Ii(n),
3099
3099
  catch: (e) => e
3100
3100
  });
3101
3101
  if (r.length === 0) return {
3102
3102
  pending: [],
3103
3103
  skipped: []
3104
3104
  };
3105
- let i = new Set(yield* Ii(e));
3105
+ let i = new Set(yield* Li(e));
3106
3106
  return {
3107
3107
  pending: r.filter((e) => !i.has(e.migration.id)),
3108
3108
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
3109
3109
  };
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);
3110
+ }), Vi = (e, t) => Bi(e, t).pipe(b.map((e) => e.pending.map((e) => e.migration.id))), Hi = (e, t) => b.gen(function* () {
3111
+ let { pending: n, skipped: r } = yield* Bi(e, t.projectRoot);
3112
3112
  if (n.length === 0) return {
3113
3113
  applied: [],
3114
3114
  skipped: r
3115
3115
  };
3116
- yield* T(e, { schema: t.lockSchema });
3116
+ yield* E(e, { schema: t.lockSchema });
3117
3117
  let i = [];
3118
3118
  try {
3119
3119
  for (let r of n) {
@@ -3122,7 +3122,7 @@ BEGIN
3122
3122
  id: r.migration.id,
3123
3123
  file: r.file
3124
3124
  }));
3125
- let { durationMs: n } = yield* Ri(e, r, t.env, t.appliedBy);
3125
+ let { durationMs: n } = yield* zi(e, r, t.env, t.appliedBy);
3126
3126
  i.push({
3127
3127
  id: r.migration.id,
3128
3128
  durationMs: n
@@ -3133,28 +3133,28 @@ BEGIN
3133
3133
  }));
3134
3134
  }
3135
3135
  } finally {
3136
- yield* E(e, { schema: t.lockSchema }).pipe(b.orDie);
3136
+ yield* D(e, { schema: t.lockSchema }).pipe(b.orDie);
3137
3137
  }
3138
3138
  return {
3139
3139
  applied: i,
3140
3140
  skipped: r
3141
3141
  };
3142
- }), Hi = (e, t) => e`
3142
+ }), Ui = (e, t) => e`
3143
3143
  SELECT ${e("id")}
3144
3144
  FROM ${e("_voltro_migration_plans")}
3145
3145
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
3146
3146
  LIMIT 1
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)`));
3147
+ `, Wi = (e, t) => b.gen(function* () {
3148
+ if (!(yield* Ui(e, t.id))[0]) return yield* b.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3149
3149
  let n = yield* b.tryPromise({
3150
- try: () => Pi(ne(t.projectRoot, "migrations")),
3150
+ try: () => Fi(ne(t.projectRoot, "migrations")),
3151
3151
  catch: (e) => e
3152
3152
  }), r = (yield* b.tryPromise({
3153
- try: () => Fi(n),
3153
+ try: () => Ii(n),
3154
3154
  catch: (e) => e
3155
3155
  })).find((e) => e.migration.id === t.id);
3156
3156
  if (!r) return yield* b.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3157
- yield* T(e, { schema: t.lockSchema });
3157
+ yield* E(e, { schema: t.lockSchema });
3158
3158
  let i = Date.now();
3159
3159
  try {
3160
3160
  let n = {
@@ -3181,9 +3181,9 @@ BEGIN
3181
3181
  durationMs: o
3182
3182
  };
3183
3183
  } finally {
3184
- yield* E(e, { schema: t.lockSchema }).pipe(b.orDie);
3184
+ yield* D(e, { schema: t.lockSchema }).pipe(b.orDie);
3185
3185
  }
3186
- }), Wi = (e) => b.gen(function* () {
3186
+ }), Gi = (e) => b.gen(function* () {
3187
3187
  let t = yield* C.SqlClient, n = yield* t`
3188
3188
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
3189
3189
  WHERE source = 'auto-diff'
@@ -3228,7 +3228,7 @@ BEGIN
3228
3228
  snapshotFingerprint: e.fingerprint,
3229
3229
  snapshotId: i
3230
3230
  };
3231
- }), Gi = { safe: !0 }, Ki = (e) => {
3231
+ }), Ki = { safe: !0 }, qi = (e) => {
3232
3232
  switch (e.kind) {
3233
3233
  case "drop-column": return {
3234
3234
  safe: !1,
@@ -3255,7 +3255,7 @@ BEGIN
3255
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`,
3256
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"
3257
3257
  };
3258
- case "alter-column-nullability": return e.toNullable ? Gi : {
3258
+ case "alter-column-nullability": return e.toNullable ? Ki : {
3259
3259
  safe: !1,
3260
3260
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
3261
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)`
@@ -3285,12 +3285,12 @@ BEGIN
3285
3285
  case "drop-unique":
3286
3286
  case "drop-unique-composite":
3287
3287
  case "drop-foreign-key":
3288
- case "drop-check": return Gi;
3288
+ case "drop-check": return Ki;
3289
3289
  }
3290
- }, qi = (e) => {
3290
+ }, Ji = (e) => {
3291
3291
  let t = [];
3292
3292
  for (let n of e) {
3293
- let e = Ki(n.op);
3293
+ let e = qi(n.op);
3294
3294
  e.safe || t.push({
3295
3295
  op: n,
3296
3296
  reason: e.reason,
@@ -3298,7 +3298,7 @@ BEGIN
3298
3298
  });
3299
3299
  }
3300
3300
  return t;
3301
- }, Ji = (e) => {
3301
+ }, Yi = (e) => {
3302
3302
  if (!e.enabled || e.unsafeCount === 0) return {
3303
3303
  refuse: !1,
3304
3304
  warnForced: !1,
@@ -3314,18 +3314,18 @@ BEGIN
3314
3314
  warnForced: !1,
3315
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.`
3316
3316
  };
3317
- }, Yi = (e) => {
3317
+ }, Xi = (e) => {
3318
3318
  let t = e.table;
3319
3319
  if (typeof t == "string") return t;
3320
3320
  let n = e.from;
3321
3321
  return typeof n == "string" ? n : void 0;
3322
- }, Xi = (e) => ({
3322
+ }, Zi = (e) => ({
3323
3323
  kind: e.op.kind,
3324
- table: Yi(e.op),
3324
+ table: Xi(e.op),
3325
3325
  classification: e.classification,
3326
3326
  reason: e.reason,
3327
3327
  blockedFix: e.blocked?.fix
3328
- }), Zi = (e) => e.operations.map(Xi), Qi = async (e) => {
3328
+ }), Qi = (e) => e.operations.map(Zi), $i = async (e) => {
3329
3329
  let t = e.log ?? (() => {}), n = {
3330
3330
  branchId: e.branchId,
3331
3331
  mechanism: e.mechanism,
@@ -3344,10 +3344,10 @@ BEGIN
3344
3344
  applied: !1,
3345
3345
  converged: !1,
3346
3346
  residual: r,
3347
- infidelity: Zi(o)
3347
+ infidelity: Qi(o)
3348
3348
  };
3349
3349
  else {
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);
3350
+ let i = await e.plan(), o = Qi(i), s = o.filter((e) => e.classification === "lossy"), c = ki(i), l = c.operations.filter((e) => e.blocked !== void 0).map(Zi);
3351
3351
  if (l.length > 0) a = {
3352
3352
  ...n,
3353
3353
  outcome: "blocked",
@@ -3372,7 +3372,7 @@ BEGIN
3372
3372
  };
3373
3373
  else {
3374
3374
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
3375
- let i = Zi(await e.replan());
3375
+ let i = Qi(await e.replan());
3376
3376
  a = {
3377
3377
  ...n,
3378
3378
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -3410,7 +3410,7 @@ BEGIN
3410
3410
  ...a,
3411
3411
  tornDown: o
3412
3412
  };
3413
- }, $i = (e) => {
3413
+ }, ea = (e) => {
3414
3414
  switch (e.outcome) {
3415
3415
  case "clean": return 0;
3416
3416
  case "lossy": return 2;
@@ -3419,22 +3419,22 @@ BEGIN
3419
3419
  case "infidelity": return 1;
3420
3420
  case "failed": return 1;
3421
3421
  }
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) => {
3422
+ }, ta = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, na = (e) => {
3423
3423
  let t = [];
3424
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"}`);
3425
3425
  else if (e.outcome === "infidelity") {
3426
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:");
3427
- for (let n of e.infidelity) t.push(ea(n));
3427
+ for (let n of e.infidelity) t.push(ta(n));
3428
3428
  } else {
3429
3429
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
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));
3430
+ for (let n of e.operations) t.push(ta(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(ta(n));
3432
3432
  }
3433
3433
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
3434
- }, na = (e, ...t) => ({
3434
+ }, ra = (e, ...t) => ({
3435
3435
  _tag: "RawSqlFragment",
3436
3436
  strings: [...e],
3437
3437
  values: [...t]
3438
- }), ra = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3438
+ }), ia = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3439
3439
  //#endregion
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 };
3440
+ export { k as DEFAULT_CDC_CHANNEL, u as FILE_MIGRATION_PATTERN, Ri as FileMigrationLedgerError, Ke as REACTIVE_TRIGGER_PREFIX, fe as VOLTRO_MIGRATION_LOCK_KEY, E as acquireMigrationLock, U as appliedAtValue, Ft as applyNamespacedSchema, vi as applyPlan, Tt as applySchema, Yi as assessRollingDeployGate, ea as branchRehearsalExitCode, In as chunkTables, qi as classifyRollingDeploySafety, I as declaredSnapshot, Qe as defaultArrayClause, Ze as defaultClause, M as defaultJsonClause, Ni as describeOutcome, Di as destructiveScope, qt as detectReactiveTriggerDrift, Ir as emitAddIndexMysql, _r as emitCreateTableMysql, er as emitDropColumnDdl, tr as emitDropColumnDdlMysql, wt as emitFrameworkBootstrapSql, St as emitNamespaceProvisionDdl, Ct as emitNamespacedSchemaSql, xt as emitSchemaSql, P as fingerprintSchema, ve as fnv1a64, na as formatBranchRehearsal, Jt as formatReactiveTriggerDrift, Ei as ignoreTablesFromEnv, Jn as introspectSchema, o as isFileMigration, ia as isRawSqlFragment, Dt as isReRunSafeDdl, jn as mapPgType, h as migration, ye as migrationLockKeyForSchema, T as migrationLockNameForSchema, Mr as mysqlIndexPrefixFor, Je as notifyFunctionName, N as numericIdSql, An as parseEnumCheck, Vi as pendingFileMigrationIds, kn as planMigrations, It as provisionTenantNamespace, qe as reactiveTriggerName, ft as reactiveTriggerRepairSql, xi as recordUpToDate, $i as rehearseMigrationOnBranch, Zi as rehearsedOperation, D as releaseMigrationLock, gr as renderColumnMysql, dr as renderColumnPg, me as resolveMigrationLockSchema, Wi as rollbackFileBasedMigration, Ji as rollingDeployUnsafeOps, Hi as runFileBasedMigrations, Lt as runFrameworkBootstrap, Pt as runMigrate, Mi as runPlannedMigrations, F as shortFingerprint, Ut as snapshotColumn, ra as sql, j as sqlType, Gi as squashMigrationPlans, ki as unblockLossy, je as withMigrationLock };