@voltro/database 0.42.0 → 0.43.1

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
@@ -94,67 +94,67 @@ var ae = (e, t, n, r = 400) => {
94
94
  }, be = (e) => {
95
95
  let t = me(e);
96
96
  return t === void 0 ? pe : ye(`voltro_migration_lock:${t}`) & 9223372036854775807n;
97
- }, T = (e) => {
97
+ }, xe = (e) => {
98
98
  let t = `voltro_migration_${pe.toString(36)}`, n = me(e);
99
99
  if (n === void 0) return t;
100
100
  let r = `${t}_${n}`;
101
101
  return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(ye(`voltro_migration_lock:${n}`) & ve).toString(16)}`;
102
- }, xe = 250, Se = () => {
102
+ }, Se = 250, Ce = () => {
103
103
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
104
104
  return Number.isFinite(e) && e > 0 ? e : 3e4;
105
- }, Ce = (e, t) => x.gen(function* () {
106
- let n = Se(), r = Date.now();
105
+ }, we = (e, t) => x.gen(function* () {
106
+ let n = Ce(), r = Date.now();
107
107
  for (;;) {
108
108
  if ((yield* e`
109
109
  SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`)[0]?.got) return;
110
- Date.now() - r >= n && (yield* x.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* x.sleep(`${xe} millis`);
110
+ Date.now() - r >= n && (yield* x.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* x.sleep(`${Se} millis`);
111
111
  }
112
- }), we = (e, t) => x.gen(function* () {
112
+ }), Te = (e, t) => x.gen(function* () {
113
113
  yield* e`SELECT pg_advisory_unlock(${t.toString()}::bigint)`;
114
- }), Te = 30, Ee = (e, t) => x.gen(function* () {
114
+ }), Ee = 30, De = (e, t) => x.gen(function* () {
115
115
  (yield* e`
