@voltro/database 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sql.js CHANGED
@@ -39,7 +39,7 @@ var b = (e, t, n, r = 400) => {
39
39
  t !== void 0 && s.push(`db.${e}: ${t}`);
40
40
  }
41
41
  return s.push(""), s.join("\n");
42
- }, x = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, S = (e) => e.replace(/"/g, "`"), ee = (e) => typeof e == "string" ? e : e.name ?? String(e), te = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ne = (e, t) => {
42
+ }, x = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, S = (e) => e.replace(/"/g, "`"), ee = (e) => typeof e == "string" ? e : e.name ?? String(e), C = (e, t) => `_ua_${t}_${e}`.slice(0, 64), te = (e, t) => {
43
43
  if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(x)) return e;
44
44
  let n = { ...e.fields }, r = [], i = [];
45
45
  for (let t of e.appliedIndexes) {
@@ -51,7 +51,7 @@ var b = (e, t, n, r = 400) => {
51
51
  for (let r of t.fields) {
52
52
  let i = ee(r);
53
53
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
54
- let s = te(t.name, i);
54
+ let s = C(t.name, i);
55
55
  o.push(s), n[s] = {
56
56
  type: "text",
57
57
  nullable: !0,
@@ -74,54 +74,54 @@ var b = (e, t, n, r = 400) => {
74
74
  appliedIndexes: r,
75
75
  appliedUniques: [...e.appliedUniques ?? [], ...i]
76
76
  };
77
- }, C = (e, t) => `${e}::${t}`, re = (e, t) => {
77
+ }, w = (e, t) => `${e}::${t}`, ne = (e, t) => {
78
78
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
79
79
  n.add(e);
80
80
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
81
- for (let t of o) n.has(t.target) ? i.add(C(e, t.column)) : r.has(t.target) || a(t.target);
81
+ for (let t of o) n.has(t.target) ? i.add(w(e, t.column)) : r.has(t.target) || a(t.target);
82
82
  n.delete(e), r.add(e);
83
83
  };
84
84
  for (let t of [...e].sort()) r.has(t) || a(t);
85
85
  return i;
86
- }, ie = 6322741009312437n, ae = 250, oe = () => {
86
+ }, re = 6322741009312437n, ie = 250, ae = () => {
87
87
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
88
88
  return Number.isFinite(e) && e > 0 ? e : 3e4;
89
- }, se = (e) => p.gen(function* () {
90
- let t = oe(), n = Date.now();
89
+ }, oe = (e) => p.gen(function* () {
90
+ let t = ae(), n = Date.now();
91
91
  for (;;) {
92
92
  if ((yield* e`
93
93
  SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
94
- Date.now() - n >= t && (yield* p.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* p.sleep(`${ae} millis`);
94
+ Date.now() - n >= t && (yield* p.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* p.sleep(`${ie} millis`);
95
95
  }
96
- }), ce = (e) => p.gen(function* () {
97
- yield* e`SELECT pg_advisory_unlock(${ie.toString()}::bigint)`;
98
- }), le = `voltro_migration_${ie.toString(36)}`, ue = 30, de = (e) => p.gen(function* () {
96
+ }), se = (e) => p.gen(function* () {
97
+ yield* e`SELECT pg_advisory_unlock(${re.toString()}::bigint)`;
98
+ }), ce = `voltro_migration_${re.toString(36)}`, le = 30, ue = (e) => p.gen(function* () {
99
99
  (yield* e`
100
- SELECT GET_LOCK(${le}, ${ue}) AS got`)[0]?.got !== 1 && (yield* p.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${le}' within ${ue}s (another migration is in progress, or a prior one left it held).`)));
101
- }), fe = (e) => p.gen(function* () {
102
- yield* e`SELECT RELEASE_LOCK(${le})`;
103
- }), pe = `voltro_migration_${ie.toString(36)}`, me = 3e4, he = (e) => p.gen(function* () {
100
+ SELECT GET_LOCK(${ce}, ${le}) AS got`)[0]?.got !== 1 && (yield* p.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ce}' within ${le}s (another migration is in progress, or a prior one left it held).`)));
101
+ }), de = (e) => p.gen(function* () {
102
+ yield* e`SELECT RELEASE_LOCK(${ce})`;
103
+ }), fe = `voltro_migration_${re.toString(36)}`, pe = 3e4, me = (e) => p.gen(function* () {
104
104
  let t = yield* e`
105
105
  DECLARE @res int;
106
- EXEC @res = sp_getapplock @Resource = ${pe}, @LockMode = 'Exclusive',
107
- @LockOwner = 'Session', @LockTimeout = ${me};
106
+ EXEC @res = sp_getapplock @Resource = ${fe}, @LockMode = 'Exclusive',
107
+ @LockOwner = 'Session', @LockTimeout = ${pe};
108
108
  SELECT @res AS res`;
109
- (t[0]?.res ?? -999) < 0 && (yield* p.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${pe}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
- }), ge = (e) => p.gen(function* () {
111
- yield* e`EXEC sp_releaseapplock @Resource = ${pe}, @LockOwner = 'Session'`;
112
- }), _e = p.void, w = (e) => e.onDialectOrElse({
109
+ (t[0]?.res ?? -999) < 0 && (yield* p.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${fe}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
+ }), he = (e) => p.gen(function* () {
111
+ yield* e`EXEC sp_releaseapplock @Resource = ${fe}, @LockOwner = 'Session'`;
112
+ }), ge = p.void, T = (e) => e.onDialectOrElse({
113
+ mysql: () => ue(e),
114
+ mssql: () => me(e),
115
+ sqlite: () => ge,
116
+ orElse: () => oe(e)
117
+ }), E = (e) => e.onDialectOrElse({
113
118
  mysql: () => de(e),
114
119
  mssql: () => he(e),
115
- sqlite: () => _e,
120
+ sqlite: () => ge,
116
121
  orElse: () => se(e)
117
- }), T = (e) => e.onDialectOrElse({
118
- mysql: () => fe(e),
119
- mssql: () => ge(e),
120
- sqlite: () => _e,
121
- orElse: () => ce(e)
122
- }), ve = (e, t) => p.acquireUseRelease(w(e), () => t, () => T(e).pipe(p.orDie)), ye = m({ scope: "voltro:migrate" }), E = (e) => {
122
+ }), D = (e, t) => p.acquireUseRelease(T(e), () => t, () => E(e).pipe(p.orDie)), O = "framework_changes", k = "framework_changes_", _e = (e, t) => t === "framework_changes" ? `${k}${e}` : `${k}${t}_${e}`, ve = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, ye = m({ scope: "voltro:migrate" }), A = (e) => {
123
123
  ye.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
124
- }, D = (t, n) => {
124
+ }, j = (t, n) => {
125
125
  let r = t.type;
126
126
  if (t.spatial) {
127
127
  if (n === "postgres") return `${t.spatial.kind}(${t.spatial.geomKind},${t.spatial.srid})`;
@@ -132,7 +132,7 @@ var b = (e, t, n, r = 400) => {
132
132
  return t.rawDdl;
133
133
  }
134
134
  if (r === "array" && t.arrayElement) {
135
- if (n === "postgres") return `${D({
135
+ if (n === "postgres") return `${j({
136
136
  ...t,
137
137
  type: t.arrayElement,
138
138
  arrayElement: void 0
@@ -235,19 +235,19 @@ var b = (e, t, n, r = 400) => {
235
235
  }, be = (t, n) => {
236
236
  if (!t.hasDefault || t.defaultFactory !== void 0) return null;
237
237
  let r = t.defaultValue;
238
- return r === "now" ? e(n) ? "DEFAULT CURRENT_TIMESTAMP" : n === "mssql" ? "DEFAULT SYSUTCDATETIME()" : n === "mysql" || n === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof r == "boolean" ? n === "postgres" ? `DEFAULT ${r}` : `DEFAULT ${+!!r}` : typeof r == "number" ? `DEFAULT ${r}` : typeof r == "string" ? `DEFAULT '${r.replace(/'/g, "''")}'` : Array.isArray(r) ? xe(r, t, n) : typeof r == "object" && r ? O(r, n) : null;
238
+ return r === "now" ? e(n) ? "DEFAULT CURRENT_TIMESTAMP" : n === "mssql" ? "DEFAULT SYSUTCDATETIME()" : n === "mysql" || n === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof r == "boolean" ? n === "postgres" ? `DEFAULT ${r}` : `DEFAULT ${+!!r}` : typeof r == "number" ? `DEFAULT ${r}` : typeof r == "string" ? `DEFAULT '${r.replace(/'/g, "''")}'` : Array.isArray(r) ? xe(r, t, n) : typeof r == "object" && r ? M(r, n) : null;
239
239
  }, xe = (e, t, n) => {
240
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return O(e, n);
241
- let r = D({
240
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return M(e, n);
241
+ let r = j({
242
242
  ...t,
243
243
  type: t.arrayElement,
244
244
  arrayElement: void 0
245
245
  }, n);
246
246
  return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
247
- }, O = (e, t) => {
247
+ }, M = (e, t) => {
248
248
  let n = JSON.stringify(e).replace(/'/g, "''");
249
249
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
250
- }, k = (e, t) => {
250
+ }, N = (e, t) => {
251
251
  switch (t) {
252
252
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
253
253
  case "mysql":
@@ -256,7 +256,7 @@ var b = (e, t, n, r = 400) => {
256
256
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
257
257
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
258
258
  }
259
- }, A = (e, t) => {
259
+ }, Se = (e, t) => {
260
260
  if (e === "restrict" && t === "mssql") return "NO ACTION";
261
261
  switch (e) {
262
262
  case "cascade": return "CASCADE";
@@ -264,26 +264,26 @@ var b = (e, t, n, r = 400) => {
264
264
  case "setNull": return "SET NULL";
265
265
  case "noAction": return "NO ACTION";
266
266
  }
267
- }, Se = (e, n, r) => r === null ? t(e, n) : `${t(r, n)}.${t(e, n)}`, Ce = 191, we = (e, n, r) => {
267
+ }, Ce = (e, n, r) => r === null ? t(e, n) : `${t(r, n)}.${t(e, n)}`, we = 191, Te = (e, n, r) => {
268
268
  let i = t(e, r);
269
269
  if (r !== "mysql" && r !== "mariadb") return i;
270
270
  let a = n[e];
271
271
  if (!a) return i;
272
- let o = D(a, r).toUpperCase();
273
- return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${Ce})` : i;
274
- }, Te = (e, t) => {
272
+ let o = j(a, r).toUpperCase();
273
+ return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${we})` : i;
274
+ }, Ee = (e, t) => {
275
275
  if (!e.generatedAs) return null;
276
276
  let { expr: n, stored: r } = e.generatedAs;
277
- if (t === "postgres") return r || E("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
277
+ if (t === "postgres") return r || A("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
278
278
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
279
279
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
280
280
  if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
281
281
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
282
- }, Ee = (n, r, i, a, o = !1, s = !1) => {
283
- if (r.type === "id" && r.idScheme?.kind === "numeric") return k(n, i);
284
- let c = i === "mssql" && r.type === "text" && !r.generatedAs && r.maxLength === void 0 && a?.has(n) ? "NVARCHAR(450)" : D(r, i), l = [t(n, i), c];
282
+ }, De = (n, r, i, a, o = !1, s = !1) => {
283
+ if (r.type === "id" && r.idScheme?.kind === "numeric") return N(n, i);
284
+ let c = i === "mssql" && r.type === "text" && !r.generatedAs && r.maxLength === void 0 && a?.has(n) ? "NVARCHAR(450)" : j(r, i), l = [t(n, i), c];
285
285
  r.type === "id" && !s && l.push("PRIMARY KEY");
286
- let u = Te(r, i);
286
+ let u = Ee(r, i);
287
287
  if (u) l.push(u);
288
288
  else {
289
289
  r.nullable || l.push("NOT NULL"), r.unique && r.type !== "id" && l.push("UNIQUE");
@@ -293,9 +293,9 @@ var b = (e, t, n, r = 400) => {
293
293
  if (r.type === "reference" && r.references && !o) {
294
294
  let e = r.references();
295
295
  l.push(`REFERENCES ${t(e.tableName, i)} (${t("id", i)})`);
296
- let n = A(r.onDelete ?? "restrict", i);
296
+ let n = Se(r.onDelete ?? "restrict", i);
297
297
  l.push(`ON DELETE ${n}`);
298
- let a = A(r.refOnUpdate ?? "noAction", i);
298
+ let a = Se(r.refOnUpdate ?? "noAction", i);
299
299
  a !== "NO ACTION" && l.push(`ON UPDATE ${a}`);
300
300
  }
301
301
  if (r.oneOf && r.oneOf.length > 0) {
@@ -312,18 +312,18 @@ var b = (e, t, n, r = 400) => {
312
312
  e(i) ? l.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : i === "mssql" && l.push(`CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
313
313
  }
314
314
  return l.join(" ");
315
- }, De = (e, n, r = null, i) => {
315
+ }, Oe = (e, n, r = null, i) => {
316
316
  let a = /* @__PURE__ */ new Set();
317
317
  for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
318
318
  for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
319
- let o = e.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(e.fields).map(([e, t]) => ` ${Ee(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((r) => {
320
- let i = r.fields.map((t) => we(t, e.fields, n)).join(", ");
319
+ let o = e.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(e.fields).map(([e, t]) => ` ${De(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((r) => {
320
+ let i = r.fields.map((t) => Te(t, e.fields, n)).join(", ");
321
321
  return ` CONSTRAINT ${t(r.name, n)} UNIQUE (${i})`;
322
322
  }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${t(e.name, n)} CHECK (${e.expr})`), d = [
323
- ...s ? [` PRIMARY KEY (${o.map((t) => we(t, e.fields, n)).join(", ")})`] : [],
323
+ ...s ? [` PRIMARY KEY (${o.map((t) => Te(t, e.fields, n)).join(", ")})`] : [],
324
324
  ...l,
325
325
  ...u
326
- ], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = Se(e.tableName, n, r);
326
+ ], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = Ce(e.tableName, n, r);
327
327
  if (n === "mssql") {
328
328
  let t = r === null ? e.tableName : `${r}.${e.tableName}`, n = `CREATE TABLE ${p} (\n${f}\n)`;
329
329
  return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
@@ -333,10 +333,10 @@ var b = (e, t, n, r = 400) => {
333
333
  f,
334
334
  ");"
335
335
  ].join("\n");
336
- }, Oe = (e, n, r) => {
336
+ }, ke = (e, n, r) => {
337
337
  let i = `${e}_${n.name}_fts`, a = (e) => t(e, r), o = n.columns.map(a).join(", "), s = n.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
338
338
  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;
339
- }, ke = (e, n, r = null) => {
339
+ }, Ae = (e, n, r = null) => {
340
340
  let i = [], a = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, t, r, i) => {
341
341
  let a = {
342
342
  using: "",
@@ -348,21 +348,21 @@ var b = (e, t, n, r = 400) => {
348
348
  using: " USING GIST",
349
349
  withSuffix: "",
350
350
  skip: !1
351
- } : (E(`[voltro:migrate] index '${e}' on '${t}': ${n} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), a);
351
+ } : (A(`[voltro:migrate] index '${e}' on '${t}': ${n} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), a);
352
352
  if (r === "gin") return n === "postgres" ? {
353
353
  using: " USING GIN",
354
354
  withSuffix: "",
355
355
  skip: !1
356
- } : n === "mysql" || n === "mariadb" ? (E(`[voltro:migrate] gin index '${e}' on '${t}': ${n} 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(...).`), {
356
+ } : n === "mysql" || n === "mariadb" ? (A(`[voltro:migrate] gin index '${e}' on '${t}': ${n} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
357
357
  using: "",
358
358
  withSuffix: "",
359
359
  skip: !0
360
- }) : (E(`[voltro:migrate] gin index '${e}' on '${t}': ${n} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), a);
360
+ }) : (A(`[voltro:migrate] gin index '${e}' on '${t}': ${n} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), a);
361
361
  if (r === "brin") return n === "postgres" ? {
362
362
  using: " USING BRIN",
363
363
  withSuffix: "",
364
364
  skip: !1
365
- } : (E(`[voltro:migrate] brin index '${e}' on '${t}': ${n} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
365
+ } : (A(`[voltro:migrate] brin index '${e}' on '${t}': ${n} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
366
366
  if (r === "hnsw") {
367
367
  if (n === "postgres") {
368
368
  let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? u(i?.hnsw?.distance);
@@ -373,7 +373,7 @@ var b = (e, t, n, r = 400) => {
373
373
  skip: !1
374
374
  };
375
375
  }
376
- return E(`[voltro:migrate] hnsw index '${e}' on '${t}': ${n} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
376
+ return A(`[voltro:migrate] hnsw index '${e}' on '${t}': ${n} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
377
377
  using: "",
378
378
  withSuffix: "",
379
379
  skip: !0
@@ -382,7 +382,7 @@ var b = (e, t, n, r = 400) => {
382
382
  return a;
383
383
  }, c = (t, r) => {
384
384
  let i = t.map((t) => {
385
- if (typeof t == "string") return we(t, e.fields, n);
385
+ if (typeof t == "string") return Te(t, e.fields, n);
386
386
  if ("jsonPath" in t) {
387
387
  let { column: e, path: r, numeric: i } = t.jsonPath;
388
388
  return `(${f(e, r, n, { numeric: i })})`;
@@ -393,7 +393,7 @@ var b = (e, t, n, r = 400) => {
393
393
  }, l = (e, i, a, o, l, u = "", d = !1) => {
394
394
  let f = s(e, i, o, l);
395
395
  if (f.skip) return "";
396
- let p = c(a, f.opclass), m = `${f.withSuffix}${u}`, h = Se(i, n, r), g = d ? "UNIQUE " : "";
396
+ let p = c(a, f.opclass), m = `${f.withSuffix}${u}`, h = Ce(i, n, r), g = d ? "UNIQUE " : "";
397
397
  return n === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${t(e, n)} ON ${h}${f.using} (${p})${m};` : n === "mysql" ? `CREATE ${g}INDEX ${t(e, n)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${t(e, n)} ON ${h}${f.using} (${p})${m};`;
398
398
  };
399
399
  for (let r of e.appliedFullText ?? []) if (n === "postgres") {
@@ -406,15 +406,15 @@ var b = (e, t, n, r = 400) => {
406
406
  let a = r.columns.map((e) => t(e, n)).join(", ");
407
407
  i.push(`CREATE FULLTEXT INDEX ${t(r.name, n)} ON ${t(e.tableName, n)} (${a});`);
408
408
  } else if (n === "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.`);
409
- else n === "sqlite" ? i.push(...Oe(e.tableName, r, n)) : E(`[voltro:migrate] full-text index '${r.name}' on '${e.tableName}': ${n} uses a ranked LIKE search at query time (no native FTS catalog required).`);
409
+ else n === "sqlite" ? i.push(...ke(e.tableName, r, n)) : A(`[voltro:migrate] full-text index '${r.name}' on '${e.tableName}': ${n} uses a ranked LIKE search at query time (no native FTS catalog required).`);
410
410
  for (let t of e.appliedIndexes) {
411
411
  if ((n === "mariadb" || n === "mssql") && t.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
412
- E(`[voltro:migrate] json-path index '${t.name}' on '${e.tableName}': ${n} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${n}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
412
+ A(`[voltro:migrate] json-path index '${t.name}' on '${e.tableName}': ${n} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${n}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
413
413
  continue;
414
414
  }
415
415
  if (t.unique && t.where !== void 0 && t.where.length > 0 && (n === "mysql" || n === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${t.name}' on '${e.tableName}' cannot be expressed on ${n} — 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 ${n}, or move this table to postgres/sqlite/mssql.`);
416
416
  let r = "";
417
- t.where !== void 0 && t.where.length > 0 && (n === "mysql" || n === "mariadb" ? E(`[voltro:migrate] partial index '${t.name}' on '${e.tableName}': ${n} does not support WHERE clauses on indexes — emitting a full index`) : r = ` WHERE ${t.where}`);
417
+ t.where !== void 0 && t.where.length > 0 && (n === "mysql" || n === "mariadb" ? A(`[voltro:migrate] partial index '${t.name}' on '${e.tableName}': ${n} does not support WHERE clauses on indexes — emitting a full index`) : r = ` WHERE ${t.where}`);
418
418
  let s = l(t.name, e.tableName, t.fields, t.kind, t.kindOptions, r, t.unique === !0);
419
419
  s !== "" && i.push(s), t.fields.every((e) => typeof e == "string") && a.add(o(t.fields));
420
420
  }
@@ -424,12 +424,12 @@ var b = (e, t, n, r = 400) => {
424
424
  i.push(l(r, e.tableName, [t])), a.add(o([t]));
425
425
  }
426
426
  return i.join("\n");
427
- }, j = "framework_changes", Ae = (e, t, n = j) => {
427
+ }, je = (e, t, n = O) => {
428
428
  if (t !== "postgres") return [];
429
429
  let r = e.filter((e) => e.isReactive !== !1);
430
- return r.length === 0 ? [] : [Me(n), ...r.map((e) => Ne(e, n))];
431
- }, je = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Me = (e) => `
432
- CREATE OR REPLACE FUNCTION ${je(e)}() RETURNS trigger AS $$
430
+ return r.length === 0 ? [] : [Me(n), ...r.map((e) => Pe(e, n))];
431
+ }, Me = (e) => `
432
+ CREATE OR REPLACE FUNCTION ${ve(e)}() RETURNS trigger AS $$
433
433
  DECLARE
434
434
  payload TEXT;
435
435
  BEGIN
@@ -464,16 +464,23 @@ BEGIN
464
464
  END;
465
465
  $$ LANGUAGE plpgsql;
466
466
  `.trim(), Ne = (e, t) => {
467
- let n = t === "framework_changes" ? `framework_changes_${e.tableName}` : `framework_changes_${t}_${e.tableName}`;
468
- return `
469
- ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
470
- DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}";
471
- CREATE TRIGGER ${n}
472
- AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
473
- FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
474
- `.trim();
475
- }, Pe = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Fe = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Ie = (e) => {
476
- let t = new Map(e.map((e) => [e.tableName, e])), n = re(e.map((e) => e.tableName), (e) => {
467
+ let n = _e(e.tableName, t);
468
+ return [
469
+ `ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
470
+ `DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
471
+ `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${ve(t)}()`
472
+ ];
473
+ }, Pe = (e, t) => Ne(e, t).map((e) => `${e};`).join("\n"), Fe = (e) => {
474
+ if (e.dialect !== "postgres") return [];
475
+ 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));
476
+ if (i.length > 0) {
477
+ r.push(Me(t));
478
+ for (let e of i) r.push(...Ne(n.get(e), t));
479
+ }
480
+ for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${_e(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
481
+ return r;
482
+ }, Ie = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Le = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Re = (e) => {
483
+ let t = new Map(e.map((e) => [e.tableName, e])), n = ne(e.map((e) => e.tableName), (e) => {
477
484
  let n = t.get(e);
478
485
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
479
486
  if (n.type !== "reference" || !n.references) return [];
@@ -484,7 +491,7 @@ FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
484
491
  }] : [];
485
492
  }) : [];
486
493
  }), r = [];
487
- for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(C(t.tableName, e)) && r.push({
494
+ for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(w(t.tableName, e)) && r.push({
488
495
  table: t.tableName,
489
496
  column: e,
490
497
  targetTable: i.references().tableName,
@@ -495,7 +502,7 @@ FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
495
502
  if (!(i.has(e.tableName) || a.has(e.tableName))) {
496
503
  a.add(e.tableName);
497
504
  for (let [r, i] of Object.entries(e.fields)) {
498
- if (i.type !== "reference" || !i.references || n.has(C(e.tableName, r))) continue;
505
+ if (i.type !== "reference" || !i.references || n.has(w(e.tableName, r))) continue;
499
506
  let a = i.references();
500
507
  if (a.tableName === e.tableName) continue;
501
508
  let o = t.get(a.tableName);
@@ -509,8 +516,8 @@ FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
509
516
  sorted: o,
510
517
  cyclic: r
511
518
  };
512
- }, Le = (e, n, r = null) => {
513
- let i = (e) => r ? `${t(r, n)}.${t(e, n)}` : t(e, n), a = `${e.table}_${e.column}_fkey`, o = A(e.onDelete, n), s = A(e.onUpdate, n), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${t(a, n)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${t(e.column, n)}) REFERENCES ${i(e.targetTable)} (${t("id", n)})${c}`;
519
+ }, ze = (e, n, r = null) => {
520
+ let i = (e) => r ? `${t(r, n)}.${t(e, n)}` : t(e, n), a = `${e.table}_${e.column}_fkey`, o = Se(e.onDelete, n), s = Se(e.onUpdate, n), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${t(a, n)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${t(e.column, n)}) REFERENCES ${i(e.targetTable)} (${t("id", n)})${c}`;
514
521
  switch (n) {
515
522
  case "postgres": return [
516
523
  "DO $$ BEGIN",
@@ -524,7 +531,7 @@ FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
524
531
  case "mariadb": return `ALTER TABLE ${i(e.table)} ${l(!0)};`;
525
532
  default: return `ALTER TABLE ${i(e.table)} ${l(!1)};`;
526
533
  }
527
- }, Re = (t, n) => {
534
+ }, Be = (t, n) => {
528
535
  let r = /* @__PURE__ */ new Map();
529
536
  if (e(n)) return r;
530
537
  for (let e of t) {
@@ -532,7 +539,7 @@ FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
532
539
  t.add(e.column), r.set(e.table, t);
533
540
  }
534
541
  return r;
535
- }, ze = (e, t) => {
542
+ }, Ve = (e, t) => {
536
543
  if (t !== "postgres") return "";
537
544
  let n = /* @__PURE__ */ new Map();
538
545
  for (let t of e) for (let e of Object.values(t.fields)) {
@@ -548,7 +555,7 @@ FOR EACH ROW EXECUTE FUNCTION ${je(t)}();
548
555
  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 $$;`);
549
556
  }
550
557
  return r.join("\n\n");
551
- }, Be = (e, t) => {
558
+ }, He = (e, t) => {
552
559
  if (t !== "postgres") return "";
553
560
  let n = /* @__PURE__ */ new Set();
554
561
  for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
@@ -562,30 +569,30 @@ BEGIN
562
569
  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 $$;`);
563
570
  }
564
571
  return r.join("\n\n");
565
- }, Ve = (e) => {
572
+ }, Ue = (e) => {
566
573
  let t = [], n = [];
567
574
  for (let i of e) r(i) ? n.push(i) : t.push(i);
568
575
  return {
569
576
  tables: t,
570
577
  views: n
571
578
  };
572
- }, M = (t, n, r = j) => {
573
- let { tables: a, views: o } = Ve(t), { sorted: s, cyclic: c } = Ie(a.map((e) => ne(e, n))), l = Re(c, n), u = [];
574
- n === "postgres" && Pe(s) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && Fe(s) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
575
- let d = Be(s, n);
579
+ }, We = (t, n, r = O) => {
580
+ let { tables: a, views: o } = Ue(t), { sorted: s, cyclic: c } = Re(a.map((e) => te(e, n))), l = Be(c, n), u = [];
581
+ n === "postgres" && Ie(s) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && Le(s) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
582
+ let d = He(s, n);
576
583
  d && u.push(d);
577
- let f = ze(s, n);
584
+ let f = Ve(s, n);
578
585
  f && u.push(f);
579
- for (let e of s) u.push(De(e, n, null, l.get(e.tableName)));
580
- if (!e(n)) for (let e of c) u.push(Le(e, n));
586
+ for (let e of s) u.push(Oe(e, n, null, l.get(e.tableName)));
587
+ if (!e(n)) for (let e of c) u.push(ze(e, n));
581
588
  for (let e of s) {
582
- let t = ke(e, n);
589
+ let t = Ae(e, n);
583
590
  t && u.push(t);
584
591
  }
585
- u.push(...Ae(s, n, r));
592
+ u.push(...je(s, n, r));
586
593
  for (let e of o) u.push(i(e, n));
587
594
  return u.join("\n\n") + "\n";
588
- }, He = (e, n, r) => {
595
+ }, Ge = (e, n, r) => {
589
596
  let i = t(e, n);
590
597
  switch (n) {
591
598
  case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
@@ -595,38 +602,38 @@ BEGIN
595
602
  case "turso":
596
603
  case "sqlite": return `ATTACH DATABASE '${(r ?? `${e}.db`).replace(/'/g, "''")}' AS ${i};`;
597
604
  }
598
- }, Ue = (n, r, i, a) => {
599
- let o = He(i, r, a), s = t(i, r);
600
- if (r === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${M(n, r)}`;
601
- if (r === "mysql" || r === "mariadb") return `${o}\n\nUSE ${s};\n\n${M(n, r)}`;
602
- let { sorted: c, cyclic: l } = Ie(n), u = Re(l, r), d = [o];
603
- for (let e of c) d.push(De(e, r, i, u.get(e.tableName)));
604
- if (!e(r)) for (let e of l) d.push(Le(e, r, i));
605
+ }, Ke = (n, r, i, a) => {
606
+ let o = Ge(i, r, a), s = t(i, r);
607
+ if (r === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${We(n, r)}`;
608
+ if (r === "mysql" || r === "mariadb") return `${o}\n\nUSE ${s};\n\n${We(n, r)}`;
609
+ let { sorted: c, cyclic: l } = Re(n), u = Be(l, r), d = [o];
610
+ for (let e of c) d.push(Oe(e, r, i, u.get(e.tableName)));
611
+ if (!e(r)) for (let e of l) d.push(ze(e, r, i));
605
612
  for (let e of c) {
606
- let t = ke(e, r, i);
613
+ let t = Ae(e, r, i);
607
614
  t && d.push(t);
608
615
  }
609
616
  return d.join("\n\n") + "\n";
610
- }, We = (e, t, n = j) => {
611
- let { sorted: r, cyclic: i } = Ie(e), a = Re(i, t), o = [], s = Be(r, t);
617
+ }, qe = (e, t, n = O) => {
618
+ let { sorted: r, cyclic: i } = Re(e), a = Be(i, t), o = [], s = He(r, t);
612
619
  s && o.push(s);
613
- let c = ze(r, t);
620
+ let c = Ve(r, t);
614
621
  c && o.push(c);
615
- for (let e of r) o.push(De(e, t, null, a.get(e.tableName)));
616
- for (let e of i) o.push(Le(e, t));
617
- return o.push(...Ae(r, t, n)), o.join("\n\n") + "\n";
618
- }, Ge = (e, t = "postgres", n = j) => p.gen(function* () {
622
+ for (let e of r) o.push(Oe(e, t, null, a.get(e.tableName)));
623
+ for (let e of i) o.push(ze(e, t));
624
+ return o.push(...je(r, t, n)), o.join("\n\n") + "\n";
625
+ }, Je = (e, t = "postgres", n = O) => p.gen(function* () {
619
626
  let r = yield* h.SqlClient;
620
- yield* ve(r, Je(r, M(e, t, n), t)).pipe(p.orDie);
621
- }), Ke = (e, t) => {
627
+ yield* D(r, Ze(r, We(e, t, n), t)).pipe(p.orDie);
628
+ }), Ye = (e, t) => {
622
629
  let n = t.cause ?? {};
623
630
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
624
- }, qe = (e) => p.gen(function* () {
631
+ }, Xe = (e) => p.gen(function* () {
625
632
  let t = yield* h.SqlClient;
626
- for (let n of Ye(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ye.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(p.catchIf((e) => Ke(n, e), () => p.void), p.tapError((e) => p.sync(() => {
633
+ for (let n of Qe(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ye.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(p.catchIf((e) => Ye(n, e), () => p.void), p.tapError((e) => p.sync(() => {
627
634
  ye.error(b("migrate: statement failed", n, e, 200));
628
635
  })), p.orDieWith((e) => Error(b("migrate: statement failed", n, e, 400).trim())));
629
- }), Je = (e, t, n) => (n === "turso" ? qe(t) : e.withTransaction(qe(t))).pipe(p.orDie), Ye = (e) => {
636
+ }), Ze = (e, t, n) => (n === "turso" ? Xe(t) : e.withTransaction(Xe(t))).pipe(p.orDie), Qe = (e) => {
630
637
  let t = [], n = "", r = !1;
631
638
  for (let i = 0; i < e.length; i++) {
632
639
  if (e.slice(i, i + 2) === "$$") {
@@ -641,40 +648,40 @@ BEGIN
641
648
  }
642
649
  let i = n.trim();
643
650
  return i.length > 0 && t.push(i), t;
644
- }, Xe = async (e, t, n = "postgres") => {
645
- await p.runPromise(Ge(e, n).pipe(p.provide(t)));
646
- }, Ze = (e, t, n = "postgres") => p.gen(function* () {
647
- let r = Ue(e, n, t), i = yield* h.SqlClient;
648
- yield* ve(i, Je(i, r, n)).pipe(p.orDie);
649
- }), Qe = async (e, t, n, r = "postgres") => {
650
- await p.runPromise(Ze(e, t, r).pipe(p.provide(n)));
651
651
  }, $e = async (e, t, n = "postgres") => {
652
+ await p.runPromise(Je(e, n).pipe(p.provide(t)));
653
+ }, et = (e, t, n = "postgres") => p.gen(function* () {
654
+ let r = Ke(e, n, t), i = yield* h.SqlClient;
655
+ yield* D(i, Ze(i, r, n)).pipe(p.orDie);
656
+ }), tt = async (e, t, n, r = "postgres") => {
657
+ await p.runPromise(et(e, t, r).pipe(p.provide(n)));
658
+ }, nt = async (e, t, n = "postgres") => {
652
659
  await p.runPromise(p.gen(function* () {
653
- let t = We(e, n), r = yield* h.SqlClient;
654
- yield* ve(r, Je(r, t, n)).pipe(p.orDie);
660
+ let t = qe(e, n), r = yield* h.SqlClient;
661
+ yield* D(r, Ze(r, t, n)).pipe(p.orDie);
655
662
  }).pipe(p.provide(t)));
656
- }, et = (e) => {
663
+ }, rt = (e) => {
657
664
  if (e == null) return e;
658
- if (Array.isArray(e)) return e.map(et);
665
+ if (Array.isArray(e)) return e.map(rt);
659
666
  if (typeof e != "object") return e;
660
667
  let t = {};
661
668
  for (let n of Object.keys(e).sort()) {
662
669
  let r = e[n];
663
- r !== void 0 && (t[n] = et(r));
670
+ r !== void 0 && (t[n] = rt(r));
664
671
  }
665
672
  return t;
666
- }, tt = (e) => {
673
+ }, it = (e) => {
667
674
  if (!e.idScheme && !e.sensitive && !e.safe) return e;
668
675
  let { idScheme: t, sensitive: n, safe: r, ...i } = e;
669
676
  return i;
670
- }, nt = (e) => [...e].map(tt).sort((e, t) => e.name.localeCompare(t.name)), rt = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), it = (e) => [...e].map((e) => ({
677
+ }, at = (e) => [...e].map(it).sort((e, t) => e.name.localeCompare(t.name)), ot = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), st = (e) => [...e].map((e) => ({
671
678
  name: e.name,
672
- columns: nt(e.columns),
673
- indexes: rt(e.indexes)
674
- })).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
675
- let t = { tables: it(e.tables) }, n = JSON.stringify(et(t));
679
+ columns: at(e.columns),
680
+ indexes: ot(e.indexes)
681
+ })).sort((e, t) => e.name.localeCompare(t.name)), P = (e) => {
682
+ let t = { tables: st(e.tables) }, n = JSON.stringify(rt(t));
676
683
  return g("sha256").update(n).digest("hex");
677
- }, P = (e) => e.slice(0, 16), at = (e, t) => {
684
+ }, F = (e) => e.slice(0, 16), ct = (e, t) => {
678
685
  let n = t.references ? {
679
686
  table: t.references().tableName,
680
687
  column: "id",
@@ -713,7 +720,7 @@ BEGIN
713
720
  ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
714
721
  ...t.spatial === void 0 ? {} : { spatial: t.spatial }
715
722
  };
716
- }, ot = (e) => {
723
+ }, lt = (e) => {
717
724
  let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
718
725
  n.has(e.name) || (n.add(e.name), t.push(e));
719
726
  }, i = e.appliedPrimaryKey ?? [];
@@ -761,11 +768,11 @@ BEGIN
761
768
  });
762
769
  }
763
770
  return t;
764
- }, st = (e) => {
771
+ }, ut = (e) => {
765
772
  let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
766
773
  for (let [r, i] of Object.entries(e.fields)) {
767
774
  if (i.dropped) continue;
768
- let e = at(r, i);
775
+ let e = ct(r, i);
769
776
  n.push(t.has(r) ? {
770
777
  ...e,
771
778
  unique: !0
@@ -775,44 +782,44 @@ BEGIN
775
782
  return {
776
783
  name: e.tableName,
777
784
  columns: n,
778
- indexes: ot(e),
785
+ indexes: lt(e),
779
786
  ...r.length > 0 ? { primaryKey: [...r] } : {},
780
787
  ...i === void 0 ? {} : { renamedFrom: i }
781
788
  };
782
- }, ct = (e) => {
789
+ }, dt = (e) => {
783
790
  let t = /* @__PURE__ */ new Map();
784
791
  for (let n of e) for (let e of n.indexes) {
785
792
  let r = t.get(e.name);
786
793
  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}').`);
787
794
  t.set(e.name, n.name);
788
795
  }
789
- }, F = (e, t) => {
790
- let n = e.map((e) => st(ne(e, t)));
791
- return ct(n), { tables: n };
792
- }, lt = "framework_changes_", ut = (e, t) => p.gen(function* () {
793
- let n = t.filter((e) => !e.tableName.startsWith("_voltro_"));
794
- if (n.length === 0) return {
796
+ }, I = (e, t) => {
797
+ let n = e.map((e) => ut(te(e, t)));
798
+ return dt(n), { tables: n };
799
+ }, ft = (e, t, n = O) => p.gen(function* () {
800
+ let r = t.filter((e) => !e.tableName.startsWith("_voltro_"));
801
+ if (r.length === 0) return {
795
802
  missing: [],
796
803
  stale: []
797
804
  };
798
- let r = yield* e`
805
+ let i = yield* e`
799
806
  SELECT t.tgname
800
807
  FROM pg_trigger t
801
808
  JOIN pg_class c ON c.oid = t.tgrelid
802
809
  JOIN pg_namespace n ON n.oid = c.relnamespace
803
810
  WHERE NOT t.tgisinternal
804
811
  AND n.nspname = current_schema()
805
- AND t.tgname LIKE ${`${lt}%`}
806
- `, i = new Set(r.map((e) => e.tgname)), a = [], o = [];
807
- for (let e of n) {
808
- let t = i.has(`${lt}${e.tableName}`), n = e.isReactive !== !1;
809
- n && !t && a.push(e.tableName), !n && t && o.push(e.tableName);
812
+ AND t.tgname LIKE ${`${k}%`}
813
+ `, a = new Set(i.map((e) => e.tgname)), o = [], s = [];
814
+ for (let e of r) {
815
+ let t = a.has(_e(e.tableName, n)), r = e.isReactive !== !1;
816
+ r && !t && o.push(e.tableName), !r && t && s.push(e.tableName);
810
817
  }
811
818
  return {
812
- missing: a.sort(),
813
- stale: o.sort()
819
+ missing: o.sort(),
820
+ stale: s.sort()
814
821
  };
815
- }), dt = (e) => {
822
+ }), pt = (e) => {
816
823
  let t = [];
817
824
  if (e.missing.length > 0) {
818
825
  let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
@@ -823,19 +830,19 @@ BEGIN
823
830
  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.`);
824
831
  }
825
832
  return t.length > 0 ? t.join("\n") : void 0;
826
- }, ft = {
833
+ }, mt = {
827
834
  postgres: !0,
828
835
  mysql: !0,
829
836
  mariadb: !0,
830
837
  mssql: !0,
831
838
  sqlite: !0
832
- }, pt = {
839
+ }, ht = {
833
840
  postgres: !0,
834
841
  mysql: !1,
835
842
  mariadb: !1,
836
843
  mssql: !0,
837
844
  sqlite: !0
838
- }, mt = (e) => {
845
+ }, gt = (e) => {
839
846
  switch (e) {
840
847
  case "add-column":
841
848
  case "drop-column":
@@ -845,43 +852,43 @@ BEGIN
845
852
  case "add-foreign-key":
846
853
  case "add-unique":
847
854
  case "add-unique-composite":
848
- case "add-check": return pt;
849
- default: return ft;
855
+ case "add-check": return ht;
856
+ default: return mt;
850
857
  }
851
- }, ht = (e, t) => {
858
+ }, _t = (e, t) => {
852
859
  let n = new Map(t.tables.map((e) => [e.name, e]));
853
860
  return new Map(e.map((e) => [e.tableName, {
854
861
  table: e,
855
862
  snapshot: n.get(e.tableName),
856
863
  columnDefs: e.fields
857
864
  }]));
858
- }, I = (e) => {
865
+ }, L = (e) => {
859
866
  if (typeof e != "object" || !e) return JSON.stringify(e);
860
- if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
867
+ if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
861
868
  let t = e;
862
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
863
- }, gt = (e) => {
869
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
870
+ }, vt = (e) => {
864
871
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
865
872
  let t = e.defaultValue;
866
873
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
867
874
  if (typeof t == "number") return String(t);
868
- if (typeof t != "string") return I(t);
875
+ if (typeof t != "string") return L(t);
869
876
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
870
877
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
871
878
  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);
872
879
  if (o) try {
873
- return I(JSON.parse(o[1]));
880
+ return L(JSON.parse(o[1]));
874
881
  } catch {}
875
882
  if (a.startsWith("{") || a.startsWith("[")) try {
876
- return I(JSON.parse(a));
883
+ return L(JSON.parse(a));
877
884
  } catch {}
878
885
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
879
- }, _t = (e, t) => {
880
- let n = gt(e), r = gt(t);
886
+ }, yt = (e, t) => {
887
+ let n = vt(e), r = vt(t);
881
888
  if (n === r) return !0;
882
889
  let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
883
890
  return i(n) === i(r);
884
- }, L = (e) => {
891
+ }, bt = (e) => {
885
892
  if (!e) return null;
886
893
  let t = (e) => e === "restrict" ? "noAction" : e;
887
894
  return {
@@ -890,25 +897,25 @@ BEGIN
890
897
  onDelete: t(e.onDelete),
891
898
  onUpdate: t(e.onUpdate)
892
899
  };
893
- }, vt = (e, t) => {
900
+ }, xt = (e, t) => {
894
901
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
895
902
  if (!n && !r) return !0;
896
903
  if (!n || !r || n.length !== r.length) return !1;
897
904
  let i = [...n].sort(), a = [...r].sort();
898
905
  return i.every((e, t) => e === a[t]);
899
- }, yt = (e, t) => {
906
+ }, St = (e, t) => {
900
907
  try {
901
- let n = /\((\d+)\)/.exec(D(e, t));
908
+ let n = /\((\d+)\)/.exec(j(e, t));
902
909
  return n ? Number(n[1]) : void 0;
903
910
  } catch {
904
911
  return;
905
912
  }
906
- }, bt = (t, n, r) => r === void 0 || e(r) ? !0 : t.type !== "text" || n.type !== "text" || yt(t, r) === n.maxLength, xt = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && _t(e, t) && bt(e, t, n) && JSON.stringify(L(e.references)) === JSON.stringify(L(t.references)) && vt(e.oneOf, t.oneOf), St = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
913
+ }, Ct = (t, n, r) => r === void 0 || e(r) ? !0 : t.type !== "text" || n.type !== "text" || St(t, r) === n.maxLength, wt = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && yt(e, t) && Ct(e, t, n) && JSON.stringify(bt(e.references)) === JSON.stringify(bt(t.references)) && xt(e.oneOf, t.oneOf), Tt = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
907
914
  kind: "add-check",
908
915
  table: e,
909
916
  column: t.name,
910
917
  values: t.oneOf
911
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Ct = (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])), wt = (e, t, n) => {
918
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Et = (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])), Dt = (e, t, n) => {
912
919
  let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
913
920
  for (let t of e.columns) {
914
921
  let e = r.get(t.name);
@@ -916,7 +923,7 @@ BEGIN
916
923
  a.push(t);
917
924
  continue;
918
925
  }
919
- xt(t, e, n) || s.push({
926
+ wt(t, e, n) || s.push({
920
927
  declared: t,
921
928
  live: e
922
929
  });
@@ -927,11 +934,11 @@ BEGIN
927
934
  removed: o,
928
935
  changed: s
929
936
  };
930
- }, Tt = (e, t) => {
937
+ }, Ot = (e, t) => {
931
938
  let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
932
939
  for (let t of e.indexes) {
933
940
  let e = n.get(t.name);
934
- (!e || !Ct(t, e)) && i.push(t);
941
+ (!e || !Et(t, e)) && i.push(t);
935
942
  }
936
943
  for (let e of t.indexes) r.has(e.name) || a.push(e);
937
944
  return {
@@ -941,33 +948,33 @@ BEGIN
941
948
  }, R = (e, t, n, r) => ({
942
949
  op: e,
943
950
  classification: t,
944
- atomicByDialect: mt(e.kind),
951
+ atomicByDialect: gt(e.kind),
945
952
  ...n ? { reason: n } : {},
946
953
  ...r ? { blocked: r } : {}
947
- }), Et = (e, t, n) => {
954
+ }), kt = (e, t, n) => {
948
955
  let r = {
949
956
  kind: "add-column",
950
957
  table: e,
951
958
  column: t
952
959
  };
953
960
  return t.nullable ? R(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? R(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? R(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : R(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
954
- }, Dt = (e, t, n) => {
961
+ }, At = (e, t, n) => {
955
962
  let r = {
956
963
  kind: "drop-column",
957
964
  table: e,
958
965
  column: t.name
959
966
  };
960
967
  return n?.dropped ? R(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : R(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
961
- }, Ot = (e, t, n, r, i) => R({
968
+ }, jt = (e, t, n, r, i) => R({
962
969
  kind: "create-table",
963
970
  table: e,
964
971
  columns: t,
965
972
  indexes: n,
966
973
  ...r && r.length > 0 ? { primaryKey: r } : {}
967
- }, "safe", i ?? "new table — no data to preserve"), kt = (e) => R({
974
+ }, "safe", i ?? "new table — no data to preserve"), Mt = (e) => R({
968
975
  kind: "drop-table",
969
976
  table: e
970
- }, "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" }), At = 5e4, jt = (e, t, n, r) => {
977
+ }, "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" }), Nt = 5e4, Pt = (e, t, n, r) => {
971
978
  let i = (n ?? 0) >= r, a;
972
979
  return a = t.unique ? t.columns.length === 1 ? {
973
980
  kind: "add-unique",
@@ -983,7 +990,7 @@ BEGIN
983
990
  table: e,
984
991
  index: t
985
992
  }, i ? R(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
986
- }, Mt = (e, t) => t.unique && t.columns.length > 1 ? R({
993
+ }, Ft = (e, t) => t.unique && t.columns.length > 1 ? R({
987
994
  kind: "drop-unique-composite",
988
995
  table: e,
989
996
  name: t.name
@@ -991,7 +998,7 @@ BEGIN
991
998
  kind: "drop-index",
992
999
  table: e,
993
1000
  index: t.name
994
- }, "safe", "drop index (no data loss — index is derived data)"), Nt = (e, t) => {
1001
+ }, "safe", "drop index (no data loss — index is derived data)"), It = (e, t) => {
995
1002
  if (e === "reference") return "text";
996
1003
  switch (t) {
997
1004
  case "sqlite":
@@ -999,7 +1006,7 @@ BEGIN
999
1006
  case "mssql": return e === "json" ? "text" : e;
1000
1007
  default: return e;
1001
1008
  }
1002
- }, Pt = (t, n, r, i, a, o) => {
1009
+ }, Lt = (t, n, r, i, a, o) => {
1003
1010
  let s = [];
1004
1011
  if (n.nullable !== r.nullable) {
1005
1012
  let e = {
@@ -1022,7 +1029,7 @@ BEGIN
1022
1029
  table: t,
1023
1030
  column: n.name
1024
1031
  }, "safe", `drop unique constraint on ${t}.${n.name} — constraint is derived metadata, no data loss`));
1025
- if (Nt(n.type, i) !== Nt(r.type, i)) {
1032
+ if (It(n.type, i) !== It(r.type, i)) {
1026
1033
  let e = n.narrowedFrom;
1027
1034
  if (e && e.from === r.type) {
1028
1035
  let i = {
@@ -1055,7 +1062,7 @@ BEGIN
1055
1062
  to: "text"
1056
1063
  }, e ? "safe" : "needs-backfill", e ? `text length ${i} → ${a} on ${t}.${n.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${t}.${n.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(n.maxLength)}. Check first: SELECT COUNT(*) FROM ${t} WHERE LENGTH(${n.name}) > ${String(n.maxLength)}`));
1057
1064
  }
1058
- if (!_t(n, r)) {
1065
+ if (!yt(n, r)) {
1059
1066
  let e = {
1060
1067
  kind: "alter-column-default",
1061
1068
  table: t,
@@ -1065,16 +1072,16 @@ BEGIN
1065
1072
  };
1066
1073
  s.push(R(e, "safe", `default change on ${t}.${n.name} affects only future inserts`));
1067
1074
  }
1068
- if (!vt(n.oneOf, r.oneOf)) {
1075
+ if (!xt(n.oneOf, r.oneOf)) {
1069
1076
  r.oneOf && r.oneOf.length > 0 && s.push(R({
1070
1077
  kind: "drop-check",
1071
1078
  table: t,
1072
1079
  column: n.name
1073
1080
  }, "safe", `drop stale enum CHECK on ${t}.${n.name}`));
1074
- let e = St(t, n);
1081
+ let e = Tt(t, n);
1075
1082
  e && s.push(e);
1076
1083
  }
1077
- if (JSON.stringify(L(n.references)) !== JSON.stringify(L(r.references)) && (r.references && s.push(R({
1084
+ if (JSON.stringify(bt(n.references)) !== JSON.stringify(bt(r.references)) && (r.references && s.push(R({
1078
1085
  kind: "drop-foreign-key",
1079
1086
  table: t,
1080
1087
  column: n.name
@@ -1094,7 +1101,7 @@ BEGIN
1094
1101
  }, "lossy", r === "delete" ? `add FK ${t}.${n.name} → ${e}: orphanPolicy 'delete' first DELETES rows whose ${n.name} points at a missing ${e}` : `add FK ${t}.${n.name} → ${e}: orphanPolicy 'null' first NULLs ${n.name} where it points at a missing ${e}`)) : s.push(R(i, "needs-backfill", `add FK ${t}.${n.name} → ${e} — existing rows must already reference a valid ${e} (else set orphanPolicy:'null'/'delete')`));
1095
1102
  }
1096
1103
  return s;
1097
- }, Ft = (e, t, n) => {
1104
+ }, Rt = (e, t, n) => {
1098
1105
  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));
1099
1106
  for (let [n, c] of Object.entries(t)) {
1100
1107
  let t = c.renamedFrom;
@@ -1110,22 +1117,22 @@ BEGIN
1110
1117
  consumedAddedNames: i,
1111
1118
  consumedRemovedNames: a
1112
1119
  };
1113
- }, It = /* @__PURE__ */ new Set([
1120
+ }, zt = /* @__PURE__ */ new Set([
1114
1121
  "postgres",
1115
1122
  "mysql",
1116
1123
  "mariadb",
1117
1124
  "mssql"
1118
- ]), Lt = {
1125
+ ]), Bt = {
1119
1126
  ops: [],
1120
1127
  consumedAddedNames: /* @__PURE__ */ new Set(),
1121
1128
  consumedRemovedNames: /* @__PURE__ */ new Set()
1122
- }, Rt = (e) => !e.unique && !e.expression, zt = (e, t, n, r, i) => {
1123
- if (i === void 0 || !It.has(i)) return Lt;
1124
- let a = t.added.filter((e) => Rt(e) && !r.has(e.name));
1125
- if (a.length === 0) return Lt;
1129
+ }, Vt = (e) => !e.unique && !e.expression, Ht = (e, t, n, r, i) => {
1130
+ if (i === void 0 || !zt.has(i)) return Bt;
1131
+ let a = t.added.filter((e) => Vt(e) && !r.has(e.name));
1132
+ if (a.length === 0) return Bt;
1126
1133
  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();
1127
1134
  for (let n of t.removed) {
1128
- if (!Rt(n)) continue;
1135
+ if (!Vt(n)) continue;
1129
1136
  let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
1130
1137
  if (r.length !== 1) continue;
1131
1138
  let i = r[0];
@@ -1141,7 +1148,7 @@ BEGIN
1141
1148
  consumedAddedNames: l,
1142
1149
  consumedRemovedNames: u
1143
1150
  };
1144
- }, Bt = (e, t, n) => {
1151
+ }, Ut = (e, t, n) => {
1145
1152
  let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
1146
1153
  for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
1147
1154
  for (let c of e.tables) {
@@ -1181,12 +1188,12 @@ BEGIN
1181
1188
  claimedOldNames: c,
1182
1189
  refusals: o
1183
1190
  };
1184
- }, Vt = (e, t, n, r) => {
1191
+ }, Wt = (e, t, n, r) => {
1185
1192
  if (t === void 0) return {
1186
1193
  live: e,
1187
1194
  ops: []
1188
1195
  };
1189
- let i = r !== void 0 && It.has(r), a = [], o = e.indexes.map((e) => {
1196
+ let i = r !== void 0 && zt.has(r), a = [], o = e.indexes.map((e) => {
1190
1197
  if (!e.name.startsWith(t)) return e;
1191
1198
  let r = `${n}${e.name.slice(t.length)}`;
1192
1199
  return r === e.name ? e : e.name === `${t}_pkey` ? {
@@ -1212,7 +1219,7 @@ BEGIN
1212
1219
  },
1213
1220
  ops: a
1214
1221
  };
1215
- }, Ht = (e) => {
1222
+ }, Gt = (e) => {
1216
1223
  let t = {
1217
1224
  safe: 0,
1218
1225
  needsDefault: 0,
@@ -1247,42 +1254,42 @@ BEGIN
1247
1254
  break;
1248
1255
  }
1249
1256
  return t;
1250
- }, Ut = (e) => {
1251
- let t = F(e.declared, e.dialect), n = ht(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? At, a = [], o = Bt(t, r, n);
1257
+ }, Kt = (e) => {
1258
+ let t = I(e.declared, e.dialect), n = _t(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Nt, a = [], o = Ut(t, r, n);
1252
1259
  a.push(...o.ops);
1253
1260
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1254
- a.push(Ot(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1261
+ a.push(jt(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1255
1262
  for (let t of e.columns) {
1256
- let n = St(e.name, t);
1263
+ let n = Tt(e.name, t);
1257
1264
  n && a.push(n);
1258
1265
  }
1259
1266
  }
1260
1267
  let c = new Set(e.ignoreTables ?? []);
1261
- for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || s(t.name) || d(t.name) || c.has(t.name) || a.push(kt(t.name));
1268
+ for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || s(t.name) || d(t.name) || c.has(t.name) || a.push(Mt(t.name));
1262
1269
  for (let s of t.tables) {
1263
1270
  let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
1264
1271
  if (!c) continue;
1265
- let l = Vt(c, t, s.name, e.dialect);
1272
+ let l = Wt(c, t, s.name, e.dialect);
1266
1273
  a.push(...l.ops);
1267
- let u = l.live, f = n.get(s.name), p = wt(s, u, e.dialect), m = Tt(s, u), h = Ft(f.table, f.columnDefs, p);
1274
+ let u = l.live, f = n.get(s.name), p = Dt(s, u, e.dialect), m = Ot(s, u), h = Rt(f.table, f.columnDefs, p);
1268
1275
  a.push(...h.ops);
1269
1276
  for (let e of p.removed) {
1270
1277
  if (h.consumedRemovedNames.has(e.name) || d(e.name)) continue;
1271
1278
  let t = f.columnDefs[e.name];
1272
- a.push(Dt(s.name, e, t));
1279
+ a.push(At(s.name, e, t));
1273
1280
  }
1274
1281
  for (let e of p.added) {
1275
1282
  if (h.consumedAddedNames.has(e.name)) continue;
1276
1283
  let t = f.columnDefs[e.name];
1277
- a.push(Et(s.name, e, t));
1278
- let n = St(s.name, e);
1284
+ a.push(kt(s.name, e, t));
1285
+ let n = Tt(s.name, e);
1279
1286
  n && a.push(n);
1280
1287
  }
1281
- let g = new Map(h.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), _ = zt(s.name, m, g, new Set(u.indexes.map((e) => e.name)), e.dialect);
1288
+ let g = new Map(h.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), _ = Ht(s.name, m, g, new Set(u.indexes.map((e) => e.name)), e.dialect);
1282
1289
  a.push(..._.ops);
1283
- for (let e of m.added) _.consumedAddedNames.has(e.name) || a.push(jt(s.name, e, u.rowCount, i));
1284
- for (let e of m.removed) _.consumedRemovedNames.has(e.name) || a.push(Mt(s.name, e));
1285
- for (let { declared: t, live: n } of p.changed) a.push(...Pt(s.name, t, n, e.dialect, u.rowCount, i));
1290
+ for (let e of m.added) _.consumedAddedNames.has(e.name) || a.push(Pt(s.name, e, u.rowCount, i));
1291
+ for (let e of m.removed) _.consumedRemovedNames.has(e.name) || a.push(Ft(s.name, e));
1292
+ for (let { declared: t, live: n } of p.changed) a.push(...Lt(s.name, t, n, e.dialect, u.rowCount, i));
1286
1293
  }
1287
1294
  let l = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), u = new Map(t.tables.map((e) => [e.name, e])), f = (e) => {
1288
1295
  let t = u.get(e);
@@ -1290,8 +1297,8 @@ BEGIN
1290
1297
  column: e.name,
1291
1298
  target: e.references.table
1292
1299
  }] : []) : [];
1293
- }, p = re([...l], f), m = [];
1294
- for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) !t.references || !p.has(C(e.name, t.name)) || m.push(R({
1300
+ }, p = ne([...l], f), m = [];
1301
+ for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) !t.references || !p.has(w(e.name, t.name)) || m.push(R({
1295
1302
  kind: "add-foreign-key",
1296
1303
  table: e.name,
1297
1304
  column: t.name,
@@ -1306,8 +1313,8 @@ BEGIN
1306
1313
  let n = a[t];
1307
1314
  if (n.op.kind !== "create-table") continue;
1308
1315
  let r = n.op;
1309
- if (!r.columns.some((e) => p.has(C(r.table, e.name)))) continue;
1310
- let i = r.columns.map((t) => p.has(C(r.table, t.name)) ? e(t) : t);
1316
+ if (!r.columns.some((e) => p.has(w(r.table, e.name)))) continue;
1317
+ let i = r.columns.map((t) => p.has(w(r.table, t.name)) ? e(t) : t);
1311
1318
  a[t] = {
1312
1319
  ...n,
1313
1320
  op: {
@@ -1327,7 +1334,7 @@ BEGIN
1327
1334
  let i = new Set(t).add(e), a = 0;
1328
1335
  for (let t of r.columns) {
1329
1336
  let n = t.references?.table;
1330
- n && n !== e && !p.has(C(e, t.name)) && (a = Math.max(a, _(n, i) + 1));
1337
+ n && n !== e && !p.has(w(e, t.name)) && (a = Math.max(a, _(n, i) + 1));
1331
1338
  }
1332
1339
  return g.set(e, a), a;
1333
1340
  }, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
@@ -1363,11 +1370,11 @@ BEGIN
1363
1370
  });
1364
1371
  return {
1365
1372
  operations: S,
1366
- fromFingerprint: N(e.live),
1367
- toFingerprint: N(t),
1368
- summary: Ht(S)
1373
+ fromFingerprint: P(e.live),
1374
+ toFingerprint: P(t),
1375
+ summary: Gt(S)
1369
1376
  };
1370
- }, Wt = (e) => {
1377
+ }, qt = (e) => {
1371
1378
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1372
1379
  if (!t) return null;
1373
1380
  let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
@@ -1375,7 +1382,7 @@ BEGIN
1375
1382
  column: t[1],
1376
1383
  values: n
1377
1384
  };
1378
- }, Gt = (e, t) => {
1385
+ }, Jt = (e, t) => {
1379
1386
  if (t === "vector") return "vector";
1380
1387
  switch (e) {
1381
1388
  case "text":
@@ -1410,25 +1417,25 @@ BEGIN
1410
1417
  case "SET DEFAULT": return "noAction";
1411
1418
  default: return "noAction";
1412
1419
  }
1413
- }, Kt = (e, t) => {
1420
+ }, Yt = (e, t) => {
1414
1421
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1415
1422
  return Number.isInteger(n) && n > 0 ? n : t;
1416
- }, qt = () => Kt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Jt = 300, Yt = () => {
1423
+ }, Xt = () => Yt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Zt = 300, Qt = () => {
1417
1424
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1418
- return e !== void 0 && e.trim() === "0" ? 0 : Kt(e, 3e4);
1419
- }, Xt = (e, t) => {
1425
+ return e !== void 0 && e.trim() === "0" ? 0 : Yt(e, 3e4);
1426
+ }, $t = (e, t) => {
1420
1427
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1421
1428
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1422
1429
  return r;
1423
- }, Zt = (e) => {
1424
- let t = Yt(), n = p.gen(function* () {
1430
+ }, en = (e) => {
1431
+ let t = Qt(), n = p.gen(function* () {
1425
1432
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1426
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = qt(), a = (e, t) => p.gen(function* () {
1433
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Xt(), a = (e, t) => p.gen(function* () {
1427
1434
  let r = [];
1428
- for (let a of Xt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1435
+ for (let a of $t(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1429
1436
  return r;
1430
1437
  }), o = [];
1431
- for (let t = 0;; t += Jt) {
1438
+ for (let t = 0;; t += Zt) {
1432
1439
  let n = yield* e`
1433
1440
  SELECT c.relname AS table_name,
1434
1441
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1436,9 +1443,9 @@ BEGIN
1436
1443
  JOIN pg_namespace n ON n.oid = c.relnamespace
1437
1444
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1438
1445
  ORDER BY c.relname
1439
- LIMIT ${r(Jt)} OFFSET ${r(t)}
1446
+ LIMIT ${r(Zt)} OFFSET ${r(t)}
1440
1447
  `;
1441
- if (o.push(...n), n.length < Jt) break;
1448
+ if (o.push(...n), n.length < Zt) break;
1442
1449
  }
1443
1450
  let s = /* @__PURE__ */ new Set(), c = [];
1444
1451
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
@@ -1533,18 +1540,18 @@ BEGIN
1533
1540
  let t = y.get(e.table_name);
1534
1541
  t || (t = /* @__PURE__ */ new Set(), y.set(e.table_name, t)), t.add(e.column_name);
1535
1542
  }
1536
- let te = /* @__PURE__ */ new Map();
1543
+ let C = /* @__PURE__ */ new Map();
1537
1544
  for (let e of f) {
1538
- let t = `${e.table_name}\u0000${e.constraint_name}`, n = te.get(t);
1545
+ let t = `${e.table_name}\u0000${e.constraint_name}`, n = C.get(t);
1539
1546
  n || (n = {
1540
1547
  table: e.table_name,
1541
1548
  columns: []
1542
- }, te.set(t, n)), n.columns.push({
1549
+ }, C.set(t, n)), n.columns.push({
1543
1550
  name: e.column_name,
1544
1551
  position: e.position
1545
1552
  });
1546
1553
  }
1547
- for (let [e, t] of te) {
1554
+ for (let [e, t] of C) {
1548
1555
  let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
1549
1556
  if (n.length === 1) {
1550
1557
  let e = b.get(t.table);
@@ -1569,10 +1576,10 @@ BEGIN
1569
1576
  let n = t.get(e.index_name);
1570
1577
  n || (n = [], t.set(e.index_name, n)), n.push(e);
1571
1578
  }
1572
- let ne = [];
1579
+ let te = [];
1573
1580
  for (let e of c) {
1574
1581
  let t = /* @__PURE__ */ new Set(), n = (v.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = b.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) => {
1575
- 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" : Gt(t.data_type, t.udt_name), c = a ? {
1582
+ 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" : Jt(t.data_type, t.udt_name), c = a ? {
1576
1583
  table: a.target_table,
1577
1584
  column: a.target_column,
1578
1585
  onDelete: z(a.delete_rule),
@@ -1613,20 +1620,20 @@ BEGIN
1613
1620
  unique: !0
1614
1621
  });
1615
1622
  let d = Number(e.row_count ?? 0);
1616
- ne.push({
1623
+ te.push({
1617
1624
  name: e.table_name,
1618
1625
  columns: c,
1619
1626
  indexes: l,
1620
1627
  ...d > 0 ? { rowCount: d } : {}
1621
1628
  });
1622
1629
  }
1623
- return { tables: ne };
1630
+ return { tables: te };
1624
1631
  });
1625
1632
  return (t > 0 ? e.withTransaction(n) : n).pipe(p.catchAll((e) => {
1626
1633
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1627
1634
  return n.includes("statement timeout") || n.includes("57014") ? p.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.`)) : p.fail(e);
1628
1635
  }));
1629
- }, Qt = (e, t) => {
1636
+ }, tn = (e, t) => {
1630
1637
  switch (e.toLowerCase()) {
1631
1638
  case "varchar":
1632
1639
  case "char":
@@ -1662,7 +1669,7 @@ BEGIN
1662
1669
  let t = e, n = {};
1663
1670
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1664
1671
  return n;
1665
- }), $t = (e) => p.gen(function* () {
1672
+ }), nn = (e) => p.gen(function* () {
1666
1673
  let t = B(yield* e`
1667
1674
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1668
1675
  FROM information_schema.tables
@@ -1696,7 +1703,7 @@ BEGIN
1696
1703
  o.add(`${e.table_name}.${t[1]}`);
1697
1704
  continue;
1698
1705
  }
1699
- let n = Wt(e.check_clause);
1706
+ let n = qt(e.check_clause);
1700
1707
  n && s.set(`${e.table_name}.${n.column}`, n.values);
1701
1708
  }
1702
1709
  let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
@@ -1719,7 +1726,7 @@ BEGIN
1719
1726
  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);
1720
1727
  if (f) for (let e of f.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1721
1728
  let p = t.map((t) => {
1722
- 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" : Qt(t.data_type, t.column_type), u = c ? {
1729
+ 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" : tn(t.data_type, t.column_type), u = c ? {
1723
1730
  table: c.target_table,
1724
1731
  column: c.target_column,
1725
1732
  onDelete: z(c.delete_rule),
@@ -1761,10 +1768,10 @@ BEGIN
1761
1768
  });
1762
1769
  }
1763
1770
  return { tables: d };
1764
- }), en = (e) => {
1771
+ }), rn = (e) => {
1765
1772
  let t = e.toUpperCase();
1766
1773
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1767
- }, tn = (e) => p.gen(function* () {
1774
+ }, an = (e) => p.gen(function* () {
1768
1775
  let t = yield* e`
1769
1776
  SELECT name, sql FROM sqlite_master
1770
1777
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1781,7 +1788,7 @@ BEGIN
1781
1788
  d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1782
1789
  }
1783
1790
  let p = o.map((e) => {
1784
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : en(e.type), a = r ? {
1791
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : rn(e.type), a = r ? {
1785
1792
  table: r.table,
1786
1793
  column: r.to,
1787
1794
  onDelete: z(r.on_delete),
@@ -1820,7 +1827,7 @@ BEGIN
1820
1827
  });
1821
1828
  }
1822
1829
  return { tables: r };
1823
- }), nn = (e) => {
1830
+ }), on = (e) => {
1824
1831
  switch (e.toLowerCase()) {
1825
1832
  case "int":
1826
1833
  case "smallint":
@@ -1842,7 +1849,7 @@ BEGIN
1842
1849
  case "image": return "bytes";
1843
1850
  default: return "text";
1844
1851
  }
1845
- }, V = (e) => e === !0 || e === 1, rn = (e) => p.gen(function* () {
1852
+ }, V = (e) => e === !0 || e === 1, sn = (e) => p.gen(function* () {
1846
1853
  let t = yield* e`
1847
1854
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
1848
1855
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
@@ -1903,12 +1910,12 @@ BEGIN
1903
1910
  else V(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
1904
1911
  }
1905
1912
  let p = t.map((t) => {
1906
- 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" : nn(t.data_type), s = i ? {
1913
+ 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" : on(t.data_type), s = i ? {
1907
1914
  table: i.target_table,
1908
1915
  column: i.target_column,
1909
- onDelete: an(i.delete_rule),
1910
- onUpdate: an(i.update_rule)
1911
- } : void 0, c = t.column_default === null ? null : on(t.column_default), l = o.get(`${e}.${t.column_name}`);
1916
+ onDelete: cn(i.delete_rule),
1917
+ onUpdate: cn(i.update_rule)
1918
+ } : void 0, c = t.column_default === null ? null : ln(t.column_default), l = o.get(`${e}.${t.column_name}`);
1912
1919
  return {
1913
1920
  name: t.column_name,
1914
1921
  type: a,
@@ -1942,18 +1949,18 @@ BEGIN
1942
1949
  });
1943
1950
  }
1944
1951
  return { tables: u };
1945
- }), an = (e) => {
1952
+ }), cn = (e) => {
1946
1953
  switch (e.toUpperCase().replace(/_/g, " ")) {
1947
1954
  case "CASCADE": return "cascade";
1948
1955
  case "SET NULL": return "setNull";
1949
1956
  case "SET DEFAULT": return "noAction";
1950
1957
  default: return "noAction";
1951
1958
  }
1952
- }, on = (e) => {
1959
+ }, ln = (e) => {
1953
1960
  let t = e.trim();
1954
1961
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
1955
1962
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
1956
- }, sn = /* @__PURE__ */ new Set([
1963
+ }, un = /* @__PURE__ */ new Set([
1957
1964
  "character varying",
1958
1965
  "varchar",
1959
1966
  "nvarchar",
@@ -1961,29 +1968,32 @@ BEGIN
1961
1968
  "character",
1962
1969
  "nchar"
1963
1970
  ]), H = (e, t) => {
1964
- if (!sn.has(e.toLowerCase())) return;
1971
+ if (!un.has(e.toLowerCase())) return;
1965
1972
  let n = Number(t);
1966
1973
  if (!(!Number.isFinite(n) || n <= 0)) return n;
1967
1974
  }, U = (e) => e.onDialectOrElse({
1968
- mysql: () => $t(e),
1969
- mssql: () => rn(e),
1970
- sqlite: () => tn(e),
1971
- orElse: () => Zt(e)
1972
- }), cn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, ln = (e, t) => {
1975
+ mysql: () => nn(e),
1976
+ mssql: () => sn(e),
1977
+ sqlite: () => an(e),
1978
+ orElse: () => en(e)
1979
+ }), dn = (e, t) => e.onDialectOrElse({
1980
+ mysql: () => p.succeed(t.replace("T", " ").replace("Z", "")),
1981
+ orElse: () => p.succeed(t)
1982
+ }), fn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, W = (e, t) => {
1973
1983
  if (!(e.type === "text" && e.maxLength !== void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
1974
1984
  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;
1975
1985
  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.`);
1976
- return D(e, t);
1977
- }, un = (e) => {
1978
- let t = ln(e, "postgres");
1979
- return t === void 0 ? dn(e) : t;
1980
- }, dn = (e) => {
1986
+ return j(e, t);
1987
+ }, pn = (e) => {
1988
+ let t = W(e, "postgres");
1989
+ return t === void 0 ? mn(e) : t;
1990
+ }, mn = (e) => {
1981
1991
  switch (e.type) {
1982
1992
  case "id": return "text";
1983
1993
  case "text": return "text";
1984
1994
  case "integer": return "integer";
1985
1995
  case "real": return "double precision";
1986
- case "decimal": return cn(e, "NUMERIC");
1996
+ case "decimal": return fn(e, "NUMERIC");
1987
1997
  case "bigint": return "bigint";
1988
1998
  case "boolean": return "boolean";
1989
1999
  case "timestamp": return "timestamptz";
@@ -1997,15 +2007,15 @@ BEGIN
1997
2007
  case "interval": return "interval";
1998
2008
  case "raw": return e.rawDdl ?? "text";
1999
2009
  }
2000
- }, fn = (e) => {
2001
- let t = ln(e, "mariadb");
2010
+ }, hn = (e) => {
2011
+ let t = W(e, "mariadb");
2002
2012
  if (t !== void 0) return t;
2003
2013
  switch (e.type) {
2004
2014
  case "id": return "VARCHAR(64)";
2005
2015
  case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
2006
2016
  case "integer": return "INT";
2007
2017
  case "real": return "DOUBLE";
2008
- case "decimal": return cn(e, "DECIMAL");
2018
+ case "decimal": return fn(e, "DECIMAL");
2009
2019
  case "bigint": return "BIGINT";
2010
2020
  case "boolean": return "TINYINT(1)";
2011
2021
  case "timestamp": return "DATETIME(6)";
@@ -2019,82 +2029,82 @@ BEGIN
2019
2029
  case "interval": return "BIGINT";
2020
2030
  case "raw": return e.rawDdl ?? "LONGTEXT";
2021
2031
  }
2022
- }, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, pn = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, mn = (e) => `ALTER TABLE ${G(e.table)} DROP COLUMN IF EXISTS ${G(e.column)}, ALGORITHM=COPY;`, hn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, gn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Bn(t)}`)};`, _n = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${vn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, vn = (e, t) => {
2032
+ }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, gn = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, _n = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, vn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, yn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Wn(t)}`)};`, bn = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${xn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, xn = (e, t) => {
2023
2033
  let n = t(e.defaultValue);
2024
2034
  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.`);
2025
2035
  return n;
2026
- }, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], yn = (e, t, n) => {
2027
- let r = K(e, t, n);
2028
- return r ? at(n, r) : void 0;
2029
- }, bn = (e, t, n) => {
2036
+ }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Sn = (e, t, n) => {
2037
+ let r = q(e, t, n);
2038
+ return r ? ct(n, r) : void 0;
2039
+ }, Cn = (e, t, n) => {
2030
2040
  let r = n ?? e.nullable, i = be(e, "mariadb");
2031
2041
  return [
2032
- G(t),
2033
- D(e, "mariadb"),
2042
+ K(t),
2043
+ j(e, "mariadb"),
2034
2044
  r ? null : "NOT NULL",
2035
2045
  i
2036
2046
  ].filter(Boolean).join(" ");
2037
- }, xn = (e, t) => e == null ? null : Array.isArray(e) ? Sn(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" ? O(e, "mysql") : null, Sn = (e, t, n) => xe(e, t ?? { type: "json" }, n), Cn = (e, t) => e == null ? null : Array.isArray(e) ? Sn(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" ? O(e, "postgres") : null, q = (e, t) => {
2047
+ }, wn = (e, t) => e == null ? null : Array.isArray(e) ? Tn(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, "mysql") : null, Tn = (e, t, n) => xe(e, t ?? { type: "json" }, n), En = (e, t) => e == null ? null : Array.isArray(e) ? Tn(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, J = (e, t) => {
2038
2048
  if (!e.generatedAs) return null;
2039
2049
  let { expr: n, stored: r } = e.generatedAs;
2040
2050
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2041
- }, wn = (e) => {
2042
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "postgres");
2043
- let t = q(e, "postgres");
2044
- if (t) return `${W(e.name)} ${un(e)} ${t}`;
2045
- let n = [W(e.name), un(e)];
2051
+ }, Dn = (e) => {
2052
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "postgres");
2053
+ let t = J(e, "postgres");
2054
+ if (t) return `${G(e.name)} ${pn(e)} ${t}`;
2055
+ let n = [G(e.name), pn(e)];
2046
2056
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2047
- let t = Cn(e.defaultValue, e);
2057
+ let t = En(e.defaultValue, e);
2048
2058
  t && n.push(t);
2049
2059
  }
2050
- return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2060
+ return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2051
2061
  cascade: "CASCADE",
2052
2062
  restrict: "RESTRICT",
2053
2063
  setNull: "SET NULL",
2054
2064
  noAction: "NO ACTION"
2055
2065
  }[e.references.onDelete]}`)), n.join(" ");
2056
- }, Tn = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", En = (e) => {
2057
- let t = e.columns.map((e) => ` ${wn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Tn(e, W)}\n)`];
2058
- 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(Gn).join(", ")})`);
2066
+ }, On = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", kn = (e) => {
2067
+ let t = e.columns.map((e) => ` ${Dn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${On(e, G)}\n)`];
2068
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(Yn).join(", ")})`);
2059
2069
  return n;
2060
- }, Dn = 191, J = (e) => {
2061
- let t = fn(e).toUpperCase();
2070
+ }, An = 191, jn = (e) => {
2071
+ let t = hn(e).toUpperCase();
2062
2072
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2063
- }, On = (e) => {
2064
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mariadb");
2065
- let t = q(e, "mariadb");
2066
- if (t) return `${G(e.name)} ${fn(e)} ${t}`;
2067
- let n = [G(e.name), fn(e)];
2068
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !J(e) && n.push("UNIQUE"), e.hasDefault) {
2069
- let t = xn(e.defaultValue, e);
2073
+ }, Mn = (e) => {
2074
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mariadb");
2075
+ let t = J(e, "mariadb");
2076
+ if (t) return `${K(e.name)} ${hn(e)} ${t}`;
2077
+ let n = [K(e.name), hn(e)];
2078
+ if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !jn(e) && n.push("UNIQUE"), e.hasDefault) {
2079
+ let t = wn(e.defaultValue, e);
2070
2080
  t && n.push(t);
2071
2081
  }
2072
- return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2082
+ return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2073
2083
  cascade: "CASCADE",
2074
2084
  restrict: "RESTRICT",
2075
2085
  setNull: "SET NULL",
2076
2086
  noAction: "NO ACTION"
2077
2087
  }[e.references.onDelete]}`)), n.join(" ");
2078
- }, kn = (e) => {
2088
+ }, Nn = (e) => {
2079
2089
  let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
2080
2090
  let n = t.get(e);
2081
- return n && J(n) ? `${G(e)}(${Dn})` : G(e);
2082
- }, r = e.columns.map((e) => ` ${On(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${r}${Tn(e, n)}\n)`];
2083
- for (let t of e.columns) t.unique && t.type !== "id" && J(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${G(`${e.table}_${t.name}_key`)} ON ${G(e.table)} (${n(t.name)})`);
2084
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(n).join(", ")})`);
2091
+ return n && jn(n) ? `${K(e)}(${An})` : K(e);
2092
+ }, r = e.columns.map((e) => ` ${Mn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${On(e, n)}\n)`];
2093
+ for (let t of e.columns) t.unique && t.type !== "id" && jn(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
2094
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(n).join(", ")})`);
2085
2095
  return i;
2086
- }, An = {
2096
+ }, Pn = {
2087
2097
  cascade: "CASCADE",
2088
2098
  restrict: "RESTRICT",
2089
2099
  setNull: "SET NULL",
2090
2100
  noAction: "NO ACTION"
2091
- }, jn = {
2101
+ }, Fn = {
2092
2102
  cascade: "CASCADE",
2093
2103
  restrict: "NO ACTION",
2094
2104
  setNull: "SET NULL",
2095
2105
  noAction: "NO ACTION"
2096
- }, Mn = (e) => {
2097
- let t = ln(e, "sqlite");
2106
+ }, In = (e) => {
2107
+ let t = W(e, "sqlite");
2098
2108
  if (t !== void 0) return t;
2099
2109
  switch (e.type) {
2100
2110
  case "integer":
@@ -2105,60 +2115,60 @@ BEGIN
2105
2115
  case "bytes": return "BLOB";
2106
2116
  default: return "TEXT";
2107
2117
  }
2108
- }, Y = (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" ? O(e, "sqlite") : null, Nn = (e) => {
2109
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "sqlite");
2110
- let t = q(e, "sqlite");
2111
- if (t) return `${W(e.name)} ${Mn(e)} ${t}`;
2112
- let n = [W(e.name), Mn(e)];
2118
+ }, Y = (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, Ln = (e) => {
2119
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "sqlite");
2120
+ let t = J(e, "sqlite");
2121
+ if (t) return `${G(e.name)} ${In(e)} ${t}`;
2122
+ let n = [G(e.name), In(e)];
2113
2123
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2114
2124
  let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
2115
2125
  t && n.push(t);
2116
2126
  }
2117
- if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${An[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2127
+ if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Pn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2118
2128
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2119
- n.push(`CHECK (${W(e.name)} IN (${t}))`);
2129
+ n.push(`CHECK (${G(e.name)} IN (${t}))`);
2120
2130
  }
2121
2131
  return n.join(" ");
2122
- }, Pn = (e) => {
2123
- let t = e.columns.map((e) => ` ${Nn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Tn(e, W)}\n)`];
2124
- 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(", ")})`);
2132
+ }, Rn = (e) => {
2133
+ let t = e.columns.map((e) => ` ${Ln(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${On(e, G)}\n)`];
2134
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(G).join(", ")})`);
2125
2135
  return n;
2126
2136
  }, X = (e, t) => {
2127
2137
  let n = t.find((t) => t.tableName === e);
2128
2138
  if (!n) return [];
2129
- let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
2130
- ...Pn({
2139
+ let r = I([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
2140
+ ...Rn({
2131
2141
  kind: "create-table",
2132
2142
  table: i,
2133
2143
  columns: r.columns,
2134
2144
  indexes: [],
2135
2145
  ...r.primaryKey ? { primaryKey: r.primaryKey } : {}
2136
2146
  }),
2137
- `INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
2138
- `DROP TABLE ${W(e)}`,
2139
- `ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
2147
+ `INSERT INTO ${G(i)} (${a}) SELECT ${a} FROM ${G(e)}`,
2148
+ `DROP TABLE ${G(e)}`,
2149
+ `ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
2140
2150
  ];
2141
- 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(", ")})`);
2151
+ for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e)} (${t.columns.map(G).join(", ")})`);
2142
2152
  return o;
2143
- }, Fn = (e, t, n, r) => {
2153
+ }, zn = (e, t, n, r) => {
2144
2154
  let i = r ?? e.nullable;
2145
- return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${D(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2146
- }, In = (e) => {
2155
+ return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${j(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2156
+ }, Bn = (e) => {
2147
2157
  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 ${Z(e.table)} DROP CONSTRAINT [' + @dc + ']');`;
2148
2158
  if (!e.hasDefault) return t;
2149
2159
  let n = Y(e.defaultValue, "SYSUTCDATETIME()");
2150
2160
  if (!n) return t;
2151
2161
  let r = n.replace(/^DEFAULT\s+/i, "");
2152
2162
  return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
2153
- }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Ln = (e) => {
2154
- let t = ln(e, "mssql");
2163
+ }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Vn = (e) => {
2164
+ let t = W(e, "mssql");
2155
2165
  if (t !== void 0) return t;
2156
2166
  switch (e.type) {
2157
2167
  case "id":
2158
2168
  case "reference": return "NVARCHAR(64)";
2159
2169
  case "integer": return "INT";
2160
2170
  case "real": return "FLOAT";
2161
- case "decimal": return cn(e, "DECIMAL");
2171
+ case "decimal": return fn(e, "DECIMAL");
2162
2172
  case "bigint": return "BIGINT";
2163
2173
  case "boolean": return "BIT";
2164
2174
  case "timestamp": return "DATETIME2(6)";
@@ -2166,40 +2176,40 @@ BEGIN
2166
2176
  case "bytes": return "VARBINARY(MAX)";
2167
2177
  default: return "NVARCHAR(MAX)";
2168
2178
  }
2169
- }, Rn = (e, t) => {
2170
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mssql");
2171
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Ln(e), r = q(e, "mssql");
2179
+ }, Hn = (e, t) => {
2180
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mssql");
2181
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Vn(e), r = J(e, "mssql");
2172
2182
  if (r) return `${Z(e.name)} ${r}`;
2173
2183
  let i = [Z(e.name), n];
2174
2184
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2175
2185
  let t = Y(e.defaultValue, "SYSUTCDATETIME()");
2176
2186
  t && i.push(t);
2177
2187
  }
2178
- return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${jn[e.references.onDelete]}`)), i.join(" ");
2179
- }, zn = (e) => {
2180
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Rn(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${Tn(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2188
+ return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${Fn[e.references.onDelete]}`)), i.join(" ");
2189
+ }, Un = (e) => {
2190
+ let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Hn(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${On(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2181
2191
  for (let n of e.indexes) {
2182
2192
  if (n.name === `${e.table}_pkey`) continue;
2183
2193
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
2184
2194
  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)}')`);
2185
2195
  }
2186
2196
  return a;
2187
- }, Bn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Vn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Hn = (e, t, n) => {
2188
- let r = `${e.table}${Bn(t)}`;
2197
+ }, Wn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Gn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Kn = (e, t, n) => {
2198
+ let r = `${e.table}${Wn(t)}`;
2189
2199
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2190
- }, Un = (e, t, n) => {
2191
- let r = K(e, t, n);
2192
- return r ? J({ type: r.type }) : !1;
2193
- }, Wn = (e, t, n) => Un(e, t, n) ? `${G(n)}(${Dn})` : G(n), Gn = (e) => e.startsWith("(") ? e : W(e), Kn = (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(Gn).join(", ")});`, qn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => Wn(t, e.table, n)).join(", ")});`, Jn = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, Yn = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, Xn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, Zn = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Qn = (e) => {
2200
+ }, qn = (e, t, n) => {
2201
+ let r = q(e, t, n);
2202
+ return r ? jn({ type: r.type }) : !1;
2203
+ }, Jn = (e, t, n) => qn(e, t, n) ? `${K(n)}(${An})` : K(n), Yn = (e) => e.startsWith("(") ? e : G(e), Xn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map(Yn).join(", ")});`, Zn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Jn(t, e.table, n)).join(", ")});`, Qn = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, $n = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, er = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, tr = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, nr = (e) => {
2194
2204
  let t = (e) => e.replace(/'/g, "''");
2195
2205
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
2196
- }, $n = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, er = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, tr = (e) => {
2206
+ }, rr = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, ir = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, ar = (e) => {
2197
2207
  let t = (e) => e.replace(/'/g, "''");
2198
2208
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2199
- }, nr = (e) => {
2209
+ }, or = (e) => {
2200
2210
  let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Z(e.index.name)} ON ${Z(e.table)} (${e.index.columns.map(Z).join(", ")})`;
2201
2211
  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)}');`;
2202
- }, rr = (e, t, n) => {
2212
+ }, sr = (e, t, n) => {
2203
2213
  let r = n.find((t) => t.tableName === e);
2204
2214
  if (!r) return [];
2205
2215
  let i = [];
@@ -2208,13 +2218,13 @@ BEGIN
2208
2218
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2209
2219
  }
2210
2220
  return i;
2211
- }, ir = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, ar = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${Wn(t, e.table, e.column)});`, or = (e) => {
2212
- let t = e.fields.map((e) => W(e)).join(", ");
2213
- return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
2214
- }, sr = (e, t) => {
2215
- let n = e.fields.map((n) => Wn(t, e.table, n)).join(", ");
2216
- return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
2217
- }, cr = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, lr = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, ur = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, dr = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, fr = (e, t) => {
2221
+ }, cr = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, lr = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Jn(t, e.table, e.column)});`, ur = (e) => {
2222
+ let t = e.fields.map((e) => G(e)).join(", ");
2223
+ return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
2224
+ }, dr = (e, t) => {
2225
+ let n = e.fields.map((n) => Jn(t, e.table, n)).join(", ");
2226
+ return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
2227
+ }, fr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, pr = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, mr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, hr = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, gr = (e, t) => {
2218
2228
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2219
2229
  if (e.orphanPolicy) {
2220
2230
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2232,11 +2242,11 @@ BEGIN
2232
2242
  setNull: "SET NULL",
2233
2243
  noAction: "NO ACTION"
2234
2244
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2235
- }, pr = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, mr = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, hr = (e, t) => {
2245
+ }, _r = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, vr = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, yr = (e, t) => {
2236
2246
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2237
2247
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2238
- }, gr = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, _r = (e) => `ALTER TABLE ${G(e.table)} DROP CHECK ${G(`${e.table}_${e.column}_check`)};`, vr = (e, t, n, r) => {
2239
- let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? Z : W, s = a ? fn(i) : r === "mssql" ? Ln(i) : r === "sqlite" ? Mn(i) : un(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? xn(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : Cn(e, i), u = q(i, r);
2248
+ }, br = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, xr = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, Sr = (e, t, n, r) => {
2249
+ let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? hn(i) : r === "mssql" ? Vn(i) : r === "sqlite" ? In(i) : pn(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? wn(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : En(e, i), u = J(i, r);
2240
2250
  if (u) {
2241
2251
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2242
2252
  return {
@@ -2264,7 +2274,7 @@ BEGIN
2264
2274
  post: f ? [f] : []
2265
2275
  };
2266
2276
  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;
2267
- }, yr = (e) => {
2277
+ }, Cr = (e) => {
2268
2278
  let t = new Map(e.map((e) => [e.tableName, e]));
2269
2279
  return (e, n) => {
2270
2280
  let r = t.get(e);
@@ -2289,109 +2299,109 @@ BEGIN
2289
2299
  })), p.mapError((e) => {
2290
2300
  let r = b(`applier: statement failed (op=${n})`, t, e, 400).trim();
2291
2301
  return Object.assign(e, { message: r });
2292
- }), p.map(() => void 0)), $ = (e, t, n) => p.forEach(t, (t) => Q(e, t, n), { discard: !0 }), br = (e, t, n) => p.gen(function* () {
2293
- let r = process.hrtime.bigint(), i = yr(n.declared), a = t.op;
2302
+ }), p.map(() => void 0)), $ = (e, t, n) => p.forEach(t, (t) => Q(e, t, n), { discard: !0 }), wr = (e, t, n) => p.gen(function* () {
2303
+ let r = process.hrtime.bigint(), i = Cr(n.declared), a = t.op;
2294
2304
  switch (a.kind) {
2295
2305
  case "create-table": {
2296
2306
  let t = yield* e.onDialectOrElse({
2297
- mysql: () => p.succeed(kn(a)),
2298
- mssql: () => p.succeed(zn(a)),
2299
- sqlite: () => p.succeed(Pn(a)),
2300
- orElse: () => p.succeed(En(a))
2307
+ mysql: () => p.succeed(Nn(a)),
2308
+ mssql: () => p.succeed(Un(a)),
2309
+ sqlite: () => p.succeed(Rn(a)),
2310
+ orElse: () => p.succeed(kn(a))
2301
2311
  });
2302
2312
  for (let n of t) yield* Q(e, n, a.kind);
2303
2313
  break;
2304
2314
  }
2305
2315
  case "drop-table": {
2306
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Hn(a, n, e) : Vn(a, e);
2316
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Kn(a, n, e) : Gn(a, e);
2307
2317
  yield* e.onDialectOrElse({
2308
- mysql: () => Q(e, r(G), a.kind),
2309
- orElse: () => Q(e, r(W), a.kind)
2318
+ mysql: () => Q(e, r(K), a.kind),
2319
+ orElse: () => Q(e, r(G), a.kind)
2310
2320
  });
2311
2321
  break;
2312
2322
  }
2313
2323
  case "drop-column": {
2314
2324
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2315
2325
  yield* e.onDialectOrElse({
2316
- mysql: () => Q(e, t ? gn(a, n, G) : mn(a), a.kind),
2317
- orElse: () => Q(e, t ? gn(a, n, W) : pn(a, W), a.kind)
2326
+ mysql: () => Q(e, t ? yn(a, n, K) : _n(a), a.kind),
2327
+ orElse: () => Q(e, t ? yn(a, n, G) : gn(a, G), a.kind)
2318
2328
  });
2319
2329
  break;
2320
2330
  }
2321
2331
  case "rename-column":
2322
2332
  yield* e.onDialectOrElse({
2323
- mysql: () => Q(e, hn(a, G), a.kind),
2333
+ mysql: () => Q(e, vn(a, K), a.kind),
2324
2334
  mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
2325
- orElse: () => Q(e, hn(a, W), a.kind)
2335
+ orElse: () => Q(e, vn(a, G), a.kind)
2326
2336
  });
2327
2337
  break;
2328
2338
  case "add-index":
2329
2339
  yield* e.onDialectOrElse({
2330
- mysql: () => Q(e, qn(a, n.declared), a.kind),
2331
- mssql: () => $(e, [...rr(a.table, a.index.columns, n.declared), nr(a)], a.kind),
2332
- orElse: () => Q(e, Kn(a, t.classification === "online-required"), a.kind)
2340
+ mysql: () => Q(e, Zn(a, n.declared), a.kind),
2341
+ mssql: () => $(e, [...sr(a.table, a.index.columns, n.declared), or(a)], a.kind),
2342
+ orElse: () => Q(e, Xn(a, t.classification === "online-required"), a.kind)
2333
2343
  });
2334
2344
  break;
2335
2345
  case "drop-index":
2336
2346
  yield* e.onDialectOrElse({
2337
- mysql: () => Q(e, Yn(a), a.kind),
2338
- mssql: () => Q(e, Xn(a), a.kind),
2339
- orElse: () => Q(e, Jn(a), a.kind)
2347
+ mysql: () => Q(e, $n(a), a.kind),
2348
+ mssql: () => Q(e, er(a), a.kind),
2349
+ orElse: () => Q(e, Qn(a), a.kind)
2340
2350
  });
2341
2351
  break;
2342
2352
  case "rename-table":
2343
2353
  yield* e.onDialectOrElse({
2344
- mysql: () => Q(e, Zn(a, G), a.kind),
2345
- mssql: () => Q(e, Qn(a), a.kind),
2346
- orElse: () => Q(e, Zn(a, W), a.kind)
2354
+ mysql: () => Q(e, tr(a, K), a.kind),
2355
+ mssql: () => Q(e, nr(a), a.kind),
2356
+ orElse: () => Q(e, tr(a, G), a.kind)
2347
2357
  });
2348
2358
  break;
2349
2359
  case "rename-index":
2350
2360
  yield* e.onDialectOrElse({
2351
- mysql: () => Q(e, er(a), a.kind),
2352
- mssql: () => Q(e, tr(a), a.kind),
2353
- orElse: () => Q(e, $n(a), a.kind)
2361
+ mysql: () => Q(e, ir(a), a.kind),
2362
+ mssql: () => Q(e, ar(a), a.kind),
2363
+ orElse: () => Q(e, rr(a), a.kind)
2354
2364
  });
2355
2365
  break;
2356
2366
  case "add-unique":
2357
2367
  yield* e.onDialectOrElse({
2358
- mysql: () => Q(e, ar(a, n.declared), a.kind),
2368
+ mysql: () => Q(e, lr(a, n.declared), a.kind),
2359
2369
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2360
- mssql: () => $(e, [...rr(a.table, [a.column], n.declared), ir(a)], a.kind),
2361
- orElse: () => Q(e, ir(a), a.kind)
2370
+ mssql: () => $(e, [...sr(a.table, [a.column], n.declared), cr(a)], a.kind),
2371
+ orElse: () => Q(e, cr(a), a.kind)
2362
2372
  });
2363
2373
  break;
2364
2374
  case "drop-unique":
2365
2375
  yield* e.onDialectOrElse({
2366
- mysql: () => Q(e, dr(a), a.kind),
2376
+ mysql: () => Q(e, hr(a), a.kind),
2367
2377
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2368
- orElse: () => Q(e, ur(a), a.kind)
2378
+ orElse: () => Q(e, mr(a), a.kind)
2369
2379
  });
2370
2380
  break;
2371
2381
  case "add-unique-composite":
2372
2382
  yield* e.onDialectOrElse({
2373
- mysql: () => Q(e, sr(a, n.declared), a.kind),
2383
+ mysql: () => Q(e, dr(a, n.declared), a.kind),
2374
2384
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2375
- mssql: () => $(e, [...rr(a.table, a.fields, n.declared), or(a)], a.kind),
2376
- orElse: () => Q(e, or(a), a.kind)
2385
+ mssql: () => $(e, [...sr(a.table, a.fields, n.declared), ur(a)], a.kind),
2386
+ orElse: () => Q(e, ur(a), a.kind)
2377
2387
  });
2378
2388
  break;
2379
2389
  case "drop-unique-composite":
2380
2390
  yield* e.onDialectOrElse({
2381
- mysql: () => Q(e, lr(a), a.kind),
2391
+ mysql: () => Q(e, pr(a), a.kind),
2382
2392
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2383
- orElse: () => Q(e, cr(a), a.kind)
2393
+ orElse: () => Q(e, fr(a), a.kind)
2384
2394
  });
2385
2395
  break;
2386
2396
  case "add-foreign-key":
2387
2397
  yield* e.onDialectOrElse({
2388
- mysql: () => $(e, fr(a, G), a.kind),
2398
+ mysql: () => $(e, gr(a, K), a.kind),
2389
2399
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2390
- orElse: () => $(e, fr(a, W), a.kind)
2400
+ orElse: () => $(e, gr(a, G), a.kind)
2391
2401
  });
2392
2402
  break;
2393
2403
  case "add-column": {
2394
- let n = vr(a, t, i, yield* e.onDialectOrElse({
2404
+ let n = Sr(a, t, i, yield* e.onDialectOrElse({
2395
2405
  mysql: () => p.succeed("mariadb"),
2396
2406
  mssql: () => p.succeed("mssql"),
2397
2407
  sqlite: () => p.succeed("sqlite"),
@@ -2436,41 +2446,41 @@ BEGIN
2436
2446
  case "alter-column-nullability":
2437
2447
  yield* e.onDialectOrElse({
2438
2448
  mysql: () => {
2439
- let t = K(n.declared, a.table, a.column);
2440
- return t ? Q(e, `ALTER TABLE ${G(a.table)} MODIFY COLUMN ${bn(t, a.column, a.toNullable)};`, a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2449
+ let t = q(n.declared, a.table, a.column);
2450
+ return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${Cn(t, a.column, a.toNullable)};`, a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2441
2451
  },
2442
2452
  mssql: () => {
2443
- let t = K(n.declared, a.table, a.column);
2444
- return t ? Q(e, Fn(t, a.column, a.table, a.toNullable), a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
2453
+ let t = q(n.declared, a.table, a.column);
2454
+ return t ? Q(e, zn(t, a.column, a.table, a.toNullable), a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
2445
2455
  },
2446
2456
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2447
- orElse: () => Q(e, `ALTER TABLE ${W(a.table)} ALTER COLUMN ${W(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
2457
+ orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
2448
2458
  });
2449
2459
  break;
2450
2460
  case "alter-column-default": {
2451
- let t = yn(n.declared, a.table, a.column);
2461
+ let t = Sn(n.declared, a.table, a.column);
2452
2462
  yield* e.onDialectOrElse({
2453
- mysql: () => Q(e, _n(a, G, (e) => xn(e, t)), a.kind),
2454
- mssql: () => Q(e, In(a), a.kind),
2463
+ mysql: () => Q(e, bn(a, K, (e) => wn(e, t)), a.kind),
2464
+ mssql: () => Q(e, Bn(a), a.kind),
2455
2465
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2456
- orElse: () => Q(e, _n(a, W, (e) => Cn(e, t)), a.kind)
2466
+ orElse: () => Q(e, bn(a, G, (e) => En(e, t)), a.kind)
2457
2467
  });
2458
2468
  break;
2459
2469
  }
2460
2470
  case "alter-column-type": {
2461
- let r = un(yn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
2471
+ let r = pn(Sn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
2462
2472
  if (t.classification !== "online-required") {
2463
2473
  yield* e.onDialectOrElse({
2464
2474
  mysql: () => {
2465
- let t = K(n.declared, a.table, a.column);
2466
- return t ? Q(e, `ALTER TABLE ${G(a.table)} MODIFY COLUMN ${bn(t, a.column)};`, a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2475
+ let t = q(n.declared, a.table, a.column);
2476
+ return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${Cn(t, a.column)};`, a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2467
2477
  },
2468
2478
  mssql: () => {
2469
- let t = K(n.declared, a.table, a.column);
2470
- return t ? Q(e, Fn(t, a.column, a.table), a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2479
+ let t = q(n.declared, a.table, a.column);
2480
+ return t ? Q(e, zn(t, a.column, a.table), a.kind) : p.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2471
2481
  },
2472
2482
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2473
- orElse: () => Q(e, `ALTER TABLE ${W(a.table)} ALTER COLUMN ${W(a.column)} TYPE ${r}${i};`, a.kind)
2483
+ orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} TYPE ${r}${i};`, a.kind)
2474
2484
  });
2475
2485
  break;
2476
2486
  }
@@ -2479,35 +2489,35 @@ BEGIN
2479
2489
  orElse: () => p.void
2480
2490
  });
2481
2491
  let o = `${a.column}__shadow`, s = `${a.column}__old`;
2482
- yield* e.unsafe(`ALTER TABLE ${W(a.table)} ADD COLUMN ${W(o)} ${r}`);
2483
- let c = a.using ?? W(a.column), l;
2492
+ yield* e.unsafe(`ALTER TABLE ${G(a.table)} ADD COLUMN ${G(o)} ${r}`);
2493
+ let c = a.using ?? G(a.column), l;
2484
2494
  for (;;) {
2485
2495
  let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL ORDER BY ${e("id")} LIMIT 5000` : yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} LIMIT 5000`;
2486
2496
  if (t.length === 0) break;
2487
- yield* e.unsafe(`UPDATE ${W(a.table)} SET ${W(o)} = ${c} WHERE ${W(a.column)} IS NOT NULL AND ${W(o)} IS NULL AND ${W("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2497
+ yield* e.unsafe(`UPDATE ${G(a.table)} SET ${G(o)} = ${c} WHERE ${G(a.column)} IS NOT NULL AND ${G(o)} IS NULL AND ${G("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2488
2498
  }
2489
- yield* p.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(p.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${W(a.table)} RENAME COLUMN ${W(a.column)} TO ${W(s)}`), yield* e.unsafe(`ALTER TABLE ${W(a.table)} RENAME COLUMN ${W(o)} TO ${W(a.column)}`), yield* e.unsafe(`ALTER TABLE ${W(a.table)} DROP COLUMN ${W(s)}`);
2499
+ yield* p.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(p.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${G(a.table)} RENAME COLUMN ${G(a.column)} TO ${G(s)}`), yield* e.unsafe(`ALTER TABLE ${G(a.table)} RENAME COLUMN ${G(o)} TO ${G(a.column)}`), yield* e.unsafe(`ALTER TABLE ${G(a.table)} DROP COLUMN ${G(s)}`);
2490
2500
  break;
2491
2501
  }
2492
2502
  case "drop-foreign-key":
2493
2503
  yield* e.onDialectOrElse({
2494
- mysql: () => Q(e, mr(a), a.kind),
2504
+ mysql: () => Q(e, vr(a), a.kind),
2495
2505
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2496
- orElse: () => Q(e, pr(a), a.kind)
2506
+ orElse: () => Q(e, _r(a), a.kind)
2497
2507
  });
2498
2508
  break;
2499
2509
  case "add-check":
2500
2510
  yield* e.onDialectOrElse({
2501
- mysql: () => Q(e, hr(a, G), a.kind),
2511
+ mysql: () => Q(e, yr(a, K), a.kind),
2502
2512
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2503
- orElse: () => Q(e, hr(a, W), a.kind)
2513
+ orElse: () => Q(e, yr(a, G), a.kind)
2504
2514
  });
2505
2515
  break;
2506
2516
  case "drop-check":
2507
2517
  yield* e.onDialectOrElse({
2508
- mysql: () => Q(e, _r(a), a.kind),
2518
+ mysql: () => Q(e, xr(a), a.kind),
2509
2519
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2510
- orElse: () => Q(e, gr(a), a.kind)
2520
+ orElse: () => Q(e, br(a), a.kind)
2511
2521
  });
2512
2522
  break;
2513
2523
  }
@@ -2516,10 +2526,10 @@ BEGIN
2516
2526
  status: "applied",
2517
2527
  durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
2518
2528
  };
2519
- }), xr = (e, t, n) => p.gen(function* () {
2529
+ }), Tr = (e, t, n) => p.gen(function* () {
2520
2530
  let r = t.operations.filter((e) => e.blocked);
2521
2531
  if (r.length > 0) return yield* p.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
2522
- yield* w(e);
2532
+ yield* T(e);
2523
2533
  let i = Date.now(), a = [];
2524
2534
  try {
2525
2535
  let r = yield* e.onDialectOrElse({
@@ -2529,21 +2539,18 @@ BEGIN
2529
2539
  }), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
2530
2540
  i.length > 0 && (yield* e.withTransaction(p.gen(function* () {
2531
2541
  let e = yield* h.SqlClient;
2532
- for (let t of i) a.push(yield* br(e, t, n));
2542
+ for (let t of i) a.push(yield* wr(e, t, n));
2533
2543
  })));
2534
- for (let t of o) a.push(yield* br(e, t, n));
2544
+ for (let t of o) a.push(yield* wr(e, t, n));
2535
2545
  } finally {
2536
- yield* T(e).pipe(p.orDie);
2546
+ yield* E(e).pipe(p.orDie);
2537
2547
  }
2538
2548
  let o = yield* n.replan(e);
2539
2549
  if (o.operations.length > 0) {
2540
2550
  let e = o.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");
2541
2551
  return yield* p.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 ${o.operations.length}:\n${e}${o.operations.length > 10 ? `\n … and ${o.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.`));
2542
2552
  }
2543
- let s = a.filter((e) => e.status === "applied").length, c = Date.now() - i, l = `plan_${Date.now().toString(36)}`, u = (/* @__PURE__ */ new Date()).toISOString(), d = yield* e.onDialectOrElse({
2544
- mysql: () => p.succeed(u.replace("T", " ").replace("Z", "")),
2545
- orElse: () => p.succeed(u)
2546
- });
2553
+ let s = a.filter((e) => e.status === "applied").length, c = Date.now() - i, l = `plan_${Date.now().toString(36)}`, u = (/* @__PURE__ */ new Date()).toISOString(), d = yield* dn(e, u);
2547
2554
  return yield* e`
2548
2555
  INSERT INTO ${e("_voltro_migration_plans")}
2549
2556
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -2565,19 +2572,19 @@ BEGIN
2565
2572
  source: n.source,
2566
2573
  ...n.notes ? { notes: n.notes } : {}
2567
2574
  };
2568
- }), Sr = (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"), Cr = (e) => e`
2575
+ }), Er = (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"), Dr = (e) => e`
2569
2576
  SELECT fingerprint
2570
2577
  FROM _voltro_migration_plans
2571
2578
  ORDER BY ${e("appliedAt")} DESC
2572
2579
  LIMIT 1
2573
- `.pipe(p.map((e) => e.length > 0 ? e[0].fingerprint : void 0), p.catchAll(() => p.succeed(void 0))), wr = (e) => e.onDialectOrElse({
2580
+ `.pipe(p.map((e) => e.length > 0 ? e[0].fingerprint : void 0), p.catchAll(() => p.succeed(void 0))), Or = (e) => e.onDialectOrElse({
2574
2581
  pg: () => "postgres",
2575
2582
  mysql: () => "mysql",
2576
2583
  mssql: () => "mssql",
2577
2584
  sqlite: () => "sqlite",
2578
2585
  orElse: () => "sqlite"
2579
- }), Tr = (e, t) => p.gen(function* () {
2580
- let n = N(F(t, wr(e))), r = yield* Cr(e);
2586
+ }), kr = (e, t) => p.gen(function* () {
2587
+ let n = P(I(t, Or(e))), r = yield* Dr(e);
2581
2588
  return r === n ? {
2582
2589
  kind: "up-to-date",
2583
2590
  fingerprint: n
@@ -2586,23 +2593,23 @@ BEGIN
2586
2593
  expected: n,
2587
2594
  ...r === void 0 ? {} : { actual: r }
2588
2595
  };
2589
- }), Er = [
2596
+ }), Ar = [
2590
2597
  "pgeagertest_",
2591
2598
  "mig_e2e_",
2592
2599
  "mig_test_",
2593
2600
  "mysqleagertest_",
2594
2601
  "mssqleagertest_",
2595
2602
  "sqliteeagertest_"
2596
- ], Dr = (e) => Er.some((t) => e.startsWith(t)), Or = (e, t) => p.gen(function* () {
2603
+ ], jr = (e) => Ar.some((t) => e.startsWith(t)), Mr = (e, t) => p.gen(function* () {
2597
2604
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2598
- let n = t.filter((e) => Dr(e.name)).map((e) => e.name);
2605
+ let n = t.filter((e) => jr(e.name)).map((e) => e.name);
2599
2606
  if (n.length === 0) return [];
2600
2607
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(p.catchAll(() => p.void));
2601
2608
  return n;
2602
- }), kr = () => {
2609
+ }), Nr = () => {
2603
2610
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2604
2611
  return e.length > 0 ? { ignoreTables: e } : {};
2605
- }, Ar = (e) => {
2612
+ }, Pr = (e) => {
2606
2613
  if (e === void 0) return;
2607
2614
  let t = e.trim();
2608
2615
  if (t === "") return;
@@ -2612,43 +2619,43 @@ BEGIN
2612
2619
  kind: "tables",
2613
2620
  tables: new Set(n)
2614
2621
  } : void 0;
2615
- }, jr = (e) => typeof e.table == "string" ? e.table : void 0, Mr = (e, t = { kind: "all" }) => ({
2622
+ }, Fr = (e) => typeof e.table == "string" ? e.table : void 0, Ir = (e, t = { kind: "all" }) => ({
2616
2623
  ...e,
2617
2624
  operations: e.operations.map((e) => {
2618
2625
  if (!e.blocked || e.classification !== "lossy") return e;
2619
2626
  if (t?.kind === "tables") {
2620
- let n = jr(e.op);
2627
+ let n = Fr(e.op);
2621
2628
  if (n === void 0 || !t.tables.has(n)) return e;
2622
2629
  }
2623
2630
  let { blocked: n, ...r } = e;
2624
2631
  return r;
2625
2632
  })
2626
- }), Nr = (e, t, n) => t === "postgres" ? ut(e, n).pipe(p.flatMap((e) => {
2627
- let t = dt(e);
2633
+ }), Lr = (e, t, n) => t === "postgres" ? ft(e, n).pipe(p.flatMap((e) => {
2634
+ let t = pt(e);
2628
2635
  return t === void 0 ? p.void : p.logWarning(`auto-migrate: ${t}`).pipe(p.annotateLogs({ scope: "voltro:migrate" }));
2629
- }), p.catchAll(() => p.void)) : p.void, Pr = (e, t, n) => p.gen(function* () {
2630
- let r = wr(e), i = t;
2636
+ }), p.catchAll(() => p.void)) : p.void, Rr = (e, t, n) => p.gen(function* () {
2637
+ let r = Or(e), i = t;
2631
2638
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2632
- let t = N(F(i, r));
2633
- if ((yield* Cr(e)) === t) return yield* Nr(e, r, i), {
2639
+ let t = P(I(i, r));
2640
+ if ((yield* Dr(e)) === t) return yield* Lr(e, r, i), {
2634
2641
  kind: "up-to-date",
2635
2642
  fingerprint: t
2636
2643
  };
2637
2644
  }
2638
- let a = yield* U(e), o = yield* Or(e, a.tables);
2645
+ let a = yield* U(e), o = yield* Mr(e, a.tables);
2639
2646
  o.length > 0 && (yield* p.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(p.annotateLogs({
2640
2647
  scope: "voltro:migrate",
2641
2648
  count: o.length
2642
2649
  })), a = yield* U(e));
2643
- let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !s(e.name) || c.has(e.name)), u = Ut({
2650
+ let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !s(e.name) || c.has(e.name)), u = Kt({
2644
2651
  declared: i,
2645
2652
  live: { tables: l(a.tables) },
2646
2653
  dialect: r,
2647
- ...kr()
2654
+ ...Nr()
2648
2655
  });
2649
2656
  if (u.summary.blocked > 0) {
2650
- let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Ar(process.env.VOLTRO_DESTRUCTIVE_OK);
2651
- if (t === void 0 || !e || (u = Mr(u, t), u.operations.some((e) => e.blocked))) return {
2657
+ let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Pr(process.env.VOLTRO_DESTRUCTIVE_OK);
2658
+ if (t === void 0 || !e || (u = Ir(u, t), u.operations.some((e) => e.blocked))) return {
2652
2659
  kind: "refused-blocked",
2653
2660
  plan: u
2654
2661
  };
@@ -2658,37 +2665,37 @@ BEGIN
2658
2665
  fingerprint: u.toFingerprint
2659
2666
  } : {
2660
2667
  kind: "applied",
2661
- applied: yield* xr(e, u, {
2668
+ applied: yield* Tr(e, u, {
2662
2669
  declared: t,
2663
2670
  appliedBy: n.appliedBy,
2664
2671
  environment: n.environment === "prod" ? "dev" : n.environment,
2665
2672
  source: "auto-diff",
2666
2673
  replan: (e) => p.gen(function* () {
2667
2674
  let t = yield* U(e);
2668
- return Ut({
2675
+ return Kt({
2669
2676
  declared: i,
2670
2677
  live: { tables: l(t.tables) },
2671
2678
  dialect: r,
2672
- ...kr()
2679
+ ...Nr()
2673
2680
  });
2674
2681
  })
2675
2682
  }),
2676
2683
  plan: u
2677
2684
  };
2678
- }), Fr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? p.succeed({
2685
+ }), zr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? p.succeed({
2679
2686
  kind: "skipped",
2680
2687
  reason: "VOLTRO_AUTO_MIGRATE=0"
2681
- }) : n.environment === "prod" ? Tr(e, t) : Pr(e, t, n), Ir = (e, t) => {
2688
+ }) : n.environment === "prod" ? kr(e, t) : Rr(e, t, n), Br = (e, t) => {
2682
2689
  switch (e.kind) {
2683
2690
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
2684
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
2691
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${F(e.fingerprint)})`;
2685
2692
  case "applied": {
2686
2693
  let t = e.plan.summary;
2687
- return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${P(e.applied.fingerprint)}`;
2694
+ return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${F(e.applied.fingerprint)}`;
2688
2695
  }
2689
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${P(e.expected)}` + (e.actual ? ` live=${P(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2696
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${F(e.expected)}` + (e.actual ? ` live=${F(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2690
2697
  case "refused-blocked": {
2691
- 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` + Sr(e.plan), c = [""];
2698
+ 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` + Er(e.plan), c = [""];
2692
2699
  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) {
2693
2700
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2694
2701
  for (let r of e.plan.operations) {
@@ -2705,7 +2712,7 @@ BEGIN
2705
2712
  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");
2706
2713
  }
2707
2714
  }
2708
- }, Lr = /* @__PURE__ */ new Set([
2715
+ }, Vr = /* @__PURE__ */ new Set([
2709
2716
  "node_modules",
2710
2717
  "dist",
2711
2718
  "build",
@@ -2714,11 +2721,11 @@ BEGIN
2714
2721
  ".next",
2715
2722
  ".git",
2716
2723
  ".framework"
2717
- ]), Rr = async (e) => {
2724
+ ]), Hr = async (e) => {
2718
2725
  let t = [], n = async (e) => {
2719
2726
  let r = await _.readdir(e, { withFileTypes: !0 }).catch(() => []);
2720
2727
  for (let i of r) {
2721
- if (Lr.has(i.name)) continue;
2728
+ if (Vr.has(i.name)) continue;
2722
2729
  let r = v(e, i.name);
2723
2730
  i.isDirectory() ? await n(r) : i.isFile() && o.test(i.name) && t.push(r);
2724
2731
  }
@@ -2727,7 +2734,7 @@ BEGIN
2727
2734
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
2728
2735
  return n.localeCompare(r);
2729
2736
  });
2730
- }, zr = async (e) => {
2737
+ }, Ur = async (e) => {
2731
2738
  let t = [];
2732
2739
  for (let r of e) {
2733
2740
  let e = (await import(y(r).href)).default;
@@ -2741,11 +2748,19 @@ BEGIN
2741
2748
  });
2742
2749
  }
2743
2750
  return t;
2744
- }, Br = (e) => e`
2751
+ }, Wr = (e) => e`
2745
2752
  SELECT ${e("id")}
2746
2753
  FROM ${e("_voltro_migration_plans")}
2747
2754
  WHERE ${e("source")} = 'file'
2748
- `.pipe(p.map((e) => e.map((e) => e.id)), p.catchAll(() => p.succeed([]))), Vr = (e, t, n, r) => p.gen(function* () {
2755
+ `.pipe(p.map((e) => e.map((e) => e.id)), p.catchAll(() => p.succeed([]))), Gr = class extends Error {
2756
+ migrationId;
2757
+ file;
2758
+ cause;
2759
+ _tag = "FileMigrationLedgerError";
2760
+ constructor(e, t, n) {
2761
+ 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";
2762
+ }
2763
+ }, Kr = (e, t, n, r) => p.gen(function* () {
2749
2764
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
2750
2765
  sql: e,
2751
2766
  log: {
@@ -2765,7 +2780,9 @@ BEGIN
2765
2780
  catch: (e) => e
2766
2781
  });
2767
2782
  let c = Date.now() - i;
2768
- return !p.isEffect(s) && c < 2 && (yield* p.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(p.annotateLogs({ scope: `migrations:file:${t.migration.id}` }))), yield* e`
2783
+ !p.isEffect(s) && c < 2 && (yield* p.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(p.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
2784
+ let l = yield* dn(e, a);
2785
+ return yield* e`
2769
2786
  INSERT INTO ${e("_voltro_migration_plans")}
2770
2787
  (${e("id")}, ${e("fingerprint")}, ${e("operations")},
2771
2788
  ${e("appliedBy")}, ${e("environment")}, ${e("source")},
@@ -2776,11 +2793,11 @@ BEGIN
2776
2793
  file: t.file
2777
2794
  }])},
2778
2795
  ${r}, ${n}, ${"file"},
2779
- ${c}, ${a}, ${t.migration.description})
2780
- `, { durationMs: c };
2781
- }), Hr = (e, t) => p.gen(function* () {
2796
+ ${c}, ${l}, ${t.migration.description})
2797
+ `.pipe(p.mapError((e) => new Gr(t.migration.id, t.file, e))), { durationMs: c };
2798
+ }), qr = (e, t) => p.gen(function* () {
2782
2799
  let n = yield* p.tryPromise({
2783
- try: () => Rr(v(t, "migrations")),
2800
+ try: () => Hr(v(t, "migrations")),
2784
2801
  catch: (e) => e
2785
2802
  });
2786
2803
  if (n.length === 0) return {
@@ -2788,25 +2805,25 @@ BEGIN
2788
2805
  skipped: []
2789
2806
  };
2790
2807
  let r = yield* p.tryPromise({
2791
- try: () => zr(n),
2808
+ try: () => Ur(n),
2792
2809
  catch: (e) => e
2793
2810
  });
2794
2811
  if (r.length === 0) return {
2795
2812
  pending: [],
2796
2813
  skipped: []
2797
2814
  };
2798
- let i = new Set(yield* Br(e));
2815
+ let i = new Set(yield* Wr(e));
2799
2816
  return {
2800
2817
  pending: r.filter((e) => !i.has(e.migration.id)),
2801
2818
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
2802
2819
  };
2803
- }), Ur = (e, t) => Hr(e, t).pipe(p.map((e) => e.pending.map((e) => e.migration.id))), Wr = (e, t) => p.gen(function* () {
2804
- let { pending: n, skipped: r } = yield* Hr(e, t.projectRoot);
2820
+ }), Jr = (e, t) => qr(e, t).pipe(p.map((e) => e.pending.map((e) => e.migration.id))), Yr = (e, t) => p.gen(function* () {
2821
+ let { pending: n, skipped: r } = yield* qr(e, t.projectRoot);
2805
2822
  if (n.length === 0) return {
2806
2823
  applied: [],
2807
2824
  skipped: r
2808
2825
  };
2809
- yield* w(e);
2826
+ yield* T(e);
2810
2827
  let i = [];
2811
2828
  try {
2812
2829
  for (let r of n) {
@@ -2815,7 +2832,7 @@ BEGIN
2815
2832
  id: r.migration.id,
2816
2833
  file: r.file
2817
2834
  }));
2818
- let { durationMs: n } = yield* Vr(e, r, t.env, t.appliedBy);
2835
+ let { durationMs: n } = yield* Kr(e, r, t.env, t.appliedBy);
2819
2836
  i.push({
2820
2837
  id: r.migration.id,
2821
2838
  durationMs: n
@@ -2826,28 +2843,28 @@ BEGIN
2826
2843
  }));
2827
2844
  }
2828
2845
  } finally {
2829
- yield* T(e).pipe(p.orDie);
2846
+ yield* E(e).pipe(p.orDie);
2830
2847
  }
2831
2848
  return {
2832
2849
  applied: i,
2833
2850
  skipped: r
2834
2851
  };
2835
- }), Gr = (e, t) => e`
2852
+ }), Xr = (e, t) => e`
2836
2853
  SELECT ${e("id")}
2837
2854
  FROM ${e("_voltro_migration_plans")}
2838
2855
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
2839
2856
  LIMIT 1
2840
- `, Kr = (e, t) => p.gen(function* () {
2841
- if (!(yield* Gr(e, t.id))[0]) return yield* p.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2857
+ `, Zr = (e, t) => p.gen(function* () {
2858
+ if (!(yield* Xr(e, t.id))[0]) return yield* p.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2842
2859
  let n = yield* p.tryPromise({
2843
- try: () => Rr(v(t.projectRoot, "migrations")),
2860
+ try: () => Hr(v(t.projectRoot, "migrations")),
2844
2861
  catch: (e) => e
2845
2862
  }), r = (yield* p.tryPromise({
2846
- try: () => zr(n),
2863
+ try: () => Ur(n),
2847
2864
  catch: (e) => e
2848
2865
  })).find((e) => e.migration.id === t.id);
2849
2866
  if (!r) return yield* p.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
2850
- yield* w(e);
2867
+ yield* T(e);
2851
2868
  let i = Date.now();
2852
2869
  try {
2853
2870
  let n = {
@@ -2874,9 +2891,9 @@ BEGIN
2874
2891
  durationMs: o
2875
2892
  };
2876
2893
  } finally {
2877
- yield* T(e).pipe(p.orDie);
2894
+ yield* E(e).pipe(p.orDie);
2878
2895
  }
2879
- }), qr = (e) => p.gen(function* () {
2896
+ }), Qr = (e) => p.gen(function* () {
2880
2897
  let t = yield* h.SqlClient, n = yield* t`
2881
2898
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
2882
2899
  WHERE source = 'auto-diff'
@@ -2921,10 +2938,80 @@ BEGIN
2921
2938
  snapshotFingerprint: e.fingerprint,
2922
2939
  snapshotId: i
2923
2940
  };
2924
- }), Jr = (e, ...t) => ({
2941
+ }), $r = { safe: !0 }, ei = (e) => {
2942
+ switch (e.kind) {
2943
+ case "drop-column": return {
2944
+ safe: !1,
2945
+ reason: `old instances still SELECT/INSERT "${e.table}"."${e.column}"; after the drop those queries error mid-rollout`,
2946
+ remedy: "stop reading the column in code and deploy that first; drop it in a LATER deploy (expand/contract)"
2947
+ };
2948
+ case "drop-table": return {
2949
+ safe: !1,
2950
+ reason: `old instances still query table "${e.table}"; after the drop every such query errors mid-rollout`,
2951
+ remedy: `remove all code that touches "${e.table}" and deploy that first; drop the table in a LATER deploy`
2952
+ };
2953
+ case "rename-column": return {
2954
+ safe: !1,
2955
+ reason: `old instances reference "${e.table}"."${e.from}", which no longer exists after the rename`,
2956
+ remedy: `add "${e.to}" alongside "${e.from}" + backfill + dual-write, cut code over, then drop "${e.from}" in a LATER deploy`
2957
+ };
2958
+ case "rename-table": return {
2959
+ safe: !1,
2960
+ reason: `old instances query table "${e.from}", which no longer exists after the rename`,
2961
+ remedy: `create "${e.to}" as a copy + dual-write, cut code over, then drop "${e.from}" in a LATER deploy`
2962
+ };
2963
+ case "alter-column-type": return {
2964
+ safe: !1,
2965
+ 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`,
2966
+ remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
2967
+ };
2968
+ case "alter-column-nullability": return e.toNullable ? $r : {
2969
+ safe: !1,
2970
+ reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
2971
+ 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)`
2972
+ };
2973
+ case "add-unique":
2974
+ case "add-unique-composite": return {
2975
+ safe: !1,
2976
+ reason: `old instances still write "${e.table}" without honouring the new uniqueness; a colliding insert now fails mid-rollout`,
2977
+ remedy: "make code enforce uniqueness first and deploy that; add the constraint in a LATER deploy once no old writer remains"
2978
+ };
2979
+ case "add-check": return {
2980
+ safe: !1,
2981
+ reason: `old instances may write values to "${e.table}" the new CHECK rejects`,
2982
+ remedy: "make code satisfy the constraint first and deploy that; add the CHECK in a LATER deploy"
2983
+ };
2984
+ case "add-foreign-key": return {
2985
+ safe: !1,
2986
+ reason: `old instances may write "${e.table}"."${e.column}" values with no matching parent row, which the new FK rejects`,
2987
+ remedy: "make code guarantee the referent first and deploy that; add the FK in a LATER deploy"
2988
+ };
2989
+ case "create-table":
2990
+ case "add-column":
2991
+ case "add-index":
2992
+ case "drop-index":
2993
+ case "rename-index":
2994
+ case "alter-column-default":
2995
+ case "drop-unique":
2996
+ case "drop-unique-composite":
2997
+ case "drop-foreign-key":
2998
+ case "drop-check": return $r;
2999
+ }
3000
+ }, ti = (e) => {
3001
+ let t = [];
3002
+ for (let n of e) {
3003
+ let e = ei(n.op);
3004
+ e.safe || t.push({
3005
+ op: n,
3006
+ reason: e.reason,
3007
+ remedy: e.remedy
3008
+ });
3009
+ }
3010
+ return t;
3011
+ }, ni = (e, ...t) => ({
2925
3012
  _tag: "RawSqlFragment",
2926
3013
  strings: [...e],
2927
3014
  values: [...t]
2928
- }), Yr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3015
+ }), ri = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2929
3016
  //#endregion
2930
- export { j as DEFAULT_CDC_CHANNEL, o as FILE_MIGRATION_PATTERN, lt as REACTIVE_TRIGGER_PREFIX, ie as VOLTRO_MIGRATION_LOCK_KEY, w as acquireMigrationLock, Ze as applyNamespacedSchema, xr as applyPlan, Ge as applySchema, Xt as chunkTables, F as declaredSnapshot, xe as defaultArrayClause, be as defaultClause, O as defaultJsonClause, Ir as describeOutcome, Ar as destructiveScope, ut as detectReactiveTriggerDrift, pn as emitDropColumnDdl, mn as emitDropColumnDdlMysql, We as emitFrameworkBootstrapSql, He as emitNamespaceProvisionDdl, Ue as emitNamespacedSchemaSql, M as emitSchemaSql, N as fingerprintSchema, dt as formatReactiveTriggerDrift, kr as ignoreTablesFromEnv, U as introspectSchema, n as isFileMigration, Yr as isRawSqlFragment, Gt as mapPgType, c as migration, k as numericIdSql, Wt as parseEnumCheck, Ur as pendingFileMigrationIds, Ut as planMigrations, Qe as provisionTenantNamespace, T as releaseMigrationLock, On as renderColumnMysql, wn as renderColumnPg, Kr as rollbackFileBasedMigration, Wr as runFileBasedMigrations, $e as runFrameworkBootstrap, Xe as runMigrate, Fr as runPlannedMigrations, P as shortFingerprint, at as snapshotColumn, Jr as sql, D as sqlType, qr as squashMigrationPlans, Mr as unblockLossy, ve as withMigrationLock };
3017
+ export { O as DEFAULT_CDC_CHANNEL, o as FILE_MIGRATION_PATTERN, Gr as FileMigrationLedgerError, k as REACTIVE_TRIGGER_PREFIX, re as VOLTRO_MIGRATION_LOCK_KEY, T as acquireMigrationLock, et as applyNamespacedSchema, Tr as applyPlan, Je as applySchema, $t as chunkTables, ei as classifyRollingDeploySafety, I as declaredSnapshot, xe as defaultArrayClause, be as defaultClause, M as defaultJsonClause, Br as describeOutcome, Pr as destructiveScope, ft as detectReactiveTriggerDrift, gn as emitDropColumnDdl, _n as emitDropColumnDdlMysql, qe as emitFrameworkBootstrapSql, Ge as emitNamespaceProvisionDdl, Ke as emitNamespacedSchemaSql, We as emitSchemaSql, P as fingerprintSchema, pt as formatReactiveTriggerDrift, Nr as ignoreTablesFromEnv, U as introspectSchema, n as isFileMigration, ri as isRawSqlFragment, Jt as mapPgType, c as migration, N as numericIdSql, qt as parseEnumCheck, Jr as pendingFileMigrationIds, Kt as planMigrations, tt as provisionTenantNamespace, Fe as reactiveTriggerRepairSql, E as releaseMigrationLock, Mn as renderColumnMysql, Dn as renderColumnPg, Zr as rollbackFileBasedMigration, ti as rollingDeployUnsafeOps, Yr as runFileBasedMigrations, nt as runFrameworkBootstrap, $e as runMigrate, zr as runPlannedMigrations, F as shortFingerprint, ct as snapshotColumn, ni as sql, j as sqlType, Qr as squashMigrationPlans, Ir as unblockLossy, D as withMigrationLock };