116
- SELECT GET_LOCK(${t}, ${Te}) AS got`)[0]?.got !== 1 && (yield* x.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Te}s (another migration is in progress, or a prior one left it held).`)));
117
- }), De = (e, t) => x.gen(function* () {
116
+ SELECT GET_LOCK(${t}, ${Ee}) AS got`)[0]?.got !== 1 && (yield* x.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Ee}s (another migration is in progress, or a prior one left it held).`)));
117
+ }), Oe = (e, t) => x.gen(function* () {
118
118
  yield* e`SELECT RELEASE_LOCK(${t})`;
119
- }), Oe = 3e4, ke = (e, t) => x.gen(function* () {
119
+ }), ke = 3e4, Ae = (e, t) => x.gen(function* () {
120
120
  let n = yield* e`
121
121
  DECLARE @res int;
122
122
  EXEC @res = sp_getapplock @Resource = ${t}, @LockMode = 'Exclusive',
123
- @LockOwner = 'Session', @LockTimeout = ${Oe};
123
+ @LockOwner = 'Session', @LockTimeout = ${ke};
124
124
  SELECT @res AS res`;
125
125
  (n[0]?.res ?? -999) < 0 && (yield* x.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
126
- }), Ae = (e, t) => x.gen(function* () {
126
+ }), je = (e, t) => x.gen(function* () {
127
127
  yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
128
- }), je = x.void, E = (e, t) => {
128
+ }), Me = x.void, T = (e, t) => {
129
129
  let n = he(t);
130
130
  return e.onDialectOrElse({
131
- mysql: () => Ee(e, T(n)),
132
- mssql: () => ke(e, T(n)),
133
- sqlite: () => je,
134
- orElse: () => Ce(e, be(n))
131
+ mysql: () => De(e, xe(n)),
132
+ mssql: () => Ae(e, xe(n)),
133
+ sqlite: () => Me,
134
+ orElse: () => we(e, be(n))
135
135
  });
136
- }, D = (e, t) => {
136
+ }, E = (e, t) => {
137
137
  let n = he(t);
138
138
  return e.onDialectOrElse({
139
- mysql: () => De(e, T(n)),
140
- mssql: () => Ae(e, T(n)),
141
- sqlite: () => je,
142
- orElse: () => we(e, be(n))
139
+ mysql: () => Oe(e, xe(n)),
140
+ mssql: () => je(e, xe(n)),
141
+ sqlite: () => Me,
142
+ orElse: () => Te(e, be(n))
143
143
  });
144
- }, Me = (e, t, n) => x.acquireUseRelease(E(e, n), () => t, () => D(e, n).pipe(x.orDie)), Ne = (e) => e.onDialectOrElse({
144
+ }, Ne = (e, t, n) => x.acquireUseRelease(T(e, n), () => t, () => E(e, n).pipe(x.orDie)), Pe = (e) => e.onDialectOrElse({
145
145
  pg: () => "postgres",
146
146
  mysql: () => "mysql",
147
147
  mssql: () => "mssql",
148
148
  sqlite: () => "sqlite",
149
149
  orElse: () => "sqlite"
150
- }), Pe = {
150
+ }), Fe = {
151
151
  postgres: "plan-transactional",
152
152
  mssql: "plan-transactional",
153
153
  mysql: "per-operation",
154
154
  mariadb: "per-operation",
155
155
  sqlite: "per-operation",
156
156
  turso: "per-operation"
157
- }, Fe = (e) => Pe[e], O = "_voltro_migration_ops", Ie = y(O, {
157
+ }, Ie = (e) => Fe[e], D = "_voltro_migration_ops", Le = y(D, {
158
158
  id: t({ prefix: "mop" }),
159
159
  runId: e(),
160
160
  planFingerprint: e(),
@@ -167,7 +167,7 @@ var ae = (e, t, n, r = 400) => {
167
167
  appliedAt: a().nullable(),
168
168
  durationMs: r().nullable(),
169
169
  createdAt: a().default("now")
170
- }), Le = (e) => {
170
+ }), Re = (e) => {
171
171
  switch (e.kind) {
172
172
  case "create-table": return /* @__PURE__ */ new Set([
173
173
  `table:${e.table}`,
@@ -194,11 +194,11 @@ var ae = (e, t, n, r = 400) => {
194
194
  case "add-unique-composite":
195
195
  case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
196
196
  }
197
- }, Re = (e) => [...Le(e)].join(" "), ze = (e, t) => {
198
- let n = Le(t);
199
- for (let t of Le(e)) if (n.has(t)) return !0;
197
+ }, ze = (e) => [...Re(e)].join(" "), Be = (e, t) => {
198
+ let n = Re(t);
199
+ for (let t of Re(e)) if (n.has(t)) return !0;
200
200
  return !1;
201
- }, Be = (e, t) => e.operations.some((e) => ze(e.op, t)), Ve = "__voltro_rebuild", He = "__shadow", Ue = "__old", We = /* @__PURE__ */ new Set([
201
+ }, Ve = (e, t) => e.operations.some((e) => Be(e.op, t)), He = "__voltro_rebuild", Ue = "__shadow", We = "__old", Ge = /* @__PURE__ */ new Set([
202
202
  "add-unique",
203
203
  "drop-unique",
204
204
  "add-unique-composite",
@@ -210,16 +210,16 @@ var ae = (e, t, n, r = 400) => {
210
210
  "alter-column-nullability",
211
211
  "alter-column-type",
212
212
  "alter-column-default"
213
- ]), Ge = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Ke = (e, t, n) => {
213
+ ]), Ke = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), qe = (e, t, n) => {
214
214
  let r = n === "sqlite" || n === "turso";
215
- return e.kind === "alter-column-type" && t === "online-required" || r && We.has(e.kind) ? "artefact-repair" : Ge.has(e.kind) ? "idempotent" : "probe-then-replay";
215
+ return e.kind === "alter-column-type" && t === "online-required" || r && Ge.has(e.kind) ? "artefact-repair" : Ke.has(e.kind) ? "idempotent" : "probe-then-replay";
216
216
  };
217
- Object.keys(Pe);
217
+ Object.keys(Fe);
218
218
  //#endregion
219
219
  //#region src/migrations/reactiveTriggerName.ts
220
- var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "framework_changes" ? `${qe}${e}` : `${qe}${t}_${e}`, Ye = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Xe = "voltro:notify:v2", Ze = ee({ scope: "voltro:migrate" }), A = (e) => {
221
- Ze.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
222
- }, j = (e, t) => {
220
+ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "framework_changes" ? `${Je}${e}` : `${Je}${t}_${e}`, Xe = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Ze = "voltro:notify:v2", Qe = ee({ scope: "voltro:migrate" }), k = (e) => {
221
+ Qe.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
222
+ }, A = (e, t) => {
223
223
  let n = e.type;
224
224
  if (e.spatial) {
225
225
  if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
@@ -230,7 +230,7 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
230
230
  return e.rawDdl;
231
231
  }
232
232
  if (n === "array" && e.arrayElement) {
233
- if (t === "postgres") return `${j({
233
+ if (t === "postgres") return `${A({
234
234
  ...e,
235
235
  type: e.arrayElement,
236
236
  arrayElement: void 0
@@ -330,22 +330,22 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
330
330
  case "array": return "TEXT[]";
331
331
  case "interval": return "INTERVAL";
332
332
  }
333
- }, Qe = (e, t) => {
333
+ }, $e = (e, t) => {
334
334
  if (!e.hasDefault || e.defaultFactory !== void 0) return null;
335
335
  let n = e.defaultValue;
336
- return n === "now" ? o(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) ? $e(n, e, t) : typeof n == "object" && n ? M(n, t) : null;
337
- }, $e = (e, t, n) => {
338
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return M(e, n);
339
- let r = j({
336
+ return n === "now" ? o(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) ? et(n, e, t) : typeof n == "object" && n ? j(n, t) : null;
337
+ }, et = (e, t, n) => {
338
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return j(e, n);
339
+ let r = A({
340
340
  ...t,
341
341
  type: t.arrayElement,
342
342
  arrayElement: void 0
343
343
  }, n);
344
344
  return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
345
- }, M = (e, t) => {
345
+ }, j = (e, t) => {
346
346
  let n = JSON.stringify(e).replace(/'/g, "''");
347
347
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
348
- }, N = (e, t) => {
348
+ }, M = (e, t) => {
349
349
  switch (t) {
350
350
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
351
351
  case "mysql":
@@ -354,7 +354,7 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
354
354
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
355
355
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
356
356
  }
357
- }, P = (e, t) => {
357
+ }, N = (e, t) => {
358
358
  if (e === "restrict" && t === "mssql") return "NO ACTION";
359
359
  switch (e) {
360
360
  case "cascade": return "CASCADE";
@@ -362,42 +362,42 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
362
362
  case "setNull": return "SET NULL";
363
363
  case "noAction": return "NO ACTION";
364
364
  }
365
- }, et = (e, t, r) => r === null ? n(e, t) : `${n(r, t)}.${n(e, t)}`, tt = 191, nt = (e, t) => {
365
+ }, tt = (e, t, r) => r === null ? n(e, t) : `${n(r, t)}.${n(e, t)}`, nt = 191, rt = (e, t) => {
366
366
  if (!e || t !== "mysql" && t !== "mariadb") return !1;
367
- let n = j(e, t).toUpperCase();
367
+ let n = A(e, t).toUpperCase();
368
368
  return n.endsWith("TEXT") || n.endsWith("BLOB");
369
- }, rt = (e, t, r) => {
369
+ }, it = (e, t, r) => {
370
370
  let i = n(e, r);
371
371
  if (r !== "mysql" && r !== "mariadb") return i;
372
372
  let a = t[e];
373
373
  if (!a) return i;
374
- let o = j(a, r).toUpperCase();
375
- return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${tt})` : i;
376
- }, it = (e, t) => {
374
+ let o = A(a, r).toUpperCase();
375
+ return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${nt})` : i;
376
+ }, at = (e, t) => {
377
377
  if (!e.generatedAs) return null;
378
378
  let { expr: n, stored: r } = e.generatedAs;
379
- if (t === "postgres") return r || A("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
379
+ if (t === "postgres") return r || k("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
380
380
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
381
381
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
382
382
  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.");
383
383
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
384
- }, at = (e, t, r, a, s = !1, c = !1) => {
385
- if (t.type === "id" && t.idScheme?.kind === "numeric") return N(e, r);
386
- let l = r === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" : j(t, r), u = [n(e, r), l];
384
+ }, ot = (e, t, r, a, s = !1, c = !1) => {
385
+ if (t.type === "id" && t.idScheme?.kind === "numeric") return M(e, r);
386
+ let l = r === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" : A(t, r), u = [n(e, r), l];
387
387
  t.type === "id" && !c && u.push("PRIMARY KEY");
388
- let d = it(t, r);
388
+ let d = at(t, r);
389
389
  if (d) u.push(d);
390
390
  else {
391
- t.nullable || u.push("NOT NULL"), t.unique && t.type !== "id" && !nt(t, r) && u.push("UNIQUE");
392
- let e = Qe(t, r);
391
+ t.nullable || u.push("NOT NULL"), t.unique && t.type !== "id" && !rt(t, r) && u.push("UNIQUE");
392
+ let e = $e(t, r);
393
393
  e && u.push(e);
394
394
  }
395
395
  if (t.type === "reference" && t.references && !s && !i(r)) {
396
396
  let e = t.references();
397
397
  u.push(`REFERENCES ${n(e.tableName, r)} (${n("id", r)})`);
398
- let i = P(t.onDelete ?? "restrict", r);
398
+ let i = N(t.onDelete ?? "restrict", r);
399
399
  u.push(`ON DELETE ${i}`);
400
- let a = P(t.refOnUpdate ?? "noAction", r);
400
+ let a = N(t.refOnUpdate ?? "noAction", r);
401
401
  a !== "NO ACTION" && u.push(`ON UPDATE ${a}`);
402
402
  }
403
403
  if (t.oneOf && t.oneOf.length > 0) {
@@ -414,23 +414,23 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
414
414
  o(r) ? u.push(`CHECK (${t} IS NULL OR json_valid(${t}))`) : r === "mssql" && u.push(`CHECK (${t} IS NULL OR ISJSON(${t}) = 1)`);
415
415
  }
416
416
  return u.join(" ");
417
- }, ot = (e, t, r = null, a) => {
417
+ }, st = (e, t, r = null, a) => {
418
418
  let o = /* @__PURE__ */ new Set();
419
419
  for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && o.add(e);
420
420
  for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && o.add(e);
421
- let s = e.appliedPrimaryKey ?? [], c = s.length > 0, l = Object.entries(e.fields).map(([e, n]) => ` ${at(e, n, t, o, a?.has(e) ?? !1, c)}`).join(",\n"), u = (e.appliedUniques ?? []).map((r) => {
422
- let i = r.fields.map((n) => rt(n, e.fields, t)).join(", ");
421
+ let s = e.appliedPrimaryKey ?? [], c = s.length > 0, l = Object.entries(e.fields).map(([e, n]) => ` ${ot(e, n, t, o, a?.has(e) ?? !1, c)}`).join(",\n"), u = (e.appliedUniques ?? []).map((r) => {
422
+ let i = r.fields.map((n) => it(n, e.fields, t)).join(", ");
423
423
  return ` CONSTRAINT ${n(r.name, t)} UNIQUE (${i})`;
424
- }), d = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${n(e.name, t)} CHECK (${e.expr})`), f = c ? [` PRIMARY KEY (${s.map((n) => rt(n, e.fields, t)).join(", ")})`] : [], p = i(t) ? Object.entries(e.fields).flatMap(([i, o]) => {
424
+ }), d = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${n(e.name, t)} CHECK (${e.expr})`), f = c ? [` PRIMARY KEY (${s.map((n) => it(n, e.fields, t)).join(", ")})`] : [], p = i(t) ? Object.entries(e.fields).flatMap(([i, o]) => {
425
425
  if (o.type !== "reference" || !o.references || (a?.has(i) ?? !1)) return [];
426
- let s = o.references(), c = P(o.onDelete ?? "restrict", t), l = P(o.refOnUpdate ?? "noAction", t);
427
- return [` CONSTRAINT ${n(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${n(i, t)}) REFERENCES ${et(s.tableName, t, r)} (${n("id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
426
+ let s = o.references(), c = N(o.onDelete ?? "restrict", t), l = N(o.refOnUpdate ?? "noAction", t);
427
+ return [` CONSTRAINT ${n(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${n(i, t)}) REFERENCES ${tt(s.tableName, t, r)} (${n("id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
428
428
  }) : [], m = [
429
429
  ...f,
430
430
  ...u,
431
431
  ...d,
432
432
  ...p
433
- ], h = m.length > 0 ? `${l},\n${m.join(",\n")}` : l, g = et(e.tableName, t, r);
433
+ ], h = m.length > 0 ? `${l},\n${m.join(",\n")}` : l, g = tt(e.tableName, t, r);
434
434
  if (t === "mssql") {
435
435
  let t = r === null ? e.tableName : `${r}.${e.tableName}`, n = `CREATE TABLE ${g} (\n${h}\n)`;
436
436
  return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
@@ -440,10 +440,10 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
440
440
  h,
441
441
  ");"
442
442
  ].join("\n");
443
- }, st = (e, t, r) => {
443
+ }, ct = (e, t, r) => {
444
444
  let i = `${e}_${t.name}_fts`, a = (e) => n(e, r), o = t.columns.map(a).join(", "), s = t.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
445
445
  return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(i)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ai`)} AFTER INSERT ON ${a(e)} BEGIN\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ad`)} AFTER DELETE ON ${a(e)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_au`)} AFTER UPDATE ON ${a(e)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
446
- }, ct = (e, t, r = null) => {
446
+ }, lt = (e, t, r = null) => {
447
447
  let i = [], a = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, n, r, i) => {
448
448
  let a = {
449
449
  using: "",
@@ -455,21 +455,21 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
455
455
  using: " USING GIST",
456
456
  withSuffix: "",
457
457
  skip: !1
458
- } : (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);
458
+ } : (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);
459
459
  if (r === "gin") return t === "postgres" ? {
460
460
  using: " USING GIN",
461
461
  withSuffix: "",
462
462
  skip: !1
463
- } : 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(...).`), {
463
+ } : 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(...).`), {
464
464
  using: "",
465
465
  withSuffix: "",
466
466
  skip: !0
467
- }) : (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);
467
+ }) : (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);
468
468
  if (r === "brin") return t === "postgres" ? {
469
469
  using: " USING BRIN",
470
470
  withSuffix: "",
471
471
  skip: !1
472
- } : (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);
472
+ } : (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);
473
473
  if (r === "hnsw") {
474
474
  if (t === "postgres") {
475
475
  let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? h(i?.hnsw?.distance);
@@ -480,7 +480,7 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
480
480
  skip: !1
481
481
  };
482
482
  }
483
- 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.`), {
483
+ 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.`), {
484
484
  using: "",
485
485
  withSuffix: "",
486
486
  skip: !0
@@ -489,7 +489,7 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
489
489
  return a;
490
490
  }, c = (n, r) => {
491
491
  let i = n.map((n) => {
492
- if (typeof n == "string") return rt(n, e.fields, t);
492
+ if (typeof n == "string") return it(n, e.fields, t);
493
493
  if ("jsonPath" in n) {
494
494
  let { column: e, path: r, numeric: i } = n.jsonPath;
495
495
  return `(${_(e, r, t, { numeric: i })})`;
@@ -500,11 +500,11 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
500
500
  }, l = (e, i, a, o, l, u = "", d = !1) => {
501
501
  let f = s(e, i, o, l);
502
502
  if (f.skip) return "";
503
- let p = c(a, f.opclass), m = `${f.withSuffix}${u}`, h = et(i, t, r), g = d ? "UNIQUE " : "";
503
+ let p = c(a, f.opclass), m = `${f.withSuffix}${u}`, h = tt(i, t, r), g = d ? "UNIQUE " : "";
504
504
  return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${n(e, t)} ON ${h}${f.using} (${p})${m};` : t === "mysql" ? `CREATE ${g}INDEX ${n(e, t)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${n(e, t)} ON ${h}${f.using} (${p})${m};`;
505
505
  };
506
506
  if (t === "mysql" || t === "mariadb") for (let [n, r] of Object.entries(e.fields)) {
507
- if (!r.unique || r.type === "id" || !nt(r, t)) continue;
507
+ if (!r.unique || r.type === "id" || !rt(r, t)) continue;
508
508
  let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
509
509
  a && i.push(a);
510
510
  }
@@ -518,15 +518,15 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
518
518
  let a = r.columns.map((e) => n(e, t)).join(", ");
519
519
  i.push(`CREATE FULLTEXT INDEX ${n(r.name, t)} ON ${n(e.tableName, t)} (${a});`);
520
520
  } else if (t === "turso") throw Error(`@voltro/sql-turso: full-text index '${r.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.`);
521
- else t === "sqlite" ? i.push(...st(e.tableName, r, t)) : A(`[voltro:migrate] full-text index '${r.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
521
+ else t === "sqlite" ? i.push(...ct(e.tableName, r, t)) : k(`[voltro:migrate] full-text index '${r.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
522
522
  for (let n of e.appliedIndexes) {
523
523
  if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
524
- 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(...).`);
524
+ 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(...).`);
525
525
  continue;
526
526
  }
527
527
  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.`);
528
528
  let r = "";
529
- 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`) : r = ` WHERE ${n.where}`);
529
+ 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`) : r = ` WHERE ${n.where}`);
530
530
  let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, r, n.unique === !0);
531
531
  s !== "" && i.push(s), n.fields.every((e) => typeof e == "string") && a.add(o(n.fields));
532
532
  }
@@ -536,17 +536,17 @@ var k = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
536
536
  i.push(l(r, e.tableName, [t])), a.add(o([t]));
537
537
  }
538
538
  return i.join("\n");
539
- }, lt = (e, t, n = k) => {
539
+ }, ut = (e, t, n = O) => {
540
540
  if (t !== "postgres") return [];
541
541
  let r = e.filter((e) => e.isReactive !== !1);
542
- return r.length === 0 ? [] : [ut(n), ...r.map((e) => ft(e, n))];
543
- }, ut = (e) => `
544
- CREATE OR REPLACE FUNCTION ${Ye(e)}() RETURNS trigger AS $$
542
+ return r.length === 0 ? [] : [dt(n), ...r.map((e) => pt(e, n))];
543
+ }, dt = (e) => `
544
+ CREATE OR REPLACE FUNCTION ${Xe(e)}() RETURNS trigger AS $$
545
545
  DECLARE
546
546
  payload TEXT;
547
547
  pk JSONB;
548
548
  BEGIN
549
- -- ${Xe}
549
+ -- ${Ze}
550
550
  payload := json_build_object(
551
551
  'table', TG_TABLE_NAME,
552
552
  -- The schema the write landed in. Under namespace isolation this is
@@ -600,21 +600,21 @@ BEGIN
600
600
  RETURN COALESCE(NEW, OLD);
601
601
  END;
602
602
  $$ LANGUAGE plpgsql;
603
- `.trim(), dt = (e, t) => {
604
- let n = Je(e.tableName, t);
603
+ `.trim(), ft = (e, t) => {
604
+ let n = Ye(e.tableName, t);
605
605
  return [
606
606
  `ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
607
607
  `DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
608
- `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Ye(t)}()`
608
+ `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Xe(t)}()`
609
609
  ];
610
- }, ft = (e, t) => dt(e, t).map((e) => `${e};`).join("\n"), pt = (e) => {
610
+ }, pt = (e, t) => ft(e, t).map((e) => `${e};`).join("\n"), mt = (e) => {
611
611
  if (e.dialect !== "postgres") return [];
612
612
  let t = e.channel ?? "framework_changes", n = new Map(e.tables.map((e) => [e.tableName, e])), r = [], i = e.missing.filter((e) => n.has(e));
613
- (i.length > 0 || e.functionOutdated === !0) && r.push(ut(t));
614
- for (let e of i) r.push(...dt(n.get(e), t));
615
- for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Je(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
613
+ (i.length > 0 || e.functionOutdated === !0) && r.push(dt(t));
614
+ for (let e of i) r.push(...ft(n.get(e), t));
615
+ for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Ye(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
616
616
  return r;
617
- }, mt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), ht = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), gt = (e) => {
617
+ }, ht = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), gt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), _t = (e) => {
618
618
  let t = new Map(e.map((e) => [e.tableName, e])), n = fe(e.map((e) => e.tableName), (e) => {
619
619
  let n = t.get(e);
620
620
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
@@ -651,8 +651,8 @@ $$ LANGUAGE plpgsql;
651
651
  sorted: o,
652
652
  cyclic: r
653
653
  };
654
- }, _t = (e, t, r = null) => {
655
- let i = (e) => r ? `${n(r, t)}.${n(e, t)}` : n(e, t), a = `${e.table}_${e.column}_fkey`, o = P(e.onDelete, t), s = P(e.onUpdate, t), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${n(a, t)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${n(e.column, t)}) REFERENCES ${i(e.targetTable)} (${n("id", t)})${c}`;
654
+ }, vt = (e, t, r = null) => {
655
+ let i = (e) => r ? `${n(r, t)}.${n(e, t)}` : n(e, t), a = `${e.table}_${e.column}_fkey`, o = N(e.onDelete, t), s = N(e.onUpdate, t), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${n(a, t)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${n(e.column, t)}) REFERENCES ${i(e.targetTable)} (${n("id", t)})${c}`;
656
656
  switch (t) {
657
657
  case "postgres": return [
658
658
  "DO $$ BEGIN",
@@ -666,7 +666,7 @@ $$ LANGUAGE plpgsql;
666
666
  case "mariadb": return `ALTER TABLE ${i(e.table)} ${l(!0)};`;
667
667
  default: return `ALTER TABLE ${i(e.table)} ${l(!1)};`;
668
668
  }
669
- }, vt = (e, t) => {
669
+ }, yt = (e, t) => {
670
670
  let n = /* @__PURE__ */ new Map();
671
671
  if (o(t)) return n;
672
672
  for (let t of e) {
@@ -674,7 +674,7 @@ $$ LANGUAGE plpgsql;
674
674
  e.add(t.column), n.set(t.table, e);
675
675
  }
676
676
  return n;
677
- }, yt = (e, t) => {
677
+ }, bt = (e, t) => {
678
678
  if (t !== "postgres") return "";
679
679
  let n = /* @__PURE__ */ new Map();
680
680
  for (let t of e) for (let e of Object.values(t.fields)) {
@@ -690,7 +690,7 @@ $$ LANGUAGE plpgsql;
690
690
  r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
691
691
  }
692
692
  return r.join("\n\n");
693
- }, bt = (e, t) => {
693
+ }, xt = (e, t) => {
694
694
  if (t !== "postgres") return "";
695
695
  let n = /* @__PURE__ */ new Set();
696
696
  for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
@@ -704,30 +704,30 @@ BEGIN
704
704
  SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
705
705
  }
706
706
  return r.join("\n\n");
707
- }, xt = (e) => {
707
+ }, St = (e) => {
708
708
  let t = [], n = [];
709
709
  for (let r of e) p(r) ? n.push(r) : t.push(r);
710
710
  return {
711
711
  tables: t,
712
712
  views: n
713
713
  };
714
- }, St = (e, t, n = k) => {
715
- let { tables: r, views: i } = xt(e), { sorted: a, cyclic: c } = gt(r.map((e) => de(e, t))), l = vt(c, t), u = [];
716
- t === "postgres" && mt(a) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && ht(a) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
717
- let d = bt(a, t);
714
+ }, Ct = (e, t, n = O) => {
715
+ let { tables: r, views: i } = St(e), { sorted: a, cyclic: c } = _t(r.map((e) => de(e, t))), l = yt(c, t), u = [];
716
+ t === "postgres" && ht(a) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && gt(a) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
717
+ let d = xt(a, t);
718
718
  d && u.push(d);
719
- let f = yt(a, t);
719
+ let f = bt(a, t);
720
720
  f && u.push(f);
721
- for (let e of a) u.push(ot(e, t, null, l.get(e.tableName)));
722
- if (!o(t)) for (let e of c) u.push(_t(e, t));
721
+ for (let e of a) u.push(st(e, t, null, l.get(e.tableName)));
722
+ if (!o(t)) for (let e of c) u.push(vt(e, t));
723
723
  for (let e of a) {
724
- let n = ct(e, t);
724
+ let n = lt(e, t);
725
725
  n && u.push(n);
726
726
  }
727
- u.push(...lt(a, t, n));
727
+ u.push(...ut(a, t, n));
728
728
  for (let e of i) u.push(s(e, t));
729
729
  return u.join("\n\n") + "\n";
730
- }, Ct = (e, t, r) => {
730
+ }, wt = (e, t, r) => {
731
731
  let i = n(e, t);
732
732
  switch (t) {
733
733
  case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
@@ -737,62 +737,62 @@ BEGIN
737
737
  case "turso":
738
738
  case "sqlite": return `ATTACH DATABASE '${(r ?? `${e}.db`).replace(/'/g, "''")}' AS ${i};`;
739
739
  }
740
- }, wt = (e, t, r, i) => {
741
- let a = Ct(r, t, i), s = n(r, t);
742
- if (t === "postgres") return `${a}\n\nSET search_path TO ${s};\n\n${St(e, t)}`;
743
- if (t === "mysql" || t === "mariadb") return `${a}\n\nUSE ${s};\n\n${St(e, t)}`;
744
- let { sorted: c, cyclic: l } = gt(e), u = vt(l, t), d = [a];
745
- for (let e of c) d.push(ot(e, t, r, u.get(e.tableName)));
746
- if (!o(t)) for (let e of l) d.push(_t(e, t, r));
740
+ }, Tt = (e, t, r, i) => {
741
+ let a = wt(r, t, i), s = n(r, t);
742
+ if (t === "postgres") return `${a}\n\nSET search_path TO ${s};\n\n${Ct(e, t)}`;
743
+ if (t === "mysql" || t === "mariadb") return `${a}\n\nUSE ${s};\n\n${Ct(e, t)}`;
744
+ let { sorted: c, cyclic: l } = _t(e), u = yt(l, t), d = [a];
745
+ for (let e of c) d.push(st(e, t, r, u.get(e.tableName)));
746
+ if (!o(t)) for (let e of l) d.push(vt(e, t, r));
747
747
  for (let e of c) {
748
- let n = ct(e, t, r);
748
+ let n = lt(e, t, r);
749
749
  n && d.push(n);
750
750
  }
751
751
  return d.join("\n\n") + "\n";
752
- }, Tt = (e, t, n = k) => {
753
- let { sorted: r, cyclic: i } = gt(e), a = vt(i, t), o = [], s = bt(r, t);
752
+ }, Et = (e, t, n = O) => {
753
+ let { sorted: r, cyclic: i } = _t(e), a = yt(i, t), o = [], s = xt(r, t);
754
754
  s && o.push(s);
755
- let c = yt(r, t);
755
+ let c = bt(r, t);
756
756
  c && o.push(c);
757
- for (let e of r) o.push(ot(e, t, null, a.get(e.tableName)));
758
- for (let e of i) o.push(_t(e, t));
759
- return o.push(...lt(r, t, n)), o.join("\n\n") + "\n";
760
- }, Et = (e, t = "postgres", n = k, r = {}) => x.gen(function* () {
757
+ for (let e of r) o.push(st(e, t, null, a.get(e.tableName)));
758
+ for (let e of i) o.push(vt(e, t));
759
+ return o.push(...ut(r, t, n)), o.join("\n\n") + "\n";
760
+ }, Dt = (e, t = "postgres", n = O, r = {}) => x.gen(function* () {
761
761
  let i = yield* C.SqlClient;
762
- yield* Me(i, Nt(i, St(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
763
- }), Dt = (e, t) => {
762
+ yield* Ne(i, Pt(i, Ct(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
763
+ }), Ot = (e, t) => {
764
764
  let n = t.cause ?? {};
765
765
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
766
- }, Ot = (e, t) => {
766
+ }, kt = (e, t) => {
767
767
  let n = e.trimStart();
768
768
  return !!(/\bIF NOT EXISTS\b/i.test(n) || /^CREATE OR REPLACE\b/i.test(n) || /^DROP\s[\s\S]*?\bIF EXISTS\b/i.test(n) || /^SET search_path\b/i.test(n) || /^USE[\s`"[]/i.test(n) || /^IF\s/i.test(n) || (t === "mysql" || t === "mariadb") && /^CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(n));
769
- }, kt = () => {
769
+ }, At = () => {
770
770
  let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
771
771
  return Number.isInteger(e) && e >= 0 ? e : 4;
772
- }, At = (e) => ({
772
+ }, jt = (e) => ({
773
773
  while: e,
774
- times: kt(),
774
+ times: At(),
775
775
  schedule: S.jittered(S.exponential("50 millis"))
776
- }), jt = class {
776
+ }), Mt = class {
777
777
  statement;
778
778
  error;
779
779
  _tag = "DdlStatementFailed";
780
780
  constructor(e, t) {
781
781
  this.statement = e, this.error = t;
782
782
  }
783
- }, Mt = (e, t, n) => x.gen(function* () {
784
- let r = yield* C.SqlClient, i = n !== void 0 && Fe(t) === "per-operation";
785
- for (let a of Pt(e)) {
786
- process.env.VOLTRO_MIGRATE_DEBUG === "1" && Ze.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
787
- let e = r.unsafe(a).pipe(x.catchIf((e) => Dt(a, e), () => x.succeed([])), x.tapError((e) => x.sync(() => {
788
- Ze.error(ae("migrate: statement failed", a, e, 200));
783
+ }, Nt = (e, t, n) => x.gen(function* () {
784
+ let r = yield* C.SqlClient, i = n !== void 0 && Ie(t) === "per-operation";
785
+ for (let a of Ft(e)) {
786
+ process.env.VOLTRO_MIGRATE_DEBUG === "1" && Qe.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
787
+ let e = r.unsafe(a).pipe(x.catchIf((e) => Ot(a, e), () => x.succeed([])), x.tapError((e) => x.sync(() => {
788
+ Qe.error(ae("migrate: statement failed", a, e, 200));
789
789
  })));
790
- yield* (i && n !== void 0 && Ot(a, t) ? e.pipe(x.retry(At((e) => n(e) === "retry"))) : e).pipe(x.mapError((e) => new jt(a, e)));
790
+ yield* (i && n !== void 0 && kt(a, t) ? e.pipe(x.retry(jt((e) => n(e) === "retry"))) : e).pipe(x.mapError((e) => new Mt(a, e)));
791
791
  }
792
- }), Nt = (e, t, n, r) => {
793
- let i = n === "turso" ? Mt(t, n, r) : e.withTransaction(Mt(t, n, r)), a = (e) => e instanceof jt ? e.error : e;
794
- return (r !== void 0 && Fe(n) === "plan-transactional" ? i.pipe(x.retry(At((e) => r(a(e)) === "retry"))) : i).pipe(x.orDieWith((e) => e instanceof jt ? Error(ae("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
795
- }, Pt = (e) => {
792
+ }), Pt = (e, t, n, r) => {
793
+ let i = n === "turso" ? Nt(t, n, r) : e.withTransaction(Nt(t, n, r)), a = (e) => e instanceof Mt ? e.error : e;
794
+ return (r !== void 0 && Ie(n) === "plan-transactional" ? i.pipe(x.retry(jt((e) => r(a(e)) === "retry"))) : i).pipe(x.orDieWith((e) => e instanceof Mt ? Error(ae("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
795
+ }, Ft = (e) => {
796
796
  let t = [], n = "", r = !1;
797
797
  for (let i = 0; i < e.length; i++) {
798
798
  if (e.slice(i, i + 2) === "$$") {
@@ -807,43 +807,43 @@ BEGIN
807
807
  }
808
808
  let i = n.trim();
809
809
  return i.length > 0 && t.push(i), t;
810
- }, Ft = async (e, t, n = "postgres", r = {}) => {
811
- await x.runPromise(Et(e, n, void 0, r).pipe(x.provide(t)));
812
- }, It = (e, t, n = "postgres", r = {}) => x.gen(function* () {
813
- let i = wt(e, n, t), a = yield* C.SqlClient;
814
- yield* Me(a, Nt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
815
- }), Lt = async (e, t, n, r = "postgres", i = {}) => {
816
- await x.runPromise(It(e, t, r, i).pipe(x.provide(n))), await f({
810
+ }, It = async (e, t, n = "postgres", r = {}) => {
811
+ await x.runPromise(Dt(e, n, void 0, r).pipe(x.provide(t)));
812
+ }, Lt = (e, t, n = "postgres", r = {}) => x.gen(function* () {
813
+ let i = Tt(e, n, t), a = yield* C.SqlClient;
814
+ yield* Ne(a, Pt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
815
+ }), Rt = async (e, t, n, r = "postgres", i = {}) => {
816
+ await x.runPromise(Lt(e, t, r, i).pipe(x.provide(n))), await f({
817
817
  namespace: t,
818
818
  dialect: r
819
819
  });
820
- }, Rt = async (e, t, n = "postgres", r = {}) => {
820
+ }, zt = async (e, t, n = "postgres", r = {}) => {
821
821
  await x.runPromise(x.gen(function* () {
822
- let t = Tt(e, n), i = yield* C.SqlClient;
823
- yield* Me(i, Nt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
822
+ let t = Et(e, n), i = yield* C.SqlClient;
823
+ yield* Ne(i, Pt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
824
824
  }).pipe(x.provide(t)));
825
- }, zt = (e) => {
825
+ }, Bt = (e) => {
826
826
  if (e == null) return e;
827
- if (Array.isArray(e)) return e.map(zt);
827
+ if (Array.isArray(e)) return e.map(Bt);
828
828
  if (typeof e != "object") return e;
829
829
  let t = {};
830
830
  for (let n of Object.keys(e).sort()) {
831
831
  let r = e[n];
832
- r !== void 0 && (t[n] = zt(r));
832
+ r !== void 0 && (t[n] = Bt(r));
833
833
  }
834
834
  return t;
835
- }, Bt = (e) => {
836
- if (!e.idScheme && !e.sensitive && !e.safe) return e;
837
- let { idScheme: t, sensitive: n, safe: r, ...i } = e;
838
- return i;
839
- }, Vt = (e) => [...e].map(Bt).sort((e, t) => e.name.localeCompare(t.name)), Ht = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), Ut = (e) => [...e].map((e) => ({
835
+ }, Vt = (e) => {
836
+ if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs) return e;
837
+ let { idScheme: t, sensitive: n, safe: r, generatedAs: i, ...a } = e;
838
+ return a;
839
+ }, Ht = (e) => [...e].map(Vt).sort((e, t) => e.name.localeCompare(t.name)), Ut = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), Wt = (e) => [...e].map((e) => ({
840
840
  name: e.name,
841
- columns: Vt(e.columns),
842
- indexes: Ht(e.indexes)
843
- })).sort((e, t) => e.name.localeCompare(t.name)), F = (e) => {
844
- let t = { tables: Ut(e.tables) }, n = JSON.stringify(zt(t));
841
+ columns: Ht(e.columns),
842
+ indexes: Ut(e.indexes)
843
+ })).sort((e, t) => e.name.localeCompare(t.name)), P = (e) => {
844
+ let t = { tables: Wt(e.tables) }, n = JSON.stringify(Bt(t));
845
845
  return te("sha256").update(n).digest("hex");
846
- }, I = (e) => e.slice(0, 16), Wt = (e, t) => {
846
+ }, Gt = (e) => e.slice(0, 16), Kt = (e, t) => {
847
847
  let n = t.references ? {
848
848
  table: t.references().tableName,
849
849
  column: "id",
@@ -882,7 +882,7 @@ BEGIN
882
882
  ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
883
883
  ...t.spatial === void 0 ? {} : { spatial: t.spatial }
884
884
  };
885
- }, Gt = (e) => {
885
+ }, qt = (e) => {
886
886
  let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
887
887
  n.has(e.name) || (n.add(e.name), t.push(e));
888
888
  }, i = e.appliedPrimaryKey ?? [];
@@ -930,11 +930,11 @@ BEGIN
930
930
  });
931
931
  }
932
932
  return t;
933
- }, Kt = (e) => {
933
+ }, Jt = (e) => {
934
934
  let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
935
935
  for (let [r, i] of Object.entries(e.fields)) {
936
936
  if (i.dropped) continue;
937
- let e = Wt(r, i);
937
+ let e = Kt(r, i);
938
938
  n.push(t.has(r) ? {
939
939
  ...e,
940
940
  unique: !0
@@ -944,27 +944,27 @@ BEGIN
944
944
  return {
945
945
  name: e.tableName,
946
946
  columns: n,
947
- indexes: Gt(e),
947
+ indexes: qt(e),
948
948
  ...r.length > 0 ? { primaryKey: [...r] } : {},
949
949
  ...i === void 0 ? {} : { renamedFrom: i }
950
950
  };
951
- }, qt = (e) => {
951
+ }, Yt = (e) => {
952
952
  let t = /* @__PURE__ */ new Map();
953
953
  for (let n of e) for (let e of n.indexes) {
954
954
  let r = t.get(e.name);
955
955
  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}').`);
956
956
  t.set(e.name, n.name);
957
957
  }
958
- }, L = (e, t) => {
959
- let n = e.map((e) => Kt(de(e, t)));
960
- return qt(n), { tables: n };
961
- }, Jt = (e, t, n = k) => x.gen(function* () {
958
+ }, F = (e, t) => {
959
+ let n = e.map((e) => Jt(de(e, t)));
960
+ return Yt(n), { tables: n };
961
+ }, Xt = (e, t, n = O) => x.gen(function* () {
962
962
  let r = (yield* e`
963
963
  SELECT p.prosrc
964
964
  FROM pg_proc p
965
965
  JOIN pg_namespace n ON n.oid = p.pronamespace
966
966
  WHERE n.nspname = current_schema()
967
- AND p.proname = ${Ye(n)}
967
+ AND p.proname = ${Xe(n)}
968
968
  `)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
969
969
  if (a.length === 0) return {
970
970
  missing: [],
@@ -978,10 +978,10 @@ BEGIN
978
978
  JOIN pg_namespace n ON n.oid = c.relnamespace
979
979
  WHERE NOT t.tgisinternal
980
980
  AND n.nspname = current_schema()
981
- AND t.tgname LIKE ${`${qe}%`}
981
+ AND t.tgname LIKE ${`${Je}%`}
982
982
  `, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
983
983
  for (let e of a) {
984
- let t = s.has(Je(e.tableName, n)), r = e.isReactive !== !1;
984
+ let t = s.has(Ye(e.tableName, n)), r = e.isReactive !== !1;
985
985
  r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
986
986
  }
987
987
  return {
@@ -989,7 +989,7 @@ BEGIN
989
989
  stale: l.sort(),
990
990
  functionOutdated: i
991
991
  };
992
- }), Yt = (e) => {
992
+ }), Zt = (e) => {
993
993
  let t = [];
994
994
  if (e.missing.length > 0) {
995
995
  let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
@@ -1000,19 +1000,19 @@ BEGIN
1000
1000
  t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
1001
1001
  }
1002
1002
  return e.functionOutdated && t.push("The change-notify function in this database is OLDER than the framework installed here. Its triggers fire, so nothing looks wrong — but a row too large for a NOTIFY payload (postgres caps it at 8000 bytes) is emitted without its primary key, and a change that carries no key cannot be re-read: it reaches subscriptions as a re-query and reaches every TAP — search index, analytics mirror, cdc-out, row history — as nothing at all. Run `voltro db apply` to replace it."), t.length > 0 ? t.join("\n") : void 0;
1003
- }, Xt = {
1003
+ }, Qt = {
1004
1004
  postgres: !0,
1005
1005
  mysql: !0,
1006
1006
  mariadb: !0,
1007
1007
  mssql: !0,
1008
1008
  sqlite: !0
1009
- }, Zt = {
1009
+ }, $t = {
1010
1010
  postgres: !0,
1011
1011
  mysql: !1,
1012
1012
  mariadb: !1,
1013
1013
  mssql: !0,
1014
1014
  sqlite: !0
1015
- }, Qt = (e) => {
1015
+ }, en = (e) => {
1016
1016
  switch (e) {
1017
1017
  case "add-column":
1018
1018
  case "drop-column":
@@ -1022,47 +1022,47 @@ BEGIN
1022
1022
  case "add-foreign-key":
1023
1023
  case "add-unique":
1024
1024
  case "add-unique-composite":
1025
- case "add-check": return Zt;
1026
- default: return Xt;
1025
+ case "add-check": return $t;
1026
+ default: return Qt;
1027
1027
  }
1028
- }, $t = (e, t) => {
1028
+ }, tn = (e, t) => {
1029
1029
  let n = new Map(t.tables.map((e) => [e.name, e]));
1030
1030
  return new Map(e.map((e) => [e.tableName, {
1031
1031
  table: e,
1032
1032
  snapshot: n.get(e.tableName),
1033
1033
  columnDefs: e.fields
1034
1034
  }]));
1035
- }, R = (e) => {
1035
+ }, I = (e) => {
1036
1036
  if (typeof e != "object" || !e) return JSON.stringify(e);
1037
- if (Array.isArray(e)) return `[${e.map(R).join(",")}]`;
1037
+ if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
1038
1038
  let t = e;
1039
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${R(t[e])}`).join(",")}}`;
1040
- }, en = (e) => {
1039
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
1040
+ }, nn = (e) => {
1041
1041
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
1042
1042
  let t = e.defaultValue;
1043
1043
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
1044
1044
  if (typeof t == "number") return String(t);
1045
- if (typeof t != "string") return R(t);
1045
+ if (typeof t != "string") return I(t);
1046
1046
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
1047
1047
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
1048
1048
  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);
1049
1049
  if (o) try {
1050
- return R(JSON.parse(o[1]));
1050
+ return I(JSON.parse(o[1]));
1051
1051
  } catch {}
1052
1052
  let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
1053
1053
  if (s) try {
1054
- return R(JSON.parse(s[1]));
1054
+ return I(JSON.parse(s[1]));
1055
1055
  } catch {}
1056
1056
  if (a.startsWith("{") || a.startsWith("[")) try {
1057
- return R(JSON.parse(a));
1057
+ return I(JSON.parse(a));
1058
1058
  } catch {}
1059
1059
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
1060
- }, tn = (e, t) => {
1061
- let n = en(e), r = en(t);
1060
+ }, rn = (e, t) => {
1061
+ let n = nn(e), r = nn(t);
1062
1062
  if (n === r) return !0;
1063
1063
  let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
1064
1064
  return i(n) === i(r);
1065
- }, nn = (e) => {
1065
+ }, an = (e) => {
1066
1066
  if (!e) return null;
1067
1067
  let t = (e) => e === "restrict" ? "noAction" : e;
1068
1068
  return {
@@ -1071,25 +1071,25 @@ BEGIN
1071
1071
  onDelete: t(e.onDelete),
1072
1072
  onUpdate: t(e.onUpdate)
1073
1073
  };
1074
- }, rn = (e, t) => {
1074
+ }, on = (e, t) => {
1075
1075
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
1076
1076
  if (!n && !r) return !0;
1077
1077
  if (!n || !r || n.length !== r.length) return !1;
1078
1078
  let i = [...n].sort(), a = [...r].sort();
1079
1079
  return i.every((e, t) => e === a[t]);
1080
- }, an = (e, t) => {
1080
+ }, sn = (e, t) => {
1081
1081
  try {
1082
- let n = /\((\d+)\)/.exec(j(e, t));
1082
+ let n = /\((\d+)\)/.exec(A(e, t));
1083
1083
  return n ? Number(n[1]) : void 0;
1084
1084
  } catch {
1085
1085
  return;
1086
1086
  }
1087
- }, on = (e, t, n) => n === void 0 || o(n) ? !0 : e.type !== "text" || t.type !== "text" || an(e, n) === t.maxLength, sn = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && tn(e, t) && on(e, t, n) && JSON.stringify(nn(e.references)) === JSON.stringify(nn(t.references)) && rn(e.oneOf, t.oneOf), cn = (e, t) => t.oneOf && t.oneOf.length > 0 ? z({
1087
+ }, cn = (e, t, n) => n === void 0 || o(n) ? !0 : e.type !== "text" || t.type !== "text" || sn(e, n) === t.maxLength, ln = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && rn(e, t) && cn(e, t, n) && JSON.stringify(an(e.references)) === JSON.stringify(an(t.references)) && on(e.oneOf, t.oneOf), un = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
1088
1088
  kind: "add-check",
1089
1089
  table: e,
1090
1090
  column: t.name,
1091
1091
  values: t.oneOf
1092
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, ln = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), un = (e, t, n) => {
1092
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, dn = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), fn = (e, t, n) => {
1093
1093
  let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
1094
1094
  for (let t of e.columns) {
1095
1095
  let e = r.get(t.name);
@@ -1097,7 +1097,7 @@ BEGIN
1097
1097
  a.push(t);
1098
1098
  continue;
1099
1099
  }
1100
- sn(t, e, n) || s.push({
1100
+ ln(t, e, n) || s.push({
1101
1101
  declared: t,
1102
1102
  live: e
1103
1103
  });
@@ -1108,47 +1108,47 @@ BEGIN
1108
1108
  removed: o,
1109
1109
  changed: s
1110
1110
  };
1111
- }, dn = (e, t) => {
1111
+ }, pn = (e, t) => {
1112
1112
  let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
1113
1113
  for (let t of e.indexes) {
1114
1114
  let e = n.get(t.name);
1115
- (!e || !ln(t, e)) && i.push(t);
1115
+ (!e || !dn(t, e)) && i.push(t);
1116
1116
  }
1117
1117
  for (let e of t.indexes) r.has(e.name) || a.push(e);
1118
1118
  return {
1119
1119
  added: i,
1120
1120
  removed: a
1121
1121
  };
1122
- }, z = (e, t, n, r) => ({
1122
+ }, L = (e, t, n, r) => ({
1123
1123
  op: e,
1124
1124
  classification: t,
1125
- atomicByDialect: Qt(e.kind),
1125
+ atomicByDialect: en(e.kind),
1126
1126
  ...n ? { reason: n } : {},
1127
1127
  ...r ? { blocked: r } : {}
1128
- }), fn = (e, t, n) => {
1128
+ }), mn = (e, t, n) => {
1129
1129
  let r = {
1130
1130
  kind: "add-column",
1131
1131
  table: e,
1132
1132
  column: t
1133
1133
  };
1134
- return t.nullable ? z(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? z(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? z(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : z(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` });
1135
- }, pn = (e, t, n) => {
1134
+ 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` });
1135
+ }, hn = (e, t, n) => {
1136
1136
  let r = {
1137
1137
  kind: "drop-column",
1138
1138
  table: e,
1139
1139
  column: t.name
1140
1140
  };
1141
- return n?.dropped ? z(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : z(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1142
- }, mn = (e, t, n, r, i) => z({
1141
+ 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` });
1142
+ }, gn = (e, t, n, r, i) => L({
1143
1143
  kind: "create-table",
1144
1144
  table: e,
1145
1145
  columns: t,
1146
1146
  indexes: n,
1147
1147
  ...r && r.length > 0 ? { primaryKey: r } : {}
1148
- }, "safe", i ?? "new table — no data to preserve"), hn = (e) => z({
1148
+ }, "safe", i ?? "new table — no data to preserve"), _n = (e) => L({
1149
1149
  kind: "drop-table",
1150
1150
  table: e
1151
- }, "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" }), gn = 5e4, _n = (e, t, n, r) => {
1151
+ }, "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" }), vn = 5e4, yn = (e, t, n, r) => {
1152
1152
  let i = (n ?? 0) >= r, a;
1153
1153
  return a = t.unique ? t.columns.length === 1 ? {
1154
1154
  kind: "add-unique",
@@ -1163,16 +1163,16 @@ BEGIN
1163
1163
  kind: "add-index",
1164
1164
  table: e,
1165
1165
  index: t
1166
- }, i ? z(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
1167
- }, vn = (e, t) => t.unique && t.columns.length > 1 ? z({
1166
+ }, 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");
1167
+ }, bn = (e, t) => t.unique && t.columns.length > 1 ? L({
1168
1168
  kind: "drop-unique-composite",
1169
1169
  table: e,
1170
1170
  name: t.name
1171
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : z({
1171
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
1172
1172
  kind: "drop-index",
1173
1173
  table: e,
1174
1174
  index: t.name
1175
- }, "safe", "drop index (no data loss — index is derived data)"), yn = (e, t) => {
1175
+ }, "safe", "drop index (no data loss — index is derived data)"), xn = (e, t) => {
1176
1176
  if (e === "reference") return "text";
1177
1177
  switch (t) {
1178
1178
  case "sqlite":
@@ -1180,7 +1180,10 @@ BEGIN
1180
1180
  case "mssql": return e === "json" ? "text" : e;
1181
1181
  default: return e;
1182
1182
  }
1183
- }, bn = (e, t, n, r, i, a) => {
1183
+ }, Sn = (e, t, n) => {
1184
+ let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
1185
+ return n === "postgres" ? `${r} — add \`{ using: '${t.name}::${t.type}' }\` when the cast is not implicit, or use a file-based migration` : `${r} — ${n === void 0 ? "this dialect" : n} converts in place (\`using\` is postgres-only and is ignored here), so verify the conversion is value-preserving for your data, or use a file-based migration`;
1186
+ }, Cn = (e, t, n, r, i, a) => {
1184
1187
  let s = [];
1185
1188
  if (t.nullable !== n.nullable) {
1186
1189
  let n = {
@@ -1189,7 +1192,7 @@ BEGIN
1189
1192
  column: t.name,
1190
1193
  toNullable: t.nullable
1191
1194
  };
1192
- s.push(t.nullable ? z(n, "safe", `loosen ${e}.${t.name} to nullable`) : z(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1195
+ 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`));
1193
1196
  }
1194
1197
  if (t.unique !== n.unique) {
1195
1198
  if (t.unique) {
@@ -1198,39 +1201,39 @@ BEGIN
1198
1201
  table: e,
1199
1202
  column: t.name
1200
1203
  }, r = (i ?? 0) >= a;
1201
- s.push(r ? z(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1202
- } else s.push(z({
1204
+ s.push(r ? L(n, "online-required", `online unique build on ${i} 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)`));
1205
+ } else s.push(L({
1203
1206
  kind: "drop-unique",
1204
1207
  table: e,
1205
1208
  column: t.name
1206
1209
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
1207
1210
  }
1208
- if (yn(t.type, r) !== yn(n.type, r)) {
1209
- let r = t.narrowedFrom;
1210
- if (r && r.from === n.type) {
1211
- let i = {
1211
+ if (xn(t.type, r) !== xn(n.type, r)) {
1212
+ let i = t.narrowedFrom;
1213
+ if (i && i.from === n.type) {
1214
+ let r = {
1212
1215
  kind: "alter-column-type",
1213
1216
  table: e,
1214
1217
  column: t.name,
1215
1218
  from: n.type,
1216
1219
  to: t.type,
1217
- ...r.using === void 0 ? {} : { using: r.using }
1220
+ ...i.using === void 0 ? {} : { using: i.using }
1218
1221
  };
1219
- s.push(z(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)")));
1222
+ s.push(L(r, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${i.from}') declared` + (i.using ? ` with USING ${i.using}` : " (implicit cast)")));
1220
1223
  } else {
1221
- let r = {
1224
+ let i = {
1222
1225
  kind: "alter-column-type",
1223
1226
  table: e,
1224
1227
  column: t.name,
1225
1228
  from: n.type,
1226
1229
  to: t.type
1227
1230
  };
1228
- s.push(z(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` }));
1231
+ s.push(L(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Sn(n.type, t, r) }));
1229
1232
  }
1230
1233
  }
1231
1234
  if (t.type === "text" && n.type === "text" && !o(r ?? "postgres") && t.maxLength !== n.maxLength) {
1232
1235
  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})`;
1233
- s.push(z({
1236
+ s.push(L({
1234
1237
  kind: "alter-column-type",
1235
1238
  table: e,
1236
1239
  column: t.name,
@@ -1238,7 +1241,7 @@ BEGIN
1238
1241
  to: "text"
1239
1242
  }, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
1240
1243
  }
1241
- if (!tn(t, n)) {
1244
+ if (!rn(t, n)) {
1242
1245
  let n = {
1243
1246
  kind: "alter-column-default",
1244
1247
  table: e,
@@ -1246,23 +1249,23 @@ BEGIN
1246
1249
  hasDefault: t.hasDefault,
1247
1250
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
1248
1251
  };
1249
- s.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1252
+ s.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1250
1253
  }
1251
- if (!rn(t.oneOf, n.oneOf)) {
1252
- n.oneOf && n.oneOf.length > 0 && s.push(z({
1254
+ if (!on(t.oneOf, n.oneOf)) {
1255
+ n.oneOf && n.oneOf.length > 0 && s.push(L({
1253
1256
  kind: "drop-check",
1254
1257
  table: e,
1255
1258
  column: t.name
1256
1259
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
1257
- let r = cn(e, t);
1260
+ let r = un(e, t);
1258
1261
  r && s.push(r);
1259
1262
  }
1260
- return JSON.stringify(nn(t.references)) !== JSON.stringify(nn(n.references)) && (n.references && s.push(z({
1263
+ return JSON.stringify(an(t.references)) !== JSON.stringify(an(n.references)) && (n.references && s.push(L({
1261
1264
  kind: "drop-foreign-key",
1262
1265
  table: e,
1263
1266
  column: t.name
1264
- }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), s.push(...xn(e, t))), s;
1265
- }, xn = (e, t) => {
1267
+ }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), s.push(...wn(e, t))), s;
1268
+ }, wn = (e, t) => {
1266
1269
  let n = [];
1267
1270
  if (!t.references) return n;
1268
1271
  let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
@@ -1274,15 +1277,15 @@ BEGIN
1274
1277
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1275
1278
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1276
1279
  };
1277
- return i === "null" && !t.nullable ? n.push(z(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(z({
1280
+ 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({
1278
1281
  ...a,
1279
1282
  orphanPolicy: i
1280
- }, "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(z(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1281
- }, Sn = (e, t, n) => {
1283
+ }, "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;
1284
+ }, Tn = (e, t, n) => {
1282
1285
  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));
1283
1286
  for (let [n, c] of Object.entries(t)) {
1284
1287
  let t = c.renamedFrom;
1285
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(z({
1288
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
1286
1289
  kind: "rename-column",
1287
1290
  table: e.tableName,
1288
1291
  from: t,
@@ -1294,26 +1297,26 @@ BEGIN
1294
1297
  consumedAddedNames: i,
1295
1298
  consumedRemovedNames: a
1296
1299
  };
1297
- }, Cn = /* @__PURE__ */ new Set([
1300
+ }, En = /* @__PURE__ */ new Set([
1298
1301
  "postgres",
1299
1302
  "mysql",
1300
1303
  "mariadb",
1301
1304
  "mssql"
1302
- ]), wn = {
1305
+ ]), Dn = {
1303
1306
  ops: [],
1304
1307
  consumedAddedNames: /* @__PURE__ */ new Set(),
1305
1308
  consumedRemovedNames: /* @__PURE__ */ new Set()
1306
- }, Tn = (e) => !e.unique && !e.expression, En = (e, t, n, r, i) => {
1307
- if (i === void 0 || !Cn.has(i)) return wn;
1308
- let a = t.added.filter((e) => Tn(e) && !r.has(e.name));
1309
- if (a.length === 0) return wn;
1309
+ }, On = (e) => !e.unique && !e.expression, kn = (e, t, n, r, i) => {
1310
+ if (i === void 0 || !En.has(i)) return Dn;
1311
+ let a = t.added.filter((e) => On(e) && !r.has(e.name));
1312
+ if (a.length === 0) return Dn;
1310
1313
  let o = (e) => e.columns.map((e) => n.get(e) ?? e).join("\0"), s = (e) => e.columns.join("\0"), c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set();
1311
1314
  for (let n of t.removed) {
1312
- if (!Tn(n)) continue;
1315
+ if (!On(n)) continue;
1313
1316
  let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
1314
1317
  if (r.length !== 1) continue;
1315
1318
  let i = r[0];
1316
- i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(z({
1319
+ i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(L({
1317
1320
  kind: "rename-index",
1318
1321
  table: e,
1319
1322
  from: n.name,
@@ -1325,7 +1328,7 @@ BEGIN
1325
1328
  consumedAddedNames: l,
1326
1329
  consumedRemovedNames: u
1327
1330
  };
1328
- }, Dn = (e, t, n) => {
1331
+ }, An = (e, t, n) => {
1329
1332
  let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
1330
1333
  for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
1331
1334
  for (let c of e.tables) {
@@ -1336,7 +1339,7 @@ BEGIN
1336
1339
  continue;
1337
1340
  }
1338
1341
  if (t.has(c.name)) {
1339
- r.push(z({
1342
+ r.push(L({
1340
1343
  kind: "rename-table",
1341
1344
  from: e,
1342
1345
  to: c.name
@@ -1344,14 +1347,14 @@ BEGIN
1344
1347
  continue;
1345
1348
  }
1346
1349
  if ((s.get(e) ?? 0) !== 1) {
1347
- r.push(z({
1350
+ r.push(L({
1348
1351
  kind: "rename-table",
1349
1352
  from: e,
1350
1353
  to: c.name
1351
1354
  }, "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.` }));
1352
1355
  continue;
1353
1356
  }
1354
- i.set(c.name, e), a.add(e), r.push(z({
1357
+ i.set(c.name, e), a.add(e), r.push(L({
1355
1358
  kind: "rename-table",
1356
1359
  from: e,
1357
1360
  to: c.name
@@ -1365,19 +1368,19 @@ BEGIN
1365
1368
  claimedOldNames: c,
1366
1369
  refusals: o
1367
1370
  };
1368
- }, On = (e, t, n, r) => {
1371
+ }, jn = (e, t, n, r) => {
1369
1372
  if (t === void 0) return {
1370
1373
  live: e,
1371
1374
  ops: []
1372
1375
  };
1373
- let i = r !== void 0 && Cn.has(r), a = [], o = e.indexes.map((e) => {
1376
+ let i = r !== void 0 && En.has(r), a = [], o = e.indexes.map((e) => {
1374
1377
  if (!e.name.startsWith(t)) return e;
1375
1378
  let r = `${n}${e.name.slice(t.length)}`;
1376
1379
  return r === e.name ? e : e.name === `${t}_pkey` ? {
1377
1380
  ...e,
1378
1381
  name: r,
1379
1382
  table: n
1380
- } : i ? (a.push(z({
1383
+ } : i ? (a.push(L({
1381
1384
  kind: "rename-index",
1382
1385
  table: n,
1383
1386
  from: e.name,
@@ -1396,7 +1399,7 @@ BEGIN
1396
1399
  },
1397
1400
  ops: a
1398
1401
  };
1399
- }, kn = (e) => {
1402
+ }, Mn = (e) => {
1400
1403
  let t = {
1401
1404
  safe: 0,
1402
1405
  needsDefault: 0,
@@ -1429,42 +1432,42 @@ BEGIN
1429
1432
  case "multi-step": t.multiStep++;
1430
1433
  }
1431
1434
  return t;
1432
- }, An = (e) => {
1433
- let t = L(e.declared, e.dialect), n = $t(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? gn, a = [], o = Dn(t, r, n);
1435
+ }, Nn = (e) => {
1436
+ let t = F(e.declared, e.dialect), n = tn(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? vn, a = [], o = An(t, r, n);
1434
1437
  a.push(...o.ops);
1435
1438
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1436
- a.push(mn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1439
+ a.push(gn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1437
1440
  for (let t of e.columns) {
1438
- let n = cn(e.name, t);
1441
+ let n = un(e.name, t);
1439
1442
  n && a.push(n);
1440
1443
  }
1441
1444
  }
1442
1445
  let s = new Set(e.ignoreTables ?? []);
1443
- for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || m(t.name) || v(t.name) || s.has(t.name) || a.push(hn(t.name));
1446
+ for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || m(t.name) || v(t.name) || s.has(t.name) || a.push(_n(t.name));
1444
1447
  for (let s of t.tables) {
1445
1448
  let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
1446
1449
  if (!c) continue;
1447
- let l = On(c, t, s.name, e.dialect);
1450
+ let l = jn(c, t, s.name, e.dialect);
1448
1451
  a.push(...l.ops);
1449
- let u = l.live, d = n.get(s.name), f = un(s, u, e.dialect), p = dn(s, u), m = Sn(d.table, d.columnDefs, f);
1452
+ let u = l.live, d = n.get(s.name), f = fn(s, u, e.dialect), p = pn(s, u), m = Tn(d.table, d.columnDefs, f);
1450
1453
  a.push(...m.ops);
1451
1454
  for (let e of f.removed) {
1452
1455
  if (m.consumedRemovedNames.has(e.name) || v(e.name)) continue;
1453
1456
  let t = d.columnDefs[e.name];
1454
- a.push(pn(s.name, e, t));
1457
+ a.push(hn(s.name, e, t));
1455
1458
  }
1456
1459
  for (let e of f.added) {
1457
1460
  if (m.consumedAddedNames.has(e.name)) continue;
1458
1461
  let t = d.columnDefs[e.name];
1459
- a.push(fn(s.name, e, t));
1460
- let n = cn(s.name, e);
1461
- n && a.push(n), a.push(...xn(s.name, e));
1462
+ a.push(mn(s.name, e, t));
1463
+ let n = un(s.name, e);
1464
+ n && a.push(n), a.push(...wn(s.name, e));
1462
1465
  }
1463
- let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = En(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1466
+ let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = kn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1464
1467
  a.push(...g.ops);
1465
- for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(_n(s.name, e, u.rowCount, i));
1466
- for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(vn(s.name, e));
1467
- for (let { declared: t, live: n } of f.changed) a.push(...bn(s.name, t, n, e.dialect, u.rowCount, i));
1468
+ for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(yn(s.name, e, u.rowCount, i));
1469
+ for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(bn(s.name, e));
1470
+ for (let { declared: t, live: n } of f.changed) a.push(...Cn(s.name, t, n, e.dialect, u.rowCount, i));
1468
1471
  }
1469
1472
  let c = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), l = new Map(t.tables.map((e) => [e.name, e])), u = (e) => {
1470
1473
  let t = l.get(e);
@@ -1473,7 +1476,7 @@ BEGIN
1473
1476
  target: e.references.table
1474
1477
  }] : []) : [];
1475
1478
  }, d = fe([...c], u), f = [];
1476
- 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(z({
1479
+ 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({
1477
1480
  kind: "add-foreign-key",
1478
1481
  table: e.name,
1479
1482
  column: t.name,
@@ -1545,19 +1548,19 @@ BEGIN
1545
1548
  });
1546
1549
  return {
1547
1550
  operations: S,
1548
- fromFingerprint: F(e.live),
1549
- toFingerprint: F(t),
1550
- summary: kn(S)
1551
+ fromFingerprint: P(e.live),
1552
+ toFingerprint: P(t),
1553
+ summary: Mn(S)
1551
1554
  };
1552
- }, jn = (e) => {
1555
+ }, Pn = (e) => {
1553
1556
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1554
1557
  if (!t) return null;
1555
- let n = [...e.replace(/\\'/g, "''").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
1558
+ let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
1556
1559
  return n.length === 0 ? null : {
1557
1560
  column: t[1],
1558
1561
  values: n
1559
1562
  };
1560
- }, Mn = (e, t) => {
1563
+ }, Fn = (e, t) => {
1561
1564
  if (t === "vector") return "vector";
1562
1565
  switch (e) {
1563
1566
  case "text":
@@ -1584,7 +1587,10 @@ BEGIN
1584
1587
  case "USER-DEFINED": return "text";
1585
1588
  default: return "text";
1586
1589
  }
1587
- }, B = (e) => {
1590
+ }, In = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
1591
+ expr: e,
1592
+ stored: t
1593
+ } }, R = (e) => {
1588
1594
  switch (e.toUpperCase()) {
1589
1595
  case "CASCADE": return "cascade";
1590
1596
  case "RESTRICT": return "restrict";
@@ -1592,25 +1598,25 @@ BEGIN
1592
1598
  case "SET DEFAULT": return "noAction";
1593
1599
  default: return "noAction";
1594
1600
  }
1595
- }, Nn = (e, t) => {
1601
+ }, Ln = (e, t) => {
1596
1602
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1597
1603
  return Number.isInteger(n) && n > 0 ? n : t;
1598
- }, Pn = () => Nn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Fn = 300, In = () => {
1604
+ }, Rn = () => Ln(process.env.VOLTRO_INTROSPECT_BATCH, 20), zn = 300, Bn = () => {
1599
1605
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1600
- return e !== void 0 && e.trim() === "0" ? 0 : Nn(e, 3e4);
1601
- }, Ln = (e, t) => {
1606
+ return e !== void 0 && e.trim() === "0" ? 0 : Ln(e, 3e4);
1607
+ }, Vn = (e, t) => {
1602
1608
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1603
1609
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1604
1610
  return r;
1605
- }, Rn = (e) => {
1606
- let t = In(), n = x.gen(function* () {
1611
+ }, Hn = (e) => {
1612
+ let t = Bn(), n = x.gen(function* () {
1607
1613
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1608
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Pn(), a = (e, t) => x.gen(function* () {
1614
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Rn(), a = (e, t) => x.gen(function* () {
1609
1615
  let r = [];
1610
- for (let a of Ln(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1616
+ for (let a of Vn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1611
1617
  return r;
1612
1618
  }), o = [];
1613
- for (let t = 0;; t += Fn) {
1619
+ for (let t = 0;; t += zn) {
1614
1620
  let n = yield* e`
1615
1621
  SELECT c.relname AS table_name,
1616
1622
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1618,15 +1624,15 @@ BEGIN
1618
1624
  JOIN pg_namespace n ON n.oid = c.relnamespace
1619
1625
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1620
1626
  ORDER BY c.relname
1621
- LIMIT ${r(Fn)} OFFSET ${r(t)}
1627
+ LIMIT ${r(zn)} OFFSET ${r(t)}
1622
1628
  `;
1623
- if (o.push(...n), n.length < Fn) break;
1629
+ if (o.push(...n), n.length < zn) break;
1624
1630
  }
1625
1631
  let s = /* @__PURE__ */ new Set(), c = [];
1626
1632
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
1627
1633
  let l = c.map((e) => e.table_name), u = yield* a(l, (t) => e`
1628
1634
  SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,
1629
- character_maximum_length
1635
+ character_maximum_length, is_generated, generation_expression
1630
1636
  FROM information_schema.columns
1631
1637
  WHERE table_schema = current_schema() AND table_name IN ${t}
1632
1638
  ORDER BY table_name, ordinal_position
@@ -1754,22 +1760,23 @@ BEGIN
1754
1760
  let te = [];
1755
1761
  for (let e of c) {
1756
1762
  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) => {
1757
- 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" : Mn(t.data_type, t.udt_name), c = a ? {
1763
+ 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" : Fn(t.data_type, t.udt_name), c = a ? {
1758
1764
  table: a.target_table,
1759
1765
  column: a.target_column,
1760
- onDelete: B(a.delete_rule),
1761
- onUpdate: B(a.update_rule)
1766
+ onDelete: R(a.delete_rule),
1767
+ onUpdate: R(a.update_rule)
1762
1768
  } : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
1763
1769
  return {
1764
1770
  name: t.column_name,
1765
1771
  type: s,
1766
- ...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
1772
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1767
1773
  nullable: t.is_nullable === "YES",
1768
1774
  unique: i.has(t.column_name) || n && t.column_name === "id",
1769
1775
  hasDefault: t.column_default !== null,
1770
1776
  ...t.column_default === null ? {} : { defaultValue: t.column_default },
1771
1777
  ...c ? { references: c } : {},
1772
- ...l ? { oneOf: l } : {}
1778
+ ...l ? { oneOf: l } : {},
1779
+ ...In(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
1773
1780
  };
1774
1781
  }), l = [], u = ee.get(e.table_name);
1775
1782
  if (u) for (let [t, n] of u) {
@@ -1808,7 +1815,7 @@ BEGIN
1808
1815
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1809
1816
  return n.includes("statement timeout") || n.includes("57014") ? x.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : x.fail(e);
1810
1817
  }));
1811
- }, zn = (e, t) => {
1818
+ }, Un = (e, t) => {
1812
1819
  switch (e.toLowerCase()) {
1813
1820
  case "varchar":
1814
1821
  case "char":
@@ -1840,21 +1847,21 @@ BEGIN
1840
1847
  case "json": return "json";
1841
1848
  default: return "text";
1842
1849
  }
1843
- }, V = (e) => e.map((e) => {
1850
+ }, z = (e) => e.map((e) => {
1844
1851
  let t = e, n = {};
1845
1852
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1846
1853
  return n;
1847
- }), Bn = (e) => x.gen(function* () {
1848
- let t = V(yield* e`
1854
+ }), Wn = (e) => x.gen(function* () {
1855
+ let t = z(yield* e`
1849
1856
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1850
1857
  FROM information_schema.tables
1851
1858
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1852
- ORDER BY table_name`), n = V(yield* e`
1859
+ ORDER BY table_name`), n = z(yield* e`
1853
1860
  SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
1854
- character_maximum_length
1861
+ character_maximum_length, generation_expression, extra
1855
1862
  FROM information_schema.columns
1856
1863
  WHERE table_schema = DATABASE()
1857
- ORDER BY table_name, ordinal_position`), r = V(yield* e`
1864
+ ORDER BY table_name, ordinal_position`), r = z(yield* e`
1858
1865
  SELECT k.table_name AS source_table,
1859
1866
  k.column_name AS source_column,
1860
1867
  k.referenced_table_name AS target_table,
@@ -1864,65 +1871,69 @@ BEGIN
1864
1871
  JOIN information_schema.referential_constraints r
1865
1872
  ON k.constraint_name = r.constraint_name
1866
1873
  AND k.table_schema = r.constraint_schema
1867
- WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = V(yield* e`
1874
+ WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = z(yield* e`
1868
1875
  SELECT table_name, index_name, non_unique, column_name, seq_in_index
1869
1876
  FROM information_schema.statistics
1870
1877
  WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
1871
- ORDER BY table_name, index_name, seq_in_index`), a = V(yield* e`
1878
+ ORDER BY table_name, index_name, seq_in_index`), a = e`
1879
+ SELECT cc.table_name AS table_name, cc.check_clause AS check_clause
1880
+ FROM information_schema.check_constraints cc
1881
+ WHERE cc.constraint_schema = DATABASE()`.unprepared, o = e`
1872
1882
  SELECT tc.table_name AS table_name, cc.check_clause AS check_clause
1873
1883
  FROM information_schema.check_constraints cc
1874
1884
  JOIN information_schema.table_constraints tc
1875
1885
  ON tc.constraint_schema = cc.constraint_schema
1876
1886
  AND tc.constraint_name = cc.constraint_name
1877
- WHERE cc.constraint_schema = DATABASE()`.unprepared.pipe(x.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
1878
- for (let e of a) {
1887
+ WHERE cc.constraint_schema = DATABASE()`.unprepared, s = z(yield* a.pipe(x.orElse(() => o), x.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
1888
+ for (let e of s) {
1879
1889
  let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
1880
1890
  if (t) {
1881
- o.add(`${e.table_name}.${t[1]}`);
1891
+ c.add(`${e.table_name}.${t[1]}`);
1882
1892
  continue;
1883
1893
  }
1884
- let n = jn(e.check_clause);
1885
- n && s.set(`${e.table_name}.${n.column}`, n.values);
1894
+ let n = Pn(e.check_clause);
1895
+ n && l.set(`${e.table_name}.${n.column}`, n.values);
1886
1896
  }
1887
- let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
1897
+ let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
1888
1898
  for (let e of n) {
1889
- let t = c.get(e.table_name) ?? [];
1890
- t.push(e), c.set(e.table_name, t);
1899
+ let t = u.get(e.table_name) ?? [];
1900
+ t.push(e), u.set(e.table_name, t);
1891
1901
  }
1892
1902
  for (let e of r) {
1893
- let t = l.get(e.source_table) ?? [];
1894
- t.push(e), l.set(e.source_table, t);
1903
+ let t = d.get(e.source_table) ?? [];
1904
+ t.push(e), d.set(e.source_table, t);
1895
1905
  }
1896
1906
  for (let e of i) {
1897
- let t = u.get(e.table_name);
1898
- t || (t = /* @__PURE__ */ new Map(), u.set(e.table_name, t));
1907
+ let t = f.get(e.table_name);
1908
+ t || (t = /* @__PURE__ */ new Map(), f.set(e.table_name, t));
1899
1909
  let n = t.get(e.index_name) ?? [];
1900
1910
  n.push(e), t.set(e.index_name, n);
1901
1911
  }
1902
- let d = [];
1912
+ let p = [];
1903
1913
  for (let e of t) {
1904
- let t = c.get(e.table_name) ?? [], n = l.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), f = u.get(e.table_name);
1905
- if (f) for (let e of f.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1906
- let p = t.map((t) => {
1907
- 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" : zn(t.data_type, t.column_type), u = c ? {
1908
- table: c.target_table,
1909
- column: c.target_column,
1910
- onDelete: B(c.delete_rule),
1911
- onUpdate: B(c.update_rule)
1912
- } : 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}`);
1914
+ let t = u.get(e.table_name) ?? [], n = d.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), o = f.get(e.table_name);
1915
+ if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1916
+ let s = t.map((t) => {
1917
+ let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" : Un(t.data_type, t.column_type), u = o ? {
1918
+ table: o.target_table,
1919
+ column: o.target_column,
1920
+ onDelete: R(o.delete_rule),
1921
+ onUpdate: R(o.update_rule)
1922
+ } : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = l.get(`${e.table_name}.${t.column_name}`);
1913
1923
  return {
1914
1924
  name: t.column_name,
1915
- type: l,
1925
+ type: s,
1916
1926
  nullable: t.is_nullable === "YES",
1917
- ...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
1927
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1918
1928
  unique: d,
1919
1929
  hasDefault: f !== null,
1920
1930
  ...f === null ? {} : { defaultValue: f },
1921
1931
  ...u ? { references: u } : {},
1922
- ...p ? { oneOf: p } : {}
1932
+ ...p ? { oneOf: p } : {},
1933
+ ...In(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
1923
1934
  };
1924
1935
  }), m = new Set(n.map((e) => e.source_column)), h = [];
1925
- if (f) for (let [t, n] of f) {
1936
+ if (o) for (let [t, n] of o) {
1926
1937
  let r = [...n].sort((e, t) => e.seq_in_index - t.seq_in_index);
1927
1938
  (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({
1928
1939
  name: t,
@@ -1938,18 +1949,18 @@ BEGIN
1938
1949
  unique: !0
1939
1950
  });
1940
1951
  let g = Number(e.table_rows ?? 0);
1941
- d.push({
1952
+ p.push({
1942
1953
  name: e.table_name,
1943
- columns: p,
1954
+ columns: s,
1944
1955
  indexes: h,
1945
1956
  ...g > 0 ? { rowCount: g } : {}
1946
1957
  });
1947
1958
  }
1948
- return { tables: d };
1949
- }), Vn = (e) => {
1959
+ return { tables: p };
1960
+ }), Gn = (e) => {
1950
1961
  let t = e.toUpperCase();
1951
1962
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1952
- }, Hn = (e) => x.gen(function* () {
1963
+ }, Kn = (e) => x.gen(function* () {
1953
1964
  let t = yield* e`
1954
1965
  SELECT name, sql FROM sqlite_master
1955
1966
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1960,17 +1971,17 @@ BEGIN
1960
1971
  let n = [...e[2].matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
1961
1972
  n.length > 0 && t.set(e[1], n);
1962
1973
  }
1963
- let o = yield* e.unsafe(`PRAGMA table_info(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set();
1974
+ let o = yield* e.unsafe(`PRAGMA table_xinfo(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set();
1964
1975
  for (let t of c) {
1965
1976
  let r = (yield* e.unsafe(`PRAGMA index_info(${n(t.name)})`)).map((e) => e.name).filter((e) => e !== null);
1966
1977
  d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1967
1978
  }
1968
1979
  let p = o.map((e) => {
1969
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Vn(e.type), a = r ? {
1980
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Gn(e.type), a = r ? {
1970
1981
  table: r.table,
1971
1982
  column: r.to,
1972
- onDelete: B(r.on_delete),
1973
- onUpdate: B(r.on_update)
1983
+ onDelete: R(r.on_delete),
1984
+ onUpdate: R(r.on_update)
1974
1985
  } : void 0, o = t.get(e.name);
1975
1986
  return {
1976
1987
  name: e.name,
@@ -1980,7 +1991,8 @@ BEGIN
1980
1991
  hasDefault: e.dflt_value !== null,
1981
1992
  ...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
1982
1993
  ...a ? { references: a } : {},
1983
- ...o ? { oneOf: o } : {}
1994
+ ...o ? { oneOf: o } : {},
1995
+ ...In(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
1984
1996
  };
1985
1997
  }), m = new Set(s.map((e) => e.from)), h = [];
1986
1998
  for (let e of c) {
@@ -2005,7 +2017,7 @@ BEGIN
2005
2017
  });
2006
2018
  }
2007
2019
  return { tables: r };
2008
- }), Un = (e) => {
2020
+ }), qn = (e) => {
2009
2021
  switch (e.toLowerCase()) {
2010
2022
  case "int":
2011
2023
  case "smallint":
@@ -2027,14 +2039,19 @@ BEGIN
2027
2039
  case "image": return "bytes";
2028
2040
  default: return "text";
2029
2041
  }
2030
- }, H = (e) => e === !0 || e === 1, Wn = (e) => x.gen(function* () {
2042
+ }, B = (e) => e === !0 || e === 1, Jn = (e) => x.gen(function* () {
2031
2043
  let t = yield* e`
2032
2044
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
2033
2045
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
2034
2046
  SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
2035
2047
  IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
2036
2048
  CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
2037
- FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* e`
2049
+ FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* x.orElseSucceed(e`
2050
+ SELECT t.name AS table_name, c.name AS column_name, cc.definition AS definition,
2051
+ cc.is_persisted AS is_persisted
2052
+ FROM sys.computed_columns cc
2053
+ JOIN sys.columns c ON c.object_id = cc.object_id AND c.column_id = cc.column_id
2054
+ JOIN sys.tables t ON t.object_id = cc.object_id`, () => []), i = new Map(r.map((e) => [`${e.table_name}.${e.column_name}`, e])), a = yield* e`
2038
2055
  SELECT st.name AS source_table, sc.name AS source_column,
2039
2056
  tt.name AS target_table, tc.name AS target_column,
2040
2057
  fk.delete_referential_action_desc AS delete_rule,
@@ -2044,7 +2061,7 @@ BEGIN
2044
2061
  JOIN sys.tables st ON st.object_id = fkc.parent_object_id
2045
2062
  JOIN sys.columns sc ON sc.object_id = fkc.parent_object_id AND sc.column_id = fkc.parent_column_id
2046
2063
  JOIN sys.tables tt ON tt.object_id = fkc.referenced_object_id
2047
- JOIN sys.columns tc ON tc.object_id = fkc.referenced_object_id AND tc.column_id = fkc.referenced_column_id`, i = yield* e`
2064
+ JOIN sys.columns tc ON tc.object_id = fkc.referenced_object_id AND tc.column_id = fkc.referenced_column_id`, o = yield* e`
2048
2065
  SELECT t.name AS table_name, i.name AS index_name, i.is_unique AS is_unique,
2049
2066
  i.is_primary_key AS is_primary, c.name AS column_name, ic.key_ordinal AS key_ordinal
2050
2067
  FROM sys.indexes i
@@ -2052,162 +2069,166 @@ BEGIN
2052
2069
  JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
2053
2070
  JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
2054
2071
  WHERE i.type > 0 AND ic.is_included_column = 0
2055
- ORDER BY t.name, i.name, ic.key_ordinal`, a = yield* e`
2072
+ ORDER BY t.name, i.name, ic.key_ordinal`, s = yield* e`
2056
2073
  SELECT t.name AS table_name, c.name AS column_name, cc.definition AS def
2057
2074
  FROM sys.check_constraints cc
2058
2075
  JOIN sys.tables t ON t.object_id = cc.parent_object_id
2059
2076
  JOIN sys.columns c ON c.object_id = cc.parent_object_id AND c.column_id = cc.parent_column_id
2060
- WHERE cc.parent_column_id <> 0`, o = /* @__PURE__ */ new Map();
2061
- for (let e of a) {
2077
+ WHERE cc.parent_column_id <> 0`, c = /* @__PURE__ */ new Map();
2078
+ for (let e of s) {
2062
2079
  let t = [...e.def.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
2063
- t.length > 0 && o.set(`${e.table_name}.${e.column_name}`, t);
2080
+ t.length > 0 && c.set(`${e.table_name}.${e.column_name}`, t);
2064
2081
  }
2065
- let s = /* @__PURE__ */ new Map();
2082
+ let l = /* @__PURE__ */ new Map();
2066
2083
  for (let e of n) {
2067
- let t = s.get(e.table_name) ?? [];
2068
- t.push(e), s.set(e.table_name, t);
2084
+ let t = l.get(e.table_name) ?? [];
2085
+ t.push(e), l.set(e.table_name, t);
2069
2086
  }
2070
- let c = /* @__PURE__ */ new Map();
2071
- for (let e of r) {
2072
- let t = c.get(e.source_table) ?? [];
2073
- t.push(e), c.set(e.source_table, t);
2087
+ let u = /* @__PURE__ */ new Map();
2088
+ for (let e of a) {
2089
+ let t = u.get(e.source_table) ?? [];
2090
+ t.push(e), u.set(e.source_table, t);
2074
2091
  }
2075
- let l = /* @__PURE__ */ new Map();
2076
- for (let e of i) {
2077
- let t = l.get(e.table_name);
2078
- t || (t = /* @__PURE__ */ new Map(), l.set(e.table_name, t));
2092
+ let d = /* @__PURE__ */ new Map();
2093
+ for (let e of o) {
2094
+ let t = d.get(e.table_name);
2095
+ t || (t = /* @__PURE__ */ new Map(), d.set(e.table_name, t));
2079
2096
  let n = t.get(e.index_name) ?? [];
2080
2097
  n.push(e), t.set(e.index_name, n);
2081
2098
  }
2082
- let u = [];
2099
+ let f = [];
2083
2100
  for (let { table_name: e } of t) {
2084
- 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();
2085
- if (a) for (let [, e] of a) {
2101
+ let t = l.get(e) ?? [], n = u.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), a = new Set(n.map((e) => e.source_column)), o = d.get(e), s = [], p = /* @__PURE__ */ new Set();
2102
+ if (o) for (let [, e] of o) {
2086
2103
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
2087
- if (H(t[0].is_primary)) for (let e of t) d.push(e.column_name);
2088
- else H(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
2104
+ if (B(t[0].is_primary)) for (let e of t) s.push(e.column_name);
2105
+ else B(t[0].is_unique) && t.length === 1 && p.add(t[0].column_name);
2089
2106
  }
2090
- let p = t.map((t) => {
2091
- 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" : Un(t.data_type), s = i ? {
2092
- table: i.target_table,
2093
- column: i.target_column,
2094
- onDelete: Gn(i.delete_rule),
2095
- onUpdate: Gn(i.update_rule)
2096
- } : void 0, c = t.column_default === null ? null : Kn(t.column_default), l = o.get(`${e}.${t.column_name}`);
2107
+ let m = t.map((t) => {
2108
+ let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : qn(t.data_type), l = a ? {
2109
+ table: a.target_table,
2110
+ column: a.target_column,
2111
+ onDelete: Yn(a.delete_rule),
2112
+ onUpdate: Yn(a.update_rule)
2113
+ } : void 0, u = t.column_default === null ? null : Xn(t.column_default), d = c.get(`${e}.${t.column_name}`);
2097
2114
  return {
2098
2115
  name: t.column_name,
2099
- type: a,
2116
+ type: o,
2100
2117
  nullable: t.is_nullable === "YES",
2101
- ...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
2102
- unique: f.has(t.column_name) || n && t.column_name === "id",
2103
- hasDefault: c !== null,
2104
- ...c === null ? {} : { defaultValue: c },
2105
- ...s ? { references: s } : {},
2106
- ...l ? { oneOf: l } : {}
2118
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
2119
+ unique: p.has(t.column_name) || n && t.column_name === "id",
2120
+ hasDefault: u !== null,
2121
+ ...u === null ? {} : { defaultValue: u },
2122
+ ...l ? { references: l } : {},
2123
+ ...d ? { oneOf: d } : {},
2124
+ ...In(i.get(`${e}.${t.column_name}`)?.definition ?? null, B(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2107
2125
  };
2108
- }), m = [];
2109
- if (a) for (let [t, n] of a) {
2126
+ }), h = [];
2127
+ if (o) for (let [t, n] of o) {
2110
2128
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
2111
- H(r[0].is_primary) || r.length === 1 && H(r[0].is_unique) || r.length === 1 && !H(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
2129
+ B(r[0].is_primary) || r.length === 1 && B(r[0].is_unique) || r.length === 1 && !B(r[0].is_unique) && a.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || h.push({
2112
2130
  name: t,
2113
2131
  table: e,
2114
2132
  columns: r.map((e) => e.column_name),
2115
- unique: H(r[0].is_unique)
2133
+ unique: B(r[0].is_unique)
2116
2134
  });
2117
2135
  }
2118
- d.length > 0 && m.push({
2136
+ s.length > 0 && h.push({
2119
2137
  name: `${e}_pkey`,
2120
2138
  table: e,
2121
- columns: d,
2139
+ columns: s,
2122
2140
  unique: !0
2123
- }), u.push({
2141
+ }), f.push({
2124
2142
  name: e,
2125
- columns: p,
2126
- indexes: m
2143
+ columns: m,
2144
+ indexes: h
2127
2145
  });
2128
2146
  }
2129
- return { tables: u };
2130
- }), Gn = (e) => {
2147
+ return { tables: f };
2148
+ }), Yn = (e) => {
2131
2149
  switch (e.toUpperCase().replace(/_/g, " ")) {
2132
2150
  case "CASCADE": return "cascade";
2133
2151
  case "SET NULL": return "setNull";
2134
2152
  case "SET DEFAULT": return "noAction";
2135
2153
  default: return "noAction";
2136
2154
  }
2137
- }, Kn = (e) => {
2155
+ }, Xn = (e) => {
2138
2156
  let t = e.trim();
2139
2157
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
2140
2158
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
2141
- }, qn = /* @__PURE__ */ new Set([
2159
+ }, Zn = /* @__PURE__ */ new Set([
2142
2160
  "character varying",
2143
2161
  "varchar",
2144
2162
  "nvarchar",
2145
2163
  "char",
2146
2164
  "character",
2147
2165
  "nchar"
2148
- ]), U = (e, t) => {
2149
- if (!qn.has(e.toLowerCase())) return;
2166
+ ]), V = (e, t) => {
2167
+ if (!Zn.has(e.toLowerCase())) return;
2150
2168
  let n = Number(t);
2151
2169
  if (!(!Number.isFinite(n) || n <= 0)) return n;
2152
- }, Jn = /* @__PURE__ */ new Set([O]), Yn = (e) => e.onDialectOrElse({
2153
- mysql: () => Bn(e),
2154
- mssql: () => Wn(e),
2155
- sqlite: () => Hn(e),
2156
- orElse: () => Rn(e)
2170
+ }, Qn = /* @__PURE__ */ new Set([D]), $n = (e) => e.onDialectOrElse({
2171
+ mysql: () => Wn(e),
2172
+ mssql: () => Jn(e),
2173
+ sqlite: () => Kn(e),
2174
+ orElse: () => Hn(e)
2157
2175
  }).pipe(x.map((e) => ({
2158
2176
  ...e,
2159
- tables: e.tables.filter((e) => !Jn.has(e.name))
2160
- }))), Xn = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", Zn = /* @__PURE__ */ new WeakMap(), W = (e) => x.suspend(() => {
2161
- let t = Zn.get(e);
2162
- return t === void 0 ? Qn(e).pipe(x.tap((t) => x.sync(() => Zn.set(e, t)))) : x.succeed(t);
2163
- }), Qn = (e) => e.unsafe("SELECT VERSION() AS v").pipe(x.map((e) => {
2177
+ tables: e.tables.filter((e) => !Qn.has(e.name))
2178
+ }))), er = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", tr = /* @__PURE__ */ new WeakMap(), H = (e) => x.suspend(() => {
2179
+ let t = tr.get(e);
2180
+ return t === void 0 ? nr(e).pipe(x.tap((t) => x.sync(() => tr.set(e, t)))) : x.succeed(t);
2181
+ }), nr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(x.map((e) => {
2164
2182
  let t = e[0]?.v;
2165
- return typeof t == "string" ? Xn(t) : "mysql";
2166
- }), x.catchAll(() => x.succeed("mysql"))), $n = (e) => {
2183
+ return typeof t == "string" ? er(t) : "mysql";
2184
+ }), x.catchAll(() => x.succeed("mysql"))), rr = (e) => {
2167
2185
  let t = e;
2168
2186
  for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
2169
2187
  let e = t;
2170
2188
  if (typeof e.errno == "number") return e.errno;
2171
2189
  t = e.cause;
2172
2190
  }
2173
- }, er = (e) => {
2191
+ }, ir = (e) => {
2174
2192
  let t = [], n = e;
2175
2193
  for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
2176
2194
  let e = n;
2177
2195
  typeof e.message == "string" && t.push(e.message), n = e.cause;
2178
2196
  }
2179
2197
  return t.join(" | ");
2180
- }, tr = (e, t) => {
2198
+ }, ar = (e, t) => {
2181
2199
  if (t.length === 0) return !1;
2182
- let n = $n(e), r = er(e);
2200
+ let n = rr(e), r = ir(e);
2183
2201
  return t.some((e) => e.errno !== void 0 && n !== void 0 && e.errno.includes(n) || e.messageIncludes !== void 0 && e.messageIncludes.some((e) => r.includes(e)));
2184
- }, nr = {
2202
+ }, or = {
2185
2203
  why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
2186
2204
  errno: [1061]
2187
- }, rr = {
2205
+ }, sr = {
2188
2206
  why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
2189
2207
  errno: [1091]
2190
- }, ir = {
2208
+ }, cr = {
2191
2209
  why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
2192
2210
  messageIncludes: ["no such column"]
2193
- }, G = (e, t) => e.onDialectOrElse({
2211
+ }, lr = {
2212
+ why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
2213
+ errno: [1091, 3940]
2214
+ }, U = (e, t) => e.onDialectOrElse({
2194
2215
  mysql: () => x.succeed(t.replace("T", " ").replace("Z", "")),
2195
2216
  orElse: () => x.succeed(t)
2196
- }), ar = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, or = (e, t) => {
2217
+ }), ur = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, dr = (e, t) => {
2197
2218
  if ((e.type !== "text" || e.maxLength === void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2198
2219
  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;
2199
2220
  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.`);
2200
- return j(e, t);
2201
- }, sr = (e) => {
2202
- let t = or(e, "postgres");
2203
- return t === void 0 ? cr(e) : t;
2204
- }, cr = (e) => {
2221
+ return A(e, t);
2222
+ }, fr = (e) => {
2223
+ let t = dr(e, "postgres");
2224
+ return t === void 0 ? pr(e) : t;
2225
+ }, pr = (e) => {
2205
2226
  switch (e.type) {
2206
2227
  case "id": return "text";
2207
2228
  case "text": return "text";
2208
2229
  case "integer": return "integer";
2209
2230
  case "real": return "double precision";
2210
- case "decimal": return ar(e, "NUMERIC");
2231
+ case "decimal": return ur(e, "NUMERIC");
2211
2232
  case "bigint": return "bigint";
2212
2233
  case "boolean": return "boolean";
2213
2234
  case "timestamp": return "timestamptz";
@@ -2221,15 +2242,15 @@ BEGIN
2221
2242
  case "interval": return "interval";
2222
2243
  case "raw": return e.rawDdl ?? "text";
2223
2244
  }
2224
- }, lr = (e) => {
2225
- let t = or(e, "mariadb");
2245
+ }, mr = (e) => {
2246
+ let t = dr(e, "mariadb");
2226
2247
  if (t !== void 0) return t;
2227
2248
  switch (e.type) {
2228
2249
  case "id": return "VARCHAR(64)";
2229
2250
  case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
2230
2251
  case "integer": return "INT";
2231
2252
  case "real": return "DOUBLE";
2232
- case "decimal": return ar(e, "DECIMAL");
2253
+ case "decimal": return ur(e, "DECIMAL");
2233
2254
  case "bigint": return "BIGINT";
2234
2255
  case "boolean": return "TINYINT(1)";
2235
2256
  case "timestamp": return "DATETIME(6)";
@@ -2243,58 +2264,58 @@ BEGIN
2243
2264
  case "interval": return "BIGINT";
2244
2265
  case "raw": return e.rawDdl ?? "LONGTEXT";
2245
2266
  }
2246
- }, K = (e) => `"${e}"`, q = (e) => `\`${e.replace(/`/g, "``")}\``, ur = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", dr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, fr = (e, t = "mariadb") => `ALTER TABLE ${q(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${q(e.column)}, ALGORITHM=COPY;`, pr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, mr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Ur(t)}`)};`, hr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${gr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, gr = (e, t) => {
2267
+ }, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, hr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", gr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, _r = (e, t = "mariadb") => `ALTER TABLE ${G(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${G(e.column)}, ALGORITHM=COPY;`, vr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, yr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Kr(t)}`)};`, br = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${xr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, xr = (e, t) => {
2247
2268
  let n = t(e.defaultValue);
2248
2269
  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.`);
2249
2270
  return n;
2250
- }, _r = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], vr = (e, t, n) => {
2251
- let r = _r(e, t, n);
2252
- return r ? Wt(n, r) : void 0;
2253
- }, yr = (e, t, n) => {
2254
- let r = n ?? e.nullable, i = Qe(e, "mariadb");
2271
+ }, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Sr = (e, t, n) => {
2272
+ let r = K(e, t, n);
2273
+ return r ? Kt(n, r) : void 0;
2274
+ }, Cr = (e, t, n) => {
2275
+ let r = n ?? e.nullable, i = $e(e, "mariadb");
2255
2276
  return [
2256
- q(t),
2257
- j(e, "mariadb"),
2277
+ G(t),
2278
+ A(e, "mariadb"),
2258
2279
  r ? null : "NOT NULL",
2259
2280
  i
2260
2281
  ].filter(Boolean).join(" ");
2261
- }, br = (e, t) => e == null ? null : Array.isArray(e) ? xr(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, xr = (e, t, n) => $e(e, t ?? { type: "json" }, n), Sr = (e, t) => e == null ? null : Array.isArray(e) ? xr(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, Cr = (e, t) => {
2282
+ }, wr = (e, t) => e == null ? null : Array.isArray(e) ? Tr(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, Tr = (e, t, n) => et(e, t ?? { type: "json" }, n), Er = (e, t) => e == null ? null : Array.isArray(e) ? Tr(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, q = (e, t) => {
2262
2283
  if (!e.generatedAs) return null;
2263
2284
  let { expr: n, stored: r } = e.generatedAs;
2264
2285
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2265
- }, wr = (e) => {
2266
- if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "postgres");
2267
- let t = Cr(e, "postgres");
2268
- if (t) return `${K(e.name)} ${sr(e)} ${t}`;
2269
- let n = [K(e.name), sr(e)];
2286
+ }, Dr = (e) => {
2287
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "postgres");
2288
+ let t = q(e, "postgres");
2289
+ if (t) return `${W(e.name)} ${fr(e)} ${t}`;
2290
+ let n = [W(e.name), fr(e)];
2270
2291
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2271
- let t = Sr(e.defaultValue, e);
2292
+ let t = Er(e.defaultValue, e);
2272
2293
  t && n.push(t);
2273
2294
  }
2274
- return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2295
+ return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2275
2296
  cascade: "CASCADE",
2276
2297
  restrict: "RESTRICT",
2277
2298
  setNull: "SET NULL",
2278
2299
  noAction: "NO ACTION"
2279
2300
  }[e.references.onDelete]}`)), n.join(" ");
2280
- }, Tr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Er = (e) => {
2281
- let t = e.columns.map((e) => ` ${wr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${t}${Tr(e, K)}\n)`];
2282
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(Jr).join(", ")})`);
2301
+ }, Or = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", kr = (e) => {
2302
+ let t = e.columns.map((e) => ` ${Dr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Or(e, W)}\n)`];
2303
+ 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(Zr).join(", ")})`);
2283
2304
  return n;
2284
- }, Dr = 191, Or = (e) => {
2285
- let t = lr(e).toUpperCase();
2305
+ }, Ar = 191, jr = (e) => {
2306
+ let t = mr(e).toUpperCase();
2286
2307
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2287
- }, kr = (e) => {
2288
- if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mariadb");
2289
- let t = Cr(e, "mariadb");
2290
- if (t) return `${q(e.name)} ${lr(e)} ${t}`;
2291
- let n = [q(e.name), lr(e)];
2292
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !Or(e) && n.push("UNIQUE"), e.hasDefault) {
2293
- let t = br(e.defaultValue, e);
2308
+ }, Mr = (e) => {
2309
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "mariadb");
2310
+ let t = q(e, "mariadb");
2311
+ if (t) return `${G(e.name)} ${mr(e)} ${t}`;
2312
+ let n = [G(e.name), mr(e)];
2313
+ if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !jr(e) && n.push("UNIQUE"), e.hasDefault) {
2314
+ let t = wr(e.defaultValue, e);
2294
2315
  t && n.push(t);
2295
2316
  }
2296
2317
  return n.join(" ");
2297
- }, Ar = (e) => e.columns.flatMap((t) => {
2318
+ }, Nr = (e) => e.columns.flatMap((t) => {
2298
2319
  if (!t.references) return [];
2299
2320
  let n = t.references.onDelete ? ` ON DELETE ${{
2300
2321
  cascade: "CASCADE",
@@ -2302,27 +2323,27 @@ BEGIN
2302
2323
  setNull: "SET NULL",
2303
2324
  noAction: "NO ACTION"
2304
2325
  }[t.references.onDelete]}` : "";
2305
- return [` CONSTRAINT ${q(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${q(t.name)}) REFERENCES ${q(t.references.table)} (${q(t.references.column)})${n}`];
2306
- }), jr = (e, t = "mariadb") => {
2326
+ return [` CONSTRAINT ${G(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${G(t.name)}) REFERENCES ${G(t.references.table)} (${G(t.references.column)})${n}`];
2327
+ }), Pr = (e, t = "mariadb") => {
2307
2328
  let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
2308
- let t = Kr(n.get(e));
2309
- return t === void 0 ? q(e) : `${q(e)}(${t})`;
2310
- }, i = e.columns.map((e) => ` ${kr(e)}`).join(",\n"), a = Ar(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${q(e.table)} (\n${o}${Tr(e, r)}\n)`];
2311
- for (let n of e.columns) n.unique && n.type !== "id" && Or(n) && s.push(`CREATE UNIQUE INDEX ${ur(t)}${q(`${e.table}_${n.name}_key`)} ON ${q(e.table)} (${r(n.name)})`);
2312
- for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${ur(t)}${q(n.name)} ON ${q(e.table)} (${n.columns.map(r).join(", ")})`);
2329
+ let t = Yr(n.get(e));
2330
+ return t === void 0 ? G(e) : `${G(e)}(${t})`;
2331
+ }, i = e.columns.map((e) => ` ${Mr(e)}`).join(",\n"), a = Nr(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${o}${Or(e, r)}\n)`];
2332
+ for (let n of e.columns) n.unique && n.type !== "id" && jr(n) && s.push(`CREATE UNIQUE INDEX ${hr(t)}${G(`${e.table}_${n.name}_key`)} ON ${G(e.table)} (${r(n.name)})`);
2333
+ for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${hr(t)}${G(n.name)} ON ${G(e.table)} (${n.columns.map(r).join(", ")})`);
2313
2334
  return s;
2314
- }, Mr = {
2335
+ }, Fr = {
2315
2336
  cascade: "CASCADE",
2316
2337
  restrict: "RESTRICT",
2317
2338
  setNull: "SET NULL",
2318
2339
  noAction: "NO ACTION"
2319
- }, Nr = {
2340
+ }, Ir = {
2320
2341
  cascade: "CASCADE",
2321
2342
  restrict: "NO ACTION",
2322
2343
  setNull: "SET NULL",
2323
2344
  noAction: "NO ACTION"
2324
- }, Pr = (e) => {
2325
- let t = or(e, "sqlite");
2345
+ }, Lr = (e) => {
2346
+ let t = dr(e, "sqlite");
2326
2347
  if (t !== void 0) return t;
2327
2348
  switch (e.type) {
2328
2349
  case "integer":
@@ -2333,60 +2354,60 @@ BEGIN
2333
2354
  case "bytes": return "BLOB";
2334
2355
  default: return "TEXT";
2335
2356
  }
2336
- }, Fr = (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, Ir = (e) => {
2337
- if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "sqlite");
2338
- let t = Cr(e, "sqlite");
2339
- if (t) return `${K(e.name)} ${Pr(e)} ${t}`;
2340
- let n = [K(e.name), Pr(e)];
2357
+ }, Rr = (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, zr = (e) => {
2358
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "sqlite");
2359
+ let t = q(e, "sqlite");
2360
+ if (t) return `${W(e.name)} ${Lr(e)} ${t}`;
2361
+ let n = [W(e.name), Lr(e)];
2341
2362
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2342
- let t = Fr(e.defaultValue, "CURRENT_TIMESTAMP");
2363
+ let t = Rr(e.defaultValue, "CURRENT_TIMESTAMP");
2343
2364
  t && n.push(t);
2344
2365
  }
2345
- if (e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Mr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2366
+ if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Fr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2346
2367
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2347
- n.push(`CHECK (${K(e.name)} IN (${t}))`);
2368
+ n.push(`CHECK (${W(e.name)} IN (${t}))`);
2348
2369
  }
2349
2370
  return n.join(" ");
2350
- }, Lr = (e) => {
2351
- let t = e.columns.map((e) => ` ${Ir(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${t}${Tr(e, K)}\n)`];
2352
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(K).join(", ")})`);
2371
+ }, Br = (e) => {
2372
+ let t = e.columns.map((e) => ` ${zr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Or(e, W)}\n)`];
2373
+ 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(", ")})`);
2353
2374
  return n;
2354
2375
  }, J = (e, t) => {
2355
2376
  let n = t.find((t) => t.tableName === e);
2356
2377
  if (!n) return [];
2357
- let r = L([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => K(e.name)).join(", "), o = [
2358
- ...Lr({
2378
+ let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
2379
+ ...Br({
2359
2380
  kind: "create-table",
2360
2381
  table: i,
2361
2382
  columns: r.columns,
2362
2383
  indexes: [],
2363
2384
  ...r.primaryKey ? { primaryKey: r.primaryKey } : {}
2364
2385
  }),
2365
- `INSERT INTO ${K(i)} (${a}) SELECT ${a} FROM ${K(e)}`,
2366
- `DROP TABLE ${K(e)}`,
2367
- `ALTER TABLE ${K(i)} RENAME TO ${K(e)}`
2386
+ `INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
2387
+ `DROP TABLE ${W(e)}`,
2388
+ `ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
2368
2389
  ];
2369
- for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e)} (${t.columns.map(K).join(", ")})`);
2390
+ 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(", ")})`);
2370
2391
  return o;
2371
- }, Rr = (e, t, n, r) => {
2392
+ }, Vr = (e, t, n, r) => {
2372
2393
  let i = r ?? e.nullable;
2373
- return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${j(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2374
- }, zr = (e) => {
2394
+ return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${A(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2395
+ }, Hr = (e) => {
2375
2396
  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 + ']');`;
2376
2397
  if (!e.hasDefault) return t;
2377
- let n = Fr(e.defaultValue, "SYSUTCDATETIME()");
2398
+ let n = Rr(e.defaultValue, "SYSUTCDATETIME()");
2378
2399
  if (!n) return t;
2379
2400
  let r = n.replace(/^DEFAULT\s+/i, "");
2380
2401
  return `${t} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${r} FOR ${Y(e.column)};`;
2381
- }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Br = (e) => {
2382
- let t = or(e, "mssql");
2402
+ }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Ur = (e) => {
2403
+ let t = dr(e, "mssql");
2383
2404
  if (t !== void 0) return t;
2384
2405
  switch (e.type) {
2385
2406
  case "id":
2386
2407
  case "reference": return "NVARCHAR(64)";
2387
2408
  case "integer": return "INT";
2388
2409
  case "real": return "FLOAT";
2389
- case "decimal": return ar(e, "DECIMAL");
2410
+ case "decimal": return ur(e, "DECIMAL");
2390
2411
  case "bigint": return "BIGINT";
2391
2412
  case "boolean": return "BIT";
2392
2413
  case "timestamp": return "DATETIME2(6)";
@@ -2394,44 +2415,44 @@ BEGIN
2394
2415
  case "bytes": return "VARBINARY(MAX)";
2395
2416
  default: return "NVARCHAR(MAX)";
2396
2417
  }
2397
- }, Vr = (e, t) => {
2398
- if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mssql");
2399
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Br(e), r = Cr(e, "mssql");
2418
+ }, Wr = (e, t) => {
2419
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return M(e.name, "mssql");
2420
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Ur(e), r = q(e, "mssql");
2400
2421
  if (r) return `${Y(e.name)} ${r}`;
2401
2422
  let i = [Y(e.name), n];
2402
2423
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2403
- let t = Fr(e.defaultValue, "SYSUTCDATETIME()");
2424
+ let t = Rr(e.defaultValue, "SYSUTCDATETIME()");
2404
2425
  t && i.push(t);
2405
2426
  }
2406
- return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${Nr[e.references.onDelete]}`)), i.join(" ");
2407
- }, Hr = (e) => {
2408
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Vr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${Tr(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2427
+ return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${Ir[e.references.onDelete]}`)), i.join(" ");
2428
+ }, Gr = (e) => {
2429
+ let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Wr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${Or(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2409
2430
  for (let n of e.indexes) {
2410
2431
  if (n.name === `${e.table}_pkey`) continue;
2411
2432
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})`;
2412
2433
  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)}')`);
2413
2434
  }
2414
2435
  return a;
2415
- }, Ur = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Wr = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Gr = (e, t, n) => {
2416
- let r = `${e.table}${Ur(t)}`;
2436
+ }, Kr = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, qr = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Jr = (e, t, n) => {
2437
+ let r = `${e.table}${Kr(t)}`;
2417
2438
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2418
- }, Kr = (e) => {
2419
- if (e === void 0 || !Or(e)) return;
2439
+ }, Yr = (e) => {
2440
+ if (e === void 0 || !jr(e)) return;
2420
2441
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
2421
- return t === void 0 ? Dr : Math.min(Dr, t);
2422
- }, qr = (e, t, n) => {
2423
- let r = Kr(vr(e, t, n));
2424
- return r === void 0 ? q(n) : `${q(n)}(${r})`;
2425
- }, Jr = (e) => e.startsWith("(") ? e : K(e), Yr = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map(Jr).join(", ")});`, Xr = (e, t, n = "mariadb") => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${ur(n)}${q(e.index.name)} ON ${q(e.table)} (${e.index.columns.map((n) => qr(t, e.table, n)).join(", ")});`, Zr = (e) => `DROP INDEX IF EXISTS ${K(e.index)};`, Qr = (e) => `DROP INDEX ${q(e.index)} ON ${q(e.table)};`, $r = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, ei = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, ti = (e) => {
2442
+ return t === void 0 ? Ar : Math.min(Ar, t);
2443
+ }, Xr = (e, t, n) => {
2444
+ let r = Yr(Sr(e, t, n));
2445
+ return r === void 0 ? G(n) : `${G(n)}(${r})`;
2446
+ }, Zr = (e) => e.startsWith("(") ? e : W(e), Qr = (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(Zr).join(", ")});`, $r = (e, t, n = "mariadb") => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${hr(n)}${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => Xr(t, e.table, n)).join(", ")});`, ei = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, ti = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, ni = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, ri = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, ii = (e) => {
2426
2447
  let t = (e) => e.replace(/'/g, "''");
2427
2448
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
2428
- }, ni = (e) => `ALTER INDEX ${K(e.from)} RENAME TO ${K(e.to)};`, ri = (e) => `ALTER TABLE ${q(e.table)} RENAME INDEX ${q(e.from)} TO ${q(e.to)};`, ii = (e) => {
2449
+ }, ai = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, oi = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, si = (e) => {
2429
2450
  let t = (e) => e.replace(/'/g, "''");
2430
2451
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2431
- }, ai = (e) => {
2452
+ }, ci = (e) => {
2432
2453
  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(", ")})`;
2433
2454
  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)}');`;
2434
- }, oi = (e, t, n) => {
2455
+ }, li = (e, t, n) => {
2435
2456
  let r = n.find((t) => t.tableName === e);
2436
2457
  if (!r) return [];
2437
2458
  let i = [];
@@ -2440,13 +2461,13 @@ BEGIN
2440
2461
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2441
2462
  }
2442
2463
  return i;
2443
- }, si = (e) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${K(e.column)});`, ci = (e, t) => `ALTER TABLE ${q(e.table)} ADD CONSTRAINT ${q(`${e.table}_${e.column}_key`)} UNIQUE (${qr(t, e.table, e.column)});`, li = (e) => {
2444
- let t = e.fields.map((e) => K(e)).join(", ");
2445
- return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${t});`;
2446
- }, ui = (e, t) => {
2447
- let n = e.fields.map((n) => qr(t, e.table, n)).join(", ");
2448
- return `ALTER TABLE ${q(e.table)} ADD CONSTRAINT ${q(e.name)} UNIQUE (${n});`;
2449
- }, di = (e) => `ALTER TABLE ${K(e.table)} DROP CONSTRAINT IF EXISTS ${K(e.name)};`, fi = (e) => `ALTER TABLE ${q(e.table)} DROP INDEX ${q(e.name)};`, pi = (e) => `ALTER TABLE ${K(e.table)} DROP CONSTRAINT IF EXISTS ${K(`${e.table}_${e.column}_key`)};`, mi = (e) => `ALTER TABLE ${q(e.table)} DROP INDEX ${q(`${e.table}_${e.column}_key`)};`, hi = (e, t) => {
2464
+ }, ui = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, di = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${Xr(t, e.table, e.column)});`, fi = (e) => {
2465
+ let t = e.fields.map((e) => W(e)).join(", ");
2466
+ return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
2467
+ }, pi = (e, t) => {
2468
+ let n = e.fields.map((n) => Xr(t, e.table, n)).join(", ");
2469
+ return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
2470
+ }, mi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, hi = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, gi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, _i = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, vi = (e, t) => {
2450
2471
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2451
2472
  if (e.orphanPolicy) {
2452
2473
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2464,11 +2485,34 @@ BEGIN
2464
2485
  setNull: "SET NULL",
2465
2486
  noAction: "NO ACTION"
2466
2487
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2467
- }, gi = (e) => `ALTER TABLE ${K(e.table)} DROP CONSTRAINT IF EXISTS ${K(`${e.table}_${e.column}_fkey`)};`, _i = (e) => `ALTER TABLE ${q(e.table)} DROP FOREIGN KEY ${q(`${e.table}_${e.column}_fkey`)};`, vi = (e, t) => {
2488
+ }, yi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, bi = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, xi = (e, t) => {
2468
2489
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2469
2490
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2470
- }, yi = (e) => `ALTER TABLE ${K(e.table)} DROP CONSTRAINT IF EXISTS ${K(`${e.table}_${e.column}_check`)};`, bi = (e) => `ALTER TABLE ${q(e.table)} DROP CHECK ${q(`${e.table}_${e.column}_check`)};`, xi = (e, t, n, r) => {
2471
- let i = e.column, a = r === "mariadb", o = a ? q : r === "mssql" ? Y : K, s = a ? lr(i) : r === "mssql" ? Br(i) : r === "sqlite" ? Pr(i) : sr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? br(e, i) : r === "mssql" ? Fr(e, "SYSUTCDATETIME()") : r === "sqlite" ? Fr(e, "CURRENT_TIMESTAMP") : Sr(e, i), u = Cr(i, r);
2491
+ }, Si = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, Ci = (e, t) => x.gen(function* () {
2492
+ let n = yield* e`
2493
+ SELECT cc.constraint_name AS n, cc.check_clause AS c
2494
+ FROM information_schema.check_constraints cc
2495
+ WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(x.orElse(() => e`
2496
+ SELECT cc.constraint_name AS n, cc.check_clause AS c
2497
+ FROM information_schema.check_constraints cc
2498
+ JOIN information_schema.table_constraints tc
2499
+ ON tc.constraint_schema = cc.constraint_schema
2500
+ AND tc.constraint_name = cc.constraint_name
2501
+ WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), x.orElseSucceed(() => []));
2502
+ for (let e of n) {
2503
+ let n = String(e.n ?? "");
2504
+ if (n !== "" && Pn(String(e.c ?? ""))?.column === t.column) return n;
2505
+ }
2506
+ }), wi = (e, t, n) => x.gen(function* () {
2507
+ let r = yield* Ci(e, t);
2508
+ r !== void 0 && (yield* X(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [lr]));
2509
+ let i = yield* Ci(e, t);
2510
+ if (i === void 0) return;
2511
+ let a = K(n, t.table, t.column);
2512
+ if (!a) return yield* x.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
2513
+ yield* X(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${Cr(a, t.column)};`, t.kind);
2514
+ }), Ti = (e, t, n, r) => {
2515
+ let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? Y : W, s = a ? mr(i) : r === "mssql" ? Ur(i) : r === "sqlite" ? Lr(i) : fr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? wr(e, i) : r === "mssql" ? Rr(e, "SYSUTCDATETIME()") : r === "sqlite" ? Rr(e, "CURRENT_TIMESTAMP") : Er(e, i), u = q(i, r);
2472
2516
  if (u) {
2473
2517
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2474
2518
  return {
@@ -2496,7 +2540,7 @@ BEGIN
2496
2540
  post: f ? [f] : []
2497
2541
  };
2498
2542
  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;
2499
- }, Si = (e) => {
2543
+ }, Ei = (e) => {
2500
2544
  let t = new Map(e.map((e) => [e.tableName, e]));
2501
2545
  return (e, n) => {
2502
2546
  let r = t.get(e);
@@ -2516,47 +2560,47 @@ BEGIN
2516
2560
  ...o
2517
2561
  };
2518
2562
  };
2519
- }, X = (e, t, n, r = []) => e.unsafe(t).pipe(x.catchIf((e) => tr(e, r), () => x.void), x.tapError((e) => x.sync(() => {
2563
+ }, X = (e, t, n, r = []) => e.unsafe(t).pipe(x.catchIf((e) => ar(e, r), () => x.void), x.tapError((e) => x.sync(() => {
2520
2564
  process.stderr.write(ae(`applier: statement failed (op=${n})`, t, e, 400));
2521
2565
  })), x.mapError((e) => {
2522
2566
  let r = ae(`applier: statement failed (op=${n})`, t, e, 400).trim();
2523
2567
  return Object.assign(e, { message: r });
2524
- }), x.map(() => void 0)), Z = (e, t, n) => x.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, r, i) => e.unsafe(`SELECT ${i === void 0 ? "*" : n(i, t)} FROM ${n(r, t)} WHERE 1=0`).pipe(x.as(!0), x.catchAll(() => x.succeed(!1))), Ci = (e, t) => x.gen(function* () {
2525
- let n = L([Ie], t).tables[0];
2568
+ }), x.map(() => void 0)), Z = (e, t, n) => x.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, r, i) => e.unsafe(`SELECT ${i === void 0 ? "*" : n(i, t)} FROM ${n(r, t)} WHERE 1=0`).pipe(x.as(!0), x.catchAll(() => x.succeed(!1))), Di = (e, t) => x.gen(function* () {
2569
+ let n = F([Le], t).tables[0];
2526
2570
  if (!n) return yield* x.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2527
2571
  let r = {
2528
2572
  kind: "create-table",
2529
- table: O,
2573
+ table: D,
2530
2574
  columns: n.columns,
2531
2575
  indexes: []
2532
2576
  }, i = yield* e.onDialectOrElse({
2533
- mysql: () => W(e).pipe(x.map((e) => jr(r, e))),
2534
- mssql: () => x.succeed(Hr(r)),
2535
- sqlite: () => x.succeed(Lr(r)),
2536
- orElse: () => x.succeed(Er(r))
2577
+ mysql: () => H(e).pipe(x.map((e) => Pr(r, e))),
2578
+ mssql: () => x.succeed(Gr(r)),
2579
+ sqlite: () => x.succeed(Br(r)),
2580
+ orElse: () => x.succeed(kr(r))
2537
2581
  });
2538
2582
  yield* x.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2539
- }), wi = (e) => e`
2583
+ }), Oi = (e) => e`
2540
2584
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2541
2585
  ${e("status")}, ${e("payload")}
2542
- FROM ${e(O)}
2543
- `, Ti = (e, t, n, r) => x.gen(function* () {
2544
- let i = yield* G(e, (/* @__PURE__ */ new Date()).toISOString());
2586
+ FROM ${e(D)}
2587
+ `, ki = (e, t, n, r) => x.gen(function* () {
2588
+ let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2545
2589
  yield* x.forEach(r, ({ index: r, planned: a }) => e`
2546
- INSERT INTO ${e(O)}
2590
+ INSERT INTO ${e(D)}
2547
2591
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2548
2592
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
2549
2593
  ${e("createdAt")})
2550
2594
  VALUES
2551
2595
  (${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
2552
- ${a.op.kind}, ${Re(a.op)}, ${"pending"},
2596
+ ${a.op.kind}, ${ze(a.op)}, ${"pending"},
2553
2597
  ${JSON.stringify(a)}, ${i})
2554
2598
  `, { discard: !0 });
2555
- }), Ei = (e, t, n, r, i) => x.gen(function* () {
2556
- let a = yield* G(e, (/* @__PURE__ */ new Date()).toISOString());
2599
+ }), Ai = (e, t, n, r, i) => x.gen(function* () {
2600
+ let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2557
2601
  if (r === "applied") {
2558
2602
  yield* e`
2559
- UPDATE ${e(O)}
2603
+ UPDATE ${e(D)}
2560
2604
  SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
2561
2605
  ${e("durationMs")} = ${i ?? null}
2562
2606
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
@@ -2564,145 +2608,145 @@ BEGIN
2564
2608
  return;
2565
2609
  }
2566
2610
  yield* e`
2567
- UPDATE ${e(O)}
2611
+ UPDATE ${e(D)}
2568
2612
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
2569
2613
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
2570
2614
  `;
2571
- }), Di = (e, t, n, r) => x.gen(function* () {
2572
- let i = yield* G(e, (/* @__PURE__ */ new Date()).toISOString());
2615
+ }), ji = (e, t, n, r) => x.gen(function* () {
2616
+ let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2573
2617
  r.length > 0 && (yield* e`
2574
- UPDATE ${e(O)}
2618
+ UPDATE ${e(D)}
2575
2619
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
2576
2620
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
2577
2621
  `), n.length > 0 && (yield* e`
2578
- UPDATE ${e(O)}
2622
+ UPDATE ${e(D)}
2579
2623
  SET ${e("status")} = ${"pending"}
2580
2624
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
2581
2625
  `);
2582
- }), Oi = (e, t) => t === void 0 ? e`DELETE FROM ${e(O)}`.pipe(x.asVoid) : e`DELETE FROM ${e(O)} WHERE ${e("runId")} = ${t}`.pipe(x.asVoid), ki = (e, t, r) => x.gen(function* () {
2583
- if (Ke(r.op, r.classification, t) !== "artefact-repair") return "clean";
2626
+ }), Mi = (e, t) => t === void 0 ? e`DELETE FROM ${e(D)}`.pipe(x.asVoid) : e`DELETE FROM ${e(D)} WHERE ${e("runId")} = ${t}`.pipe(x.asVoid), Ni = (e, t, r) => x.gen(function* () {
2627
+ if (qe(r.op, r.classification, t) !== "artefact-repair") return "clean";
2584
2628
  let i = r.op, a = (e) => n(e, t);
2585
2629
  if (t === "sqlite" || t === "turso") {
2586
2630
  if (!("table" in i)) return "clean";
2587
- let n = `${i.table}${Ve}`;
2631
+ let n = `${i.table}${He}`;
2588
2632
  return (yield* $(e, t, n)) ? ((yield* $(e, t, i.table)) ? yield* X(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* X(e, `ALTER TABLE ${a(n)} RENAME TO ${a(i.table)}`, "resume-repair"), yield* x.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${i.table}' — replaying the operation`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
2589
2633
  }
2590
2634
  if (i.kind !== "alter-column-type") return "clean";
2591
- let o = `${i.column}${He}`, s = `${i.column}${Ue}`, c = yield* $(e, t, i.table, i.column), l = yield* $(e, t, i.table, o), u = yield* $(e, t, i.table, s), d = (e) => x.logWarning(`migration resume: ${e}`).pipe(x.annotateLogs({ scope: "voltro:migrate" }));
2635
+ let o = `${i.column}${Ue}`, s = `${i.column}${We}`, c = yield* $(e, t, i.table, i.column), l = yield* $(e, t, i.table, o), u = yield* $(e, t, i.table, s), d = (e) => x.logWarning(`migration resume: ${e}`).pipe(x.annotateLogs({ scope: "voltro:migrate" }));
2592
2636
  return !l && !u ? "clean" : c && l && !u ? (yield* X(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${i.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* X(e, `ALTER TABLE ${a(i.table)} RENAME COLUMN ${a(o)} TO ${a(i.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${i.table}.${i.column}'`), "applied") : c && !l && u ? (yield* X(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${i.table}.${s}'`), "applied") : yield* x.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${i.table}.${i.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.`));
2593
- }), Ai = (e, t, n, r = "fresh") => x.gen(function* () {
2594
- let i = process.hrtime.bigint(), a = Si(n.declared), o = t.op;
2637
+ }), Pi = (e, t, n, r = "fresh") => x.gen(function* () {
2638
+ let i = process.hrtime.bigint(), a = Ei(n.declared), o = t.op;
2595
2639
  switch (o.kind) {
2596
2640
  case "create-table": {
2597
2641
  let t = yield* e.onDialectOrElse({
2598
- mysql: () => W(e).pipe(x.map((e) => jr(o, e))),
2599
- mssql: () => x.succeed(Hr(o)),
2600
- sqlite: () => x.succeed(Lr(o)),
2601
- orElse: () => x.succeed(Er(o))
2642
+ mysql: () => H(e).pipe(x.map((e) => Pr(o, e))),
2643
+ mssql: () => x.succeed(Gr(o)),
2644
+ sqlite: () => x.succeed(Br(o)),
2645
+ orElse: () => x.succeed(kr(o))
2602
2646
  }), n = yield* e.onDialectOrElse({
2603
- mysql: () => x.succeed([nr]),
2647
+ mysql: () => x.succeed([or]),
2604
2648
  orElse: () => x.succeed([])
2605
2649
  });
2606
2650
  for (let r of t) yield* X(e, r, o.kind, n);
2607
2651
  break;
2608
2652
  }
2609
2653
  case "drop-table": {
2610
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Gr(o, n, e) : Wr(o, e);
2654
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Jr(o, n, e) : qr(o, e);
2611
2655
  yield* e.onDialectOrElse({
2612
- mysql: () => X(e, r(q), o.kind),
2613
- orElse: () => X(e, r(K), o.kind)
2656
+ mysql: () => X(e, r(G), o.kind),
2657
+ orElse: () => X(e, r(W), o.kind)
2614
2658
  });
2615
2659
  break;
2616
2660
  }
2617
2661
  case "drop-column": {
2618
2662
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2619
2663
  yield* e.onDialectOrElse({
2620
- mysql: () => W(e).pipe(x.flatMap((r) => X(e, t ? mr(o, n, q) : fr(o, r), o.kind, t ? [] : [rr]))),
2621
- sqlite: () => X(e, t ? mr(o, n, K) : dr(o, K, !1), o.kind, t ? [] : [ir]),
2622
- orElse: () => X(e, t ? mr(o, n, K) : dr(o, K), o.kind)
2664
+ mysql: () => H(e).pipe(x.flatMap((r) => X(e, t ? yr(o, n, G) : _r(o, r), o.kind, t ? [] : [sr]))),
2665
+ sqlite: () => X(e, t ? yr(o, n, W) : gr(o, W, !1), o.kind, t ? [] : [cr]),
2666
+ orElse: () => X(e, t ? yr(o, n, W) : gr(o, W), o.kind)
2623
2667
  });
2624
2668
  break;
2625
2669
  }
2626
2670
  case "rename-column":
2627
2671
  yield* e.onDialectOrElse({
2628
- mysql: () => X(e, pr(o, q), o.kind),
2672
+ mysql: () => X(e, vr(o, G), o.kind),
2629
2673
  mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
2630
- orElse: () => X(e, pr(o, K), o.kind)
2674
+ orElse: () => X(e, vr(o, W), o.kind)
2631
2675
  });
2632
2676
  break;
2633
2677
  case "add-index":
2634
2678
  yield* e.onDialectOrElse({
2635
- mysql: () => W(e).pipe(x.flatMap((t) => X(e, Xr(o, n.declared, t), o.kind, [nr]))),
2636
- mssql: () => Z(e, [...oi(o.table, o.index.columns, n.declared), ai(o)], o.kind),
2637
- orElse: () => X(e, Yr(o, t.classification === "online-required"), o.kind)
2679
+ mysql: () => H(e).pipe(x.flatMap((t) => X(e, $r(o, n.declared, t), o.kind, [or]))),
2680
+ mssql: () => Z(e, [...li(o.table, o.index.columns, n.declared), ci(o)], o.kind),
2681
+ orElse: () => X(e, Qr(o, t.classification === "online-required"), o.kind)
2638
2682
  });
2639
2683
  break;
2640
2684
  case "drop-index":
2641
2685
  yield* e.onDialectOrElse({
2642
- mysql: () => X(e, Qr(o), o.kind),
2643
- mssql: () => X(e, $r(o), o.kind),
2644
- orElse: () => X(e, Zr(o), o.kind)
2686
+ mysql: () => X(e, ti(o), o.kind),
2687
+ mssql: () => X(e, ni(o), o.kind),
2688
+ orElse: () => X(e, ei(o), o.kind)
2645
2689
  });
2646
2690
  break;
2647
2691
  case "rename-table":
2648
2692
  yield* e.onDialectOrElse({
2649
- mysql: () => X(e, ei(o, q), o.kind),
2650
- mssql: () => X(e, ti(o), o.kind),
2651
- orElse: () => X(e, ei(o, K), o.kind)
2693
+ mysql: () => X(e, ri(o, G), o.kind),
2694
+ mssql: () => X(e, ii(o), o.kind),
2695
+ orElse: () => X(e, ri(o, W), o.kind)
2652
2696
  });
2653
2697
  break;
2654
2698
  case "rename-index":
2655
2699
  yield* e.onDialectOrElse({
2656
- mysql: () => X(e, ri(o), o.kind),
2657
- mssql: () => X(e, ii(o), o.kind),
2658
- orElse: () => X(e, ni(o), o.kind)
2700
+ mysql: () => X(e, oi(o), o.kind),
2701
+ mssql: () => X(e, si(o), o.kind),
2702
+ orElse: () => X(e, ai(o), o.kind)
2659
2703
  });
2660
2704
  break;
2661
2705
  case "add-unique":
2662
2706
  yield* e.onDialectOrElse({
2663
- mysql: () => X(e, ci(o, n.declared), o.kind),
2707
+ mysql: () => X(e, di(o, n.declared), o.kind),
2664
2708
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2665
- mssql: () => Z(e, [...oi(o.table, [o.column], n.declared), si(o)], o.kind),
2666
- orElse: () => X(e, si(o), o.kind)
2709
+ mssql: () => Z(e, [...li(o.table, [o.column], n.declared), ui(o)], o.kind),
2710
+ orElse: () => X(e, ui(o), o.kind)
2667
2711
  });
2668
2712
  break;
2669
2713
  case "drop-unique":
2670
2714
  yield* e.onDialectOrElse({
2671
- mysql: () => X(e, mi(o), o.kind),
2715
+ mysql: () => X(e, _i(o), o.kind),
2672
2716
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2673
- orElse: () => X(e, pi(o), o.kind)
2717
+ orElse: () => X(e, gi(o), o.kind)
2674
2718
  });
2675
2719
  break;
2676
2720
  case "add-unique-composite":
2677
2721
  yield* e.onDialectOrElse({
2678
- mysql: () => X(e, ui(o, n.declared), o.kind),
2722
+ mysql: () => X(e, pi(o, n.declared), o.kind),
2679
2723
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2680
- mssql: () => Z(e, [...oi(o.table, o.fields, n.declared), li(o)], o.kind),
2681
- orElse: () => X(e, li(o), o.kind)
2724
+ mssql: () => Z(e, [...li(o.table, o.fields, n.declared), fi(o)], o.kind),
2725
+ orElse: () => X(e, fi(o), o.kind)
2682
2726
  });
2683
2727
  break;
2684
2728
  case "drop-unique-composite":
2685
2729
  yield* e.onDialectOrElse({
2686
- mysql: () => X(e, fi(o), o.kind),
2730
+ mysql: () => X(e, hi(o), o.kind),
2687
2731
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2688
- orElse: () => X(e, di(o), o.kind)
2732
+ orElse: () => X(e, mi(o), o.kind)
2689
2733
  });
2690
2734
  break;
2691
2735
  case "add-foreign-key":
2692
2736
  yield* e.onDialectOrElse({
2693
- mysql: () => Z(e, hi(o, q), o.kind),
2737
+ mysql: () => Z(e, vi(o, G), o.kind),
2694
2738
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2695
- orElse: () => Z(e, hi(o, K), o.kind)
2739
+ orElse: () => Z(e, vi(o, W), o.kind)
2696
2740
  });
2697
2741
  break;
2698
2742
  case "add-column": {
2699
- let n = xi(o, t, a, yield* e.onDialectOrElse({
2743
+ let n = Ti(o, t, a, yield* e.onDialectOrElse({
2700
2744
  mysql: () => x.succeed("mariadb"),
2701
2745
  mssql: () => x.succeed("mssql"),
2702
2746
  sqlite: () => x.succeed("sqlite"),
2703
2747
  orElse: () => x.succeed("postgres")
2704
2748
  }));
2705
- if (!(r === "resume" && (yield* $(e, Ne(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
2749
+ if (!(r === "resume" && (yield* $(e, Pe(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
2706
2750
  if (n.backfillKind === "sql" && n.backfillSql) {
2707
2751
  if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
2708
2752
  else {
@@ -2742,41 +2786,41 @@ BEGIN
2742
2786
  case "alter-column-nullability":
2743
2787
  yield* e.onDialectOrElse({
2744
2788
  mysql: () => {
2745
- let t = _r(n.declared, o.table, o.column);
2746
- return t ? X(e, `ALTER TABLE ${q(o.table)} MODIFY COLUMN ${yr(t, o.column, o.toNullable)};`, o.kind) : x.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.`));
2789
+ let t = K(n.declared, o.table, o.column);
2790
+ return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Cr(t, o.column, o.toNullable)};`, o.kind) : x.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.`));
2747
2791
  },
2748
2792
  mssql: () => {
2749
- let t = _r(n.declared, o.table, o.column);
2750
- return t ? X(e, Rr(t, o.column, o.table, o.toNullable), o.kind) : x.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
2793
+ let t = K(n.declared, o.table, o.column);
2794
+ return t ? X(e, Vr(t, o.column, o.table, o.toNullable), o.kind) : x.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
2751
2795
  },
2752
2796
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2753
- orElse: () => X(e, `ALTER TABLE ${K(o.table)} ALTER COLUMN ${K(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2797
+ orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2754
2798
  });
2755
2799
  break;
2756
2800
  case "alter-column-default": {
2757
- let t = vr(n.declared, o.table, o.column);
2801
+ let t = Sr(n.declared, o.table, o.column);
2758
2802
  yield* e.onDialectOrElse({
2759
- mysql: () => X(e, hr(o, q, (e) => br(e, t)), o.kind),
2760
- mssql: () => X(e, zr(o), o.kind),
2803
+ mysql: () => X(e, br(o, G, (e) => wr(e, t)), o.kind),
2804
+ mssql: () => X(e, Hr(o), o.kind),
2761
2805
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2762
- orElse: () => X(e, hr(o, K, (e) => Sr(e, t)), o.kind)
2806
+ orElse: () => X(e, br(o, W, (e) => Er(e, t)), o.kind)
2763
2807
  });
2764
2808
  break;
2765
2809
  }
2766
2810
  case "alter-column-type": {
2767
- let r = sr(vr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
2811
+ let r = fr(Sr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
2768
2812
  if (t.classification !== "online-required") {
2769
2813
  yield* e.onDialectOrElse({
2770
2814
  mysql: () => {
2771
- let t = _r(n.declared, o.table, o.column);
2772
- return t ? X(e, `ALTER TABLE ${q(o.table)} MODIFY COLUMN ${yr(t, o.column)};`, o.kind) : x.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.`));
2815
+ let t = K(n.declared, o.table, o.column);
2816
+ return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Cr(t, o.column)};`, o.kind) : x.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.`));
2773
2817
  },
2774
2818
  mssql: () => {
2775
- let t = _r(n.declared, o.table, o.column);
2776
- return t ? X(e, Rr(t, o.column, o.table), o.kind) : x.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2819
+ let t = K(n.declared, o.table, o.column);
2820
+ return t ? X(e, Vr(t, o.column, o.table), o.kind) : x.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2777
2821
  },
2778
2822
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2779
- orElse: () => X(e, `ALTER TABLE ${K(o.table)} ALTER COLUMN ${K(o.column)} TYPE ${r}${i};`, o.kind)
2823
+ orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
2780
2824
  });
2781
2825
  break;
2782
2826
  }
@@ -2785,34 +2829,34 @@ BEGIN
2785
2829
  orElse: () => x.void
2786
2830
  });
2787
2831
  let a = `${o.column}__shadow`, s = `${o.column}__old`;
2788
- yield* e.unsafe(`ALTER TABLE ${K(o.table)} ADD COLUMN ${K(a)} ${r}`);
2789
- let c = o.using ?? K(o.column), l;
2832
+ yield* e.unsafe(`ALTER TABLE ${W(o.table)} ADD COLUMN ${W(a)} ${r}`);
2833
+ let c = o.using ?? W(o.column), l;
2790
2834
  for (;;) {
2791
2835
  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)}`;
2792
2836
  if (t.length === 0) break;
2793
- yield* e.unsafe(`UPDATE ${K(o.table)} SET ${K(a)} = ${c} WHERE ${K(o.column)} IS NOT NULL AND ${K(a)} IS NULL AND ${K("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2837
+ 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;
2794
2838
  }
2795
- yield* x.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${K(o.table)} RENAME COLUMN ${K(o.column)} TO ${K(s)}`), yield* e.unsafe(`ALTER TABLE ${K(o.table)} RENAME COLUMN ${K(a)} TO ${K(o.column)}`), yield* e.unsafe(`ALTER TABLE ${K(o.table)} DROP COLUMN ${K(s)}`);
2839
+ yield* x.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(x.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)}`);
2796
2840
  break;
2797
2841
  }
2798
2842
  case "drop-foreign-key":
2799
2843
  yield* e.onDialectOrElse({
2800
- mysql: () => X(e, _i(o), o.kind),
2844
+ mysql: () => X(e, bi(o), o.kind),
2801
2845
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2802
- orElse: () => X(e, gi(o), o.kind)
2846
+ orElse: () => X(e, yi(o), o.kind)
2803
2847
  });
2804
2848
  break;
2805
2849
  case "add-check":
2806
2850
  yield* e.onDialectOrElse({
2807
- mysql: () => X(e, vi(o, q), o.kind),
2851
+ mysql: () => X(e, xi(o, G), o.kind),
2808
2852
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2809
- orElse: () => X(e, vi(o, K), o.kind)
2853
+ orElse: () => X(e, xi(o, W), o.kind)
2810
2854
  });
2811
2855
  break;
2812
2856
  case "drop-check": yield* e.onDialectOrElse({
2813
- mysql: () => X(e, bi(o), o.kind),
2857
+ mysql: () => wi(e, o, n.declared),
2814
2858
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2815
- orElse: () => X(e, yi(o), o.kind)
2859
+ orElse: () => X(e, Si(o), o.kind)
2816
2860
  });
2817
2861
  }
2818
2862
  return {
@@ -2820,32 +2864,32 @@ BEGIN
2820
2864
  status: "applied",
2821
2865
  durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
2822
2866
  };
2823
- }), ji = (e, t, n, r) => x.gen(function* () {
2867
+ }), Fi = (e, t, n, r) => x.gen(function* () {
2824
2868
  let i = [...new Set(r.map((e) => e.runId))];
2825
- if (i.length > 1) return yield* x.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.`));
2869
+ if (i.length > 1) return yield* x.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.`));
2826
2870
  let a = i[0], o = [...r].map((e) => ({
2827
2871
  index: Number(e.opIndex),
2828
2872
  status: e.status,
2829
2873
  planned: JSON.parse(e.payload)
2830
2874
  })).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
2831
- if (c > 1) return yield* x.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.`));
2832
- if (yield* x.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} ${Re(s.planned.op)}` : ""}`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
2875
+ if (c > 1) return yield* x.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.`));
2876
+ if (yield* x.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} ${ze(s.planned.op)}` : ""}`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
2833
2877
  kind: "discard",
2834
2878
  runId: a,
2835
2879
  why: "no operation had started — no DDL ran"
2836
2880
  };
2837
- let l = s ? yield* ki(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2881
+ let l = s ? yield* Ni(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2838
2882
  if (u !== n.toFingerprint) return {
2839
2883
  kind: "discard",
2840
2884
  runId: a,
2841
2885
  why: `the declared schema changed since the interruption (recorded target ${u.slice(0, 12)}…, current ${n.toFingerprint.slice(0, 12)}…) — applying the freshly-diffed plan instead`
2842
2886
  };
2843
- let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Be(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
2887
+ let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Ve(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
2844
2888
  return f.length === 0 ? {
2845
2889
  kind: "discard",
2846
2890
  runId: a,
2847
2891
  why: "every recorded operation had already taken effect"
2848
- } : (yield* Di(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* x.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), {
2892
+ } : (yield* ji(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* x.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), {
2849
2893
  kind: "resume",
2850
2894
  runId: a,
2851
2895
  ops: f.map((e) => ({
@@ -2853,39 +2897,39 @@ BEGIN
2853
2897
  planned: e.planned
2854
2898
  }))
2855
2899
  });
2856
- }), Mi = (e, t, n) => x.gen(function* () {
2900
+ }), Ii = (e, t, n) => x.gen(function* () {
2857
2901
  let r = t.operations.filter((e) => e.blocked);
2858
2902
  if (r.length > 0) return yield* x.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
2859
- yield* E(e, { schema: n.lockSchema });
2860
- let i = Date.now(), a = [], o = Ne(e), s = Fe(o) === "plan-transactional", c = 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) => ({
2903
+ yield* T(e, { schema: n.lockSchema });
2904
+ let i = Date.now(), a = [], o = Pe(e), s = Ie(o) === "plan-transactional", c = 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) => ({
2861
2905
  index: t,
2862
2906
  planned: e
2863
2907
  })), p = "fresh";
2864
2908
  try {
2865
- yield* Ci(e, o);
2866
- let r = yield* wi(e);
2909
+ yield* Di(e, o);
2910
+ let r = yield* Oi(e);
2867
2911
  if (r.length > 0) {
2868
- let n = yield* ji(e, o, t, r);
2869
- n.kind === "resume" ? (d = n.runId, f = n.ops, p = "resume") : (yield* x.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), yield* Oi(e, n.runId));
2912
+ let n = yield* Fi(e, o, t, r);
2913
+ n.kind === "resume" ? (d = n.runId, f = n.ops, p = "resume") : (yield* x.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(x.annotateLogs({ scope: "voltro:migrate" })), yield* Mi(e, n.runId));
2870
2914
  }
2871
- p === "fresh" && f.length > 0 && (yield* Ti(e, d, t.toFingerprint, f)), c.length > 0 && (yield* e.withTransaction(x.gen(function* () {
2915
+ p === "fresh" && f.length > 0 && (yield* ki(e, d, t.toFingerprint, f)), c.length > 0 && (yield* e.withTransaction(x.gen(function* () {
2872
2916
  let e = yield* C.SqlClient;
2873
- for (let t of c) a.push(yield* Ai(e, t, n));
2917
+ for (let t of c) a.push(yield* Pi(e, t, n));
2874
2918
  })));
2875
2919
  for (let { index: t, planned: r } of f) {
2876
- yield* Ei(e, d, t, "started");
2877
- let i = yield* Ai(e, r, n, p);
2878
- a.push(i), yield* Ei(e, d, t, "applied", i.durationMs);
2920
+ yield* Ai(e, d, t, "started");
2921
+ let i = a.length, o = yield* Pi(e, r, n, p).pipe(x.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${f.length + c.length} operation(s) applied before this one${c.length > 0 ? ` (${c.length} of them in a transaction)` : ""}.\n` + (s ? " This dialect applies a plan atomically, so the run is rolled back.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The next \`voltro db apply\` resumes from operation ${t} — the ledger records the sequence.\n`) })));
2922
+ a.push(o), yield* Ai(e, d, t, "applied", o.durationMs);
2879
2923
  }
2880
2924
  } finally {
2881
- yield* D(e, { schema: n.lockSchema }).pipe(x.orDie);
2925
+ yield* E(e, { schema: n.lockSchema }).pipe(x.orDie);
2882
2926
  }
2883
2927
  let m = yield* n.replan(e);
2884
2928
  if (m.operations.length > 0) {
2885
2929
  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");
2886
2930
  return yield* x.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.`));
2887
2931
  }
2888
- let h = a.filter((e) => e.status === "applied").length, g = Date.now() - i, _ = d, v = (/* @__PURE__ */ new Date()).toISOString(), y = yield* G(e, v), b = [...c, ...f.map((e) => e.planned)];
2932
+ let h = a.filter((e) => e.status === "applied").length, g = Date.now() - i, _ = d, v = (/* @__PURE__ */ new Date()).toISOString(), y = yield* U(e, v), b = [...c, ...f.map((e) => e.planned)];
2889
2933
  yield* e`
2890
2934
  INSERT INTO ${e("_voltro_migration_plans")}
2891
2935
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -2895,7 +2939,7 @@ BEGIN
2895
2939
  (${_}, ${t.toFingerprint}, ${m.fromFingerprint}, ${JSON.stringify(b)},
2896
2940
  ${n.appliedBy}, ${n.environment}, ${n.source},
2897
2941
  ${g}, ${y}, ${n.notes ?? null})
2898
- `, yield* Oi(e, d);
2942
+ `, yield* Mi(e, d);
2899
2943
  let S = [...new Set(b.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
2900
2944
  return yield* x.promise(() => l({ changedTables: S }).catch(() => {})), {
2901
2945
  id: _,
@@ -2909,14 +2953,14 @@ BEGIN
2909
2953
  source: n.source,
2910
2954
  ...n.notes ? { notes: n.notes } : {}
2911
2955
  };
2912
- }), Ni = (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"), Pi = (e) => e`
2956
+ }), Li = (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"), Ri = (e) => e`
2913
2957
  SELECT fingerprint
2914
2958
  FROM _voltro_migration_plans
2915
2959
  ORDER BY ${e("appliedAt")} DESC
2916
2960
  LIMIT 1
2917
- `.pipe(x.map((e) => e.length > 0 ? e[0].fingerprint : void 0), x.catchAll(() => x.succeed(void 0))), Fi = (e, t, n) => x.gen(function* () {
2918
- if ((yield* Pi(e)) === t.toFingerprint) return "already-current";
2919
- let r = `plan_${Date.now().toString(36)}`, i = yield* G(e, (/* @__PURE__ */ new Date()).toISOString());
2961
+ `.pipe(x.map((e) => e.length > 0 ? e[0].fingerprint : void 0), x.catchAll(() => x.succeed(void 0))), zi = (e, t, n) => x.gen(function* () {
2962
+ if ((yield* Ri(e)) === t.toFingerprint) return "already-current";
2963
+ let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2920
2964
  return yield* e`
2921
2965
  INSERT INTO ${e("_voltro_migration_plans")}
2922
2966
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -2927,8 +2971,8 @@ BEGIN
2927
2971
  ${n.appliedBy}, ${n.environment}, ${n.source},
2928
2972
  ${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
2929
2973
  `, "recorded";
2930
- }).pipe(x.catchAll(() => x.succeed("already-current"))), Ii = (e, t) => x.gen(function* () {
2931
- let n = F(L(t, Ne(e))), r = yield* Pi(e);
2974
+ }).pipe(x.catchAll(() => x.succeed("already-current"))), Bi = (e, t) => x.gen(function* () {
2975
+ let n = P(F(t, Pe(e))), r = yield* Ri(e);
2932
2976
  return r === n ? {
2933
2977
  kind: "up-to-date",
2934
2978
  fingerprint: n
@@ -2937,23 +2981,23 @@ BEGIN
2937
2981
  expected: n,
2938
2982
  ...r === void 0 ? {} : { actual: r }
2939
2983
  };
2940
- }), Li = [
2984
+ }), Vi = [
2941
2985
  "pgeagertest_",
2942
2986
  "mig_e2e_",
2943
2987
  "mig_test_",
2944
2988
  "mysqleagertest_",
2945
2989
  "mssqleagertest_",
2946
2990
  "sqliteeagertest_"
2947
- ], Ri = (e) => Li.some((t) => e.startsWith(t)), zi = (e, t) => x.gen(function* () {
2991
+ ], Hi = (e) => Vi.some((t) => e.startsWith(t)), Ui = (e, t) => x.gen(function* () {
2948
2992
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2949
- let n = t.filter((e) => Ri(e.name)).map((e) => e.name);
2993
+ let n = t.filter((e) => Hi(e.name)).map((e) => e.name);
2950
2994
  if (n.length === 0) return [];
2951
2995
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(x.catchAll(() => x.void));
2952
2996
  return n;
2953
- }), Bi = () => {
2997
+ }), Wi = () => {
2954
2998
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2955
2999
  return e.length > 0 ? { ignoreTables: e } : {};
2956
- }, Vi = (e) => {
3000
+ }, Gi = (e) => {
2957
3001
  if (e === void 0) return;
2958
3002
  let t = e.trim();
2959
3003
  if (t === "") return;
@@ -2963,48 +3007,48 @@ BEGIN
2963
3007
  kind: "tables",
2964
3008
  tables: new Set(n)
2965
3009
  } : void 0;
2966
- }, Hi = (e) => typeof e.table == "string" ? e.table : void 0, Ui = (e, t = { kind: "all" }) => ({
3010
+ }, Ki = (e) => typeof e.table == "string" ? e.table : void 0, qi = (e, t = { kind: "all" }) => ({
2967
3011
  ...e,
2968
3012
  operations: e.operations.map((e) => {
2969
3013
  if (!e.blocked || e.classification !== "lossy") return e;
2970
3014
  if (t?.kind === "tables") {
2971
- let n = Hi(e.op);
3015
+ let n = Ki(e.op);
2972
3016
  if (n === void 0 || !t.tables.has(n)) return e;
2973
3017
  }
2974
3018
  let { blocked: n, ...r } = e;
2975
3019
  return r;
2976
3020
  })
2977
- }), Wi = (e, t, n) => t === "postgres" ? Jt(e, n).pipe(x.flatMap((e) => {
2978
- let t = Yt(e);
3021
+ }), Ji = (e, t, n) => t === "postgres" ? Xt(e, n).pipe(x.flatMap((e) => {
3022
+ let t = Zt(e);
2979
3023
  return t === void 0 ? x.void : x.logWarning(`auto-migrate: ${t}`).pipe(x.annotateLogs({ scope: "voltro:migrate" }));
2980
- }), x.catchAll(() => x.void)) : x.void, Gi = (e, t, n) => x.gen(function* () {
2981
- let r = Ne(e), i = t;
3024
+ }), x.catchAll(() => x.void)) : x.void, Yi = (e, t, n) => x.gen(function* () {
3025
+ let r = Pe(e), i = t;
2982
3026
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2983
- let t = F(L(i, r));
2984
- if ((yield* Pi(e)) === t) return yield* Wi(e, r, i), {
3027
+ let t = P(F(i, r));
3028
+ if ((yield* Ri(e)) === t) return yield* Ji(e, r, i), {
2985
3029
  kind: "up-to-date",
2986
3030
  fingerprint: t
2987
3031
  };
2988
3032
  }
2989
- let a = yield* Yn(e), o = yield* zi(e, a.tables);
3033
+ let a = yield* $n(e), o = yield* Ui(e, a.tables);
2990
3034
  o.length > 0 && (yield* x.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(x.annotateLogs({
2991
3035
  scope: "voltro:migrate",
2992
3036
  count: o.length
2993
- })), a = yield* Yn(e));
2994
- let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !m(e.name) || s.has(e.name)), l = An({
3037
+ })), a = yield* $n(e));
3038
+ let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !m(e.name) || s.has(e.name)), l = Nn({
2995
3039
  declared: i,
2996
3040
  live: { tables: c(a.tables) },
2997
3041
  dialect: r,
2998
- ...Bi()
3042
+ ...Wi()
2999
3043
  });
3000
3044
  if (l.summary.blocked > 0) {
3001
- let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Vi(process.env.VOLTRO_DESTRUCTIVE_OK);
3002
- if (t === void 0 || !e || (l = Ui(l, t), l.operations.some((e) => e.blocked))) return {
3045
+ let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Gi(process.env.VOLTRO_DESTRUCTIVE_OK);
3046
+ if (t === void 0 || !e || (l = qi(l, t), l.operations.some((e) => e.blocked))) return {
3003
3047
  kind: "refused-blocked",
3004
3048
  plan: l
3005
3049
  };
3006
3050
  }
3007
- return l.operations.length === 0 ? (yield* Fi(e, l, {
3051
+ return l.operations.length === 0 ? (yield* zi(e, l, {
3008
3052
  appliedBy: n.appliedBy,
3009
3053
  environment: n.environment === "prod" ? "dev" : n.environment,
3010
3054
  source: "auto-diff"
@@ -3013,37 +3057,37 @@ BEGIN
3013
3057
  fingerprint: l.toFingerprint
3014
3058
  }) : {
3015
3059
  kind: "applied",
3016
- applied: yield* Mi(e, l, {
3060
+ applied: yield* Ii(e, l, {
3017
3061
  declared: t,
3018
3062
  appliedBy: n.appliedBy,
3019
3063
  environment: n.environment === "prod" ? "dev" : n.environment,
3020
3064
  source: "auto-diff",
3021
3065
  replan: (e) => x.gen(function* () {
3022
- let t = yield* Yn(e);
3023
- return An({
3066
+ let t = yield* $n(e);
3067
+ return Nn({
3024
3068
  declared: i,
3025
3069
  live: { tables: c(t.tables) },
3026
3070
  dialect: r,
3027
- ...Bi()
3071
+ ...Wi()
3028
3072
  });
3029
3073
  })
3030
3074
  }),
3031
3075
  plan: l
3032
3076
  };
3033
- }), Ki = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? x.succeed({
3077
+ }), Xi = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? x.succeed({
3034
3078
  kind: "skipped",
3035
3079
  reason: "VOLTRO_AUTO_MIGRATE=0"
3036
- }) : n.environment === "prod" ? Ii(e, t) : Gi(e, t, n), qi = (e, t) => {
3080
+ }) : n.environment === "prod" ? Bi(e, t) : Yi(e, t, n), Zi = (e, t) => {
3037
3081
  switch (e.kind) {
3038
3082
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
3039
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${I(e.fingerprint)})`;
3083
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${Gt(e.fingerprint)})`;
3040
3084
  case "applied": {
3041
3085
  let t = e.plan.summary;
3042
- 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=${I(e.applied.fingerprint)}`;
3086
+ 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=${Gt(e.applied.fingerprint)}`;
3043
3087
  }
3044
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${I(e.expected)}` + (e.actual ? ` live=${I(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3088
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${Gt(e.expected)}` + (e.actual ? ` live=${Gt(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3045
3089
  case "refused-blocked": {
3046
- 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` + Ni(e.plan), c = [""];
3090
+ 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` + Li(e.plan), c = [""];
3047
3091
  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) {
3048
3092
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
3049
3093
  for (let r of e.plan.operations) {
@@ -3060,7 +3104,7 @@ BEGIN
3060
3104
  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");
3061
3105
  }
3062
3106
  }
3063
- }, Ji = /* @__PURE__ */ new Set([
3107
+ }, Qi = /* @__PURE__ */ new Set([
3064
3108
  "node_modules",
3065
3109
  "dist",
3066
3110
  "build",
@@ -3069,11 +3113,11 @@ BEGIN
3069
3113
  ".next",
3070
3114
  ".git",
3071
3115
  ".framework"
3072
- ]), Yi = async (e) => {
3116
+ ]), $i = async (e) => {
3073
3117
  let t = [], n = async (e) => {
3074
3118
  let r = await ne.readdir(e, { withFileTypes: !0 }).catch(() => []);
3075
3119
  for (let i of r) {
3076
- if (Ji.has(i.name)) continue;
3120
+ if (Qi.has(i.name)) continue;
3077
3121
  let r = re(e, i.name);
3078
3122
  i.isDirectory() ? await n(r) : i.isFile() && d.test(i.name) && t.push(r);
3079
3123
  }
@@ -3082,7 +3126,7 @@ BEGIN
3082
3126
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
3083
3127
  return n.localeCompare(r);
3084
3128
  });
3085
- }, Xi = async (e) => {
3129
+ }, ea = async (e) => {
3086
3130
  let t = [];
3087
3131
  for (let n of e) {
3088
3132
  let e = (await import(ie(n).href)).default;
@@ -3096,11 +3140,11 @@ BEGIN
3096
3140
  });
3097
3141
  }
3098
3142
  return t;
3099
- }, Zi = (e) => e`
3143
+ }, ta = (e) => e`
3100
3144
  SELECT ${e("id")}
3101
3145
  FROM ${e("_voltro_migration_plans")}
3102
3146
  WHERE ${e("source")} = 'file'
3103
- `.pipe(x.map((e) => e.map((e) => e.id)), x.catchAll(() => x.succeed([]))), Qi = class extends Error {
3147
+ `.pipe(x.map((e) => e.map((e) => e.id)), x.catchAll(() => x.succeed([]))), na = class extends Error {
3104
3148
  migrationId;
3105
3149
  file;
3106
3150
  cause;
@@ -3108,7 +3152,7 @@ BEGIN
3108
3152
  constructor(e, t, n) {
3109
3153
  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";
3110
3154
  }
3111
- }, $i = (e, t, n, r) => x.gen(function* () {
3155
+ }, ra = (e, t, n, r) => x.gen(function* () {
3112
3156
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
3113
3157
  sql: e,
3114
3158
  log: {
@@ -3129,7 +3173,7 @@ BEGIN
3129
3173
  });
3130
3174
  let c = Date.now() - i;
3131
3175
  !x.isEffect(s) && c < 2 && (yield* x.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(x.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
3132
- let l = yield* G(e, a);
3176
+ let l = yield* U(e, a);
3133
3177
  return yield* e`
3134
3178
  INSERT INTO ${e("_voltro_migration_plans")}
3135
3179
  (${e("id")}, ${e("fingerprint")}, ${e("operations")},
@@ -3142,10 +3186,10 @@ BEGIN
3142
3186
  }])},
3143
3187
  ${r}, ${n}, ${"file"},
3144
3188
  ${c}, ${l}, ${t.migration.description})
3145
- `.pipe(x.mapError((e) => new Qi(t.migration.id, t.file, e))), { durationMs: c };
3146
- }), ea = (e, t) => x.gen(function* () {
3189
+ `.pipe(x.mapError((e) => new na(t.migration.id, t.file, e))), { durationMs: c };
3190
+ }), ia = (e, t) => x.gen(function* () {
3147
3191
  let n = yield* x.tryPromise({
3148
- try: () => Yi(re(t, "migrations")),
3192
+ try: () => $i(re(t, "migrations")),
3149
3193
  catch: (e) => e
3150
3194
  });
3151
3195
  if (n.length === 0) return {
@@ -3153,25 +3197,25 @@ BEGIN
3153
3197
  skipped: []
3154
3198
  };
3155
3199
  let r = yield* x.tryPromise({
3156
- try: () => Xi(n),
3200
+ try: () => ea(n),
3157
3201
  catch: (e) => e
3158
3202
  });
3159
3203
  if (r.length === 0) return {
3160
3204
  pending: [],
3161
3205
  skipped: []
3162
3206
  };
3163
- let i = new Set(yield* Zi(e));
3207
+ let i = new Set(yield* ta(e));
3164
3208
  return {
3165
3209
  pending: r.filter((e) => !i.has(e.migration.id)),
3166
3210
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
3167
3211
  };
3168
- }), ta = (e, t) => ea(e, t).pipe(x.map((e) => e.pending.map((e) => e.migration.id))), na = (e, t) => x.gen(function* () {
3169
- let { pending: n, skipped: r } = yield* ea(e, t.projectRoot);
3212
+ }), aa = (e, t) => ia(e, t).pipe(x.map((e) => e.pending.map((e) => e.migration.id))), oa = (e, t) => x.gen(function* () {
3213
+ let { pending: n, skipped: r } = yield* ia(e, t.projectRoot);
3170
3214
  if (n.length === 0) return {
3171
3215
  applied: [],
3172
3216
  skipped: r
3173
3217
  };
3174
- yield* E(e, { schema: t.lockSchema });
3218
+ yield* T(e, { schema: t.lockSchema });
3175
3219
  let i = [];
3176
3220
  try {
3177
3221
  for (let r of n) {
@@ -3180,7 +3224,7 @@ BEGIN
3180
3224
  id: r.migration.id,
3181
3225
  file: r.file
3182
3226
  }));
3183
- let { durationMs: n } = yield* $i(e, r, t.env, t.appliedBy);
3227
+ let { durationMs: n } = yield* ra(e, r, t.env, t.appliedBy);
3184
3228
  i.push({
3185
3229
  id: r.migration.id,
3186
3230
  durationMs: n
@@ -3191,28 +3235,28 @@ BEGIN
3191
3235
  }));
3192
3236
  }
3193
3237
  } finally {
3194
- yield* D(e, { schema: t.lockSchema }).pipe(x.orDie);
3238
+ yield* E(e, { schema: t.lockSchema }).pipe(x.orDie);
3195
3239
  }
3196
3240
  return {
3197
3241
  applied: i,
3198
3242
  skipped: r
3199
3243
  };
3200
- }), ra = (e, t) => e`
3244
+ }), sa = (e, t) => e`
3201
3245
  SELECT ${e("id")}
3202
3246
  FROM ${e("_voltro_migration_plans")}
3203
3247
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
3204
3248
  LIMIT 1
3205
- `, ia = (e, t) => x.gen(function* () {
3206
- if (!(yield* ra(e, t.id))[0]) return yield* x.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3249
+ `, ca = (e, t) => x.gen(function* () {
3250
+ if (!(yield* sa(e, t.id))[0]) return yield* x.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3207
3251
  let n = yield* x.tryPromise({
3208
- try: () => Yi(re(t.projectRoot, "migrations")),
3252
+ try: () => $i(re(t.projectRoot, "migrations")),
3209
3253
  catch: (e) => e
3210
3254
  }), r = (yield* x.tryPromise({
3211
- try: () => Xi(n),
3255
+ try: () => ea(n),
3212
3256
  catch: (e) => e
3213
3257
  })).find((e) => e.migration.id === t.id);
3214
3258
  if (!r) return yield* x.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3215
- yield* E(e, { schema: t.lockSchema });
3259
+ yield* T(e, { schema: t.lockSchema });
3216
3260
  let i = Date.now();
3217
3261
  try {
3218
3262
  let n = {
@@ -3239,9 +3283,9 @@ BEGIN
3239
3283
  durationMs: o
3240
3284
  };
3241
3285
  } finally {
3242
- yield* D(e, { schema: t.lockSchema }).pipe(x.orDie);
3286
+ yield* E(e, { schema: t.lockSchema }).pipe(x.orDie);
3243
3287
  }
3244
- }), aa = (e) => x.gen(function* () {
3288
+ }), la = (e) => x.gen(function* () {
3245
3289
  let t = yield* C.SqlClient, n = yield* t`
3246
3290
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
3247
3291
  WHERE source = 'auto-diff'
@@ -3286,7 +3330,7 @@ BEGIN
3286
3330
  snapshotFingerprint: e.fingerprint,
3287
3331
  snapshotId: i
3288
3332
  };
3289
- }), oa = { safe: !0 }, sa = (e) => {
3333
+ }), ua = { safe: !0 }, da = (e) => {
3290
3334
  switch (e.kind) {
3291
3335
  case "drop-column": return {
3292
3336
  safe: !1,
@@ -3313,7 +3357,7 @@ BEGIN
3313
3357
  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`,
3314
3358
  remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
3315
3359
  };
3316
- case "alter-column-nullability": return e.toNullable ? oa : {
3360
+ case "alter-column-nullability": return e.toNullable ? ua : {
3317
3361
  safe: !1,
3318
3362
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
3319
3363
  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)`
@@ -3343,12 +3387,12 @@ BEGIN
3343
3387
  case "drop-unique":
3344
3388
  case "drop-unique-composite":
3345
3389
  case "drop-foreign-key":
3346
- case "drop-check": return oa;
3390
+ case "drop-check": return ua;
3347
3391
  }
3348
- }, ca = (e) => {
3392
+ }, fa = (e) => {
3349
3393
  let t = [];
3350
3394
  for (let n of e) {
3351
- let e = sa(n.op);
3395
+ let e = da(n.op);
3352
3396
  e.safe || t.push({
3353
3397
  op: n,
3354
3398
  reason: e.reason,
@@ -3356,7 +3400,7 @@ BEGIN
3356
3400
  });
3357
3401
  }
3358
3402
  return t;
3359
- }, la = (e) => {
3403
+ }, pa = (e) => {
3360
3404
  if (!e.enabled || e.unsafeCount === 0) return {
3361
3405
  refuse: !1,
3362
3406
  warnForced: !1,
@@ -3372,18 +3416,18 @@ BEGIN
3372
3416
  warnForced: !1,
3373
3417
  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.`
3374
3418
  };
3375
- }, ua = (e) => {
3419
+ }, ma = (e) => {
3376
3420
  let t = e.table;
3377
3421
  if (typeof t == "string") return t;
3378
3422
  let n = e.from;
3379
3423
  return typeof n == "string" ? n : void 0;
3380
- }, da = (e) => ({
3424
+ }, ha = (e) => ({
3381
3425
  kind: e.op.kind,
3382
- table: ua(e.op),
3426
+ table: ma(e.op),
3383
3427
  classification: e.classification,
3384
3428
  reason: e.reason,
3385
3429
  blockedFix: e.blocked?.fix
3386
- }), fa = (e) => e.operations.map(da), pa = async (e) => {
3430
+ }), ga = (e) => e.operations.map(ha), _a = async (e) => {
3387
3431
  let t = e.log ?? (() => {}), n = {
3388
3432
  branchId: e.branchId,
3389
3433
  mechanism: e.mechanism,
@@ -3402,10 +3446,10 @@ BEGIN
3402
3446
  applied: !1,
3403
3447
  converged: !1,
3404
3448
  residual: r,
3405
- infidelity: fa(o)
3449
+ infidelity: ga(o)
3406
3450
  };
3407
3451
  else {
3408
- let i = await e.plan(), o = fa(i), s = o.filter((e) => e.classification === "lossy"), c = Ui(i), l = c.operations.filter((e) => e.blocked !== void 0).map(da);
3452
+ let i = await e.plan(), o = ga(i), s = o.filter((e) => e.classification === "lossy"), c = qi(i), l = c.operations.filter((e) => e.blocked !== void 0).map(ha);
3409
3453
  if (l.length > 0) a = {
3410
3454
  ...n,
3411
3455
  outcome: "blocked",
@@ -3430,7 +3474,7 @@ BEGIN
3430
3474
  };
3431
3475
  else {
3432
3476
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
3433
- let i = fa(await e.replan());
3477
+ let i = ga(await e.replan());
3434
3478
  a = {
3435
3479
  ...n,
3436
3480
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -3468,7 +3512,7 @@ BEGIN
3468
3512
  ...a,
3469
3513
  tornDown: o
3470
3514
  };
3471
- }, ma = (e) => {
3515
+ }, va = (e) => {
3472
3516
  switch (e.outcome) {
3473
3517
  case "clean": return 0;
3474
3518
  case "lossy": return 2;
@@ -3477,22 +3521,22 @@ BEGIN
3477
3521
  case "infidelity": return 1;
3478
3522
  case "failed": return 1;
3479
3523
  }
3480
- }, ha = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ga = (e) => {
3524
+ }, ya = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ba = (e) => {
3481
3525
  let t = [];
3482
3526
  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"}`);
3483
3527
  else if (e.outcome === "infidelity") {
3484
3528
  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:");
3485
- for (let n of e.infidelity) t.push(ha(n));
3529
+ for (let n of e.infidelity) t.push(ya(n));
3486
3530
  } else {
3487
3531
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
3488
- for (let n of e.operations) t.push(ha(n));
3489
- 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(ha(n));
3532
+ for (let n of e.operations) t.push(ya(n));
3533
+ 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(ya(n));
3490
3534
  }
3491
3535
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
3492
- }, _a = (e, ...t) => ({
3536
+ }, xa = (e, ...t) => ({
3493
3537
  _tag: "RawSqlFragment",
3494
3538
  strings: [...e],
3495
3539
  values: [...t]
3496
- }), va = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3540
+ }), Sa = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3497
3541
  //#endregion
3498
- export { k as DEFAULT_CDC_CHANNEL, d as FILE_MIGRATION_PATTERN, Qi as FileMigrationLedgerError, qe as REACTIVE_TRIGGER_PREFIX, pe as VOLTRO_MIGRATION_LOCK_KEY, E as acquireMigrationLock, G as appliedAtValue, It as applyNamespacedSchema, Mi as applyPlan, Et as applySchema, la as assessRollingDeployGate, ma as branchRehearsalExitCode, Ln as chunkTables, sa as classifyRollingDeploySafety, L as declaredSnapshot, $e as defaultArrayClause, Qe as defaultClause, M as defaultJsonClause, qi as describeOutcome, Vi as destructiveScope, Jt as detectReactiveTriggerDrift, Xr as emitAddIndexMysql, jr as emitCreateTableMysql, dr as emitDropColumnDdl, fr as emitDropColumnDdlMysql, Tt as emitFrameworkBootstrapSql, Ct as emitNamespaceProvisionDdl, wt as emitNamespacedSchemaSql, St as emitSchemaSql, Xn as engineFromVersion, F as fingerprintSchema, ye as fnv1a64, ga as formatBranchRehearsal, Yt as formatReactiveTriggerDrift, Bi as ignoreTablesFromEnv, Yn as introspectSchema, tr as isAlreadySatisfied, c as isFileMigration, va as isRawSqlFragment, Ot as isReRunSafeDdl, Mn as mapPgType, g as migration, be as migrationLockKeyForSchema, T as migrationLockNameForSchema, Kr as mysqlIndexPrefixFor, Ye as notifyFunctionName, N as numericIdSql, jn as parseEnumCheck, ta as pendingFileMigrationIds, An as planMigrations, Lt as provisionTenantNamespace, Je as reactiveTriggerName, pt as reactiveTriggerRepairSql, Fi as recordUpToDate, pa as rehearseMigrationOnBranch, da as rehearsedOperation, D as releaseMigrationLock, kr as renderColumnMysql, wr as renderColumnPg, he as resolveMigrationLockSchema, W as resolveMysqlEngine, ia as rollbackFileBasedMigration, ca as rollingDeployUnsafeOps, na as runFileBasedMigrations, Rt as runFrameworkBootstrap, Ft as runMigrate, Ki as runPlannedMigrations, I as shortFingerprint, Wt as snapshotColumn, _a as sql, j as sqlType, aa as squashMigrationPlans, Ui as unblockLossy, Me as withMigrationLock };
3542
+ export { O as DEFAULT_CDC_CHANNEL, d as FILE_MIGRATION_PATTERN, na as FileMigrationLedgerError, Je as REACTIVE_TRIGGER_PREFIX, pe as VOLTRO_MIGRATION_LOCK_KEY, T as acquireMigrationLock, U as appliedAtValue, Lt as applyNamespacedSchema, Ii as applyPlan, Dt as applySchema, pa as assessRollingDeployGate, va as branchRehearsalExitCode, Vn as chunkTables, da as classifyRollingDeploySafety, F as declaredSnapshot, et as defaultArrayClause, $e as defaultClause, j as defaultJsonClause, Zi as describeOutcome, Gi as destructiveScope, Xt as detectReactiveTriggerDrift, $r as emitAddIndexMysql, Pr as emitCreateTableMysql, gr as emitDropColumnDdl, _r as emitDropColumnDdlMysql, Et as emitFrameworkBootstrapSql, wt as emitNamespaceProvisionDdl, Tt as emitNamespacedSchemaSql, Ct as emitSchemaSql, er as engineFromVersion, P as fingerprintSchema, ye as fnv1a64, ba as formatBranchRehearsal, Zt as formatReactiveTriggerDrift, Wi as ignoreTablesFromEnv, $n as introspectSchema, ar as isAlreadySatisfied, c as isFileMigration, Sa as isRawSqlFragment, kt as isReRunSafeDdl, Fn as mapPgType, g as migration, be as migrationLockKeyForSchema, xe as migrationLockNameForSchema, Yr as mysqlIndexPrefixFor, Xe as notifyFunctionName, M as numericIdSql, Pn as parseEnumCheck, aa as pendingFileMigrationIds, Nn as planMigrations, Rt as provisionTenantNamespace, Ye as reactiveTriggerName, mt as reactiveTriggerRepairSql, zi as recordUpToDate, _a as rehearseMigrationOnBranch, ha as rehearsedOperation, E as releaseMigrationLock, Mr as renderColumnMysql, Dr as renderColumnPg, he as resolveMigrationLockSchema, H as resolveMysqlEngine, ca as rollbackFileBasedMigration, fa as rollingDeployUnsafeOps, oa as runFileBasedMigrations, zt as runFrameworkBootstrap, It as runMigrate, Xi as runPlannedMigrations, Gt as shortFingerprint, Kt as snapshotColumn, xa as sql, A as sqlType, la as squashMigrationPlans, qi as unblockLossy, Ne as withMigrationLock };