@voltro/database 0.62.3 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sql.js CHANGED
@@ -1,13 +1,13 @@
1
- import { $ as e, $t as t, Ht as n, Ut as r, a as i, at as a, c as o, d as s, en as c, et as l, g as u, h as d, i as f, it as p, o as m, r as h, s as g, tt as _, u as v, vt as y, wt as b, y as x } from "./frameworkLiveTables-CewCJ809.js";
2
- import { Effect as S, Schedule as C } from "effect";
3
- import { createHash as w } from "node:crypto";
4
- import { createLogger as T } from "@voltro/logger";
5
- import { SqlClient as E } from "@effect/sql";
6
- import { promises as ee } from "node:fs";
7
- import { join as te } from "node:path";
8
- import { pathToFileURL as ne } from "node:url";
1
+ import { C as e, Jt as t, Ot as n, St as r, a as i, an as a, at as o, b as s, c, ct as l, d as u, f as d, h as f, i as p, it as m, lt as h, m as g, o as _, on as v, qt as y, rt as b, s as x, u as S, y as ee } from "./frameworkLiveTables-BURogL9N.js";
2
+ import { Effect as C, Schedule as w } from "effect";
3
+ import { createHash as te } from "node:crypto";
4
+ import { createLogger as ne } from "@voltro/logger";
5
+ import { SqlClient as T } from "@effect/sql";
6
+ import { promises as re } from "node:fs";
7
+ import { join as ie } from "node:path";
8
+ import { pathToFileURL as ae } from "node:url";
9
9
  //#region src/migrations/ddlError.ts
10
- var re = (e, t, n, r = 400) => {
10
+ var oe = (e, t, n, r = 400) => {
11
11
  let i = n, a = i.cause ?? {}, o = (e) => {
12
12
  let t = a[e];
13
13
  return t == null || t === "" ? void 0 : String(t);
@@ -38,21 +38,21 @@ var re = (e, t, n, r = 400) => {
38
38
  let t = o(e);
39
39
  t !== void 0 && s.push(`db.${e}: ${t}`);
40
40
  }
41
- let c = ie(o("code"));
41
+ let c = se(o("code"));
42
42
  return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
43
- }, ie = (e) => e === "3F000" ? "remedy: the connection's search_path names a schema that does not exist. Voltro sets it from DB_SCHEMA — create the schema (`CREATE SCHEMA \"<name>\"`) or unset DB_SCHEMA to use the connection default. Voltro creates TABLES, never the schema itself: that is a namespace decision, and inventing one from a typo is how a migration lands somewhere nobody is looking." : void 0, ae = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, oe = (e) => e.replace(/"/g, "`"), se = (e) => typeof e == "string" ? e : e.name ?? String(e), ce = (e, t) => `_ua_${t}_${e}`.slice(0, 64), le = (e, t) => {
44
- if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(ae)) return e;
43
+ }, se = (e) => e === "3F000" ? "remedy: the connection's search_path names a schema that does not exist. Voltro sets it from DB_SCHEMA — create the schema (`CREATE SCHEMA \"<name>\"`) or unset DB_SCHEMA to use the connection default. Voltro creates TABLES, never the schema itself: that is a namespace decision, and inventing one from a typo is how a migration lands somewhere nobody is looking." : void 0, ce = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, le = (e) => e.replace(/"/g, "`"), ue = (e) => typeof e == "string" ? e : e.name ?? String(e), de = (e, t) => `_ua_${t}_${e}`.slice(0, 64), fe = (e, t) => {
44
+ if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(ce)) return e;
45
45
  let n = { ...e.fields }, r = [], i = [];
46
46
  for (let t of e.appliedIndexes) {
47
- if (!ae(t)) {
47
+ if (!ce(t)) {
48
48
  r.push(t);
49
49
  continue;
50
50
  }
51
- let a = oe(t.where), o = [];
51
+ let a = le(t.where), o = [];
52
52
  for (let r of t.fields) {
53
- let i = se(r);
53
+ let i = ue(r);
54
54
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
55
- let s = ce(t.name, i);
55
+ let s = de(t.name, i);
56
56
  o.push(s), n[s] = {
57
57
  type: "text",
58
58
  nullable: !0,
@@ -75,99 +75,99 @@ var re = (e, t, n, r = 400) => {
75
75
  appliedIndexes: r,
76
76
  appliedUniques: [...e.appliedUniques ?? [], ...i]
77
77
  };
78
- }, D = (e, t) => `${e}::${t}`, ue = (e, t) => {
78
+ }, E = (e, t) => `${e}::${t}`, pe = (e, t) => {
79
79
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
80
80
  n.add(e);
81
81
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
82
- for (let t of o) n.has(t.target) ? i.add(D(e, t.column)) : r.has(t.target) || a(t.target);
82
+ for (let t of o) n.has(t.target) ? i.add(E(e, t.column)) : r.has(t.target) || a(t.target);
83
83
  n.delete(e), r.add(e);
84
84
  };
85
85
  for (let t of [...e].sort()) r.has(t) || a(t);
86
86
  return i;
87
- }, de = 6322741009312437n, fe = (e) => {
87
+ }, me = 6322741009312437n, he = (e) => {
88
88
  let t = e?.trim();
89
89
  return t === void 0 || t === "" || t === "public" ? void 0 : t;
90
- }, pe = (e) => e?.schema === void 0 ? fe(process.env.DB_SCHEMA) : fe(e.schema), me = 14695981039346656037n, he = 1099511628211n, ge = 18446744073709551615n, _e = (e) => {
91
- let t = me;
92
- for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * he & ge;
90
+ }, ge = (e) => e?.schema === void 0 ? he(process.env.DB_SCHEMA) : he(e.schema), _e = 14695981039346656037n, ve = 1099511628211n, ye = 18446744073709551615n, be = (e) => {
91
+ let t = _e;
92
+ for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * ve & ye;
93
93
  return t;
94
- }, ve = (e) => {
95
- let t = fe(e);
96
- return t === void 0 ? de : _e(`voltro_migration_lock:${t}`) & 9223372036854775807n;
97
- }, ye = (e) => {
98
- let t = `voltro_migration_${de.toString(36)}`, n = fe(e);
94
+ }, xe = (e) => {
95
+ let t = he(e);
96
+ return t === void 0 ? me : be(`voltro_migration_lock:${t}`) & 9223372036854775807n;
97
+ }, Se = (e) => {
98
+ let t = `voltro_migration_${me.toString(36)}`, n = he(e);
99
99
  if (n === void 0) return t;
100
100
  let r = `${t}_${n}`;
101
- return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(_e(`voltro_migration_lock:${n}`) & ge).toString(16)}`;
102
- }, be = 250, xe = () => {
101
+ return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(be(`voltro_migration_lock:${n}`) & ye).toString(16)}`;
102
+ }, Ce = 250, we = () => {
103
103
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
104
104
  return Number.isFinite(e) && e > 0 ? e : 3e4;
105
- }, Se = (e, t) => S.gen(function* () {
106
- let n = xe(), r = Date.now();
105
+ }, Te = (e, t) => C.gen(function* () {
106
+ let n = we(), r = Date.now();
107
107
  for (;;) {
108
108
  if ((yield* e`
109
109
  SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`)[0]?.got) return;
110
- Date.now() - r >= n && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* S.sleep(`${be} millis`);
110
+ Date.now() - r >= n && (yield* C.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* C.sleep(`${Ce} millis`);
111
111
  }
112
- }), Ce = (e, t) => S.gen(function* () {
112
+ }), Ee = (e, t) => C.gen(function* () {
113
113
  yield* e`SELECT pg_advisory_unlock(${t.toString()}::bigint)`;
114
- }), we = 30, Te = (e, t) => S.gen(function* () {
114
+ }), De = 30, Oe = (e, t) => C.gen(function* () {
115
115
  (yield* e`
116
- SELECT GET_LOCK(${t}, ${we}) AS got`)[0]?.got !== 1 && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${we}s (another migration is in progress, or a prior one left it held).`)));
117
- }), Ee = (e, t) => S.gen(function* () {
116
+ SELECT GET_LOCK(${t}, ${De}) AS got`)[0]?.got !== 1 && (yield* C.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${De}s (another migration is in progress, or a prior one left it held).`)));
117
+ }), ke = (e, t) => C.gen(function* () {
118
118
  yield* e`SELECT RELEASE_LOCK(${t})`;
119
- }), De = 3e4, Oe = (e, t) => S.gen(function* () {
119
+ }), Ae = 3e4, je = (e, t) => C.gen(function* () {
120
120
  let n = yield* e`
121
121
  DECLARE @res int;
122
122
  EXEC @res = sp_getapplock @Resource = ${t}, @LockMode = 'Exclusive',
123
- @LockOwner = 'Session', @LockTimeout = ${De};
123
+ @LockOwner = 'Session', @LockTimeout = ${Ae};
124
124
  SELECT @res AS res`;
125
- (n[0]?.res ?? -999) < 0 && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
126
- }), ke = (e, t) => S.gen(function* () {
125
+ (n[0]?.res ?? -999) < 0 && (yield* C.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
126
+ }), Me = (e, t) => C.gen(function* () {
127
127
  yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
128
- }), Ae = S.void, je = (e, t) => {
129
- let n = pe(t);
128
+ }), Ne = C.void, Pe = (e, t) => {
129
+ let n = ge(t);
130
130
  return e.onDialectOrElse({
131
- mysql: () => Te(e, ye(n)),
132
- mssql: () => Oe(e, ye(n)),
133
- sqlite: () => Ae,
134
- orElse: () => Se(e, ve(n))
131
+ mysql: () => Oe(e, Se(n)),
132
+ mssql: () => je(e, Se(n)),
133
+ sqlite: () => Ne,
134
+ orElse: () => Te(e, xe(n))
135
135
  });
136
- }, O = (e, t) => {
137
- let n = pe(t);
136
+ }, D = (e, t) => {
137
+ let n = ge(t);
138
138
  return e.onDialectOrElse({
139
- mysql: () => Ee(e, ye(n)),
140
- mssql: () => ke(e, ye(n)),
141
- sqlite: () => Ae,
142
- orElse: () => Ce(e, ve(n))
139
+ mysql: () => ke(e, Se(n)),
140
+ mssql: () => Me(e, Se(n)),
141
+ sqlite: () => Ne,
142
+ orElse: () => Ee(e, xe(n))
143
143
  });
144
- }, Me = (e, t, n) => S.acquireUseRelease(je(e, n), () => t, () => O(e, n).pipe(S.orDie)), Ne = (e) => e.onDialectOrElse({
144
+ }, Fe = (e, t, n) => C.acquireUseRelease(Pe(e, n), () => t, () => D(e, n).pipe(C.orDie)), Ie = (e) => e.onDialectOrElse({
145
145
  pg: () => "postgres",
146
146
  mysql: () => "mysql",
147
147
  mssql: () => "mssql",
148
148
  sqlite: () => "sqlite",
149
149
  orElse: () => "sqlite"
150
- }), Pe = {
150
+ }), Le = {
151
151
  postgres: "plan-transactional",
152
152
  mssql: "plan-transactional",
153
153
  mysql: "per-operation",
154
154
  mariadb: "per-operation",
155
155
  sqlite: "per-operation",
156
156
  turso: "per-operation"
157
- }, Fe = (e) => Pe[e], k = "_voltro_migration_ops", Ie = p(k, {
158
- id: n({ prefix: "mop" }),
159
- runId: t(),
160
- planFingerprint: t(),
161
- opIndex: r(),
162
- opKind: t(),
163
- opTarget: t(),
164
- status: t(),
165
- payload: t(),
166
- startedAt: c().nullable(),
167
- appliedAt: c().nullable(),
168
- durationMs: r().nullable(),
169
- createdAt: c().default("now")
170
- }), Le = (e) => {
157
+ }, Re = (e) => Le[e], O = "_voltro_migration_ops", ze = l(O, {
158
+ id: y({ prefix: "mop" }),
159
+ runId: a(),
160
+ planFingerprint: a(),
161
+ opIndex: t(),
162
+ opKind: a(),
163
+ opTarget: a(),
164
+ status: a(),
165
+ payload: a(),
166
+ startedAt: v().nullable(),
167
+ appliedAt: v().nullable(),
168
+ durationMs: t().nullable(),
169
+ createdAt: v().default("now")
170
+ }), Be = (e) => {
171
171
  switch (e.kind) {
172
172
  case "create-table": return /* @__PURE__ */ new Set([
173
173
  `table:${e.table}`,
@@ -194,11 +194,11 @@ var re = (e, t, n, r = 400) => {
194
194
  case "add-unique-composite":
195
195
  case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
196
196
  }
197
- }, Re = (e) => [...Le(e)].join(" "), ze = (e, t) => {
198
- let n = Le(t);
199
- for (let t of Le(e)) if (n.has(t)) return !0;
197
+ }, Ve = (e) => [...Be(e)].join(" "), He = (e, t) => {
198
+ let n = Be(t);
199
+ for (let t of Be(e)) if (n.has(t)) return !0;
200
200
  return !1;
201
- }, Be = (e, t) => e.operations.some((e) => ze(e.op, t)), Ve = "__voltro_rebuild", He = "__shadow", Ue = "__old", We = /* @__PURE__ */ new Set([
201
+ }, Ue = (e, t) => e.operations.some((e) => He(e.op, t)), We = "__voltro_rebuild", Ge = "__shadow", Ke = "__old", qe = /* @__PURE__ */ new Set([
202
202
  "add-unique",
203
203
  "drop-unique",
204
204
  "add-unique-composite",
@@ -210,16 +210,21 @@ var re = (e, t, n, r = 400) => {
210
210
  "alter-column-nullability",
211
211
  "alter-column-type",
212
212
  "alter-column-default"
213
- ]), Ge = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Ke = (e, t, n) => {
213
+ ]), Je = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Ye = (e, t, n) => {
214
214
  let r = n === "sqlite" || n === "turso";
215
- return e.kind === "alter-column-type" && t === "online-required" || r && We.has(e.kind) ? "artefact-repair" : Ge.has(e.kind) ? "idempotent" : "probe-then-replay";
215
+ return e.kind === "alter-column-type" && t === "online-required" || r && qe.has(e.kind) ? "artefact-repair" : Je.has(e.kind) ? "idempotent" : "probe-then-replay";
216
216
  };
217
- Object.keys(Pe);
217
+ Object.keys(Le);
218
218
  //#endregion
219
219
  //#region src/migrations/reactiveTriggerName.ts
220
- var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "framework_changes" ? `${qe}${e}` : `${qe}${t}_${e}`, Ye = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Xe = "voltro:notify:v2", Ze = T({ scope: "voltro:migrate" }), j = (e) => {
221
- Ze.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
222
- }, M = (e, t) => {
220
+ var k = "framework_changes", Xe = "framework_changes_", Ze = (e, t) => t === "framework_changes" ? `${Xe}${e}` : `${Xe}${t}_${e}`, Qe = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, $e = "voltro:notify:v2", et = (e, t) => {
221
+ if (e.type === "text" && e.generatedAs === void 0) {
222
+ if (e.maxLength !== void 0) return e.maxLength;
223
+ if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
224
+ }
225
+ }, tt = ne({ scope: "voltro:migrate" }), A = (e) => {
226
+ tt.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
227
+ }, j = (e, t) => {
223
228
  let n = e.type;
224
229
  if (e.spatial) {
225
230
  if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
@@ -230,14 +235,14 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
230
235
  return e.rawDdl;
231
236
  }
232
237
  if (n === "array" && e.arrayElement) {
233
- if (t === "postgres") return `${M({
238
+ if (t === "postgres") return `${j({
234
239
  ...e,
235
240
  type: e.arrayElement,
236
241
  arrayElement: void 0
237
242
  }, t)}[]`;
238
243
  if (t === "mysql" || t === "mariadb") return "JSON";
239
244
  if (t === "mssql") return "NVARCHAR(MAX)";
240
- if (l(t)) return "TEXT";
245
+ if (m(t)) return "TEXT";
241
246
  }
242
247
  if (n === "vector") {
243
248
  let n = e.vectorDim;
@@ -246,27 +251,27 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
246
251
  if (t === "postgres") return r ? `HALFVEC(${n})` : `VECTOR(${n})`;
247
252
  if (t === "mysql" || t === "mariadb") return `VECTOR(${n})`;
248
253
  if (t === "mssql") return "VARBINARY(MAX)";
249
- if (l(t)) return "BLOB";
254
+ if (m(t)) return "BLOB";
250
255
  }
251
256
  if (n === "interval") {
252
257
  if (t === "postgres") return "INTERVAL";
253
258
  if (t === "mysql" || t === "mariadb" || t === "mssql") return "BIGINT";
254
- if (l(t)) return "INTEGER";
259
+ if (m(t)) return "INTEGER";
255
260
  }
256
261
  if (n === "decimal") {
257
262
  let n = e.precision, r = e.scale ?? 0;
258
263
  if (n === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
259
- return l(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
264
+ return m(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
260
265
  }
261
- if (n === "bigint") return l(t) ? "INTEGER" : "BIGINT";
266
+ if (n === "bigint") return m(t) ? "INTEGER" : "BIGINT";
262
267
  if (n === "enum") {
263
268
  if (t === "postgres") return e.enumName ?? "TEXT";
264
269
  if (t === "mysql" || t === "mariadb") return `ENUM(${(e.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
265
270
  if (t === "mssql") return "NVARCHAR(255)";
266
- if (l(t)) return "TEXT";
271
+ if (m(t)) return "TEXT";
267
272
  }
268
- if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : l(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
269
- if (l(t)) switch (n) {
273
+ if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : m(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
274
+ if (m(t)) switch (n) {
270
275
  case "id": return "TEXT";
271
276
  case "text": return "TEXT";
272
277
  case "integer": return "INTEGER";
@@ -300,7 +305,10 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
300
305
  }
301
306
  if (t === "mssql") switch (n) {
302
307
  case "id": return "NVARCHAR(64)";
303
- case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "NVARCHAR(450)" : "NVARCHAR(MAX)";
308
+ case "text": {
309
+ let t = et(e, !1);
310
+ return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
311
+ }
304
312
  case "integer": return "INT";
305
313
  case "real": return "FLOAT";
306
314
  case "boolean": return "BIT";
@@ -330,22 +338,22 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
330
338
  case "array": return "TEXT[]";
331
339
  case "interval": return "INTERVAL";
332
340
  }
333
- }, Qe = (e, t) => {
341
+ }, nt = (e, t) => {
334
342
  if (!e.hasDefault || e.defaultFactory !== void 0) return null;
335
343
  let n = e.defaultValue;
336
- return n === "now" ? l(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ? $e(n, e, t) : typeof n == "object" && n ? N(n, t) : null;
337
- }, $e = (e, t, n) => {
338
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return N(e, n);
339
- let r = M({
344
+ return n === "now" ? m(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ? rt(n, e, t) : typeof n == "object" && n ? M(n, t) : null;
345
+ }, rt = (e, t, n) => {
346
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return M(e, n);
347
+ let r = j({
340
348
  ...t,
341
349
  type: t.arrayElement,
342
350
  arrayElement: void 0
343
351
  }, n);
344
352
  return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
345
- }, N = (e, t) => {
353
+ }, M = (e, t) => {
346
354
  let n = JSON.stringify(e).replace(/'/g, "''");
347
355
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
348
- }, P = (e, t) => {
356
+ }, N = (e, t) => {
349
357
  switch (t) {
350
358
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
351
359
  case "mysql":
@@ -354,7 +362,7 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
354
362
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
355
363
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
356
364
  }
357
- }, F = (e, t) => {
365
+ }, P = (e, t) => {
358
366
  if (e === "restrict" && t === "mssql") return "NO ACTION";
359
367
  switch (e) {
360
368
  case "cascade": return "CASCADE";
@@ -362,117 +370,118 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
362
370
  case "setNull": return "SET NULL";
363
371
  case "noAction": return "NO ACTION";
364
372
  }
365
- }, et = (e, t, n) => n === null ? _(e, t) : `${_(n, t)}.${_(e, t)}`, tt = 191, nt = (e, t) => {
373
+ }, it = (e, t, n) => n === null ? o(e, t) : `${o(n, t)}.${o(e, t)}`, at = 191, ot = (e, t) => {
366
374
  if (!e || t !== "mysql" && t !== "mariadb") return !1;
367
- let n = M(e, t).toUpperCase();
375
+ let n = j(e, t).toUpperCase();
368
376
  return n.endsWith("TEXT") || n.endsWith("BLOB");
369
- }, rt = (e, t, n) => {
370
- let r = _(e, n);
377
+ }, st = (e, t, n) => {
378
+ let r = o(e, n);
371
379
  if (n !== "mysql" && n !== "mariadb") return r;
372
380
  let i = t[e];
373
381
  if (!i) return r;
374
- let a = M(i, n).toUpperCase();
375
- return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${tt})` : r;
376
- }, it = (e, t) => {
382
+ let a = j(i, n).toUpperCase();
383
+ return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${at})` : r;
384
+ }, ct = (e, t) => {
377
385
  if (!e.generatedAs) return null;
378
386
  let { expr: n, stored: r } = e.generatedAs;
379
- if (t === "postgres") return r || j("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
387
+ if (t === "postgres") return r || A("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
380
388
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
381
389
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
382
390
  if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
383
391
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
384
- }, at = (t, n, r, i, a = !1, o = !1) => {
385
- if (n.type === "id" && n.idScheme?.kind === "numeric") return P(t, r);
386
- let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" : M(n, r), c = [_(t, r), s];
387
- n.type === "id" && !o && c.push("PRIMARY KEY");
388
- let u = it(n, r);
389
- if (u) c.push(u);
392
+ }, lt = (e, t, n, r, i = !1, a = !1) => {
393
+ if (t.type === "id" && t.idScheme?.kind === "numeric") return N(e, n);
394
+ let s = n === "mssql" ? et(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? j(t, n) : `NVARCHAR(${s})`, l = [o(e, n), c];
395
+ t.type === "id" && !a && l.push("PRIMARY KEY");
396
+ let u = ct(t, n);
397
+ if (u) l.push(u);
390
398
  else {
391
- n.nullable || c.push("NOT NULL"), n.unique && n.type !== "id" && !nt(n, r) && c.push("UNIQUE");
392
- let e = Qe(n, r);
393
- e && c.push(e);
394
- }
395
- if (n.type === "reference" && n.references && !a && !e(r)) {
396
- let e = n.references();
397
- c.push(`REFERENCES ${_(e.tableName, r)} (${_("id", r)})`);
398
- let t = F(n.onDelete ?? "restrict", r);
399
- c.push(`ON DELETE ${t}`);
400
- let i = F(n.refOnUpdate ?? "noAction", r);
401
- i !== "NO ACTION" && c.push(`ON UPDATE ${i}`);
402
- }
403
- if (n.oneOf && n.oneOf.length > 0) {
404
- let e = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
405
- c.push(`CHECK (${_(t, r)} IN (${e}))`);
406
- }
407
- if (n.checks && n.checks.length > 0) for (let e of n.checks) c.push(`CHECK (${e})`);
408
- if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" || l(r))) {
409
- let e = n.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
410
- c.push(`CHECK (${_(t, r)} IN (${e}))`);
411
- }
412
- if (n.type === "json" || n.type === "array") {
413
- let e = _(t, r);
414
- l(r) ? c.push(`CHECK (${e} IS NULL OR json_valid(${e}))`) : r === "mssql" && c.push(`CHECK (${e} IS NULL OR ISJSON(${e}) = 1)`);
415
- }
416
- return c.join(" ");
417
- }, ot = (t, n, r = null, i) => {
418
- let a = /* @__PURE__ */ new Set();
419
- for (let e of t.appliedIndexes ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
420
- for (let e of t.appliedUniques ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
421
- let o = t.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(t.fields).map(([e, t]) => ` ${at(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (t.appliedUniques ?? []).map((e) => {
422
- let r = e.fields.map((e) => rt(e, t.fields, n)).join(", ");
423
- return ` CONSTRAINT ${_(e.name, n)} UNIQUE (${r})`;
424
- }), u = (t.appliedChecks ?? []).map((e) => ` CONSTRAINT ${_(e.name, n)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${o.map((e) => rt(e, t.fields, n)).join(", ")})`] : [], f = e(n) ? Object.entries(t.fields).flatMap(([e, a]) => {
425
- if (a.type !== "reference" || !a.references || (i?.has(e) ?? !1)) return [];
426
- let o = a.references(), s = F(a.onDelete ?? "restrict", n), c = F(a.refOnUpdate ?? "noAction", n);
427
- return [` CONSTRAINT ${_(`${t.tableName}_${e}_fkey`, n)} FOREIGN KEY (${_(e, n)}) REFERENCES ${et(o.tableName, n, r)} (${_("id", n)}) ON DELETE ${s}${c === "NO ACTION" ? "" : ` ON UPDATE ${c}`}`];
399
+ t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !ot(t, n) && l.push("UNIQUE");
400
+ let e = nt(t, n);
401
+ e && l.push(e);
402
+ }
403
+ if (t.type === "reference" && t.references && !i && !b(n)) {
404
+ let e = t.references();
405
+ l.push(`REFERENCES ${o(e.tableName, n)} (${o("id", n)})`);
406
+ let r = P(t.onDelete ?? "restrict", n);
407
+ l.push(`ON DELETE ${r}`);
408
+ let i = P(t.refOnUpdate ?? "noAction", n);
409
+ i !== "NO ACTION" && l.push(`ON UPDATE ${i}`);
410
+ }
411
+ if (t.oneOf && t.oneOf.length > 0) {
412
+ let r = t.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
413
+ l.push(`CHECK (${o(e, n)} IN (${r}))`);
414
+ }
415
+ if (t.checks && t.checks.length > 0) for (let e of t.checks) l.push(`CHECK (${e})`);
416
+ if (t.type === "enum" && t.enumValues && t.enumValues.length > 0 && (n === "mssql" || m(n))) {
417
+ let r = t.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
418
+ l.push(`CHECK (${o(e, n)} IN (${r}))`);
419
+ }
420
+ if (t.type === "json" || t.type === "array") {
421
+ let t = o(e, n);
422
+ m(n) ? l.push(`CHECK (${t} IS NULL OR json_valid(${t}))`) : n === "mssql" && l.push(`CHECK (${t} IS NULL OR ISJSON(${t}) = 1)`);
423
+ }
424
+ return l.join(" ");
425
+ }, ut = (e, t, n = null, r) => {
426
+ let i = /* @__PURE__ */ new Set();
427
+ for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
428
+ for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
429
+ for (let [t, n] of Object.entries(e.fields)) n.unique && i.add(t);
430
+ let a = e.appliedPrimaryKey ?? [], s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${lt(e, n, t, i, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
431
+ let r = n.fields.map((n) => st(n, e.fields, t)).join(", ");
432
+ return ` CONSTRAINT ${o(n.name, t)} UNIQUE (${r})`;
433
+ }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${o(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${a.map((n) => st(n, e.fields, t)).join(", ")})`] : [], f = b(t) ? Object.entries(e.fields).flatMap(([i, a]) => {
434
+ if (a.type !== "reference" || !a.references || (r?.has(i) ?? !1)) return [];
435
+ let s = a.references(), c = P(a.onDelete ?? "restrict", t), l = P(a.refOnUpdate ?? "noAction", t);
436
+ return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${it(s.tableName, t, n)} (${o("id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
428
437
  }) : [], p = [
429
438
  ...d,
430
439
  ...l,
431
440
  ...u,
432
441
  ...f
433
- ], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = et(t.tableName, n, r);
434
- if (n === "mssql") {
435
- let e = r === null ? t.tableName : `${r}.${t.tableName}`, n = `CREATE TABLE ${h} (\n${m}\n)`;
436
- return `IF OBJECT_ID('${e.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
442
+ ], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = it(e.tableName, t, n);
443
+ if (t === "mssql") {
444
+ let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${h} (\n${m}\n)`;
445
+ return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
437
446
  }
438
447
  return [
439
448
  `CREATE TABLE IF NOT EXISTS ${h} (`,
440
449
  m,
441
450
  ");"
442
451
  ].join("\n");
443
- }, st = (e, t, n) => {
444
- let r = `${e}_${t.name}_fts`, i = (e) => _(e, n), a = t.columns.map(i).join(", "), o = t.columns.map((e) => `new.${i(e)}`).join(", "), s = [];
445
- return s.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${i(r)} USING fts5(${a}, row_id UNINDEXED, tokenize='porter');`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ai`)} AFTER INSERT ON ${i(e)} BEGIN\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${o}, new.${i("id")});\nEND;`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ad`)} AFTER DELETE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\nEND;`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_au`)} AFTER UPDATE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${o}, new.${i("id")});\nEND;`), s;
446
- }, ct = (e, t, n = null) => {
447
- let r = [], i = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, n, r, i) => {
448
- let o = {
452
+ }, dt = (e, t, n) => {
453
+ let r = `${e}_${t.name}_fts`, i = (e) => o(e, n), a = t.columns.map(i).join(", "), s = t.columns.map((e) => `new.${i(e)}`).join(", "), c = [];
454
+ return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${i(r)} USING fts5(${a}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ai`)} AFTER INSERT ON ${i(e)} BEGIN\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${s}, new.${i("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ad`)} AFTER DELETE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_au`)} AFTER UPDATE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${s}, new.${i("id")});\nEND;`), c;
455
+ }, ft = (e, t, n = null) => {
456
+ let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i) => {
457
+ let a = {
449
458
  using: "",
450
459
  withSuffix: "",
451
460
  skip: !1
452
461
  };
453
- if (r === void 0 || r === "btree") return o;
462
+ if (r === void 0 || r === "btree") return a;
454
463
  if (r === "gist") return t === "postgres" ? {
455
464
  using: " USING GIST",
456
465
  withSuffix: "",
457
466
  skip: !1
458
- } : (j(`[voltro:migrate] index '${e}' on '${n}': ${t} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), o);
467
+ } : (A(`[voltro:migrate] index '${e}' on '${n}': ${t} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), a);
459
468
  if (r === "gin") return t === "postgres" ? {
460
469
  using: " USING GIN",
461
470
  withSuffix: "",
462
471
  skip: !1
463
- } : t === "mysql" || t === "mariadb" ? (j(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
472
+ } : t === "mysql" || t === "mariadb" ? (A(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
464
473
  using: "",
465
474
  withSuffix: "",
466
475
  skip: !0
467
- }) : (j(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), o);
476
+ }) : (A(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), a);
468
477
  if (r === "brin") return t === "postgres" ? {
469
478
  using: " USING BRIN",
470
479
  withSuffix: "",
471
480
  skip: !1
472
- } : (j(`[voltro:migrate] brin index '${e}' on '${n}': ${t} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), o);
481
+ } : (A(`[voltro:migrate] brin index '${e}' on '${n}': ${t} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
473
482
  if (r === "hnsw") {
474
483
  if (t === "postgres") {
475
- let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? a(i?.hnsw?.distance);
484
+ let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? h(i?.hnsw?.distance);
476
485
  return {
477
486
  using: " USING hnsw",
478
487
  withSuffix: ` WITH (m = ${e}, ef_construction = ${t})`,
@@ -480,73 +489,73 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
480
489
  skip: !1
481
490
  };
482
491
  }
483
- return j(`[voltro:migrate] hnsw index '${e}' on '${n}': ${t} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
492
+ return A(`[voltro:migrate] hnsw index '${e}' on '${n}': ${t} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
484
493
  using: "",
485
494
  withSuffix: "",
486
495
  skip: !0
487
496
  };
488
497
  }
489
- return o;
498
+ return a;
490
499
  }, c = (n, r) => {
491
500
  let i = n.map((n) => {
492
- if (typeof n == "string") return rt(n, e.fields, t);
501
+ if (typeof n == "string") return st(n, e.fields, t);
493
502
  if ("jsonPath" in n) {
494
503
  let { column: e, path: r, numeric: i } = n.jsonPath;
495
- return `(${d(e, r, t, { numeric: i })})`;
504
+ return `(${ee(e, r, t, { numeric: i })})`;
496
505
  }
497
506
  return `(${n.expr})`;
498
507
  });
499
508
  return r !== void 0 && i.length === 1 ? `${i[0]} ${r}` : i.join(", ");
500
- }, l = (e, r, i, a, o, l = "", u = !1) => {
501
- let d = s(e, r, a, o);
502
- if (d.skip) return "";
503
- let f = c(i, d.opclass), p = `${d.withSuffix}${l}`, m = et(r, t, n), h = u ? "UNIQUE " : "";
504
- return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${h}INDEX ${_(e, t)} ON ${m}${d.using} (${f})${p};` : t === "mysql" ? `CREATE ${h}INDEX ${_(e, t)} ON ${m}${d.using} (${f})${p};` : `CREATE ${h}INDEX IF NOT EXISTS ${_(e, t)} ON ${m}${d.using} (${f})${p};`;
509
+ }, l = (e, r, i, a, l, u = "", d = !1) => {
510
+ let f = s(e, r, a, l);
511
+ if (f.skip) return "";
512
+ let p = c(i, f.opclass), m = `${f.withSuffix}${u}`, h = it(r, t, n), g = d ? "UNIQUE " : "";
513
+ return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${o(e, t)} ON ${h}${f.using} (${p})${m};` : t === "mysql" ? `CREATE ${g}INDEX ${o(e, t)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${o(e, t)} ON ${h}${f.using} (${p})${m};`;
505
514
  };
506
515
  if (t === "mysql" || t === "mariadb") for (let [n, i] of Object.entries(e.fields)) {
507
- if (!i.unique || i.type === "id" || !nt(i, t)) continue;
516
+ if (!i.unique || i.type === "id" || !ot(i, t)) continue;
508
517
  let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
509
518
  a && r.push(a);
510
519
  }
511
520
  for (let n of e.appliedFullText ?? []) if (t === "postgres") {
512
- let i = n.config ?? "english", a = `${n.name}_tsv`, o = n.columns.map((e) => {
521
+ let i = n.config ?? "english", a = `${n.name}_tsv`, s = n.columns.map((e) => {
513
522
  let r = n.weights?.[e] ?? "A";
514
- return `setweight(to_tsvector('${i}', coalesce(${_(e, t)}, '')), '${r}')`;
523
+ return `setweight(to_tsvector('${i}', coalesce(${o(e, t)}, '')), '${r}')`;
515
524
  }).join(" || ");
516
- r.push(`ALTER TABLE ${_(e.tableName, t)} ADD COLUMN IF NOT EXISTS ${_(a, t)} tsvector GENERATED ALWAYS AS (${o}) STORED;`), r.push(`CREATE INDEX IF NOT EXISTS ${_(n.name, t)} ON ${_(e.tableName, t)} USING GIN (${_(a, t)});`);
525
+ r.push(`ALTER TABLE ${o(e.tableName, t)} ADD COLUMN IF NOT EXISTS ${o(a, t)} tsvector GENERATED ALWAYS AS (${s}) STORED;`), r.push(`CREATE INDEX IF NOT EXISTS ${o(n.name, t)} ON ${o(e.tableName, t)} USING GIN (${o(a, t)});`);
517
526
  } else if (t === "mysql" || t === "mariadb") {
518
- let i = n.columns.map((e) => _(e, t)).join(", ");
519
- r.push(`CREATE FULLTEXT INDEX ${_(n.name, t)} ON ${_(e.tableName, t)} (${i});`);
527
+ let i = n.columns.map((e) => o(e, t)).join(", ");
528
+ r.push(`CREATE FULLTEXT INDEX ${o(n.name, t)} ON ${o(e.tableName, t)} (${i});`);
520
529
  } else if (t === "turso") throw Error(`@voltro/sql-turso: full-text index '${n.name}' on '${e.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
521
- else t === "sqlite" ? r.push(...st(e.tableName, n, t)) : j(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
530
+ else t === "sqlite" ? r.push(...dt(e.tableName, n, t)) : A(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
522
531
  for (let n of e.appliedIndexes) {
523
532
  if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
524
- j(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
533
+ A(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
525
534
  continue;
526
535
  }
527
536
  if (n.unique && n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${n.name}' on '${e.tableName}' cannot be expressed on ${t} — it has no partial (WHERE) index support, and a full UNIQUE index would forbid re-creating a soft-deleted row. Use a generated STORED column (text().generatedAs("CASE WHEN \`deletedAt\` IS NULL THEN <key> ELSE NULL END", { stored: true })) + .unique([...]) on ${t}, or move this table to postgres/sqlite/mssql.`);
528
- let a = "";
529
- n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? j(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : a = ` WHERE ${n.where}`);
530
- let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, a, n.unique === !0);
531
- s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && i.add(o(n.fields));
537
+ let o = "";
538
+ n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? A(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : o = ` WHERE ${n.where}`);
539
+ let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, o, n.unique === !0);
540
+ s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && i.add(a(n.fields));
532
541
  }
533
542
  for (let [t, n] of Object.entries(e.fields)) {
534
- if (n.type !== "reference" || n.fkAutoIndex === !1 || i.has(o([t]))) continue;
535
- let a = `${e.tableName}_${t}_idx`;
536
- r.push(l(a, e.tableName, [t])), i.add(o([t]));
543
+ if (n.type !== "reference" || n.fkAutoIndex === !1 || i.has(a([t]))) continue;
544
+ let o = `${e.tableName}_${t}_idx`;
545
+ r.push(l(o, e.tableName, [t])), i.add(a([t]));
537
546
  }
538
547
  return r.join("\n");
539
- }, lt = (e, t, n = A) => {
548
+ }, pt = (e, t, n = k) => {
540
549
  if (t !== "postgres") return [];
541
550
  let r = e.filter((e) => e.isReactive !== !1);
542
- return r.length === 0 ? [] : [ut(n), ...r.map((e) => ft(e, n))];
543
- }, ut = (e) => `
544
- CREATE OR REPLACE FUNCTION ${Ye(e)}() RETURNS trigger AS $$
551
+ return r.length === 0 ? [] : [mt(n), ...r.map((e) => gt(e, n))];
552
+ }, mt = (e) => `
553
+ CREATE OR REPLACE FUNCTION ${Qe(e)}() RETURNS trigger AS $$
545
554
  DECLARE
546
555
  payload TEXT;
547
556
  pk JSONB;
548
557
  BEGIN
549
- -- ${Xe}
558
+ -- ${$e}
550
559
  payload := json_build_object(
551
560
  'table', TG_TABLE_NAME,
552
561
  -- The schema the write landed in. Under namespace isolation this is
@@ -600,22 +609,22 @@ BEGIN
600
609
  RETURN COALESCE(NEW, OLD);
601
610
  END;
602
611
  $$ LANGUAGE plpgsql;
603
- `.trim(), dt = (e, t) => {
604
- let n = Je(e.tableName, t);
612
+ `.trim(), ht = (e, t) => {
613
+ let n = Ze(e.tableName, t);
605
614
  return [
606
615
  `ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
607
616
  `DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
608
- `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Ye(t)}()`
617
+ `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Qe(t)}()`
609
618
  ];
610
- }, ft = (e, t) => dt(e, t).map((e) => `${e};`).join("\n"), pt = (e) => {
619
+ }, gt = (e, t) => ht(e, t).map((e) => `${e};`).join("\n"), _t = (e) => {
611
620
  if (e.dialect !== "postgres") return [];
612
621
  let t = e.channel ?? "framework_changes", n = new Map(e.tables.map((e) => [e.tableName, e])), r = [], i = e.missing.filter((e) => n.has(e));
613
- (i.length > 0 || e.functionOutdated === !0) && r.push(ut(t));
614
- for (let e of i) r.push(...dt(n.get(e), t));
615
- for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Je(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
622
+ (i.length > 0 || e.functionOutdated === !0) && r.push(mt(t));
623
+ for (let e of i) r.push(...ht(n.get(e), t));
624
+ for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Ze(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
616
625
  return r;
617
- }, mt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), ht = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), gt = (e) => {
618
- let t = new Map(e.map((e) => [e.tableName, e])), n = ue(e.map((e) => e.tableName), (e) => {
626
+ }, vt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), yt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), bt = (e) => {
627
+ let t = new Map(e.map((e) => [e.tableName, e])), n = pe(e.map((e) => e.tableName), (e) => {
619
628
  let n = t.get(e);
620
629
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
621
630
  if (n.type !== "reference" || !n.references) return [];
@@ -626,7 +635,7 @@ $$ LANGUAGE plpgsql;
626
635
  }] : [];
627
636
  }) : [];
628
637
  }), r = [];
629
- for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(D(t.tableName, e)) && r.push({
638
+ for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(E(t.tableName, e)) && r.push({
630
639
  table: t.tableName,
631
640
  column: e,
632
641
  targetTable: i.references().tableName,
@@ -637,7 +646,7 @@ $$ LANGUAGE plpgsql;
637
646
  if (!(i.has(e.tableName) || a.has(e.tableName))) {
638
647
  a.add(e.tableName);
639
648
  for (let [r, i] of Object.entries(e.fields)) {
640
- if (i.type !== "reference" || !i.references || n.has(D(e.tableName, r))) continue;
649
+ if (i.type !== "reference" || !i.references || n.has(E(e.tableName, r))) continue;
641
650
  let a = i.references();
642
651
  if (a.tableName === e.tableName) continue;
643
652
  let o = t.get(a.tableName);
@@ -651,30 +660,30 @@ $$ LANGUAGE plpgsql;
651
660
  sorted: o,
652
661
  cyclic: r
653
662
  };
654
- }, _t = (e, t, n = null) => {
655
- let r = (e) => n ? `${_(n, t)}.${_(e, t)}` : _(e, t), i = `${e.table}_${e.column}_fkey`, a = F(e.onDelete, t), o = F(e.onUpdate, t), s = ` ON DELETE ${a}${o === "NO ACTION" ? "" : ` ON UPDATE ${o}`}`, c = (n) => `ADD CONSTRAINT ${_(i, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${_(e.column, t)}) REFERENCES ${r(e.targetTable)} (${_("id", t)})${s}`;
663
+ }, xt = (e, t, n = null) => {
664
+ let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a = P(e.onDelete, t), s = P(e.onUpdate, t), c = ` ON DELETE ${a}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (n) => `ADD CONSTRAINT ${o(i, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${o(e.column, t)}) REFERENCES ${r(e.targetTable)} (${o("id", t)})${c}`;
656
665
  switch (t) {
657
666
  case "postgres": return [
658
667
  "DO $$ BEGIN",
659
668
  " IF NOT EXISTS (SELECT 1 FROM pg_constraint",
660
669
  ` WHERE conname = '${i}' AND conrelid = '${n ? `${n}.` : ""}${e.table}'::regclass) THEN`,
661
- ` ALTER TABLE ${r(e.table)} ${c(!1)};`,
670
+ ` ALTER TABLE ${r(e.table)} ${l(!1)};`,
662
671
  " END IF;",
663
672
  "END $$;"
664
673
  ].join("\n");
665
- case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${i}') ALTER TABLE ${r(e.table)} ${c(!1)};`;
666
- case "mariadb": return `ALTER TABLE ${r(e.table)} ${c(!0)};`;
667
- default: return `ALTER TABLE ${r(e.table)} ${c(!1)};`;
674
+ case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${i}') ALTER TABLE ${r(e.table)} ${l(!1)};`;
675
+ case "mariadb": return `ALTER TABLE ${r(e.table)} ${l(!0)};`;
676
+ default: return `ALTER TABLE ${r(e.table)} ${l(!1)};`;
668
677
  }
669
- }, vt = (e, t) => {
678
+ }, St = (e, t) => {
670
679
  let n = /* @__PURE__ */ new Map();
671
- if (l(t)) return n;
680
+ if (m(t)) return n;
672
681
  for (let t of e) {
673
682
  let e = n.get(t.table) ?? /* @__PURE__ */ new Set();
674
683
  e.add(t.column), n.set(t.table, e);
675
684
  }
676
685
  return n;
677
- }, yt = (e, t) => {
686
+ }, Ct = (e, t) => {
678
687
  if (t !== "postgres") return "";
679
688
  let n = /* @__PURE__ */ new Map();
680
689
  for (let t of e) for (let e of Object.values(t.fields)) {
@@ -690,45 +699,45 @@ $$ LANGUAGE plpgsql;
690
699
  r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
691
700
  }
692
701
  return r.join("\n\n");
693
- }, bt = (e, t) => {
702
+ }, wt = (e, t) => {
694
703
  if (t !== "postgres") return "";
695
- let n = /* @__PURE__ */ new Set();
696
- for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
697
- let r = [];
698
- for (let e of n) for (let { from: t, to: n } of b(e)) {
699
- let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
700
- r.push(`DO \$\$
704
+ let r = /* @__PURE__ */ new Set();
705
+ for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && r.add(e.enumName);
706
+ let i = [];
707
+ for (let e of r) for (let { from: t, to: r } of n(e)) {
708
+ let n = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = r.replace(/'/g, "''");
709
+ i.push(`DO \$\$
701
710
  DECLARE
702
711
  type_oid oid;
703
712
  BEGIN
704
- SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
713
+ SELECT oid INTO type_oid FROM pg_type WHERE typname = '${n}';\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', '${n}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
705
714
  }
706
- return r.join("\n\n");
707
- }, xt = (e) => {
715
+ return i.join("\n\n");
716
+ }, Tt = (e) => {
708
717
  let t = [], n = [];
709
- for (let r of e) u(r) ? n.push(r) : t.push(r);
718
+ for (let r of e) s(r) ? n.push(r) : t.push(r);
710
719
  return {
711
720
  tables: t,
712
721
  views: n
713
722
  };
714
- }, St = (e, t, n = A) => {
715
- let { tables: r, views: i } = xt(e), { sorted: a, cyclic: o } = gt(r.map((e) => le(e, t))), s = vt(o, t), c = [];
716
- t === "postgres" && mt(a) && c.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && ht(a) && c.push("CREATE EXTENSION IF NOT EXISTS postgis;");
717
- let u = bt(a, t);
718
- u && c.push(u);
719
- let d = yt(a, t);
720
- d && c.push(d);
721
- for (let e of a) c.push(ot(e, t, null, s.get(e.tableName)));
722
- if (!l(t)) for (let e of o) c.push(_t(e, t));
723
- for (let e of a) {
724
- let n = ct(e, t);
725
- n && c.push(n);
726
- }
727
- c.push(...lt(a, t, n));
728
- for (let e of i) c.push(x(e, t));
729
- return c.join("\n\n") + "\n";
730
- }, Ct = (e, t, n) => {
731
- let r = _(e, t);
723
+ }, Et = (t, n, r = k) => {
724
+ let { tables: i, views: a } = Tt(t), { sorted: o, cyclic: s } = bt(i.map((e) => fe(e, n))), c = St(s, n), l = [];
725
+ n === "postgres" && vt(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && yt(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
726
+ let u = wt(o, n);
727
+ u && l.push(u);
728
+ let d = Ct(o, n);
729
+ d && l.push(d);
730
+ for (let e of o) l.push(ut(e, n, null, c.get(e.tableName)));
731
+ if (!m(n)) for (let e of s) l.push(xt(e, n));
732
+ for (let e of o) {
733
+ let t = ft(e, n);
734
+ t && l.push(t);
735
+ }
736
+ l.push(...pt(o, n, r));
737
+ for (let t of a) l.push(e(t, n));
738
+ return l.join("\n\n") + "\n";
739
+ }, Dt = (e, t, n) => {
740
+ let r = o(e, t);
732
741
  switch (t) {
733
742
  case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
734
743
  case "mysql":
@@ -737,62 +746,62 @@ BEGIN
737
746
  case "turso":
738
747
  case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
739
748
  }
740
- }, wt = (e, t, n, r) => {
741
- let i = Ct(n, t, r), a = _(n, t);
742
- if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${St(e, t)}`;
743
- if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${St(e, t)}`;
744
- let { sorted: o, cyclic: s } = gt(e), c = vt(s, t), u = [i];
745
- for (let e of o) u.push(ot(e, t, n, c.get(e.tableName)));
746
- if (!l(t)) for (let e of s) u.push(_t(e, t, n));
747
- for (let e of o) {
748
- let r = ct(e, t, n);
749
+ }, Ot = (e, t, n, r) => {
750
+ let i = Dt(n, t, r), a = o(n, t);
751
+ if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${Et(e, t)}`;
752
+ if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${Et(e, t)}`;
753
+ let { sorted: s, cyclic: c } = bt(e), l = St(c, t), u = [i];
754
+ for (let e of s) u.push(ut(e, t, n, l.get(e.tableName)));
755
+ if (!m(t)) for (let e of c) u.push(xt(e, t, n));
756
+ for (let e of s) {
757
+ let r = ft(e, t, n);
749
758
  r && u.push(r);
750
759
  }
751
760
  return u.join("\n\n") + "\n";
752
- }, Tt = (e, t, n = A) => {
753
- let { sorted: r, cyclic: i } = gt(e), a = vt(i, t), o = [], s = bt(r, t);
761
+ }, kt = (e, t, n = k) => {
762
+ let { sorted: r, cyclic: i } = bt(e), a = St(i, t), o = [], s = wt(r, t);
754
763
  s && o.push(s);
755
- let c = yt(r, t);
764
+ let c = Ct(r, t);
756
765
  c && o.push(c);
757
- for (let e of r) o.push(ot(e, t, null, a.get(e.tableName)));
758
- for (let e of i) o.push(_t(e, t));
759
- return o.push(...lt(r, t, n)), o.join("\n\n") + "\n";
760
- }, Et = (e, t = "postgres", n = A, r = {}) => S.gen(function* () {
761
- let i = yield* E.SqlClient;
762
- yield* Me(i, Nt(i, St(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
763
- }), Dt = (e, t) => {
766
+ for (let e of r) o.push(ut(e, t, null, a.get(e.tableName)));
767
+ for (let e of i) o.push(xt(e, t));
768
+ return o.push(...pt(r, t, n)), o.join("\n\n") + "\n";
769
+ }, At = (e, t = "postgres", n = k, r = {}) => C.gen(function* () {
770
+ let i = yield* T.SqlClient;
771
+ yield* Fe(i, Lt(i, Et(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(C.orDie);
772
+ }), jt = (e, t) => {
764
773
  let n = t.cause ?? {};
765
774
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
766
- }, Ot = (e, t) => {
775
+ }, Mt = (e, t) => {
767
776
  let n = e.trimStart();
768
777
  return !!(/\bIF NOT EXISTS\b/i.test(n) || /^CREATE OR REPLACE\b/i.test(n) || /^DROP\s[\s\S]*?\bIF EXISTS\b/i.test(n) || /^SET search_path\b/i.test(n) || /^USE[\s`"[]/i.test(n) || /^IF\s/i.test(n) || (t === "mysql" || t === "mariadb") && /^CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(n));
769
- }, kt = () => {
778
+ }, Nt = () => {
770
779
  let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
771
780
  return Number.isInteger(e) && e >= 0 ? e : 4;
772
- }, At = (e) => ({
781
+ }, Pt = (e) => ({
773
782
  while: e,
774
- times: kt(),
775
- schedule: C.jittered(C.exponential("50 millis"))
776
- }), jt = class {
783
+ times: Nt(),
784
+ schedule: w.jittered(w.exponential("50 millis"))
785
+ }), Ft = class {
777
786
  statement;
778
787
  error;
779
788
  _tag = "DdlStatementFailed";
780
789
  constructor(e, t) {
781
790
  this.statement = e, this.error = t;
782
791
  }
783
- }, Mt = (e, t, n) => S.gen(function* () {
784
- let r = yield* E.SqlClient, i = n !== void 0 && Fe(t) === "per-operation";
785
- for (let a of Pt(e)) {
786
- process.env.VOLTRO_MIGRATE_DEBUG === "1" && Ze.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
787
- let e = r.unsafe(a).pipe(S.catchIf((e) => Dt(a, e), () => S.succeed([])), S.tapError((e) => S.sync(() => {
788
- Ze.error(re("migrate: statement failed", a, e, 200));
792
+ }, It = (e, t, n) => C.gen(function* () {
793
+ let r = yield* T.SqlClient, i = n !== void 0 && Re(t) === "per-operation";
794
+ for (let a of Rt(e)) {
795
+ process.env.VOLTRO_MIGRATE_DEBUG === "1" && tt.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
796
+ let e = r.unsafe(a).pipe(C.catchIf((e) => jt(a, e), () => C.succeed([])), C.tapError((e) => C.sync(() => {
797
+ tt.error(oe("migrate: statement failed", a, e, 200));
789
798
  })));
790
- yield* (i && n !== void 0 && Ot(a, t) ? e.pipe(S.retry(At((e) => n(e) === "retry"))) : e).pipe(S.mapError((e) => new jt(a, e)));
799
+ yield* (i && n !== void 0 && Mt(a, t) ? e.pipe(C.retry(Pt((e) => n(e) === "retry"))) : e).pipe(C.mapError((e) => new Ft(a, e)));
791
800
  }
792
- }), Nt = (e, t, n, r) => {
793
- let i = n === "turso" ? Mt(t, n, r) : e.withTransaction(Mt(t, n, r)), a = (e) => e instanceof jt ? e.error : e;
794
- return (r !== void 0 && Fe(n) === "plan-transactional" ? i.pipe(S.retry(At((e) => r(a(e)) === "retry"))) : i).pipe(S.orDieWith((e) => e instanceof jt ? Error(re("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
795
- }, Pt = (e) => {
801
+ }), Lt = (e, t, n, r) => {
802
+ let i = n === "turso" ? It(t, n, r) : e.withTransaction(It(t, n, r)), a = (e) => e instanceof Ft ? e.error : e;
803
+ return (r !== void 0 && Re(n) === "plan-transactional" ? i.pipe(C.retry(Pt((e) => r(a(e)) === "retry"))) : i).pipe(C.orDieWith((e) => e instanceof Ft ? Error(oe("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
804
+ }, Rt = (e) => {
796
805
  let t = [], n = "", r = !1;
797
806
  for (let i = 0; i < e.length; i++) {
798
807
  if (e.slice(i, i + 2) === "$$") {
@@ -807,43 +816,43 @@ BEGIN
807
816
  }
808
817
  let i = n.trim();
809
818
  return i.length > 0 && t.push(i), t;
810
- }, Ft = async (e, t, n = "postgres", r = {}) => {
811
- await S.runPromise(Et(e, n, void 0, r).pipe(S.provide(t)));
812
- }, It = (e, t, n = "postgres", r = {}) => S.gen(function* () {
813
- let i = wt(e, n, t), a = yield* E.SqlClient;
814
- yield* Me(a, Nt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
815
- }), Lt = async (e, t, n, r = "postgres", i = {}) => {
816
- await S.runPromise(It(e, t, r, i).pipe(S.provide(n))), await s({
819
+ }, zt = async (e, t, n = "postgres", r = {}) => {
820
+ await C.runPromise(At(e, n, void 0, r).pipe(C.provide(t)));
821
+ }, Bt = (e, t, n = "postgres", r = {}) => C.gen(function* () {
822
+ let i = Ot(e, n, t), a = yield* T.SqlClient;
823
+ yield* Fe(a, Lt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(C.orDie);
824
+ }), Vt = async (e, t, n, r = "postgres", i = {}) => {
825
+ await C.runPromise(Bt(e, t, r, i).pipe(C.provide(n))), await f({
817
826
  namespace: t,
818
827
  dialect: r
819
828
  });
820
- }, Rt = async (e, t, n = "postgres", r = {}) => {
821
- await S.runPromise(S.gen(function* () {
822
- let t = Tt(e, n), i = yield* E.SqlClient;
823
- yield* Me(i, Nt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
824
- }).pipe(S.provide(t)));
825
- }, zt = (e) => {
829
+ }, Ht = async (e, t, n = "postgres", r = {}) => {
830
+ await C.runPromise(C.gen(function* () {
831
+ let t = kt(e, n), i = yield* T.SqlClient;
832
+ yield* Fe(i, Lt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(C.orDie);
833
+ }).pipe(C.provide(t)));
834
+ }, Ut = (e) => {
826
835
  if (e == null) return e;
827
- if (Array.isArray(e)) return e.map(zt);
836
+ if (Array.isArray(e)) return e.map(Ut);
828
837
  if (typeof e != "object") return e;
829
838
  let t = {};
830
839
  for (let n of Object.keys(e).sort()) {
831
840
  let r = e[n];
832
- r !== void 0 && (t[n] = zt(r));
841
+ r !== void 0 && (t[n] = Ut(r));
833
842
  }
834
843
  return t;
835
- }, Bt = (e) => {
844
+ }, Wt = (e) => {
836
845
  if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs) return e;
837
846
  let { idScheme: t, sensitive: n, safe: r, generatedAs: i, ...a } = e;
838
847
  return a;
839
- }, Vt = (e) => [...e].map(Bt).sort((e, t) => e.name.localeCompare(t.name)), Ht = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), Ut = (e) => [...e].map((e) => ({
848
+ }, Gt = (e) => [...e].map(Wt).sort((e, t) => e.name.localeCompare(t.name)), Kt = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), qt = (e) => [...e].map((e) => ({
840
849
  name: e.name,
841
- columns: Vt(e.columns),
842
- indexes: Ht(e.indexes)
843
- })).sort((e, t) => e.name.localeCompare(t.name)), Wt = (e) => {
844
- let t = { tables: Ut(e.tables) }, n = JSON.stringify(zt(t));
845
- return w("sha256").update(n).digest("hex");
846
- }, Gt = (e) => e.slice(0, 16), Kt = (e, t) => {
850
+ columns: Gt(e.columns),
851
+ indexes: Kt(e.indexes)
852
+ })).sort((e, t) => e.name.localeCompare(t.name)), Jt = (e) => {
853
+ let t = { tables: qt(e.tables) }, n = JSON.stringify(Ut(t));
854
+ return te("sha256").update(n).digest("hex");
855
+ }, Yt = (e) => e.slice(0, 16), Xt = (e, t) => {
847
856
  let n = t.references ? {
848
857
  table: t.references().tableName,
849
858
  column: "id",
@@ -882,59 +891,59 @@ BEGIN
882
891
  ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
883
892
  ...t.spatial === void 0 ? {} : { spatial: t.spatial }
884
893
  };
885
- }, qt = (e) => {
886
- let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
894
+ }, Zt = (e) => {
895
+ let t = [], n = /* @__PURE__ */ new Set(), i = (e) => {
887
896
  n.has(e.name) || (n.add(e.name), t.push(e));
888
- }, i = e.appliedPrimaryKey ?? [];
889
- i.length > 0 ? r({
897
+ }, a = e.appliedPrimaryKey ?? [];
898
+ a.length > 0 ? i({
890
899
  name: `${e.tableName}_pkey`,
891
900
  table: e.tableName,
892
- columns: [...i],
901
+ columns: [...a],
893
902
  unique: !0
894
- }) : e.fields.id && r({
903
+ }) : e.fields.id && i({
895
904
  name: `${e.tableName}_pkey`,
896
905
  table: e.tableName,
897
906
  columns: ["id"],
898
907
  unique: !0
899
908
  });
900
- let a = e.appliedIndexes ?? [];
901
- for (let t of a) {
909
+ let o = e.appliedIndexes ?? [];
910
+ for (let t of o) {
902
911
  if (t.unique && t.where) continue;
903
- let n = t.fields.map((e) => typeof e == "string" ? e : "jsonPath" in e ? `(json:${e.jsonPath.column}->${e.jsonPath.path.join(".")}${e.jsonPath.numeric ? "::num" : ""})` : `(${e.expr})`), i = t.fields.some((e) => typeof e != "string");
904
- r({
912
+ let n = t.fields.map((e) => typeof e == "string" ? e : "jsonPath" in e ? `(json:${e.jsonPath.column}->${e.jsonPath.path.join(".")}${e.jsonPath.numeric ? "::num" : ""})` : `(${e.expr})`), r = t.fields.some((e) => typeof e != "string");
913
+ i({
905
914
  name: t.name,
906
915
  table: e.tableName,
907
916
  columns: n,
908
917
  unique: !1,
909
- ...i ? { expression: !0 } : {}
918
+ ...r ? { expression: !0 } : {}
910
919
  });
911
920
  }
912
- let o = e.appliedUniques ?? [];
913
- for (let t of o) t.fields.length < 2 || r({
921
+ let s = e.appliedUniques ?? [];
922
+ for (let t of s) t.fields.length < 2 || i({
914
923
  name: t.name,
915
924
  table: e.tableName,
916
925
  columns: t.fields,
917
926
  unique: !0
918
927
  });
919
- let s = /* @__PURE__ */ new Set();
920
- for (let e of a) e.fields.every((e) => typeof e == "string") && s.add(e.fields.join("\0"));
928
+ let c = /* @__PURE__ */ new Set();
929
+ for (let e of o) e.fields.every((e) => typeof e == "string") && c.add(e.fields.join("\0"));
921
930
  for (let [t, n] of Object.entries(e.fields)) {
922
- let i = n;
923
- if (i.dropped || !i.references || i.fkAutoIndex === !1 || s.has(t)) continue;
924
- let a = `${e.tableName}_${t}_idx`;
925
- y(e.tableName, a, !0, [t]), r({
926
- name: a,
931
+ let a = n;
932
+ if (a.dropped || !a.references || a.fkAutoIndex === !1 || c.has(t)) continue;
933
+ let o = `${e.tableName}_${t}_idx`;
934
+ r(e.tableName, o, !0, [t]), i({
935
+ name: o,
927
936
  table: e.tableName,
928
937
  columns: [t],
929
938
  unique: !1
930
939
  });
931
940
  }
932
941
  return t;
933
- }, Jt = (e) => {
942
+ }, Qt = (e) => {
934
943
  let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
935
944
  for (let [r, i] of Object.entries(e.fields)) {
936
945
  if (i.dropped) continue;
937
- let e = Kt(r, i);
946
+ let e = Xt(r, i);
938
947
  n.push(t.has(r) ? {
939
948
  ...e,
940
949
  unique: !0
@@ -944,27 +953,27 @@ BEGIN
944
953
  return {
945
954
  name: e.tableName,
946
955
  columns: n,
947
- indexes: qt(e),
956
+ indexes: Zt(e),
948
957
  ...r.length > 0 ? { primaryKey: [...r] } : {},
949
958
  ...i === void 0 ? {} : { renamedFrom: i }
950
959
  };
951
- }, Yt = (e) => {
960
+ }, $t = (e) => {
952
961
  let t = /* @__PURE__ */ new Map();
953
962
  for (let n of e) for (let e of n.indexes) {
954
963
  let r = t.get(e.name);
955
964
  if (r !== void 0 && r !== n.name) throw Error(`duplicate index name '${e.name}' across tables '${r}' and '${n.name}'. Index names must be unique per SCHEMA, not just per table — the DB creates only one, so the other never applies and 'db plan' re-emits it forever. Give each an explicit, table-prefixed name (e.g. '${n.name}_${e.name}').`);
956
965
  t.set(e.name, n.name);
957
966
  }
958
- }, I = (e, t) => {
959
- let n = e.filter((e) => !i(e.tableName)).map((e) => Jt(le(e, t)));
960
- return Yt(n), { tables: n };
961
- }, Xt = (e, t, n = A) => S.gen(function* () {
967
+ }, F = (e, t) => {
968
+ let n = e.filter((e) => !c(e.tableName)).map((e) => Qt(fe(e, t)));
969
+ return $t(n), { tables: n };
970
+ }, en = (e, t, n = k) => C.gen(function* () {
962
971
  let r = (yield* e`
963
972
  SELECT p.prosrc
964
973
  FROM pg_proc p
965
974
  JOIN pg_namespace n ON n.oid = p.pronamespace
966
975
  WHERE n.nspname = current_schema()
967
- AND p.proname = ${Ye(n)}
976
+ AND p.proname = ${Qe(n)}
968
977
  `)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
969
978
  if (a.length === 0) return {
970
979
  missing: [],
@@ -978,10 +987,10 @@ BEGIN
978
987
  JOIN pg_namespace n ON n.oid = c.relnamespace
979
988
  WHERE NOT t.tgisinternal
980
989
  AND n.nspname = current_schema()
981
- AND t.tgname LIKE ${`${qe}%`}
990
+ AND t.tgname LIKE ${`${Xe}%`}
982
991
  `, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
983
992
  for (let e of a) {
984
- let t = s.has(Je(e.tableName, n)), r = e.isReactive !== !1;
993
+ let t = s.has(Ze(e.tableName, n)), r = e.isReactive !== !1;
985
994
  r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
986
995
  }
987
996
  return {
@@ -989,7 +998,7 @@ BEGIN
989
998
  stale: l.sort(),
990
999
  functionOutdated: i
991
1000
  };
992
- }), Zt = (e) => {
1001
+ }), tn = (e) => {
993
1002
  let t = [];
994
1003
  if (e.missing.length > 0) {
995
1004
  let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
@@ -1000,19 +1009,19 @@ BEGIN
1000
1009
  t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
1001
1010
  }
1002
1011
  return e.functionOutdated && t.push("The change-notify function in this database is OLDER than the framework installed here. Its triggers fire, so nothing looks wrong — but a row too large for a NOTIFY payload (postgres caps it at 8000 bytes) is emitted without its primary key, and a change that carries no key cannot be re-read: it reaches subscriptions as a re-query and reaches every TAP — search index, analytics mirror, cdc-out, row history — as nothing at all. Run `voltro db apply` to replace it."), t.length > 0 ? t.join("\n") : void 0;
1003
- }, Qt = {
1012
+ }, nn = {
1004
1013
  postgres: !0,
1005
1014
  mysql: !0,
1006
1015
  mariadb: !0,
1007
1016
  mssql: !0,
1008
1017
  sqlite: !0
1009
- }, $t = {
1018
+ }, rn = {
1010
1019
  postgres: !0,
1011
1020
  mysql: !1,
1012
1021
  mariadb: !1,
1013
1022
  mssql: !0,
1014
1023
  sqlite: !0
1015
- }, en = (e) => {
1024
+ }, an = (e) => {
1016
1025
  switch (e) {
1017
1026
  case "add-column":
1018
1027
  case "drop-column":
@@ -1022,47 +1031,47 @@ BEGIN
1022
1031
  case "add-foreign-key":
1023
1032
  case "add-unique":
1024
1033
  case "add-unique-composite":
1025
- case "add-check": return $t;
1026
- default: return Qt;
1034
+ case "add-check": return rn;
1035
+ default: return nn;
1027
1036
  }
1028
- }, tn = (e, t) => {
1037
+ }, on = (e, t) => {
1029
1038
  let n = new Map(t.tables.map((e) => [e.name, e]));
1030
1039
  return new Map(e.map((e) => [e.tableName, {
1031
1040
  table: e,
1032
1041
  snapshot: n.get(e.tableName),
1033
1042
  columnDefs: e.fields
1034
1043
  }]));
1035
- }, L = (e) => {
1044
+ }, I = (e) => {
1036
1045
  if (typeof e != "object" || !e) return JSON.stringify(e);
1037
- if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
1046
+ if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
1038
1047
  let t = e;
1039
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
1040
- }, nn = (e) => {
1048
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
1049
+ }, sn = (e) => {
1041
1050
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
1042
1051
  let t = e.defaultValue;
1043
1052
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
1044
1053
  if (typeof t == "number") return String(t);
1045
- if (typeof t != "string") return L(t);
1054
+ if (typeof t != "string") return I(t);
1046
1055
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
1047
1056
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
1048
1057
  let i = n.replace(/::[a-zA-Z0-9_ "]+$/, "").trim(), a = /^'(.*)'$/.test(i) ? i.slice(1, -1).replace(/''/g, "'") : i, o = /^cast\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+as\s+json\s*\)$/i.exec(a);
1049
1058
  if (o) try {
1050
- return L(JSON.parse(o[1]));
1059
+ return I(JSON.parse(o[1]));
1051
1060
  } catch {}
1052
1061
  let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
1053
1062
  if (s) try {
1054
- return L(JSON.parse(s[1]));
1063
+ return I(JSON.parse(s[1]));
1055
1064
  } catch {}
1056
1065
  if (a.startsWith("{") || a.startsWith("[")) try {
1057
- return L(JSON.parse(a));
1066
+ return I(JSON.parse(a));
1058
1067
  } catch {}
1059
1068
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
1060
- }, rn = (e, t) => {
1061
- let n = nn(e), r = nn(t);
1069
+ }, cn = (e, t) => {
1070
+ let n = sn(e), r = sn(t);
1062
1071
  if (n === r) return !0;
1063
1072
  let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
1064
1073
  return i(n) === i(r);
1065
- }, an = (e) => {
1074
+ }, ln = (e) => {
1066
1075
  if (!e) return null;
1067
1076
  let t = (e) => e === "restrict" ? "noAction" : e;
1068
1077
  return {
@@ -1071,33 +1080,37 @@ BEGIN
1071
1080
  onDelete: t(e.onDelete),
1072
1081
  onUpdate: t(e.onUpdate)
1073
1082
  };
1074
- }, on = (e, t) => {
1083
+ }, un = (e, t) => {
1075
1084
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
1076
1085
  if (!n && !r) return !0;
1077
1086
  if (!n || !r || n.length !== r.length) return !1;
1078
1087
  let i = [...n].sort(), a = [...r].sort();
1079
1088
  return i.every((e, t) => e === a[t]);
1080
- }, sn = (e, t) => {
1089
+ }, dn = (e, t, n) => {
1090
+ if (t === "mssql") {
1091
+ let t = et(e, n);
1092
+ if (t !== void 0) return t;
1093
+ }
1081
1094
  try {
1082
- let n = /\((\d+)\)/.exec(M(e, t));
1095
+ let n = /\((\d+)\)/.exec(j(e, t));
1083
1096
  return n ? Number(n[1]) : void 0;
1084
1097
  } catch {
1085
1098
  return;
1086
1099
  }
1087
- }, cn = (e, t, n) => n === void 0 || l(n) ? !0 : e.type !== "text" || t.type !== "text" || sn(e, n) === t.maxLength, ln = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && rn(e, t) && cn(e, t, n) && JSON.stringify(an(e.references)) === JSON.stringify(an(t.references)) && on(e.oneOf, t.oneOf), un = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
1100
+ }, fn = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || dn(e, n, r) === t.maxLength, pn = (e, t, n, r) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && cn(e, t) && fn(e, t, n, r) && JSON.stringify(ln(e.references)) === JSON.stringify(ln(t.references)) && un(e.oneOf, t.oneOf), mn = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
1088
1101
  kind: "add-check",
1089
1102
  table: e,
1090
1103
  column: t.name,
1091
1104
  values: t.oneOf
1092
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, dn = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), fn = (e, t, n) => {
1093
- let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
1105
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, hn = (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])), gn = (e, t, n) => {
1106
+ let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [], c = new Set(e.indexes.flatMap((e) => e.columns));
1094
1107
  for (let t of e.columns) {
1095
1108
  let e = r.get(t.name);
1096
1109
  if (!e) {
1097
1110
  a.push(t);
1098
1111
  continue;
1099
1112
  }
1100
- ln(t, e, n) || s.push({
1113
+ pn(t, e, n, c.has(t.name) || t.unique) || s.push({
1101
1114
  declared: t,
1102
1115
  live: e
1103
1116
  });
@@ -1108,47 +1121,47 @@ BEGIN
1108
1121
  removed: o,
1109
1122
  changed: s
1110
1123
  };
1111
- }, pn = (e, t) => {
1112
- let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
1124
+ }, _n = (e, t, n) => {
1125
+ let r = (e) => n === "turso" || n === "sqlite" ? e.toLowerCase() : e, i = new Map(t.indexes.map((e) => [r(e.name), e])), a = new Map(e.indexes.map((e) => [r(e.name), e])), o = [], s = [];
1113
1126
  for (let t of e.indexes) {
1114
- let e = n.get(t.name);
1115
- (!e || !dn(t, e)) && i.push(t);
1127
+ let e = i.get(r(t.name));
1128
+ (!e || !hn(t, e)) && o.push(t);
1116
1129
  }
1117
- for (let e of t.indexes) r.has(e.name) || a.push(e);
1130
+ for (let e of t.indexes) a.has(r(e.name)) || s.push(e);
1118
1131
  return {
1119
- added: i,
1120
- removed: a
1132
+ added: o,
1133
+ removed: s
1121
1134
  };
1122
- }, R = (e, t, n, r) => ({
1135
+ }, L = (e, t, n, r) => ({
1123
1136
  op: e,
1124
1137
  classification: t,
1125
- atomicByDialect: en(e.kind),
1138
+ atomicByDialect: an(e.kind),
1126
1139
  ...n ? { reason: n } : {},
1127
1140
  ...r ? { blocked: r } : {}
1128
- }), mn = (e, t, n) => {
1141
+ }), vn = (e, t, n) => {
1129
1142
  let r = {
1130
1143
  kind: "add-column",
1131
1144
  table: e,
1132
1145
  column: t
1133
1146
  };
1134
- 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` });
1135
- }, hn = (e, t, n) => {
1147
+ return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
1148
+ }, yn = (e, t, n) => {
1136
1149
  let r = {
1137
1150
  kind: "drop-column",
1138
1151
  table: e,
1139
1152
  column: t.name
1140
1153
  };
1141
- 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` });
1142
- }, gn = (e, t, n, r, i) => R({
1154
+ return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1155
+ }, bn = (e, t, n, r, i) => L({
1143
1156
  kind: "create-table",
1144
1157
  table: e,
1145
1158
  columns: t,
1146
1159
  indexes: n,
1147
1160
  ...r && r.length > 0 ? { primaryKey: r } : {}
1148
- }, "safe", i ?? "new table — no data to preserve"), _n = (e) => R({
1161
+ }, "safe", i ?? "new table — no data to preserve"), xn = (e) => L({
1149
1162
  kind: "drop-table",
1150
1163
  table: e
1151
- }, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }), vn = 5e4, yn = (e, t, n, r) => {
1164
+ }, "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" }), Sn = 5e4, Cn = (e, t, n, r) => {
1152
1165
  let i = (n ?? 0) >= r, a;
1153
1166
  return a = t.unique ? t.columns.length === 1 ? {
1154
1167
  kind: "add-unique",
@@ -1163,16 +1176,16 @@ BEGIN
1163
1176
  kind: "add-index",
1164
1177
  table: e,
1165
1178
  index: t
1166
- }, 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");
1167
- }, bn = (e, t) => t.unique && t.columns.length > 1 ? R({
1179
+ }, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
1180
+ }, wn = (e, t) => t.unique && t.columns.length > 1 ? L({
1168
1181
  kind: "drop-unique-composite",
1169
1182
  table: e,
1170
1183
  name: t.name
1171
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : R({
1184
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
1172
1185
  kind: "drop-index",
1173
1186
  table: e,
1174
1187
  index: t.name
1175
- }, "safe", "drop index (no data loss — index is derived data)"), xn = (e, t) => {
1188
+ }, "safe", "drop index (no data loss — index is derived data)"), Tn = (e, t) => {
1176
1189
  if (e === "reference") return "text";
1177
1190
  switch (t) {
1178
1191
  case "sqlite":
@@ -1180,10 +1193,10 @@ BEGIN
1180
1193
  case "mssql": return e === "json" ? "text" : e;
1181
1194
  default: return e;
1182
1195
  }
1183
- }, Sn = (e, t, n) => {
1196
+ }, En = (e, t, n) => {
1184
1197
  let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
1185
1198
  return n === "postgres" ? `${r} — add \`{ using: '${t.name}::${t.type}' }\` when the cast is not implicit, or use a file-based migration` : `${r} — ${n === void 0 ? "this dialect" : n} converts in place (\`using\` is postgres-only and is ignored here), so verify the conversion is value-preserving for your data, or use a file-based migration`;
1186
- }, Cn = (e, t, n, r, i, a) => {
1199
+ }, Dn = (e, t, n, r, i, a) => {
1187
1200
  let o = [];
1188
1201
  if (t.nullable !== n.nullable) {
1189
1202
  let n = {
@@ -1192,7 +1205,7 @@ BEGIN
1192
1205
  column: t.name,
1193
1206
  toNullable: t.nullable
1194
1207
  };
1195
- o.push(t.nullable ? R(n, "safe", `loosen ${e}.${t.name} to nullable`) : R(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1208
+ o.push(t.nullable ? L(n, "safe", `loosen ${e}.${t.name} to nullable`) : L(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1196
1209
  }
1197
1210
  if (t.unique !== n.unique) {
1198
1211
  if (t.unique) {
@@ -1201,14 +1214,14 @@ BEGIN
1201
1214
  table: e,
1202
1215
  column: t.name
1203
1216
  }, r = (i ?? 0) >= a;
1204
- o.push(r ? R(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1205
- } else o.push(R({
1217
+ o.push(r ? L(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1218
+ } else o.push(L({
1206
1219
  kind: "drop-unique",
1207
1220
  table: e,
1208
1221
  column: t.name
1209
1222
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
1210
1223
  }
1211
- if (xn(t.type, r) !== xn(n.type, r)) {
1224
+ if (Tn(t.type, r) !== Tn(n.type, r)) {
1212
1225
  let i = t.narrowedFrom;
1213
1226
  if (i && i.from === n.type) {
1214
1227
  let r = {
@@ -1219,7 +1232,7 @@ BEGIN
1219
1232
  to: t.type,
1220
1233
  ...i.using === void 0 ? {} : { using: i.using }
1221
1234
  };
1222
- o.push(R(r, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${i.from}') declared` + (i.using ? ` with USING ${i.using}` : " (implicit cast)")));
1235
+ o.push(L(r, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${i.from}') declared` + (i.using ? ` with USING ${i.using}` : " (implicit cast)")));
1223
1236
  } else {
1224
1237
  let i = {
1225
1238
  kind: "alter-column-type",
@@ -1228,12 +1241,12 @@ BEGIN
1228
1241
  from: n.type,
1229
1242
  to: t.type
1230
1243
  };
1231
- o.push(R(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Sn(n.type, t, r) }));
1244
+ o.push(L(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: En(n.type, t, r) }));
1232
1245
  }
1233
1246
  }
1234
- if (t.type === "text" && n.type === "text" && !l(r ?? "postgres") && t.maxLength !== n.maxLength) {
1247
+ if (t.type === "text" && n.type === "text" && !m(r ?? "postgres") && t.maxLength !== n.maxLength) {
1235
1248
  let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
1236
- o.push(R({
1249
+ o.push(L({
1237
1250
  kind: "alter-column-type",
1238
1251
  table: e,
1239
1252
  column: t.name,
@@ -1241,7 +1254,7 @@ BEGIN
1241
1254
  to: "text"
1242
1255
  }, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
1243
1256
  }
1244
- if (!rn(t, n)) {
1257
+ if (!cn(t, n)) {
1245
1258
  let n = {
1246
1259
  kind: "alter-column-default",
1247
1260
  table: e,
@@ -1249,23 +1262,23 @@ BEGIN
1249
1262
  hasDefault: t.hasDefault,
1250
1263
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
1251
1264
  };
1252
- o.push(R(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1265
+ o.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1253
1266
  }
1254
- if (!on(t.oneOf, n.oneOf)) {
1255
- n.oneOf && n.oneOf.length > 0 && o.push(R({
1267
+ if (!un(t.oneOf, n.oneOf)) {
1268
+ n.oneOf && n.oneOf.length > 0 && o.push(L({
1256
1269
  kind: "drop-check",
1257
1270
  table: e,
1258
1271
  column: t.name
1259
1272
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
1260
- let r = un(e, t);
1273
+ let r = mn(e, t);
1261
1274
  r && o.push(r);
1262
1275
  }
1263
- return JSON.stringify(an(t.references)) !== JSON.stringify(an(n.references)) && (n.references && o.push(R({
1276
+ return JSON.stringify(ln(t.references)) !== JSON.stringify(ln(n.references)) && (n.references && o.push(L({
1264
1277
  kind: "drop-foreign-key",
1265
1278
  table: e,
1266
1279
  column: t.name
1267
- }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...wn(e, t))), o;
1268
- }, wn = (e, t) => {
1280
+ }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...On(e, t))), o;
1281
+ }, On = (e, t) => {
1269
1282
  let n = [];
1270
1283
  if (!t.references) return n;
1271
1284
  let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
@@ -1277,15 +1290,15 @@ BEGIN
1277
1290
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1278
1291
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1279
1292
  };
1280
- return i === "null" && !t.nullable ? n.push(R(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(R({
1293
+ return i === "null" && !t.nullable ? n.push(L(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(L({
1281
1294
  ...a,
1282
1295
  orphanPolicy: i
1283
- }, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(R(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1284
- }, Tn = (e, t, n) => {
1296
+ }, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(L(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1297
+ }, kn = (e, t, n) => {
1285
1298
  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));
1286
1299
  for (let [n, c] of Object.entries(t)) {
1287
1300
  let t = c.renamedFrom;
1288
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(R({
1301
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
1289
1302
  kind: "rename-column",
1290
1303
  table: e.tableName,
1291
1304
  from: t,
@@ -1297,26 +1310,26 @@ BEGIN
1297
1310
  consumedAddedNames: i,
1298
1311
  consumedRemovedNames: a
1299
1312
  };
1300
- }, En = /* @__PURE__ */ new Set([
1313
+ }, An = /* @__PURE__ */ new Set([
1301
1314
  "postgres",
1302
1315
  "mysql",
1303
1316
  "mariadb",
1304
1317
  "mssql"
1305
- ]), Dn = {
1318
+ ]), jn = {
1306
1319
  ops: [],
1307
1320
  consumedAddedNames: /* @__PURE__ */ new Set(),
1308
1321
  consumedRemovedNames: /* @__PURE__ */ new Set()
1309
- }, On = (e) => !e.unique && !e.expression, kn = (e, t, n, r, i) => {
1310
- if (i === void 0 || !En.has(i)) return Dn;
1311
- let a = t.added.filter((e) => On(e) && !r.has(e.name));
1312
- if (a.length === 0) return Dn;
1322
+ }, Mn = (e) => !e.unique && !e.expression, Nn = (e, t, n, r, i) => {
1323
+ if (i === void 0 || !An.has(i)) return jn;
1324
+ let a = t.added.filter((e) => Mn(e) && !r.has(e.name));
1325
+ if (a.length === 0) return jn;
1313
1326
  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();
1314
1327
  for (let n of t.removed) {
1315
- if (!On(n)) continue;
1328
+ if (!Mn(n)) continue;
1316
1329
  let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
1317
1330
  if (r.length !== 1) continue;
1318
1331
  let i = r[0];
1319
- i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(R({
1332
+ i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(L({
1320
1333
  kind: "rename-index",
1321
1334
  table: e,
1322
1335
  from: n.name,
@@ -1328,7 +1341,7 @@ BEGIN
1328
1341
  consumedAddedNames: l,
1329
1342
  consumedRemovedNames: u
1330
1343
  };
1331
- }, An = (e, t, n) => {
1344
+ }, Pn = (e, t, n) => {
1332
1345
  let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
1333
1346
  for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
1334
1347
  for (let c of e.tables) {
@@ -1339,7 +1352,7 @@ BEGIN
1339
1352
  continue;
1340
1353
  }
1341
1354
  if (t.has(c.name)) {
1342
- r.push(R({
1355
+ r.push(L({
1343
1356
  kind: "rename-table",
1344
1357
  from: e,
1345
1358
  to: c.name
@@ -1347,14 +1360,14 @@ BEGIN
1347
1360
  continue;
1348
1361
  }
1349
1362
  if ((s.get(e) ?? 0) !== 1) {
1350
- r.push(R({
1363
+ r.push(L({
1351
1364
  kind: "rename-table",
1352
1365
  from: e,
1353
1366
  to: c.name
1354
1367
  }, "needs-rename-annotation", `.renamedFrom('${e}') is claimed by ${s.get(e)} tables — nothing says which receives its rows`, { fix: `remove the \`.renamedFrom('${e}')\` marker from all but one of them.` }));
1355
1368
  continue;
1356
1369
  }
1357
- i.set(c.name, e), a.add(e), r.push(R({
1370
+ i.set(c.name, e), a.add(e), r.push(L({
1358
1371
  kind: "rename-table",
1359
1372
  from: e,
1360
1373
  to: c.name
@@ -1368,19 +1381,19 @@ BEGIN
1368
1381
  claimedOldNames: c,
1369
1382
  refusals: o
1370
1383
  };
1371
- }, jn = (e, t, n, r) => {
1384
+ }, Fn = (e, t, n, r) => {
1372
1385
  if (t === void 0) return {
1373
1386
  live: e,
1374
1387
  ops: []
1375
1388
  };
1376
- let i = r !== void 0 && En.has(r), a = [], o = e.indexes.map((e) => {
1389
+ let i = r !== void 0 && An.has(r), a = [], o = e.indexes.map((e) => {
1377
1390
  if (!e.name.startsWith(t)) return e;
1378
1391
  let r = `${n}${e.name.slice(t.length)}`;
1379
1392
  return r === e.name ? e : e.name === `${t}_pkey` ? {
1380
1393
  ...e,
1381
1394
  name: r,
1382
1395
  table: n
1383
- } : i ? (a.push(R({
1396
+ } : i ? (a.push(L({
1384
1397
  kind: "rename-index",
1385
1398
  table: n,
1386
1399
  from: e.name,
@@ -1399,7 +1412,7 @@ BEGIN
1399
1412
  },
1400
1413
  ops: a
1401
1414
  };
1402
- }, Mn = (e) => {
1415
+ }, In = (e) => {
1403
1416
  let t = {
1404
1417
  safe: 0,
1405
1418
  needsDefault: 0,
@@ -1432,42 +1445,42 @@ BEGIN
1432
1445
  case "multi-step": t.multiStep++;
1433
1446
  }
1434
1447
  return t;
1435
- }, Nn = (e) => {
1436
- let t = I(e.declared, e.dialect), n = tn(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? vn, a = [], o = An(t, r, n);
1448
+ }, Ln = (e) => {
1449
+ let t = F(e.declared, e.dialect), n = on(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Sn, a = [], o = Pn(t, r, n);
1437
1450
  a.push(...o.ops);
1438
1451
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1439
- a.push(gn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1452
+ a.push(bn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1440
1453
  for (let t of e.columns) {
1441
- let n = un(e.name, t);
1454
+ let n = mn(e.name, t);
1442
1455
  n && a.push(n);
1443
1456
  }
1444
1457
  }
1445
1458
  let s = new Set(e.ignoreTables ?? []);
1446
- for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || h(t.name) || f(t.name) || s.has(t.name) || a.push(_n(t.name));
1459
+ for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || _(t.name) || x(t.name) || s.has(t.name) || a.push(xn(t.name));
1447
1460
  for (let s of t.tables) {
1448
1461
  let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
1449
1462
  if (!c) continue;
1450
- let l = jn(c, t, s.name, e.dialect);
1463
+ let l = Fn(c, t, s.name, e.dialect);
1451
1464
  a.push(...l.ops);
1452
- let u = l.live, d = n.get(s.name), p = fn(s, u, e.dialect), m = pn(s, u), h = Tn(d.table, d.columnDefs, p);
1453
- a.push(...h.ops);
1454
- for (let e of p.removed) {
1455
- if (h.consumedRemovedNames.has(e.name) || f(e.name)) continue;
1465
+ let u = l.live, d = n.get(s.name), f = gn(s, u, e.dialect), p = _n(s, u, e.dialect), m = kn(d.table, d.columnDefs, f);
1466
+ a.push(...m.ops);
1467
+ for (let e of f.removed) {
1468
+ if (m.consumedRemovedNames.has(e.name) || x(e.name)) continue;
1456
1469
  let t = d.columnDefs[e.name];
1457
- a.push(hn(s.name, e, t));
1470
+ a.push(yn(s.name, e, t));
1458
1471
  }
1459
- for (let e of p.added) {
1460
- if (h.consumedAddedNames.has(e.name)) continue;
1472
+ for (let e of f.added) {
1473
+ if (m.consumedAddedNames.has(e.name)) continue;
1461
1474
  let t = d.columnDefs[e.name];
1462
- a.push(mn(s.name, e, t));
1463
- let n = un(s.name, e);
1464
- n && a.push(n), a.push(...wn(s.name, e));
1475
+ a.push(vn(s.name, e, t));
1476
+ let n = mn(s.name, e);
1477
+ n && a.push(n), a.push(...On(s.name, e));
1465
1478
  }
1466
- let g = new Map(h.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), _ = kn(s.name, m, g, new Set(u.indexes.map((e) => e.name)), e.dialect);
1467
- a.push(..._.ops);
1468
- for (let e of m.added) _.consumedAddedNames.has(e.name) || a.push(yn(s.name, e, u.rowCount, i));
1469
- for (let e of m.removed) _.consumedRemovedNames.has(e.name) || a.push(bn(s.name, e));
1470
- for (let { declared: t, live: n } of p.changed) a.push(...Cn(s.name, t, n, e.dialect, u.rowCount, i));
1479
+ let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Nn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1480
+ a.push(...g.ops);
1481
+ for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(Cn(s.name, e, u.rowCount, i));
1482
+ for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(wn(s.name, e));
1483
+ for (let { declared: t, live: n } of f.changed) a.push(...Dn(s.name, t, n, e.dialect, u.rowCount, i));
1471
1484
  }
1472
1485
  let c = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), l = new Map(t.tables.map((e) => [e.name, e])), u = (e) => {
1473
1486
  let t = l.get(e);
@@ -1475,8 +1488,8 @@ BEGIN
1475
1488
  column: e.name,
1476
1489
  target: e.references.table
1477
1490
  }] : []) : [];
1478
- }, d = ue([...c], u), p = [];
1479
- for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(D(e.name, t.name)) || p.push(R({
1491
+ }, d = pe([...c], u), f = [];
1492
+ for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(E(e.name, t.name)) || f.push(L({
1480
1493
  kind: "add-foreign-key",
1481
1494
  table: e.name,
1482
1495
  column: t.name,
@@ -1491,8 +1504,8 @@ BEGIN
1491
1504
  let n = a[t];
1492
1505
  if (n.op.kind !== "create-table") continue;
1493
1506
  let r = n.op;
1494
- if (!r.columns.some((e) => d.has(D(r.table, e.name)))) continue;
1495
- let i = r.columns.map((t) => d.has(D(r.table, t.name)) ? e(t) : t);
1507
+ if (!r.columns.some((e) => d.has(E(r.table, e.name)))) continue;
1508
+ let i = r.columns.map((t) => d.has(E(r.table, t.name)) ? e(t) : t);
1496
1509
  a[t] = {
1497
1510
  ...n,
1498
1511
  op: {
@@ -1501,24 +1514,24 @@ BEGIN
1501
1514
  }
1502
1515
  };
1503
1516
  }
1504
- a.push(...p);
1517
+ a.push(...f);
1505
1518
  }
1506
- let m = new Map(t.tables.map((e) => [e.name, e])), g = /* @__PURE__ */ new Map(), _ = (e, t = /* @__PURE__ */ new Set()) => {
1507
- let n = g.get(e);
1519
+ let p = new Map(t.tables.map((e) => [e.name, e])), m = /* @__PURE__ */ new Map(), h = (e, t = /* @__PURE__ */ new Set()) => {
1520
+ let n = m.get(e);
1508
1521
  if (n !== void 0) return n;
1509
1522
  if (t.has(e)) return 0;
1510
- let r = m.get(e);
1523
+ let r = p.get(e);
1511
1524
  if (!r) return 0;
1512
1525
  let i = new Set(t).add(e), a = 0;
1513
1526
  for (let t of r.columns) {
1514
1527
  let n = t.references?.table;
1515
- n && n !== e && !d.has(D(e, t.name)) && (a = Math.max(a, _(n, i) + 1));
1528
+ n && n !== e && !d.has(E(e, t.name)) && (a = Math.max(a, h(n, i) + 1));
1516
1529
  }
1517
- return g.set(e, a), a;
1518
- }, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
1530
+ return m.set(e, a), a;
1531
+ }, g = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, v = (e) => {
1519
1532
  let t = "table" in e ? e.table : "";
1520
- return e.kind === "create-table" ? _(t) : e.kind === "drop-table" ? -_(t) : 0;
1521
- }, b = {
1533
+ return e.kind === "create-table" ? h(t) : e.kind === "drop-table" ? -h(t) : 0;
1534
+ }, y = {
1522
1535
  "add-column": 0,
1523
1536
  "rename-column": 1,
1524
1537
  "rename-index": 1,
@@ -1536,23 +1549,23 @@ BEGIN
1536
1549
  "add-unique-composite": 5,
1537
1550
  "add-foreign-key": 5,
1538
1551
  "add-check": 5
1539
- }, x = (e) => b[e] ?? 9, S = [...a].sort((e, t) => {
1540
- let n = v(e.op.kind), r = v(t.op.kind);
1552
+ }, b = (e) => y[e] ?? 9, S = [...a].sort((e, t) => {
1553
+ let n = g(e.op.kind), r = g(t.op.kind);
1541
1554
  if (n !== r) return n - r;
1542
- let i = y(e.op), a = y(t.op);
1555
+ let i = v(e.op), a = v(t.op);
1543
1556
  if (i !== a) return i - a;
1544
1557
  let o = "table" in e.op ? e.op.table : "", s = "table" in t.op ? t.op.table : "";
1545
1558
  if (o !== s) return o.localeCompare(s);
1546
- let c = x(e.op.kind), l = x(t.op.kind);
1559
+ let c = b(e.op.kind), l = b(t.op.kind);
1547
1560
  return c === l ? e.op.kind.localeCompare(t.op.kind) : c - l;
1548
1561
  });
1549
1562
  return {
1550
1563
  operations: S,
1551
- fromFingerprint: Wt(e.live),
1552
- toFingerprint: Wt(t),
1553
- summary: Mn(S)
1564
+ fromFingerprint: Jt(e.live),
1565
+ toFingerprint: Jt(t),
1566
+ summary: In(S)
1554
1567
  };
1555
- }, Pn = (e) => {
1568
+ }, Rn = (e) => {
1556
1569
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1557
1570
  if (!t) return null;
1558
1571
  let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
@@ -1560,7 +1573,7 @@ BEGIN
1560
1573
  column: t[1],
1561
1574
  values: n
1562
1575
  };
1563
- }, Fn = (e, t) => {
1576
+ }, zn = (e, t) => {
1564
1577
  if (t === "vector") return "vector";
1565
1578
  switch (e) {
1566
1579
  case "text":
@@ -1587,10 +1600,10 @@ BEGIN
1587
1600
  case "USER-DEFINED": return "text";
1588
1601
  default: return "text";
1589
1602
  }
1590
- }, In = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
1603
+ }, Bn = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
1591
1604
  expr: e,
1592
1605
  stored: t
1593
- } }, z = (e) => {
1606
+ } }, R = (e) => {
1594
1607
  switch (e.toUpperCase()) {
1595
1608
  case "CASCADE": return "cascade";
1596
1609
  case "RESTRICT": return "restrict";
@@ -1598,25 +1611,25 @@ BEGIN
1598
1611
  case "SET DEFAULT": return "noAction";
1599
1612
  default: return "noAction";
1600
1613
  }
1601
- }, Ln = (e, t) => {
1614
+ }, Vn = (e, t) => {
1602
1615
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1603
1616
  return Number.isInteger(n) && n > 0 ? n : t;
1604
- }, Rn = () => Ln(process.env.VOLTRO_INTROSPECT_BATCH, 20), zn = 300, Bn = () => {
1617
+ }, Hn = () => Vn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Un = 300, Wn = () => {
1605
1618
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1606
- return e !== void 0 && e.trim() === "0" ? 0 : Ln(e, 3e4);
1607
- }, Vn = (e, t) => {
1619
+ return e !== void 0 && e.trim() === "0" ? 0 : Vn(e, 3e4);
1620
+ }, Gn = (e, t) => {
1608
1621
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1609
1622
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1610
1623
  return r;
1611
- }, Hn = (e) => {
1612
- let t = Bn(), n = S.gen(function* () {
1624
+ }, Kn = (e) => {
1625
+ let t = Wn(), n = C.gen(function* () {
1613
1626
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1614
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Rn(), a = (e, t) => S.gen(function* () {
1627
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Hn(), a = (e, t) => C.gen(function* () {
1615
1628
  let r = [];
1616
- for (let a of Vn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1629
+ for (let a of Gn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1617
1630
  return r;
1618
1631
  }), o = [];
1619
- for (let t = 0;; t += zn) {
1632
+ for (let t = 0;; t += Un) {
1620
1633
  let n = yield* e`
1621
1634
  SELECT c.relname AS table_name,
1622
1635
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1624,9 +1637,9 @@ BEGIN
1624
1637
  JOIN pg_namespace n ON n.oid = c.relnamespace
1625
1638
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1626
1639
  ORDER BY c.relname
1627
- LIMIT ${r(zn)} OFFSET ${r(t)}
1640
+ LIMIT ${r(Un)} OFFSET ${r(t)}
1628
1641
  `;
1629
- if (o.push(...n), n.length < zn) break;
1642
+ if (o.push(...n), n.length < Un) break;
1630
1643
  }
1631
1644
  let s = /* @__PURE__ */ new Set(), c = [];
1632
1645
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
@@ -1712,7 +1725,7 @@ BEGIN
1712
1725
  AND c.relname IN ${t}
1713
1726
  )
1714
1727
  SELECT * FROM ix ORDER BY table_name, index_name, position
1715
- `), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), C = /* @__PURE__ */ new Map();
1728
+ `), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), S = /* @__PURE__ */ new Map();
1716
1729
  for (let e of u) {
1717
1730
  let t = _.get(e.table_name);
1718
1731
  t || (t = [], _.set(e.table_name, t)), t.push(e);
@@ -1721,18 +1734,18 @@ BEGIN
1721
1734
  let t = v.get(e.table_name);
1722
1735
  t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
1723
1736
  }
1724
- let w = /* @__PURE__ */ new Map();
1737
+ let ee = /* @__PURE__ */ new Map();
1725
1738
  for (let e of f) {
1726
- let t = `${e.table_name}\u0000${e.constraint_name}`, n = w.get(t);
1739
+ let t = `${e.table_name}\u0000${e.constraint_name}`, n = ee.get(t);
1727
1740
  n || (n = {
1728
1741
  table: e.table_name,
1729
1742
  columns: []
1730
- }, w.set(t, n)), n.columns.push({
1743
+ }, ee.set(t, n)), n.columns.push({
1731
1744
  name: e.column_name,
1732
1745
  position: e.position
1733
1746
  });
1734
1747
  }
1735
- for (let [e, t] of w) {
1748
+ for (let [e, t] of ee) {
1736
1749
  let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
1737
1750
  if (n.length === 1) {
1738
1751
  let e = y.get(t.table);
@@ -1752,33 +1765,33 @@ BEGIN
1752
1765
  t || (t = [], x.set(e.source_table, t)), t.push(e);
1753
1766
  }
1754
1767
  for (let e of g) {
1755
- let t = C.get(e.table_name);
1756
- t || (t = /* @__PURE__ */ new Map(), C.set(e.table_name, t));
1768
+ let t = S.get(e.table_name);
1769
+ t || (t = /* @__PURE__ */ new Map(), S.set(e.table_name, t));
1757
1770
  let n = t.get(e.index_name);
1758
1771
  n || (n = [], t.set(e.index_name, n)), n.push(e);
1759
1772
  }
1760
- let T = [];
1773
+ let w = [];
1761
1774
  for (let e of c) {
1762
1775
  let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = x.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) => {
1763
- let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : Fn(t.data_type, t.udt_name), c = a ? {
1776
+ 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" : zn(t.data_type, t.udt_name), c = a ? {
1764
1777
  table: a.target_table,
1765
1778
  column: a.target_column,
1766
- onDelete: z(a.delete_rule),
1767
- onUpdate: z(a.update_rule)
1779
+ onDelete: R(a.delete_rule),
1780
+ onUpdate: R(a.update_rule)
1768
1781
  } : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
1769
1782
  return {
1770
1783
  name: t.column_name,
1771
1784
  type: s,
1772
- ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
1785
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1773
1786
  nullable: t.is_nullable === "YES",
1774
1787
  unique: i.has(t.column_name) || n && t.column_name === "id",
1775
1788
  hasDefault: t.column_default !== null,
1776
1789
  ...t.column_default === null ? {} : { defaultValue: t.column_default },
1777
1790
  ...c ? { references: c } : {},
1778
1791
  ...l ? { oneOf: l } : {},
1779
- ...In(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
1792
+ ...Bn(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
1780
1793
  };
1781
- }), l = [], u = C.get(e.table_name);
1794
+ }), l = [], u = S.get(e.table_name);
1782
1795
  if (u) for (let [t, n] of u) {
1783
1796
  let r = /* @__PURE__ */ new Set(), i = [...n].filter((e) => e.column_name !== null && e.position !== null).sort((e, t) => (e.position ?? 0) - (t.position ?? 0)).filter((e) => {
1784
1797
  let t = e.position;
@@ -1802,20 +1815,20 @@ BEGIN
1802
1815
  unique: !0
1803
1816
  });
1804
1817
  let d = Number(e.row_count ?? 0);
1805
- T.push({
1818
+ w.push({
1806
1819
  name: e.table_name,
1807
1820
  columns: c,
1808
1821
  indexes: l,
1809
1822
  ...d > 0 ? { rowCount: d } : {}
1810
1823
  });
1811
1824
  }
1812
- return { tables: T };
1825
+ return { tables: w };
1813
1826
  });
1814
- return (t > 0 ? e.withTransaction(n) : n).pipe(S.catchAll((e) => {
1827
+ return (t > 0 ? e.withTransaction(n) : n).pipe(C.catchAll((e) => {
1815
1828
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1816
- return n.includes("statement timeout") || n.includes("57014") ? S.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.`)) : S.fail(e);
1829
+ return n.includes("statement timeout") || n.includes("57014") ? C.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.`)) : C.fail(e);
1817
1830
  }));
1818
- }, Un = (e, t) => {
1831
+ }, qn = (e, t) => {
1819
1832
  switch (e.toLowerCase()) {
1820
1833
  case "varchar":
1821
1834
  case "char":
@@ -1847,21 +1860,21 @@ BEGIN
1847
1860
  case "json": return "json";
1848
1861
  default: return "text";
1849
1862
  }
1850
- }, B = (e) => e.map((e) => {
1863
+ }, z = (e) => e.map((e) => {
1851
1864
  let t = e, n = {};
1852
1865
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1853
1866
  return n;
1854
- }), Wn = (e) => S.gen(function* () {
1855
- let t = B(yield* e`
1867
+ }), Jn = (e) => C.gen(function* () {
1868
+ let t = z(yield* e`
1856
1869
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1857
1870
  FROM information_schema.tables
1858
1871
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1859
- ORDER BY table_name`), n = B(yield* e`
1872
+ ORDER BY table_name`), n = z(yield* e`
1860
1873
  SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
1861
1874
  character_maximum_length, generation_expression, extra
1862
1875
  FROM information_schema.columns
1863
1876
  WHERE table_schema = DATABASE()
1864
- ORDER BY table_name, ordinal_position`), r = B(yield* e`
1877
+ ORDER BY table_name, ordinal_position`), r = z(yield* e`
1865
1878
  SELECT k.table_name AS source_table,
1866
1879
  k.column_name AS source_column,
1867
1880
  k.referenced_table_name AS target_table,
@@ -1871,7 +1884,7 @@ BEGIN
1871
1884
  JOIN information_schema.referential_constraints r
1872
1885
  ON k.constraint_name = r.constraint_name
1873
1886
  AND k.table_schema = r.constraint_schema
1874
- WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = B(yield* e`
1887
+ WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = z(yield* e`
1875
1888
  SELECT table_name, index_name, non_unique, column_name, seq_in_index
1876
1889
  FROM information_schema.statistics
1877
1890
  WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
@@ -1884,14 +1897,14 @@ BEGIN
1884
1897
  JOIN information_schema.table_constraints tc
1885
1898
  ON tc.constraint_schema = cc.constraint_schema
1886
1899
  AND tc.constraint_name = cc.constraint_name
1887
- WHERE cc.constraint_schema = DATABASE()`.unprepared, s = B(yield* a.pipe(S.orElse(() => o), S.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
1900
+ WHERE cc.constraint_schema = DATABASE()`.unprepared, s = z(yield* a.pipe(C.orElse(() => o), C.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
1888
1901
  for (let e of s) {
1889
1902
  let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
1890
1903
  if (t) {
1891
1904
  c.add(`${e.table_name}.${t[1]}`);
1892
1905
  continue;
1893
1906
  }
1894
- let n = Pn(e.check_clause);
1907
+ let n = Rn(e.check_clause);
1895
1908
  n && l.set(`${e.table_name}.${n.column}`, n.values);
1896
1909
  }
1897
1910
  let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
@@ -1914,23 +1927,23 @@ BEGIN
1914
1927
  let t = u.get(e.table_name) ?? [], n = d.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), o = f.get(e.table_name);
1915
1928
  if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1916
1929
  let s = t.map((t) => {
1917
- let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" : Un(t.data_type, t.column_type), u = o ? {
1930
+ let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" : qn(t.data_type, t.column_type), u = o ? {
1918
1931
  table: o.target_table,
1919
1932
  column: o.target_column,
1920
- onDelete: z(o.delete_rule),
1921
- onUpdate: z(o.update_rule)
1933
+ onDelete: R(o.delete_rule),
1934
+ onUpdate: R(o.update_rule)
1922
1935
  } : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = l.get(`${e.table_name}.${t.column_name}`);
1923
1936
  return {
1924
1937
  name: t.column_name,
1925
1938
  type: s,
1926
1939
  nullable: t.is_nullable === "YES",
1927
- ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
1940
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1928
1941
  unique: d,
1929
1942
  hasDefault: f !== null,
1930
1943
  ...f === null ? {} : { defaultValue: f },
1931
1944
  ...u ? { references: u } : {},
1932
1945
  ...p ? { oneOf: p } : {},
1933
- ...In(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
1946
+ ...Bn(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
1934
1947
  };
1935
1948
  }), m = new Set(n.map((e) => e.source_column)), h = [];
1936
1949
  if (o) for (let [t, n] of o) {
@@ -1957,10 +1970,10 @@ BEGIN
1957
1970
  });
1958
1971
  }
1959
1972
  return { tables: p };
1960
- }), Gn = (e) => {
1973
+ }), Yn = (e) => {
1961
1974
  let t = e.toUpperCase();
1962
1975
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1963
- }, Kn = (e) => S.gen(function* () {
1976
+ }, Xn = (e) => e === 1 || e === !0, Zn = (e) => C.gen(function* () {
1964
1977
  let t = yield* e`
1965
1978
  SELECT name, sql FROM sqlite_master
1966
1979
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1971,53 +1984,53 @@ BEGIN
1971
1984
  let n = [...e[2].matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
1972
1985
  n.length > 0 && t.set(e[1], n);
1973
1986
  }
1974
- let o = yield* e.unsafe(`PRAGMA table_xinfo(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set();
1987
+ let o = yield* e.unsafe(`PRAGMA table_xinfo(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = new Map(o.map((e) => [e.name.toLowerCase(), e.name])), f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Set();
1975
1988
  for (let t of c) {
1976
- let r = (yield* e.unsafe(`PRAGMA index_info(${n(t.name)})`)).map((e) => e.name).filter((e) => e !== null);
1977
- d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1989
+ let r = (yield* e.unsafe(`PRAGMA index_info(${n(t.name)})`)).map((e) => e.name).filter((e) => e !== null).map((e) => d.get(e.toLowerCase()) ?? e);
1990
+ f.set(t.name, r), Xn(t.unique) && r.length === 1 && p.add(r[0]);
1978
1991
  }
1979
- let p = o.map((e) => {
1980
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Gn(e.type), a = r ? {
1992
+ let m = o.map((e) => {
1993
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Yn(e.type), a = r ? {
1981
1994
  table: r.table,
1982
1995
  column: r.to,
1983
- onDelete: z(r.on_delete),
1984
- onUpdate: z(r.on_update)
1996
+ onDelete: R(r.on_delete),
1997
+ onUpdate: R(r.on_update)
1985
1998
  } : void 0, o = t.get(e.name);
1986
1999
  return {
1987
2000
  name: e.name,
1988
2001
  type: i,
1989
2002
  nullable: e.notnull === 0,
1990
- unique: f.has(e.name) || n && e.name === "id",
2003
+ unique: p.has(e.name) || n && e.name === "id",
1991
2004
  hasDefault: e.dflt_value !== null,
1992
2005
  ...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
1993
2006
  ...a ? { references: a } : {},
1994
2007
  ...o ? { oneOf: o } : {},
1995
- ...In(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
2008
+ ...Bn(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
1996
2009
  };
1997
- }), m = new Set(s.map((e) => e.from)), h = [];
2010
+ }), h = new Set(s.map((e) => e.from)), g = [];
1998
2011
  for (let e of c) {
1999
2012
  if (e.origin === "pk") continue;
2000
- let t = d.get(e.name) ?? [];
2001
- (t.length !== 1 || e.unique !== 1) && (t.length === 1 && e.unique !== 1 && m.has(t[0]) && e.name !== `${i}_${t[0]}_idx` || h.push({
2013
+ let t = f.get(e.name) ?? [];
2014
+ t.length === 1 && Xn(e.unique) || t.length === 1 && !Xn(e.unique) && h.has(t[0]) && e.name !== `${i}_${t[0]}_idx` || g.push({
2002
2015
  name: e.name,
2003
2016
  table: i,
2004
2017
  columns: t,
2005
- unique: e.unique === 1
2006
- }));
2018
+ unique: Xn(e.unique)
2019
+ });
2007
2020
  }
2008
- u.length > 0 && h.push({
2021
+ u.length > 0 && g.push({
2009
2022
  name: `${i}_pkey`,
2010
2023
  table: i,
2011
2024
  columns: u,
2012
2025
  unique: !0
2013
2026
  }), r.push({
2014
2027
  name: i,
2015
- columns: p,
2016
- indexes: h
2028
+ columns: m,
2029
+ indexes: g
2017
2030
  });
2018
2031
  }
2019
2032
  return { tables: r };
2020
- }), qn = (e) => {
2033
+ }), Qn = (e) => {
2021
2034
  switch (e.toLowerCase()) {
2022
2035
  case "int":
2023
2036
  case "smallint":
@@ -2039,14 +2052,14 @@ BEGIN
2039
2052
  case "image": return "bytes";
2040
2053
  default: return "text";
2041
2054
  }
2042
- }, V = (e) => e === !0 || e === 1, Jn = (e) => S.gen(function* () {
2055
+ }, B = (e) => e === !0 || e === 1, $n = (e) => C.gen(function* () {
2043
2056
  let t = yield* e`
2044
2057
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
2045
2058
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
2046
2059
  SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
2047
2060
  IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
2048
2061
  CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
2049
- FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* S.orElseSucceed(e`
2062
+ FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* C.orElseSucceed(e`
2050
2063
  SELECT t.name AS table_name, c.name AS column_name, cc.definition AS definition,
2051
2064
  cc.is_persisted AS is_persisted
2052
2065
  FROM sys.computed_columns cc
@@ -2101,36 +2114,36 @@ BEGIN
2101
2114
  let t = l.get(e) ?? [], n = u.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), a = new Set(n.map((e) => e.source_column)), o = d.get(e), s = [], p = /* @__PURE__ */ new Set();
2102
2115
  if (o) for (let [, e] of o) {
2103
2116
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
2104
- if (V(t[0].is_primary)) for (let e of t) s.push(e.column_name);
2105
- else V(t[0].is_unique) && t.length === 1 && p.add(t[0].column_name);
2117
+ if (B(t[0].is_primary)) for (let e of t) s.push(e.column_name);
2118
+ else B(t[0].is_unique) && t.length === 1 && p.add(t[0].column_name);
2106
2119
  }
2107
2120
  let m = t.map((t) => {
2108
- let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : qn(t.data_type), l = a ? {
2121
+ let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : Qn(t.data_type), l = a ? {
2109
2122
  table: a.target_table,
2110
2123
  column: a.target_column,
2111
- onDelete: Yn(a.delete_rule),
2112
- onUpdate: Yn(a.update_rule)
2113
- } : void 0, u = t.column_default === null ? null : Xn(t.column_default), d = c.get(`${e}.${t.column_name}`);
2124
+ onDelete: er(a.delete_rule),
2125
+ onUpdate: er(a.update_rule)
2126
+ } : void 0, u = t.column_default === null ? null : tr(t.column_default), d = c.get(`${e}.${t.column_name}`);
2114
2127
  return {
2115
2128
  name: t.column_name,
2116
2129
  type: o,
2117
2130
  nullable: t.is_nullable === "YES",
2118
- ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
2131
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
2119
2132
  unique: p.has(t.column_name) || n && t.column_name === "id",
2120
2133
  hasDefault: u !== null,
2121
2134
  ...u === null ? {} : { defaultValue: u },
2122
2135
  ...l ? { references: l } : {},
2123
2136
  ...d ? { oneOf: d } : {},
2124
- ...In(i.get(`${e}.${t.column_name}`)?.definition ?? null, V(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2137
+ ...Bn(i.get(`${e}.${t.column_name}`)?.definition ?? null, B(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2125
2138
  };
2126
2139
  }), h = [];
2127
2140
  if (o) for (let [t, n] of o) {
2128
2141
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
2129
- V(r[0].is_primary) || r.length === 1 && V(r[0].is_unique) || r.length === 1 && !V(r[0].is_unique) && a.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || h.push({
2142
+ B(r[0].is_primary) || r.length === 1 && B(r[0].is_unique) || r.length === 1 && !B(r[0].is_unique) && a.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || h.push({
2130
2143
  name: t,
2131
2144
  table: e,
2132
2145
  columns: r.map((e) => e.column_name),
2133
- unique: V(r[0].is_unique)
2146
+ unique: B(r[0].is_unique)
2134
2147
  });
2135
2148
  }
2136
2149
  s.length > 0 && h.push({
@@ -2145,90 +2158,90 @@ BEGIN
2145
2158
  });
2146
2159
  }
2147
2160
  return { tables: f };
2148
- }), Yn = (e) => {
2161
+ }), er = (e) => {
2149
2162
  switch (e.toUpperCase().replace(/_/g, " ")) {
2150
2163
  case "CASCADE": return "cascade";
2151
2164
  case "SET NULL": return "setNull";
2152
2165
  case "SET DEFAULT": return "noAction";
2153
2166
  default: return "noAction";
2154
2167
  }
2155
- }, Xn = (e) => {
2168
+ }, tr = (e) => {
2156
2169
  let t = e.trim();
2157
2170
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
2158
2171
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
2159
- }, Zn = /* @__PURE__ */ new Set([
2172
+ }, nr = /* @__PURE__ */ new Set([
2160
2173
  "character varying",
2161
2174
  "varchar",
2162
2175
  "nvarchar",
2163
2176
  "char",
2164
2177
  "character",
2165
2178
  "nchar"
2166
- ]), H = (e, t) => {
2167
- if (!Zn.has(e.toLowerCase())) return;
2179
+ ]), V = (e, t) => {
2180
+ if (!nr.has(e.toLowerCase())) return;
2168
2181
  let n = Number(t);
2169
2182
  if (!(!Number.isFinite(n) || n <= 0)) return n;
2170
- }, Qn = /* @__PURE__ */ new Set([k]), $n = (e) => e.onDialectOrElse({
2171
- mysql: () => Wn(e),
2172
- mssql: () => Jn(e),
2173
- sqlite: () => Kn(e),
2174
- orElse: () => Hn(e)
2175
- }).pipe(S.map((e) => ({
2183
+ }, rr = /* @__PURE__ */ new Set([O]), ir = (e) => e.onDialectOrElse({
2184
+ mysql: () => Jn(e),
2185
+ mssql: () => $n(e),
2186
+ sqlite: () => Zn(e),
2187
+ orElse: () => Kn(e)
2188
+ }).pipe(C.map((e) => ({
2176
2189
  ...e,
2177
- tables: e.tables.filter((e) => !Qn.has(e.name))
2178
- }))), er = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", tr = /* @__PURE__ */ new WeakMap(), U = (e) => S.suspend(() => {
2179
- let t = tr.get(e);
2180
- return t === void 0 ? nr(e).pipe(S.tap((t) => S.sync(() => tr.set(e, t)))) : S.succeed(t);
2181
- }), nr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(S.map((e) => {
2190
+ tables: e.tables.filter((e) => !rr.has(e.name))
2191
+ }))), ar = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", or = /* @__PURE__ */ new WeakMap(), H = (e) => C.suspend(() => {
2192
+ let t = or.get(e);
2193
+ return t === void 0 ? sr(e).pipe(C.tap((t) => C.sync(() => or.set(e, t)))) : C.succeed(t);
2194
+ }), sr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(C.map((e) => {
2182
2195
  let t = e[0]?.v;
2183
- return typeof t == "string" ? er(t) : "mysql";
2184
- }), S.catchAll(() => S.succeed("mysql"))), rr = (e) => {
2196
+ return typeof t == "string" ? ar(t) : "mysql";
2197
+ }), C.catchAll(() => C.succeed("mysql"))), cr = (e) => {
2185
2198
  let t = e;
2186
2199
  for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
2187
2200
  let e = t;
2188
2201
  if (typeof e.errno == "number") return e.errno;
2189
2202
  t = e.cause;
2190
2203
  }
2191
- }, ir = (e) => {
2204
+ }, lr = (e) => {
2192
2205
  let t = [], n = e;
2193
2206
  for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
2194
2207
  let e = n;
2195
2208
  typeof e.message == "string" && t.push(e.message), n = e.cause;
2196
2209
  }
2197
2210
  return t.join(" | ");
2198
- }, ar = (e, t) => {
2211
+ }, ur = (e, t) => {
2199
2212
  if (t.length === 0) return !1;
2200
- let n = rr(e), r = ir(e);
2213
+ let n = cr(e), r = lr(e);
2201
2214
  return t.some((e) => e.errno !== void 0 && n !== void 0 && e.errno.includes(n) || e.messageIncludes !== void 0 && e.messageIncludes.some((e) => r.includes(e)));
2202
- }, or = {
2215
+ }, dr = {
2203
2216
  why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
2204
2217
  errno: [1061]
2205
- }, sr = {
2218
+ }, fr = {
2206
2219
  why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
2207
2220
  errno: [1091]
2208
- }, cr = {
2221
+ }, pr = {
2209
2222
  why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
2210
2223
  messageIncludes: ["no such column"]
2211
- }, lr = {
2224
+ }, mr = {
2212
2225
  why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
2213
2226
  errno: [1091, 3940]
2214
- }, W = (e, t) => e.onDialectOrElse({
2215
- mysql: () => S.succeed(t.replace("T", " ").replace("Z", "")),
2216
- orElse: () => S.succeed(t)
2217
- }), ur = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, dr = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), fr = (e, t) => {
2218
- if ((e.type !== "text" || e.maxLength === void 0) && !dr(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2227
+ }, U = (e, t) => e.onDialectOrElse({
2228
+ mysql: () => C.succeed(t.replace("T", " ").replace("Z", "")),
2229
+ orElse: () => C.succeed(t)
2230
+ }), hr = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, gr = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), _r = (e, t) => {
2231
+ if ((e.type !== "text" || e.maxLength === void 0) && !gr(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2219
2232
  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;
2220
2233
  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.`);
2221
- return M(e, t);
2222
- }, pr = (e) => {
2223
- let t = fr(e, "postgres");
2224
- return t === void 0 ? mr(e) : t;
2225
- }, mr = (e) => {
2234
+ return j(e, t);
2235
+ }, vr = (e) => {
2236
+ let t = _r(e, "postgres");
2237
+ return t === void 0 ? yr(e) : t;
2238
+ }, yr = (e) => {
2226
2239
  switch (e.type) {
2227
2240
  case "id": return "text";
2228
2241
  case "text": return "text";
2229
2242
  case "integer": return "integer";
2230
2243
  case "real": return "double precision";
2231
- case "decimal": return ur(e, "NUMERIC");
2244
+ case "decimal": return hr(e, "NUMERIC");
2232
2245
  case "bigint": return "bigint";
2233
2246
  case "boolean": return "boolean";
2234
2247
  case "timestamp": return "timestamptz";
@@ -2242,15 +2255,15 @@ BEGIN
2242
2255
  case "interval": return "interval";
2243
2256
  case "raw": return e.rawDdl ?? "text";
2244
2257
  }
2245
- }, hr = (e) => {
2246
- let t = fr(e, "mariadb");
2258
+ }, br = (e) => {
2259
+ let t = _r(e, "mariadb");
2247
2260
  if (t !== void 0) return t;
2248
2261
  switch (e.type) {
2249
2262
  case "id": return "VARCHAR(64)";
2250
2263
  case "text": return "LONGTEXT";
2251
2264
  case "integer": return "INT";
2252
2265
  case "real": return "DOUBLE";
2253
- case "decimal": return ur(e, "DECIMAL");
2266
+ case "decimal": return hr(e, "DECIMAL");
2254
2267
  case "bigint": return "BIGINT";
2255
2268
  case "boolean": return "TINYINT(1)";
2256
2269
  case "timestamp": return "DATETIME(6)";
@@ -2264,64 +2277,64 @@ BEGIN
2264
2277
  case "interval": return "BIGINT";
2265
2278
  case "raw": return e.rawDdl ?? "LONGTEXT";
2266
2279
  }
2267
- }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, gr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", _r = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, vr = (e, t = "mariadb") => `ALTER TABLE ${K(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${K(e.column)}, ALGORITHM=COPY;`, yr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, br = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Yr(t)}`)};`, xr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Cr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Sr = (e, t) => {
2280
+ }, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, xr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", Sr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Cr = (e, t = "mariadb") => `ALTER TABLE ${G(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${G(e.column)}, ALGORITHM=COPY;`, wr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Tr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${$r(t)}`)};`, Er = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Or(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Dr = (e, t) => {
2268
2281
  let { defaultFactory: n, ...r } = e;
2269
- return M(e, t) !== M({
2282
+ return j(e, t) !== j({
2270
2283
  ...r,
2271
2284
  hasDefault: !1
2272
2285
  }, t);
2273
- }, Cr = (e, t) => {
2286
+ }, Or = (e, t) => {
2274
2287
  let n = t(e.defaultValue);
2275
2288
  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.`);
2276
2289
  return n;
2277
- }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], wr = (e, t, n) => {
2278
- let r = q(e, t, n);
2279
- return r ? Kt(n, r) : void 0;
2280
- }, Tr = (e, t, n) => {
2281
- let r = n ?? e.nullable, i = Qe(e, "mariadb");
2290
+ }, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], kr = (e, t, n) => {
2291
+ let r = K(e, t, n);
2292
+ return r ? Xt(n, r) : void 0;
2293
+ }, Ar = (e, t, n) => {
2294
+ let r = n ?? e.nullable, i = nt(e, "mariadb");
2282
2295
  return [
2283
- K(t),
2284
- M(e, "mariadb"),
2296
+ G(t),
2297
+ j(e, "mariadb"),
2285
2298
  r ? null : "NOT NULL",
2286
2299
  i
2287
2300
  ].filter(Boolean).join(" ");
2288
- }, Er = (e, t) => e == null ? null : Array.isArray(e) ? Dr(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" ? N(e, "mariadb") : null, Dr = (e, t, n) => $e(e, t ?? { type: "json" }, n), Or = (e, t) => e == null ? null : Array.isArray(e) ? Dr(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" ? N(e, "postgres") : null, kr = (e, t) => {
2301
+ }, jr = (e, t) => e == null ? null : Array.isArray(e) ? Mr(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? M(e, "mariadb") : null, Mr = (e, t, n) => rt(e, t ?? { type: "json" }, n), Nr = (e, t) => e == null ? null : Array.isArray(e) ? Mr(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, Pr = (e, t) => {
2289
2302
  if (!e.generatedAs) return null;
2290
2303
  let { expr: n, stored: r } = e.generatedAs;
2291
2304
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2292
- }, Ar = (e) => {
2293
- if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "postgres");
2294
- let t = kr(e, "postgres");
2295
- if (t) return `${G(e.name)} ${pr(e)} ${t}`;
2296
- let n = [G(e.name), pr(e)];
2305
+ }, Fr = (e) => {
2306
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "postgres");
2307
+ let t = Pr(e, "postgres");
2308
+ if (t) return `${W(e.name)} ${vr(e)} ${t}`;
2309
+ let n = [W(e.name), vr(e)];
2297
2310
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2298
- let t = Or(e.defaultValue, e);
2311
+ let t = Nr(e.defaultValue, e);
2299
2312
  t && n.push(t);
2300
2313
  }
2301
- return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2314
+ return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2302
2315
  cascade: "CASCADE",
2303
2316
  restrict: "RESTRICT",
2304
2317
  setNull: "SET NULL",
2305
2318
  noAction: "NO ACTION"
2306
2319
  }[e.references.onDelete]}`)), n.join(" ");
2307
- }, jr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Mr = (e) => {
2308
- let t = e.columns.map((e) => ` ${Ar(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${jr(e, G)}\n)`];
2309
- 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(ei).join(", ")})`);
2320
+ }, Ir = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Lr = (e) => {
2321
+ let t = e.columns.map((e) => ` ${Fr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Ir(e, W)}\n)`];
2322
+ 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(ii).join(", ")})`);
2310
2323
  return n;
2311
- }, Nr = 191, Pr = (e) => {
2312
- let t = hr(e).toUpperCase();
2324
+ }, Rr = 191, zr = (e) => {
2325
+ let t = br(e).toUpperCase();
2313
2326
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2314
- }, Fr = (e) => {
2315
- if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mariadb");
2316
- let t = kr(e, "mariadb");
2317
- if (t) return `${K(e.name)} ${hr(e)} ${t}`;
2318
- let n = [K(e.name), hr(e)];
2319
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !Pr(e) && n.push("UNIQUE"), e.hasDefault) {
2320
- let t = Er(e.defaultValue, e);
2327
+ }, Br = (e) => {
2328
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mariadb");
2329
+ let t = Pr(e, "mariadb");
2330
+ if (t) return `${G(e.name)} ${br(e)} ${t}`;
2331
+ let n = [G(e.name), br(e)];
2332
+ if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !zr(e) && n.push("UNIQUE"), e.hasDefault) {
2333
+ let t = jr(e.defaultValue, e);
2321
2334
  t && n.push(t);
2322
2335
  }
2323
2336
  return n.join(" ");
2324
- }, Ir = (e) => e.columns.flatMap((t) => {
2337
+ }, Vr = (e) => e.columns.flatMap((t) => {
2325
2338
  if (!t.references) return [];
2326
2339
  let n = t.references.onDelete ? ` ON DELETE ${{
2327
2340
  cascade: "CASCADE",
@@ -2329,27 +2342,27 @@ BEGIN
2329
2342
  setNull: "SET NULL",
2330
2343
  noAction: "NO ACTION"
2331
2344
  }[t.references.onDelete]}` : "";
2332
- return [` CONSTRAINT ${K(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${K(t.name)}) REFERENCES ${K(t.references.table)} (${K(t.references.column)})${n}`];
2333
- }), Lr = (e, t = "mariadb") => {
2345
+ return [` CONSTRAINT ${G(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${G(t.name)}) REFERENCES ${G(t.references.table)} (${G(t.references.column)})${n}`];
2346
+ }), Hr = (e, t = "mariadb") => {
2334
2347
  let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
2335
- let t = Qr(n.get(e));
2336
- return t === void 0 ? K(e) : `${K(e)}(${t})`;
2337
- }, i = e.columns.map((e) => ` ${Fr(e)}`).join(",\n"), a = Ir(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${o}${jr(e, r)}\n)`];
2338
- for (let n of e.columns) n.unique && n.type !== "id" && Pr(n) && s.push(`CREATE UNIQUE INDEX ${gr(t)}${K(`${e.table}_${n.name}_key`)} ON ${K(e.table)} (${r(n.name)})`);
2339
- for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${gr(t)}${K(n.name)} ON ${K(e.table)} (${n.columns.map(r).join(", ")})`);
2348
+ let t = ni(n.get(e));
2349
+ return t === void 0 ? G(e) : `${G(e)}(${t})`;
2350
+ }, i = e.columns.map((e) => ` ${Br(e)}`).join(",\n"), a = Vr(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${o}${Ir(e, r)}\n)`];
2351
+ for (let n of e.columns) n.unique && n.type !== "id" && zr(n) && s.push(`CREATE UNIQUE INDEX ${xr(t)}${G(`${e.table}_${n.name}_key`)} ON ${G(e.table)} (${r(n.name)})`);
2352
+ for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${xr(t)}${G(n.name)} ON ${G(e.table)} (${n.columns.map(r).join(", ")})`);
2340
2353
  return s;
2341
- }, Rr = {
2354
+ }, Ur = {
2342
2355
  cascade: "CASCADE",
2343
2356
  restrict: "RESTRICT",
2344
2357
  setNull: "SET NULL",
2345
2358
  noAction: "NO ACTION"
2346
- }, zr = {
2359
+ }, Wr = {
2347
2360
  cascade: "CASCADE",
2348
2361
  restrict: "NO ACTION",
2349
2362
  setNull: "SET NULL",
2350
2363
  noAction: "NO ACTION"
2351
- }, Br = (e) => {
2352
- let t = fr(e, "sqlite");
2364
+ }, Gr = (e) => {
2365
+ let t = _r(e, "sqlite");
2353
2366
  if (t !== void 0) return t;
2354
2367
  switch (e.type) {
2355
2368
  case "integer":
@@ -2360,60 +2373,60 @@ BEGIN
2360
2373
  case "bytes": return "BLOB";
2361
2374
  default: return "TEXT";
2362
2375
  }
2363
- }, Vr = (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" ? N(e, "sqlite") : null, Hr = (e) => {
2364
- if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "sqlite");
2365
- let t = kr(e, "sqlite");
2366
- if (t) return `${G(e.name)} ${Br(e)} ${t}`;
2367
- let n = [G(e.name), Br(e)];
2376
+ }, q = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? M(e, "sqlite") : null, Kr = (e) => {
2377
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "sqlite");
2378
+ let t = Pr(e, "sqlite");
2379
+ if (t) return `${W(e.name)} ${Gr(e)} ${t}`;
2380
+ let n = [W(e.name), Gr(e)];
2368
2381
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2369
- let t = Vr(e.defaultValue, "CURRENT_TIMESTAMP");
2382
+ let t = q(e.defaultValue, "CURRENT_TIMESTAMP");
2370
2383
  t && n.push(t);
2371
2384
  }
2372
- if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Rr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2385
+ if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Ur[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2373
2386
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2374
- n.push(`CHECK (${G(e.name)} IN (${t}))`);
2387
+ n.push(`CHECK (${W(e.name)} IN (${t}))`);
2375
2388
  }
2376
2389
  return n.join(" ");
2377
- }, Ur = (e) => {
2378
- let t = e.columns.map((e) => ` ${Hr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${jr(e, G)}\n)`];
2379
- 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(", ")})`);
2390
+ }, qr = (e) => {
2391
+ let t = e.columns.map((e) => ` ${Kr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Ir(e, W)}\n)`];
2392
+ 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(", ")})`);
2380
2393
  return n;
2381
2394
  }, J = (e, t) => {
2382
2395
  let n = t.find((t) => t.tableName === e);
2383
2396
  if (!n) return [];
2384
- let r = I([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
2385
- ...Ur({
2397
+ let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
2398
+ ...qr({
2386
2399
  kind: "create-table",
2387
2400
  table: i,
2388
2401
  columns: r.columns,
2389
2402
  indexes: [],
2390
2403
  ...r.primaryKey ? { primaryKey: r.primaryKey } : {}
2391
2404
  }),
2392
- `INSERT INTO ${G(i)} (${a}) SELECT ${a} FROM ${G(e)}`,
2393
- `DROP TABLE ${G(e)}`,
2394
- `ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
2405
+ `INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
2406
+ `DROP TABLE ${W(e)}`,
2407
+ `ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
2395
2408
  ];
2396
- 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(", ")})`);
2409
+ 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(", ")})`);
2397
2410
  return o;
2398
- }, Wr = (e, t, n, r) => {
2411
+ }, Jr = (e, t, n, r) => {
2399
2412
  let i = r ?? e.nullable;
2400
- return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${M(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2401
- }, Gr = (e, t) => {
2413
+ return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${j(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2414
+ }, Yr = (e, t) => {
2402
2415
  let n = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Y(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
2403
2416
  if (!e.hasDefault) return n;
2404
- let r = Vr(e.defaultValue, "SYSUTCDATETIME()");
2417
+ let r = q(e.defaultValue, "SYSUTCDATETIME()");
2405
2418
  if (!r) return n;
2406
2419
  let i = r.replace(/^DEFAULT\s+/i, "");
2407
2420
  return `${n} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${i} FOR ${Y(e.column)};`;
2408
- }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Kr = (e) => {
2409
- let t = fr(e, "mssql");
2421
+ }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Xr = (e) => {
2422
+ let t = _r(e, "mssql");
2410
2423
  if (t !== void 0) return t;
2411
2424
  switch (e.type) {
2412
2425
  case "id":
2413
2426
  case "reference": return "NVARCHAR(64)";
2414
2427
  case "integer": return "INT";
2415
2428
  case "real": return "FLOAT";
2416
- case "decimal": return ur(e, "DECIMAL");
2429
+ case "decimal": return hr(e, "DECIMAL");
2417
2430
  case "bigint": return "BIGINT";
2418
2431
  case "boolean": return "BIT";
2419
2432
  case "timestamp": return "DATETIME2(6)";
@@ -2421,44 +2434,44 @@ BEGIN
2421
2434
  case "bytes": return "VARBINARY(MAX)";
2422
2435
  default: return "NVARCHAR(MAX)";
2423
2436
  }
2424
- }, qr = (e, t) => {
2425
- if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mssql");
2426
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Kr(e), r = kr(e, "mssql");
2437
+ }, Zr = (e, t) => {
2438
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mssql");
2439
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Xr(e), r = Pr(e, "mssql");
2427
2440
  if (r) return `${Y(e.name)} ${r}`;
2428
2441
  let i = [Y(e.name), n];
2429
2442
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2430
- let t = Vr(e.defaultValue, "SYSUTCDATETIME()");
2443
+ let t = q(e.defaultValue, "SYSUTCDATETIME()");
2431
2444
  t && i.push(t);
2432
2445
  }
2433
- return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${zr[e.references.onDelete]}`)), i.join(" ");
2434
- }, Jr = (e) => {
2435
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${qr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${jr(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2446
+ return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${Wr[e.references.onDelete]}`)), i.join(" ");
2447
+ }, Qr = (e) => {
2448
+ let t = (e) => e.replace(/'/g, "''"), n = /* @__PURE__ */ new Set([...e.indexes.flatMap((e) => e.columns), ...e.columns.filter((e) => e.unique).map((e) => e.name)]), r = e.columns.map((e) => ` ${Zr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${Ir(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2436
2449
  for (let n of e.indexes) {
2437
2450
  if (n.name === `${e.table}_pkey`) continue;
2438
2451
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})`;
2439
2452
  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)}')`);
2440
2453
  }
2441
2454
  return a;
2442
- }, Yr = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Xr = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Zr = (e, t, n) => {
2443
- let r = `${e.table}${Yr(t)}`;
2455
+ }, $r = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, ei = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, ti = (e, t, n) => {
2456
+ let r = `${e.table}${$r(t)}`;
2444
2457
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2445
- }, Qr = (e) => {
2446
- if (e === void 0 || !Pr(e)) return;
2458
+ }, ni = (e) => {
2459
+ if (e === void 0 || !zr(e)) return;
2447
2460
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
2448
- return t === void 0 ? Nr : Math.min(Nr, t);
2449
- }, $r = (e, t, n) => {
2450
- let r = Qr(wr(e, t, n));
2451
- return r === void 0 ? K(n) : `${K(n)}(${r})`;
2452
- }, ei = (e) => e.startsWith("(") ? e : G(e), ti = (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(ei).join(", ")});`, ni = (e, t, n = "mariadb") => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${gr(n)}${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => $r(t, e.table, n)).join(", ")});`, ri = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, ii = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, ai = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, oi = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, si = (e) => {
2461
+ return t === void 0 ? Rr : Math.min(Rr, t);
2462
+ }, ri = (e, t, n) => {
2463
+ let r = ni(kr(e, t, n));
2464
+ return r === void 0 ? G(n) : `${G(n)}(${r})`;
2465
+ }, ii = (e) => e.startsWith("(") ? e : W(e), ai = (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(ii).join(", ")});`, oi = (e, t, n = "mariadb") => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${xr(n)}${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => ri(t, e.table, n)).join(", ")});`, si = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, ci = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, li = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, ui = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, di = (e) => {
2453
2466
  let t = (e) => e.replace(/'/g, "''");
2454
2467
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
2455
- }, ci = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, li = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, ui = (e) => {
2468
+ }, fi = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, pi = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, mi = (e) => {
2456
2469
  let t = (e) => e.replace(/'/g, "''");
2457
2470
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2458
- }, di = (e) => {
2471
+ }, hi = (e) => {
2459
2472
  let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Y(e.index.name)} ON ${Y(e.table)} (${e.index.columns.map(Y).join(", ")})`;
2460
2473
  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)}');`;
2461
- }, fi = (e, t, n) => {
2474
+ }, gi = (e, t, n) => {
2462
2475
  let r = n.find((t) => t.tableName === e);
2463
2476
  if (!r) return [];
2464
2477
  let i = [];
@@ -2467,13 +2480,13 @@ BEGIN
2467
2480
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2468
2481
  }
2469
2482
  return i;
2470
- }, pi = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, mi = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${$r(t, e.table, e.column)});`, hi = (e) => {
2471
- let t = e.fields.map((e) => G(e)).join(", ");
2472
- return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
2473
- }, gi = (e, t) => {
2474
- let n = e.fields.map((n) => $r(t, e.table, n)).join(", ");
2475
- return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
2476
- }, _i = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, vi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, yi = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, bi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, xi = (e, t) => {
2483
+ }, _i = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, vi = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${ri(t, e.table, e.column)});`, yi = (e) => {
2484
+ let t = e.fields.map((e) => W(e)).join(", ");
2485
+ return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
2486
+ }, bi = (e, t) => {
2487
+ let n = e.fields.map((n) => ri(t, e.table, n)).join(", ");
2488
+ return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
2489
+ }, xi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, Si = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, Ci = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, wi = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, Ti = (e, t) => {
2477
2490
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2478
2491
  if (e.orphanPolicy) {
2479
2492
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2491,34 +2504,34 @@ BEGIN
2491
2504
  setNull: "SET NULL",
2492
2505
  noAction: "NO ACTION"
2493
2506
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2494
- }, Si = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, Ci = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, wi = (e, t) => {
2507
+ }, Ei = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, Di = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, Oi = (e, t) => {
2495
2508
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2496
2509
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2497
- }, Ti = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, Ei = (e, t) => S.gen(function* () {
2510
+ }, ki = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, Ai = (e, t) => C.gen(function* () {
2498
2511
  let n = yield* e`
2499
2512
  SELECT cc.constraint_name AS n, cc.check_clause AS c
2500
2513
  FROM information_schema.check_constraints cc
2501
- WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(S.orElse(() => e`
2514
+ WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(C.orElse(() => e`
2502
2515
  SELECT cc.constraint_name AS n, cc.check_clause AS c
2503
2516
  FROM information_schema.check_constraints cc
2504
2517
  JOIN information_schema.table_constraints tc
2505
2518
  ON tc.constraint_schema = cc.constraint_schema
2506
2519
  AND tc.constraint_name = cc.constraint_name
2507
- WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), S.orElseSucceed(() => []));
2520
+ WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), C.orElseSucceed(() => []));
2508
2521
  for (let e of n) {
2509
2522
  let n = String(e.n ?? "");
2510
- if (n !== "" && Pn(String(e.c ?? ""))?.column === t.column) return n;
2523
+ if (n !== "" && Rn(String(e.c ?? ""))?.column === t.column) return n;
2511
2524
  }
2512
- }), Di = (e, t, n) => S.gen(function* () {
2513
- let r = yield* Ei(e, t);
2514
- r !== void 0 && (yield* X(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [lr]));
2515
- let i = yield* Ei(e, t);
2525
+ }), ji = (e, t, n) => C.gen(function* () {
2526
+ let r = yield* Ai(e, t);
2527
+ r !== void 0 && (yield* X(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [mr]));
2528
+ let i = yield* Ai(e, t);
2516
2529
  if (i === void 0) return;
2517
- let a = q(n, t.table, t.column);
2518
- if (!a) return yield* S.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
2519
- yield* X(e, `ALTER TABLE ${K(t.table)} MODIFY COLUMN ${Tr(a, t.column)};`, t.kind);
2520
- }), Oi = (e, t, n, r) => {
2521
- let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Y : G, s = a ? hr(i) : r === "mssql" ? Kr(i) : r === "sqlite" ? Br(i) : pr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? Er(e, i) : r === "mssql" ? Vr(e, "SYSUTCDATETIME()") : r === "sqlite" ? Vr(e, "CURRENT_TIMESTAMP") : Or(e, i), u = kr(i, r);
2530
+ let a = K(n, t.table, t.column);
2531
+ if (!a) return yield* C.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
2532
+ yield* X(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${Ar(a, t.column)};`, t.kind);
2533
+ }), Mi = (e, t, n, r) => {
2534
+ let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? Y : W, s = a ? br(i) : r === "mssql" ? Xr(i) : r === "sqlite" ? Gr(i) : vr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? jr(e, i) : r === "mssql" ? q(e, "SYSUTCDATETIME()") : r === "sqlite" ? q(e, "CURRENT_TIMESTAMP") : Nr(e, i), u = Pr(i, r);
2522
2535
  if (u) {
2523
2536
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2524
2537
  return {
@@ -2546,7 +2559,7 @@ BEGIN
2546
2559
  post: f ? [f] : []
2547
2560
  };
2548
2561
  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;
2549
- }, ki = (e) => {
2562
+ }, Ni = (e) => {
2550
2563
  let t = new Map(e.map((e) => [e.tableName, e]));
2551
2564
  return (e, n) => {
2552
2565
  let r = t.get(e);
@@ -2566,47 +2579,47 @@ BEGIN
2566
2579
  ...o
2567
2580
  };
2568
2581
  };
2569
- }, X = (e, t, n, r = []) => e.unsafe(t).pipe(S.catchIf((e) => ar(e, r), () => S.void), S.tapError((e) => S.sync(() => {
2570
- process.stderr.write(re(`applier: statement failed (op=${n})`, t, e, 400));
2571
- })), S.mapError((e) => {
2572
- let r = re(`applier: statement failed (op=${n})`, t, e, 400).trim();
2582
+ }, X = (e, t, n, r = []) => e.unsafe(t).pipe(C.catchIf((e) => ur(e, r), () => C.void), C.tapError((e) => C.sync(() => {
2583
+ process.stderr.write(oe(`applier: statement failed (op=${n})`, t, e, 400));
2584
+ })), C.mapError((e) => {
2585
+ let r = oe(`applier: statement failed (op=${n})`, t, e, 400).trim();
2573
2586
  return Object.assign(e, { message: r });
2574
- }), S.map(() => void 0)), Z = (e, t, n) => S.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : _(r, t)} FROM ${_(n, t)} WHERE 1=0`).pipe(S.as(!0), S.catchAll(() => S.succeed(!1))), Ai = (e, t) => S.gen(function* () {
2575
- let n = I([Ie], t).tables[0];
2576
- if (!n) return yield* S.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2587
+ }), C.map(() => void 0)), Z = (e, t, n) => C.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : o(r, t)} FROM ${o(n, t)} WHERE 1=0`).pipe(C.as(!0), C.catchAll(() => C.succeed(!1))), Pi = (e, t) => C.gen(function* () {
2588
+ let n = F([ze], t).tables[0];
2589
+ if (!n) return yield* C.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2577
2590
  let r = {
2578
2591
  kind: "create-table",
2579
- table: k,
2592
+ table: O,
2580
2593
  columns: n.columns,
2581
2594
  indexes: []
2582
2595
  }, i = yield* e.onDialectOrElse({
2583
- mysql: () => U(e).pipe(S.map((e) => Lr(r, e))),
2584
- mssql: () => S.succeed(Jr(r)),
2585
- sqlite: () => S.succeed(Ur(r)),
2586
- orElse: () => S.succeed(Mr(r))
2596
+ mysql: () => H(e).pipe(C.map((e) => Hr(r, e))),
2597
+ mssql: () => C.succeed(Qr(r)),
2598
+ sqlite: () => C.succeed(qr(r)),
2599
+ orElse: () => C.succeed(Lr(r))
2587
2600
  });
2588
- yield* S.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2589
- }), ji = (e) => e`
2601
+ yield* C.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2602
+ }), Fi = (e) => e`
2590
2603
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2591
2604
  ${e("status")}, ${e("payload")}
2592
- FROM ${e(k)}
2593
- `, Mi = (e, t, n, r) => S.gen(function* () {
2594
- let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
2595
- yield* S.forEach(r, ({ index: r, planned: a }) => e`
2596
- INSERT INTO ${e(k)}
2605
+ FROM ${e(O)}
2606
+ `, Ii = (e, t, n, r) => C.gen(function* () {
2607
+ let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2608
+ yield* C.forEach(r, ({ index: r, planned: a }) => e`
2609
+ INSERT INTO ${e(O)}
2597
2610
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2598
2611
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
2599
2612
  ${e("createdAt")})
2600
2613
  VALUES
2601
2614
  (${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
2602
- ${a.op.kind}, ${Re(a.op)}, ${"pending"},
2615
+ ${a.op.kind}, ${Ve(a.op)}, ${"pending"},
2603
2616
  ${JSON.stringify(a)}, ${i})
2604
2617
  `, { discard: !0 });
2605
- }), Ni = (e, t, n, r, i) => S.gen(function* () {
2606
- let a = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
2618
+ }), Li = (e, t, n, r, i) => C.gen(function* () {
2619
+ let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2607
2620
  if (r === "applied") {
2608
2621
  yield* e`
2609
- UPDATE ${e(k)}
2622
+ UPDATE ${e(O)}
2610
2623
  SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
2611
2624
  ${e("durationMs")} = ${i ?? null}
2612
2625
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
@@ -2614,145 +2627,145 @@ BEGIN
2614
2627
  return;
2615
2628
  }
2616
2629
  yield* e`
2617
- UPDATE ${e(k)}
2630
+ UPDATE ${e(O)}
2618
2631
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
2619
2632
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
2620
2633
  `;
2621
- }), Pi = (e, t, n, r) => S.gen(function* () {
2622
- let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
2634
+ }), Ri = (e, t, n, r) => C.gen(function* () {
2635
+ let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2623
2636
  r.length > 0 && (yield* e`
2624
- UPDATE ${e(k)}
2637
+ UPDATE ${e(O)}
2625
2638
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
2626
2639
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
2627
2640
  `), n.length > 0 && (yield* e`
2628
- UPDATE ${e(k)}
2641
+ UPDATE ${e(O)}
2629
2642
  SET ${e("status")} = ${"pending"}
2630
2643
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
2631
2644
  `);
2632
- }), Fi = (e, t) => t === void 0 ? e`DELETE FROM ${e(k)}`.pipe(S.asVoid) : e`DELETE FROM ${e(k)} WHERE ${e("runId")} = ${t}`.pipe(S.asVoid), Ii = (e, t, n) => S.gen(function* () {
2633
- if (Ke(n.op, n.classification, t) !== "artefact-repair") return "clean";
2634
- let r = n.op, i = (e) => _(e, t);
2645
+ }), zi = (e, t) => t === void 0 ? e`DELETE FROM ${e(O)}`.pipe(C.asVoid) : e`DELETE FROM ${e(O)} WHERE ${e("runId")} = ${t}`.pipe(C.asVoid), Bi = (e, t, n) => C.gen(function* () {
2646
+ if (Ye(n.op, n.classification, t) !== "artefact-repair") return "clean";
2647
+ let r = n.op, i = (e) => o(e, t);
2635
2648
  if (t === "sqlite" || t === "turso") {
2636
2649
  if (!("table" in r)) return "clean";
2637
- let n = `${r.table}${Ve}`;
2638
- return (yield* $(e, t, n)) ? ((yield* $(e, t, r.table)) ? yield* X(e, `DROP TABLE ${i(n)}`, "resume-repair") : yield* X(e, `ALTER TABLE ${i(n)} RENAME TO ${i(r.table)}`, "resume-repair"), yield* S.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
2650
+ let n = `${r.table}${We}`;
2651
+ return (yield* $(e, t, n)) ? ((yield* $(e, t, r.table)) ? yield* X(e, `DROP TABLE ${i(n)}`, "resume-repair") : yield* X(e, `ALTER TABLE ${i(n)} RENAME TO ${i(r.table)}`, "resume-repair"), yield* C.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(C.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
2639
2652
  }
2640
2653
  if (r.kind !== "alter-column-type") return "clean";
2641
- let a = `${r.column}${He}`, o = `${r.column}${Ue}`, s = yield* $(e, t, r.table, r.column), c = yield* $(e, t, r.table, a), l = yield* $(e, t, r.table, o), u = (e) => S.logWarning(`migration resume: ${e}`).pipe(S.annotateLogs({ scope: "voltro:migrate" }));
2642
- return !c && !l ? "clean" : s && c && !l ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(a)}`, "resume-repair"), yield* u(`dropped a half-populated shadow column '${r.table}.${a}' — replaying the type change`), "outstanding") : !s && c && l ? (yield* X(e, `ALTER TABLE ${i(r.table)} RENAME COLUMN ${i(a)} TO ${i(r.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(o)}`, "resume-repair"), yield* u(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : s && !c && l ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(o)}`, "resume-repair"), yield* u(`dropped the leftover pre-swap column '${r.table}.${o}'`), "applied") : yield* S.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${r.table}.${r.column}' left a shadow-swap state this resume cannot classify (column=${s}, ${a}=${c}, ${o}=${l}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
2643
- }), Li = (e, t, n, r = "fresh") => S.gen(function* () {
2644
- let i = process.hrtime.bigint(), a = ki(n.declared), o = t.op;
2654
+ let a = `${r.column}${Ge}`, s = `${r.column}${Ke}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, a), u = yield* $(e, t, r.table, s), d = (e) => C.logWarning(`migration resume: ${e}`).pipe(C.annotateLogs({ scope: "voltro:migrate" }));
2655
+ return !l && !u ? "clean" : c && l && !u ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(a)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${r.table}.${a}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* X(e, `ALTER TABLE ${i(r.table)} RENAME COLUMN ${i(a)} TO ${i(r.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : c && !l && u ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${r.table}.${s}'`), "applied") : yield* C.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${r.table}.${r.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${a}=${l}, ${s}=${u}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
2656
+ }), Vi = (e, t, n, r = "fresh") => C.gen(function* () {
2657
+ let i = process.hrtime.bigint(), a = Ni(n.declared), o = t.op;
2645
2658
  switch (o.kind) {
2646
2659
  case "create-table": {
2647
2660
  let t = yield* e.onDialectOrElse({
2648
- mysql: () => U(e).pipe(S.map((e) => Lr(o, e))),
2649
- mssql: () => S.succeed(Jr(o)),
2650
- sqlite: () => S.succeed(Ur(o)),
2651
- orElse: () => S.succeed(Mr(o))
2661
+ mysql: () => H(e).pipe(C.map((e) => Hr(o, e))),
2662
+ mssql: () => C.succeed(Qr(o)),
2663
+ sqlite: () => C.succeed(qr(o)),
2664
+ orElse: () => C.succeed(Lr(o))
2652
2665
  }), n = yield* e.onDialectOrElse({
2653
- mysql: () => S.succeed([or]),
2654
- orElse: () => S.succeed([])
2666
+ mysql: () => C.succeed([dr]),
2667
+ orElse: () => C.succeed([])
2655
2668
  });
2656
2669
  for (let r of t) yield* X(e, r, o.kind, n);
2657
2670
  break;
2658
2671
  }
2659
2672
  case "drop-table": {
2660
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Zr(o, n, e) : Xr(o, e);
2673
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? ti(o, n, e) : ei(o, e);
2661
2674
  yield* e.onDialectOrElse({
2662
- mysql: () => X(e, r(K), o.kind),
2663
- orElse: () => X(e, r(G), o.kind)
2675
+ mysql: () => X(e, r(G), o.kind),
2676
+ orElse: () => X(e, r(W), o.kind)
2664
2677
  });
2665
2678
  break;
2666
2679
  }
2667
2680
  case "drop-column": {
2668
2681
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2669
2682
  yield* e.onDialectOrElse({
2670
- mysql: () => U(e).pipe(S.flatMap((r) => X(e, t ? br(o, n, K) : vr(o, r), o.kind, t ? [] : [sr]))),
2671
- sqlite: () => X(e, t ? br(o, n, G) : _r(o, G, !1), o.kind, t ? [] : [cr]),
2672
- orElse: () => X(e, t ? br(o, n, G) : _r(o, G), o.kind)
2683
+ mysql: () => H(e).pipe(C.flatMap((r) => X(e, t ? Tr(o, n, G) : Cr(o, r), o.kind, t ? [] : [fr]))),
2684
+ sqlite: () => X(e, t ? Tr(o, n, W) : Sr(o, W, !1), o.kind, t ? [] : [pr]),
2685
+ orElse: () => X(e, t ? Tr(o, n, W) : Sr(o, W), o.kind)
2673
2686
  });
2674
2687
  break;
2675
2688
  }
2676
2689
  case "rename-column":
2677
2690
  yield* e.onDialectOrElse({
2678
- mysql: () => X(e, yr(o, K), o.kind),
2691
+ mysql: () => X(e, wr(o, G), o.kind),
2679
2692
  mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
2680
- orElse: () => X(e, yr(o, G), o.kind)
2693
+ orElse: () => X(e, wr(o, W), o.kind)
2681
2694
  });
2682
2695
  break;
2683
2696
  case "add-index":
2684
2697
  yield* e.onDialectOrElse({
2685
- mysql: () => U(e).pipe(S.flatMap((t) => X(e, ni(o, n.declared, t), o.kind, [or]))),
2686
- mssql: () => Z(e, [...fi(o.table, o.index.columns, n.declared), di(o)], o.kind),
2687
- orElse: () => X(e, ti(o, t.classification === "online-required"), o.kind)
2698
+ mysql: () => H(e).pipe(C.flatMap((t) => X(e, oi(o, n.declared, t), o.kind, [dr]))),
2699
+ mssql: () => Z(e, [...gi(o.table, o.index.columns, n.declared), hi(o)], o.kind),
2700
+ orElse: () => X(e, ai(o, t.classification === "online-required"), o.kind)
2688
2701
  });
2689
2702
  break;
2690
2703
  case "drop-index":
2691
2704
  yield* e.onDialectOrElse({
2692
- mysql: () => X(e, ii(o), o.kind),
2693
- mssql: () => X(e, ai(o), o.kind),
2694
- orElse: () => X(e, ri(o), o.kind)
2705
+ mysql: () => X(e, ci(o), o.kind),
2706
+ mssql: () => X(e, li(o), o.kind),
2707
+ orElse: () => X(e, si(o), o.kind)
2695
2708
  });
2696
2709
  break;
2697
2710
  case "rename-table":
2698
2711
  yield* e.onDialectOrElse({
2699
- mysql: () => X(e, oi(o, K), o.kind),
2700
- mssql: () => X(e, si(o), o.kind),
2701
- orElse: () => X(e, oi(o, G), o.kind)
2712
+ mysql: () => X(e, ui(o, G), o.kind),
2713
+ mssql: () => X(e, di(o), o.kind),
2714
+ orElse: () => X(e, ui(o, W), o.kind)
2702
2715
  });
2703
2716
  break;
2704
2717
  case "rename-index":
2705
2718
  yield* e.onDialectOrElse({
2706
- mysql: () => X(e, li(o), o.kind),
2707
- mssql: () => X(e, ui(o), o.kind),
2708
- orElse: () => X(e, ci(o), o.kind)
2719
+ mysql: () => X(e, pi(o), o.kind),
2720
+ mssql: () => X(e, mi(o), o.kind),
2721
+ orElse: () => X(e, fi(o), o.kind)
2709
2722
  });
2710
2723
  break;
2711
2724
  case "add-unique":
2712
2725
  yield* e.onDialectOrElse({
2713
- mysql: () => X(e, mi(o, n.declared), o.kind),
2726
+ mysql: () => X(e, vi(o, n.declared), o.kind),
2714
2727
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2715
- mssql: () => Z(e, [...fi(o.table, [o.column], n.declared), pi(o)], o.kind),
2716
- orElse: () => X(e, pi(o), o.kind)
2728
+ mssql: () => Z(e, [...gi(o.table, [o.column], n.declared), _i(o)], o.kind),
2729
+ orElse: () => X(e, _i(o), o.kind)
2717
2730
  });
2718
2731
  break;
2719
2732
  case "drop-unique":
2720
2733
  yield* e.onDialectOrElse({
2721
- mysql: () => X(e, bi(o), o.kind),
2734
+ mysql: () => X(e, wi(o), o.kind),
2722
2735
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2723
- orElse: () => X(e, yi(o), o.kind)
2736
+ orElse: () => X(e, Ci(o), o.kind)
2724
2737
  });
2725
2738
  break;
2726
2739
  case "add-unique-composite":
2727
2740
  yield* e.onDialectOrElse({
2728
- mysql: () => X(e, gi(o, n.declared), o.kind),
2741
+ mysql: () => X(e, bi(o, n.declared), o.kind),
2729
2742
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2730
- mssql: () => Z(e, [...fi(o.table, o.fields, n.declared), hi(o)], o.kind),
2731
- orElse: () => X(e, hi(o), o.kind)
2743
+ mssql: () => Z(e, [...gi(o.table, o.fields, n.declared), yi(o)], o.kind),
2744
+ orElse: () => X(e, yi(o), o.kind)
2732
2745
  });
2733
2746
  break;
2734
2747
  case "drop-unique-composite":
2735
2748
  yield* e.onDialectOrElse({
2736
- mysql: () => X(e, vi(o), o.kind),
2749
+ mysql: () => X(e, Si(o), o.kind),
2737
2750
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2738
- orElse: () => X(e, _i(o), o.kind)
2751
+ orElse: () => X(e, xi(o), o.kind)
2739
2752
  });
2740
2753
  break;
2741
2754
  case "add-foreign-key":
2742
2755
  yield* e.onDialectOrElse({
2743
- mysql: () => Z(e, xi(o, K), o.kind),
2756
+ mysql: () => Z(e, Ti(o, G), o.kind),
2744
2757
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2745
- orElse: () => Z(e, xi(o, G), o.kind)
2758
+ orElse: () => Z(e, Ti(o, W), o.kind)
2746
2759
  });
2747
2760
  break;
2748
2761
  case "add-column": {
2749
- let n = Oi(o, t, a, yield* e.onDialectOrElse({
2750
- mysql: () => S.succeed("mariadb"),
2751
- mssql: () => S.succeed("mssql"),
2752
- sqlite: () => S.succeed("sqlite"),
2753
- orElse: () => S.succeed("postgres")
2762
+ let n = Mi(o, t, a, yield* e.onDialectOrElse({
2763
+ mysql: () => C.succeed("mariadb"),
2764
+ mssql: () => C.succeed("mssql"),
2765
+ sqlite: () => C.succeed("sqlite"),
2766
+ orElse: () => C.succeed("postgres")
2754
2767
  }));
2755
- if (!(r === "resume" && (yield* $(e, Ne(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
2768
+ if (!(r === "resume" && (yield* $(e, Ie(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
2756
2769
  if (n.backfillKind === "sql" && n.backfillSql) {
2757
2770
  if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
2758
2771
  else {
@@ -2761,10 +2774,10 @@ BEGIN
2761
2774
  let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
2762
2775
  if (s.length === 0) break;
2763
2776
  let c = s.map((e) => e.id);
2764
- yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += s.length, yield* S.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows`).pipe(S.annotateLogs({
2777
+ yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += s.length, yield* C.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows`).pipe(C.annotateLogs({
2765
2778
  scope: "voltro:migrate",
2766
2779
  mode: "sql-batched"
2767
- })), i = s[s.length - 1].id, r > 0 && (yield* S.sleep(`${r} millis`));
2780
+ })), i = s[s.length - 1].id, r > 0 && (yield* C.sleep(`${r} millis`));
2768
2781
  }
2769
2782
  }
2770
2783
  } else if (n.backfillKind === "js" && n.backfillJs) {
@@ -2773,17 +2786,17 @@ BEGIN
2773
2786
  let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
2774
2787
  if (s.length === 0) break;
2775
2788
  for (let t of s) {
2776
- let r = yield* S.tryPromise({
2789
+ let r = yield* C.tryPromise({
2777
2790
  try: () => Promise.resolve(n.backfillJs({ id: t.id })),
2778
2791
  catch: (e) => e
2779
- }).pipe(S.orDie);
2792
+ }).pipe(C.orDie);
2780
2793
  yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${r} WHERE ${e("id")} = ${t.id}`;
2781
2794
  }
2782
- a += s.length, yield* S.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows processed`).pipe(S.annotateLogs({
2795
+ a += s.length, yield* C.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows processed`).pipe(C.annotateLogs({
2783
2796
  scope: "voltro:migrate",
2784
2797
  table: o.table,
2785
2798
  column: o.column.name
2786
- })), i = s[s.length - 1].id, r > 0 && (yield* S.sleep(`${r} millis`));
2799
+ })), i = s[s.length - 1].id, r > 0 && (yield* C.sleep(`${r} millis`));
2787
2800
  }
2788
2801
  }
2789
2802
  for (let t of n.post) yield* X(e, t, o.kind);
@@ -2792,83 +2805,83 @@ BEGIN
2792
2805
  case "alter-column-nullability":
2793
2806
  yield* e.onDialectOrElse({
2794
2807
  mysql: () => {
2795
- let t = q(n.declared, o.table, o.column);
2796
- return t ? X(e, `ALTER TABLE ${K(o.table)} MODIFY COLUMN ${Tr(t, o.column, o.toNullable)};`, o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2808
+ let t = K(n.declared, o.table, o.column);
2809
+ return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Ar(t, o.column, o.toNullable)};`, o.kind) : C.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2797
2810
  },
2798
2811
  mssql: () => {
2799
- let t = q(n.declared, o.table, o.column);
2800
- return t ? X(e, Wr(t, o.column, o.table, o.toNullable), o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
2812
+ let t = K(n.declared, o.table, o.column);
2813
+ return t ? X(e, Jr(t, o.column, o.table, o.toNullable), o.kind) : C.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
2801
2814
  },
2802
2815
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2803
- orElse: () => X(e, `ALTER TABLE ${G(o.table)} ALTER COLUMN ${G(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2816
+ orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
2804
2817
  });
2805
2818
  break;
2806
2819
  case "alter-column-default": {
2807
- let t = wr(n.declared, o.table, o.column), r = q(n.declared, o.table, o.column), i = (e) => o.hasDefault && r !== void 0 && Sr(r, e) ? r : void 0;
2820
+ let t = kr(n.declared, o.table, o.column), r = K(n.declared, o.table, o.column), i = (e) => o.hasDefault && r !== void 0 && Dr(r, e) ? r : void 0;
2808
2821
  yield* e.onDialectOrElse({
2809
2822
  mysql: () => {
2810
2823
  let n = i("mariadb");
2811
- return X(e, n ? `ALTER TABLE ${K(o.table)} MODIFY COLUMN ${Tr(n, o.column)};` : xr(o, K, (e) => Er(e, t)), o.kind);
2824
+ return X(e, n ? `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Ar(n, o.column)};` : Er(o, G, (e) => jr(e, t)), o.kind);
2812
2825
  },
2813
2826
  mssql: () => {
2814
2827
  let t = i("mssql");
2815
- return X(e, Gr(o, t ? Wr(t, o.column, o.table) : void 0), o.kind);
2828
+ return X(e, Yr(o, t ? Jr(t, o.column, o.table) : void 0), o.kind);
2816
2829
  },
2817
2830
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2818
- orElse: () => X(e, xr(o, G, (e) => Or(e, t)), o.kind)
2831
+ orElse: () => X(e, Er(o, W, (e) => Nr(e, t)), o.kind)
2819
2832
  });
2820
2833
  break;
2821
2834
  }
2822
2835
  case "alter-column-type": {
2823
- let r = pr(wr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
2836
+ let r = vr(kr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
2824
2837
  if (t.classification !== "online-required") {
2825
2838
  yield* e.onDialectOrElse({
2826
2839
  mysql: () => {
2827
- let t = q(n.declared, o.table, o.column);
2828
- return t ? X(e, `ALTER TABLE ${K(o.table)} MODIFY COLUMN ${Tr(t, o.column)};`, o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2840
+ let t = K(n.declared, o.table, o.column);
2841
+ return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Ar(t, o.column)};`, o.kind) : C.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2829
2842
  },
2830
2843
  mssql: () => {
2831
- let t = q(n.declared, o.table, o.column);
2832
- return t ? X(e, Wr(t, o.column, o.table), o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2844
+ let t = K(n.declared, o.table, o.column);
2845
+ return t ? X(e, Jr(t, o.column, o.table), o.kind) : C.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
2833
2846
  },
2834
2847
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2835
- orElse: () => X(e, `ALTER TABLE ${G(o.table)} ALTER COLUMN ${G(o.column)} TYPE ${r}${i};`, o.kind)
2848
+ orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
2836
2849
  });
2837
2850
  break;
2838
2851
  }
2839
2852
  yield* e.onDialectOrElse({
2840
- mysql: () => S.die(/* @__PURE__ */ Error(`online-required alter-column-type on ${o.table}.${o.column} is not supported on mariadb (the shadow-swap path is postgres-only). Use a smaller-table window or an external online-DDL tool.`)),
2841
- orElse: () => S.void
2853
+ mysql: () => C.die(/* @__PURE__ */ Error(`online-required alter-column-type on ${o.table}.${o.column} is not supported on mariadb (the shadow-swap path is postgres-only). Use a smaller-table window or an external online-DDL tool.`)),
2854
+ orElse: () => C.void
2842
2855
  });
2843
2856
  let a = `${o.column}__shadow`, s = `${o.column}__old`;
2844
- yield* e.unsafe(`ALTER TABLE ${G(o.table)} ADD COLUMN ${G(a)} ${r}`);
2845
- let c = o.using ?? G(o.column), l;
2857
+ yield* e.unsafe(`ALTER TABLE ${W(o.table)} ADD COLUMN ${W(a)} ${r}`);
2858
+ let c = o.using ?? W(o.column), l;
2846
2859
  for (;;) {
2847
2860
  let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Q(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Q(e, 5e3)}`;
2848
2861
  if (t.length === 0) break;
2849
- yield* e.unsafe(`UPDATE ${G(o.table)} SET ${G(a)} = ${c} WHERE ${G(o.column)} IS NOT NULL AND ${G(a)} IS NULL AND ${G("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2862
+ yield* e.unsafe(`UPDATE ${W(o.table)} SET ${W(a)} = ${c} WHERE ${W(o.column)} IS NOT NULL AND ${W(a)} IS NULL AND ${W("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2850
2863
  }
2851
- yield* S.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${G(o.table)} RENAME COLUMN ${G(o.column)} TO ${G(s)}`), yield* e.unsafe(`ALTER TABLE ${G(o.table)} RENAME COLUMN ${G(a)} TO ${G(o.column)}`), yield* e.unsafe(`ALTER TABLE ${G(o.table)} DROP COLUMN ${G(s)}`);
2864
+ yield* C.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(C.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${W(o.table)} RENAME COLUMN ${W(o.column)} TO ${W(s)}`), yield* e.unsafe(`ALTER TABLE ${W(o.table)} RENAME COLUMN ${W(a)} TO ${W(o.column)}`), yield* e.unsafe(`ALTER TABLE ${W(o.table)} DROP COLUMN ${W(s)}`);
2852
2865
  break;
2853
2866
  }
2854
2867
  case "drop-foreign-key":
2855
2868
  yield* e.onDialectOrElse({
2856
- mysql: () => X(e, Ci(o), o.kind),
2869
+ mysql: () => X(e, Di(o), o.kind),
2857
2870
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2858
- orElse: () => X(e, Si(o), o.kind)
2871
+ orElse: () => X(e, Ei(o), o.kind)
2859
2872
  });
2860
2873
  break;
2861
2874
  case "add-check":
2862
2875
  yield* e.onDialectOrElse({
2863
- mysql: () => X(e, wi(o, K), o.kind),
2876
+ mysql: () => X(e, Oi(o, G), o.kind),
2864
2877
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2865
- orElse: () => X(e, wi(o, G), o.kind)
2878
+ orElse: () => X(e, Oi(o, W), o.kind)
2866
2879
  });
2867
2880
  break;
2868
2881
  case "drop-check": yield* e.onDialectOrElse({
2869
- mysql: () => Di(e, o, n.declared),
2882
+ mysql: () => ji(e, o, n.declared),
2870
2883
  sqlite: () => Z(e, J(o.table, n.declared), o.kind),
2871
- orElse: () => X(e, Ti(o), o.kind)
2884
+ orElse: () => X(e, ki(o), o.kind)
2872
2885
  });
2873
2886
  }
2874
2887
  return {
@@ -2876,32 +2889,32 @@ BEGIN
2876
2889
  status: "applied",
2877
2890
  durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
2878
2891
  };
2879
- }), Ri = (e, t, n, r) => S.gen(function* () {
2892
+ }), Hi = (e, t, n, r) => C.gen(function* () {
2880
2893
  let i = [...new Set(r.map((e) => e.runId))];
2881
- if (i.length > 1) return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${i.length} unfinished runs (${i.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${k}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
2894
+ if (i.length > 1) return yield* C.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${i.length} unfinished runs (${i.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${O}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
2882
2895
  let a = i[0], o = [...r].map((e) => ({
2883
2896
  index: Number(e.opIndex),
2884
2897
  status: e.status,
2885
2898
  planned: JSON.parse(e.payload)
2886
2899
  })).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
2887
- if (c > 1) return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${c} operations as in-flight for run ${a}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${k}\` by hand before re-running.`));
2888
- if (yield* S.logWarning(`migration resume: found an interrupted run (${a}) — ${o.filter((e) => e.status === "applied").length} of ${o.length} operation(s) completed${s ? `, in flight: ${s.planned.op.kind} ${Re(s.planned.op)}` : ""}`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
2900
+ if (c > 1) return yield* C.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${c} operations as in-flight for run ${a}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${O}\` by hand before re-running.`));
2901
+ if (yield* C.logWarning(`migration resume: found an interrupted run (${a}) — ${o.filter((e) => e.status === "applied").length} of ${o.length} operation(s) completed${s ? `, in flight: ${s.planned.op.kind} ${Ve(s.planned.op)}` : ""}`).pipe(C.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
2889
2902
  kind: "discard",
2890
2903
  runId: a,
2891
2904
  why: "no operation had started — no DDL ran"
2892
2905
  };
2893
- let l = s ? yield* Ii(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2906
+ let l = s ? yield* Bi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
2894
2907
  if (u !== n.toFingerprint) return {
2895
2908
  kind: "discard",
2896
2909
  runId: a,
2897
2910
  why: `the declared schema changed since the interruption (recorded target ${u.slice(0, 12)}…, current ${n.toFingerprint.slice(0, 12)}…) — applying the freshly-diffed plan instead`
2898
2911
  };
2899
- let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Be(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
2912
+ let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Ue(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
2900
2913
  return f.length === 0 ? {
2901
2914
  kind: "discard",
2902
2915
  runId: a,
2903
2916
  why: "every recorded operation had already taken effect"
2904
- } : (yield* Pi(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* S.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), {
2917
+ } : (yield* Ri(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* C.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(C.annotateLogs({ scope: "voltro:migrate" })), {
2905
2918
  kind: "resume",
2906
2919
  runId: a,
2907
2920
  ops: f.map((e) => ({
@@ -2909,7 +2922,7 @@ BEGIN
2909
2922
  planned: e.planned
2910
2923
  }))
2911
2924
  });
2912
- }), zi = (e) => {
2925
+ }), Ui = (e) => {
2913
2926
  let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
2914
2927
  return [
2915
2928
  t.kind,
@@ -2918,66 +2931,66 @@ BEGIN
2918
2931
  n("name"),
2919
2932
  n("to")
2920
2933
  ].join("\0");
2921
- }, Bi = (e, t, n) => S.gen(function* () {
2934
+ }, Wi = (e, t, n) => C.gen(function* () {
2922
2935
  let r = t.operations.filter((e) => e.blocked);
2923
- if (r.length > 0) return yield* S.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
2924
- yield* je(e, { schema: n.lockSchema });
2925
- let i = Date.now(), a = [], o = Ne(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => zi(e))), l = {
2936
+ if (r.length > 0) return yield* C.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
2937
+ yield* Pe(e, { schema: n.lockSchema });
2938
+ let i = Date.now(), a = [], o = Ie(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => Ui(e))), l = {
2926
2939
  ...s,
2927
2940
  operations: s.operations.map((e) => {
2928
- if (!e.blocked || !c.has(zi(e))) return e;
2941
+ if (!e.blocked || !c.has(Ui(e))) return e;
2929
2942
  let { blocked: t, ...n } = e;
2930
2943
  return n;
2931
2944
  })
2932
2945
  };
2933
- (l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* S.logInfo(`migration: re-planned under the lock — ${t.operations.length} operation(s) became ${l.operations.length}. Another writer changed the schema while this plan waited.`).pipe(S.annotateLogs({ scope: "voltro:migrate" })));
2946
+ (l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* C.logInfo(`migration: re-planned under the lock — ${t.operations.length} operation(s) became ${l.operations.length}. Another writer changed the schema while this plan waited.`).pipe(C.annotateLogs({ scope: "voltro:migrate" })));
2934
2947
  let u = l.operations.filter((e) => e.blocked);
2935
- if (u.length > 0) return yield* O(e, { schema: n.lockSchema }).pipe(S.orDie), yield* S.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — re-planning under the migration lock found ${u.length} blocked operation(s). Run \`voltro db plan\` to see the fixes.`));
2936
- let d = Fe(o) === "plan-transactional", f = d ? l.operations.filter((e) => e.classification !== "online-required") : [], p = d ? l.operations.filter((e) => e.classification === "online-required") : l.operations, m = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, h = p.map((e, t) => ({
2948
+ if (u.length > 0) return yield* D(e, { schema: n.lockSchema }).pipe(C.orDie), yield* C.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — re-planning under the migration lock found ${u.length} blocked operation(s). Run \`voltro db plan\` to see the fixes.`));
2949
+ let d = Re(o) === "plan-transactional", f = d ? l.operations.filter((e) => e.classification !== "online-required") : [], p = d ? l.operations.filter((e) => e.classification === "online-required") : l.operations, m = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, h = p.map((e, t) => ({
2937
2950
  index: t,
2938
2951
  planned: e
2939
- })), g = "fresh";
2952
+ })), _ = "fresh";
2940
2953
  try {
2941
- yield* Ai(e, o);
2942
- let t = yield* ji(e);
2954
+ yield* Pi(e, o);
2955
+ let t = yield* Fi(e);
2943
2956
  if (t.length > 0) {
2944
- let n = yield* Ri(e, o, l, t);
2945
- n.kind === "resume" ? (m = n.runId, h = n.ops, g = "resume") : (yield* S.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield* Fi(e, n.runId));
2957
+ let n = yield* Hi(e, o, l, t);
2958
+ n.kind === "resume" ? (m = n.runId, h = n.ops, _ = "resume") : (yield* C.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(C.annotateLogs({ scope: "voltro:migrate" })), yield* zi(e, n.runId));
2946
2959
  }
2947
- g === "fresh" && h.length > 0 && (yield* Mi(e, m, l.toFingerprint, h)), f.length > 0 && (yield* e.withTransaction(S.gen(function* () {
2948
- let e = yield* E.SqlClient;
2949
- for (let t of f) a.push(yield* Li(e, t, n));
2960
+ _ === "fresh" && h.length > 0 && (yield* Ii(e, m, l.toFingerprint, h)), f.length > 0 && (yield* e.withTransaction(C.gen(function* () {
2961
+ let e = yield* T.SqlClient;
2962
+ for (let t of f) a.push(yield* Vi(e, t, n));
2950
2963
  })));
2951
2964
  for (let { index: t, planned: r } of h) {
2952
- yield* Ni(e, m, t, "started");
2953
- let i = a.length, o = yield* Li(e, r, n, g).pipe(S.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${h.length + f.length} operation(s) applied before this one${f.length > 0 ? ` (${f.length} of them in a transaction)` : ""}.\n` + (d ? " This dialect applies a plan atomically, so the run is rolled back.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The next \`voltro db apply\` resumes from operation ${t} — the ledger records the sequence.\n`) })));
2954
- a.push(o), yield* Ni(e, m, t, "applied", o.durationMs);
2965
+ yield* Li(e, m, t, "started");
2966
+ let i = a.length, o = yield* Vi(e, r, n, _).pipe(C.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${h.length + f.length} operation(s) applied before this one${f.length > 0 ? ` (${f.length} of them in a transaction)` : ""}.\n` + (d ? " This dialect applies a plan atomically, so the run is rolled back.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The next \`voltro db apply\` resumes from operation ${t} — the ledger records the sequence.\n`) })));
2967
+ a.push(o), yield* Li(e, m, t, "applied", o.durationMs);
2955
2968
  }
2956
2969
  } finally {
2957
- yield* O(e, { schema: n.lockSchema }).pipe(S.orDie);
2970
+ yield* D(e, { schema: n.lockSchema }).pipe(C.orDie);
2958
2971
  }
2959
- let _ = yield* n.replan(e);
2960
- if (_.operations.length > 0) {
2961
- let e = _.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");
2962
- return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${l.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${_.operations.length}:\n${e}${_.operations.length > 10 ? `\n … and ${_.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.`));
2972
+ let v = yield* n.replan(e);
2973
+ if (v.operations.length > 0) {
2974
+ let e = v.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");
2975
+ return yield* C.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${l.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${v.operations.length}:\n${e}${v.operations.length > 10 ? `\n … and ${v.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.`));
2963
2976
  }
2964
- let y = a.filter((e) => e.status === "applied").length, b = Date.now() - i, x = m, C = (/* @__PURE__ */ new Date()).toISOString(), w = yield* W(e, C), T = [...f, ...h.map((e) => e.planned)];
2977
+ let y = a.filter((e) => e.status === "applied").length, b = Date.now() - i, x = m, S = (/* @__PURE__ */ new Date()).toISOString(), ee = yield* U(e, S), w = [...f, ...h.map((e) => e.planned)];
2965
2978
  yield* e`
2966
2979
  INSERT INTO ${e("_voltro_migration_plans")}
2967
2980
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
2968
2981
  ${e("appliedBy")}, ${e("environment")}, ${e("source")},
2969
2982
  ${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
2970
2983
  VALUES
2971
- (${x}, ${l.toFingerprint}, ${_.fromFingerprint}, ${JSON.stringify(T)},
2984
+ (${x}, ${l.toFingerprint}, ${v.fromFingerprint}, ${JSON.stringify(w)},
2972
2985
  ${n.appliedBy}, ${n.environment}, ${n.source},
2973
- ${b}, ${w}, ${n.notes ?? null})
2974
- `, yield* Fi(e, m);
2975
- let ee = [...new Set(T.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
2976
- return yield* S.promise(() => v({ changedTables: ee }).catch(() => {})), {
2986
+ ${b}, ${ee}, ${n.notes ?? null})
2987
+ `, yield* zi(e, m);
2988
+ let te = [...new Set(w.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
2989
+ return yield* C.promise(() => g({ changedTables: te }).catch(() => {})), {
2977
2990
  id: x,
2978
- appliedAt: C,
2991
+ appliedAt: S,
2979
2992
  fingerprint: l.toFingerprint,
2980
- operations: T,
2993
+ operations: w,
2981
2994
  appliedBy: n.appliedBy,
2982
2995
  environment: n.environment,
2983
2996
  durationMs: b,
@@ -2985,14 +2998,14 @@ BEGIN
2985
2998
  source: n.source,
2986
2999
  ...n.notes ? { notes: n.notes } : {}
2987
3000
  };
2988
- }), Vi = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), Hi = (e) => e`
3001
+ }), Gi = (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"), Ki = (e) => e`
2989
3002
  SELECT fingerprint
2990
3003
  FROM _voltro_migration_plans
2991
3004
  ORDER BY ${e("appliedAt")} DESC
2992
3005
  LIMIT 1
2993
- `.pipe(S.map((e) => e.length > 0 ? e[0].fingerprint : void 0), S.catchAll(() => S.succeed(void 0))), Ui = (e, t, n) => S.gen(function* () {
2994
- if ((yield* Hi(e)) === t.toFingerprint) return "already-current";
2995
- let r = `plan_${Date.now().toString(36)}`, i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
3006
+ `.pipe(C.map((e) => e.length > 0 ? e[0].fingerprint : void 0), C.catchAll(() => C.succeed(void 0))), qi = (e, t, n) => C.gen(function* () {
3007
+ if ((yield* Ki(e)) === t.toFingerprint) return "already-current";
3008
+ let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2996
3009
  return yield* e`
2997
3010
  INSERT INTO ${e("_voltro_migration_plans")}
2998
3011
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -3003,8 +3016,8 @@ BEGIN
3003
3016
  ${n.appliedBy}, ${n.environment}, ${n.source},
3004
3017
  ${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
3005
3018
  `, "recorded";
3006
- }).pipe(S.catchAll(() => S.succeed("already-current"))), Wi = (e, t) => S.gen(function* () {
3007
- let n = Wt(I(t, Ne(e))), r = yield* Hi(e);
3019
+ }).pipe(C.catchAll(() => C.succeed("already-current"))), Ji = (e, t) => C.gen(function* () {
3020
+ let n = Jt(F(t, Ie(e))), r = yield* Ki(e);
3008
3021
  return r === n ? {
3009
3022
  kind: "up-to-date",
3010
3023
  fingerprint: n
@@ -3013,23 +3026,23 @@ BEGIN
3013
3026
  expected: n,
3014
3027
  ...r === void 0 ? {} : { actual: r }
3015
3028
  };
3016
- }), Gi = [
3029
+ }), Yi = [
3017
3030
  "pgeagertest_",
3018
3031
  "mig_e2e_",
3019
3032
  "mig_test_",
3020
3033
  "mysqleagertest_",
3021
3034
  "mssqleagertest_",
3022
3035
  "sqliteeagertest_"
3023
- ], Ki = (e) => Gi.some((t) => e.startsWith(t)), qi = (e, t) => S.gen(function* () {
3036
+ ], Xi = (e) => Yi.some((t) => e.startsWith(t)), Zi = (e, t) => C.gen(function* () {
3024
3037
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
3025
- let n = t.filter((e) => Ki(e.name)).map((e) => e.name);
3038
+ let n = t.filter((e) => Xi(e.name)).map((e) => e.name);
3026
3039
  if (n.length === 0) return [];
3027
- for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(S.catchAll(() => S.void));
3040
+ for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(C.catchAll(() => C.void));
3028
3041
  return n;
3029
- }), Ji = () => {
3042
+ }), Qi = () => {
3030
3043
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
3031
3044
  return e.length > 0 ? { ignoreTables: e } : {};
3032
- }, Yi = (e) => {
3045
+ }, $i = (e) => {
3033
3046
  if (e === void 0) return;
3034
3047
  let t = e.trim();
3035
3048
  if (t === "") return;
@@ -3039,87 +3052,94 @@ BEGIN
3039
3052
  kind: "tables",
3040
3053
  tables: new Set(n)
3041
3054
  } : void 0;
3042
- }, Xi = (e) => typeof e.table == "string" ? e.table : void 0, Zi = (e, t = { kind: "all" }) => ({
3055
+ }, ea = (e) => typeof e.table == "string" ? e.table : void 0, ta = (e, t = { kind: "all" }) => ({
3043
3056
  ...e,
3044
3057
  operations: e.operations.map((e) => {
3045
3058
  if (!e.blocked || e.classification !== "lossy") return e;
3046
3059
  if (t?.kind === "tables") {
3047
- let n = Xi(e.op);
3060
+ let n = ea(e.op);
3048
3061
  if (n === void 0 || !t.tables.has(n)) return e;
3049
3062
  }
3050
3063
  let { blocked: n, ...r } = e;
3051
3064
  return r;
3052
3065
  })
3053
- }), Qi = (e, t, n) => t === "postgres" ? Xt(e, n).pipe(S.flatMap((e) => {
3054
- let t = Zt(e);
3055
- return t === void 0 ? S.void : S.logWarning(`auto-migrate: ${t}`).pipe(S.annotateLogs({ scope: "voltro:migrate" }));
3056
- }), S.catchAll(() => S.void)) : S.void, $i = (e, t, n) => S.gen(function* () {
3057
- let r = Ne(e), i = t;
3066
+ }), na = (e, t, n) => t === "postgres" ? en(e, n).pipe(C.flatMap((e) => {
3067
+ let t = tn(e);
3068
+ return t === void 0 ? C.void : C.logWarning(`auto-migrate: ${t}`).pipe(C.annotateLogs({ scope: "voltro:migrate" }));
3069
+ }), C.catchAll(() => C.void)) : C.void, ra = (e, t, n) => C.gen(function* () {
3070
+ let r = Ie(e), a = t;
3058
3071
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
3059
- let t = Wt(I(i, r));
3060
- if ((yield* Hi(e)) === t) return yield* Qi(e, r, i), {
3072
+ let t = Jt(F(a, r));
3073
+ if ((yield* Ki(e)) === t) return yield* na(e, r, a), {
3061
3074
  kind: "up-to-date",
3062
3075
  fingerprint: t
3063
3076
  };
3064
3077
  }
3065
- let a = yield* $n(e), o = yield* qi(e, a.tables);
3066
- o.length > 0 && (yield* S.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(S.annotateLogs({
3078
+ let o = yield* ir(e), s = yield* Zi(e, o.tables);
3079
+ s.length > 0 && (yield* C.logInfo(`auto-migrate: reaped ${s.length} test-fixture leftover(s)`).pipe(C.annotateLogs({
3067
3080
  scope: "voltro:migrate",
3068
- count: o.length
3069
- })), a = yield* $n(e));
3070
- let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !h(e.name) || s.has(e.name)), l = Nn({
3071
- declared: i,
3072
- live: { tables: c(a.tables) },
3081
+ count: s.length
3082
+ })), o = yield* ir(e));
3083
+ {
3084
+ let e = n.softDropRetentionDays ?? 7, t = p(o, { retentionDays: e });
3085
+ t.length > 0 && (yield* C.logWarning(`auto-migrate: ${i(t, e)}`).pipe(C.annotateLogs({
3086
+ scope: "voltro:migrate",
3087
+ snapshots: t.map((e) => e.name)
3088
+ })));
3089
+ }
3090
+ let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u = Ln({
3091
+ declared: a,
3092
+ live: { tables: l(o.tables) },
3073
3093
  dialect: r,
3074
- ...Ji()
3094
+ ...Qi()
3075
3095
  });
3076
- if (l.summary.blocked > 0) {
3077
- let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Yi(process.env.VOLTRO_DESTRUCTIVE_OK);
3078
- if (t === void 0 || !e || (l = Zi(l, t), l.operations.some((e) => e.blocked))) return {
3096
+ if (u.summary.blocked > 0) {
3097
+ let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = $i(process.env.VOLTRO_DESTRUCTIVE_OK);
3098
+ if (t === void 0 || !e || (u = ta(u, t), u.operations.some((e) => e.blocked))) return {
3079
3099
  kind: "refused-blocked",
3080
- plan: l
3100
+ plan: u
3081
3101
  };
3082
3102
  }
3083
- return l.operations.length === 0 ? (yield* Ui(e, l, {
3103
+ return u.operations.length === 0 ? (yield* qi(e, u, {
3084
3104
  appliedBy: n.appliedBy,
3085
3105
  environment: n.environment === "prod" ? "dev" : n.environment,
3086
3106
  source: "auto-diff"
3087
3107
  }), {
3088
3108
  kind: "up-to-date",
3089
- fingerprint: l.toFingerprint
3109
+ fingerprint: u.toFingerprint
3090
3110
  }) : {
3091
3111
  kind: "applied",
3092
- applied: yield* Bi(e, l, {
3112
+ applied: yield* Wi(e, u, {
3093
3113
  declared: t,
3094
3114
  appliedBy: n.appliedBy,
3095
3115
  environment: n.environment === "prod" ? "dev" : n.environment,
3096
3116
  source: "auto-diff",
3097
- replan: (e) => S.gen(function* () {
3098
- let t = yield* $n(e);
3099
- return Nn({
3100
- declared: i,
3101
- live: { tables: c(t.tables) },
3117
+ replan: (e) => C.gen(function* () {
3118
+ let t = yield* ir(e);
3119
+ return Ln({
3120
+ declared: a,
3121
+ live: { tables: l(t.tables) },
3102
3122
  dialect: r,
3103
- ...Ji()
3123
+ ...Qi()
3104
3124
  });
3105
3125
  })
3106
3126
  }),
3107
- plan: l
3127
+ plan: u
3108
3128
  };
3109
- }), ea = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? S.succeed({
3129
+ }), ia = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? C.succeed({
3110
3130
  kind: "skipped",
3111
3131
  reason: "VOLTRO_AUTO_MIGRATE=0"
3112
- }) : n.environment === "prod" ? Wi(e, t) : $i(e, t, n), ta = (e, t) => {
3132
+ }) : n.environment === "prod" ? Ji(e, t) : ra(e, t, n), aa = (e, t) => {
3113
3133
  switch (e.kind) {
3114
3134
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
3115
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${Gt(e.fingerprint)})`;
3135
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${Yt(e.fingerprint)})`;
3116
3136
  case "applied": {
3117
3137
  let t = e.plan.summary;
3118
- return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${Gt(e.applied.fingerprint)}`;
3138
+ 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=${Yt(e.applied.fingerprint)}`;
3119
3139
  }
3120
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${Gt(e.expected)}` + (e.actual ? ` live=${Gt(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3140
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${Yt(e.expected)}` + (e.actual ? ` live=${Yt(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3121
3141
  case "refused-blocked": {
3122
- let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + Vi(e.plan), c = [""];
3142
+ 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` + Gi(e.plan), c = [""];
3123
3143
  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) {
3124
3144
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
3125
3145
  for (let r of e.plan.operations) {
@@ -3136,7 +3156,7 @@ BEGIN
3136
3156
  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");
3137
3157
  }
3138
3158
  }
3139
- }, na = T({ scope: "voltro:migrate" }), ra = /* @__PURE__ */ new Set([
3159
+ }, oa = ne({ scope: "voltro:migrate" }), sa = /* @__PURE__ */ new Set([
3140
3160
  "node_modules",
3141
3161
  "dist",
3142
3162
  "build",
@@ -3145,25 +3165,25 @@ BEGIN
3145
3165
  ".next",
3146
3166
  ".git",
3147
3167
  ".framework"
3148
- ]), ia = async (e) => {
3168
+ ]), ca = async (e) => {
3149
3169
  let t = [], n = async (e) => {
3150
- let r = await ee.readdir(e, { withFileTypes: !0 }).catch(() => []);
3170
+ let r = await re.readdir(e, { withFileTypes: !0 }).catch(() => []);
3151
3171
  for (let i of r) {
3152
- if (ra.has(i.name)) continue;
3153
- let r = te(e, i.name);
3154
- i.isDirectory() ? await n(r) : i.isFile() && m.test(i.name) && t.push(r);
3172
+ if (sa.has(i.name)) continue;
3173
+ let r = ie(e, i.name);
3174
+ i.isDirectory() ? await n(r) : i.isFile() && S.test(i.name) && t.push(r);
3155
3175
  }
3156
3176
  };
3157
3177
  return await n(e), t.sort((e, t) => {
3158
3178
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
3159
3179
  return n.localeCompare(r);
3160
3180
  });
3161
- }, aa = async (e) => {
3181
+ }, la = async (e) => {
3162
3182
  let t = [];
3163
3183
  for (let n of e) {
3164
- let e = (await import(ne(n).href)).default;
3165
- if (!g(e)) {
3166
- na.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
3184
+ let e = (await import(ae(n).href)).default;
3185
+ if (!u(e)) {
3186
+ oa.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
3167
3187
  continue;
3168
3188
  }
3169
3189
  t.push({
@@ -3172,11 +3192,11 @@ BEGIN
3172
3192
  });
3173
3193
  }
3174
3194
  return t;
3175
- }, oa = (e) => e`
3195
+ }, ua = (e) => e`
3176
3196
  SELECT ${e("id")}
3177
3197
  FROM ${e("_voltro_migration_plans")}
3178
3198
  WHERE ${e("source")} = 'file'
3179
- `.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))), sa = class extends Error {
3199
+ `.pipe(C.map((e) => e.map((e) => e.id)), C.catchAll(() => C.succeed([]))), da = class extends Error {
3180
3200
  migrationId;
3181
3201
  file;
3182
3202
  cause;
@@ -3184,28 +3204,28 @@ BEGIN
3184
3204
  constructor(e, t, n) {
3185
3205
  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";
3186
3206
  }
3187
- }, ca = (e, t, n, r) => S.gen(function* () {
3207
+ }, fa = (e, t, n, r) => C.gen(function* () {
3188
3208
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
3189
3209
  sql: e,
3190
3210
  log: {
3191
- info: (e, n) => S.logInfo(e).pipe(S.annotateLogs({
3211
+ info: (e, n) => C.logInfo(e).pipe(C.annotateLogs({
3192
3212
  scope: `migrations:file:${t.migration.id}`,
3193
3213
  ...n ?? {}
3194
3214
  })),
3195
- warn: (e, n) => S.logWarning(e).pipe(S.annotateLogs({
3215
+ warn: (e, n) => C.logWarning(e).pipe(C.annotateLogs({
3196
3216
  scope: `migrations:file:${t.migration.id}`,
3197
3217
  ...n ?? {}
3198
3218
  }))
3199
3219
  },
3200
3220
  appliedAt: a
3201
3221
  }, s = t.migration.up(o);
3202
- S.isEffect(s) ? yield* s : yield* S.tryPromise({
3222
+ C.isEffect(s) ? yield* s : yield* C.tryPromise({
3203
3223
  try: () => s,
3204
3224
  catch: (e) => e
3205
3225
  });
3206
3226
  let c = Date.now() - i;
3207
- !S.isEffect(s) && c < 2 && (yield* S.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(S.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
3208
- let l = yield* W(e, a);
3227
+ !C.isEffect(s) && c < 2 && (yield* C.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(C.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
3228
+ let l = yield* U(e, a);
3209
3229
  return yield* e`
3210
3230
  INSERT INTO ${e("_voltro_migration_plans")}
3211
3231
  (${e("id")}, ${e("fingerprint")}, ${e("operations")},
@@ -3218,94 +3238,94 @@ BEGIN
3218
3238
  }])},
3219
3239
  ${r}, ${n}, ${"file"},
3220
3240
  ${c}, ${l}, ${t.migration.description})
3221
- `.pipe(S.mapError((e) => new sa(t.migration.id, t.file, e))), { durationMs: c };
3222
- }), la = (e, t) => S.gen(function* () {
3223
- let n = yield* S.tryPromise({
3224
- try: () => ia(te(t, "migrations")),
3241
+ `.pipe(C.mapError((e) => new da(t.migration.id, t.file, e))), { durationMs: c };
3242
+ }), pa = (e, t) => C.gen(function* () {
3243
+ let n = yield* C.tryPromise({
3244
+ try: () => ca(ie(t, "migrations")),
3225
3245
  catch: (e) => e
3226
3246
  });
3227
3247
  if (n.length === 0) return {
3228
3248
  pending: [],
3229
3249
  skipped: []
3230
3250
  };
3231
- let r = yield* S.tryPromise({
3232
- try: () => aa(n),
3251
+ let r = yield* C.tryPromise({
3252
+ try: () => la(n),
3233
3253
  catch: (e) => e
3234
3254
  });
3235
3255
  if (r.length === 0) return {
3236
3256
  pending: [],
3237
3257
  skipped: []
3238
3258
  };
3239
- let i = new Set(yield* oa(e));
3259
+ let i = new Set(yield* ua(e));
3240
3260
  return {
3241
3261
  pending: r.filter((e) => !i.has(e.migration.id)),
3242
3262
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
3243
3263
  };
3244
- }), ua = (e, t) => la(e, t).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), da = (e, t) => S.gen(function* () {
3245
- let { pending: n, skipped: r } = yield* la(e, t.projectRoot);
3264
+ }), ma = (e, t) => pa(e, t).pipe(C.map((e) => e.pending.map((e) => e.migration.id))), ha = (e, t) => C.gen(function* () {
3265
+ let { pending: n, skipped: r } = yield* pa(e, t.projectRoot);
3246
3266
  if (n.length === 0) return {
3247
3267
  applied: [],
3248
3268
  skipped: r
3249
3269
  };
3250
- yield* je(e, { schema: t.lockSchema });
3270
+ yield* Pe(e, { schema: t.lockSchema });
3251
3271
  let i = [];
3252
3272
  try {
3253
3273
  for (let r of n) {
3254
- yield* S.logInfo("file-based migration applying").pipe(S.annotateLogs({
3274
+ yield* C.logInfo("file-based migration applying").pipe(C.annotateLogs({
3255
3275
  scope: "voltro:migrate",
3256
3276
  id: r.migration.id,
3257
3277
  file: r.file
3258
3278
  }));
3259
- let { durationMs: n } = yield* ca(e, r, t.env, t.appliedBy);
3279
+ let { durationMs: n } = yield* fa(e, r, t.env, t.appliedBy);
3260
3280
  i.push({
3261
3281
  id: r.migration.id,
3262
3282
  durationMs: n
3263
- }), yield* S.logInfo("file-based migration applied").pipe(S.annotateLogs({
3283
+ }), yield* C.logInfo("file-based migration applied").pipe(C.annotateLogs({
3264
3284
  scope: "voltro:migrate",
3265
3285
  id: r.migration.id,
3266
3286
  durationMs: n
3267
3287
  }));
3268
3288
  }
3269
3289
  } finally {
3270
- yield* O(e, { schema: t.lockSchema }).pipe(S.orDie);
3290
+ yield* D(e, { schema: t.lockSchema }).pipe(C.orDie);
3271
3291
  }
3272
3292
  return {
3273
3293
  applied: i,
3274
3294
  skipped: r
3275
3295
  };
3276
- }), fa = (e, t) => e`
3296
+ }), ga = (e, t) => e`
3277
3297
  SELECT ${e("id")}
3278
3298
  FROM ${e("_voltro_migration_plans")}
3279
3299
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
3280
3300
  LIMIT 1
3281
- `, pa = (e, t) => S.gen(function* () {
3282
- if (!(yield* fa(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3283
- let n = yield* S.tryPromise({
3284
- try: () => ia(te(t.projectRoot, "migrations")),
3301
+ `, _a = (e, t) => C.gen(function* () {
3302
+ if (!(yield* ga(e, t.id))[0]) return yield* C.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3303
+ let n = yield* C.tryPromise({
3304
+ try: () => ca(ie(t.projectRoot, "migrations")),
3285
3305
  catch: (e) => e
3286
- }), r = (yield* S.tryPromise({
3287
- try: () => aa(n),
3306
+ }), r = (yield* C.tryPromise({
3307
+ try: () => la(n),
3288
3308
  catch: (e) => e
3289
3309
  })).find((e) => e.migration.id === t.id);
3290
- if (!r) return yield* S.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3291
- yield* je(e, { schema: t.lockSchema });
3310
+ if (!r) return yield* C.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3311
+ yield* Pe(e, { schema: t.lockSchema });
3292
3312
  let i = Date.now();
3293
3313
  try {
3294
3314
  let n = {
3295
3315
  sql: e,
3296
3316
  log: {
3297
- info: (e, n) => S.logInfo(e).pipe(S.annotateLogs({
3317
+ info: (e, n) => C.logInfo(e).pipe(C.annotateLogs({
3298
3318
  scope: `migrations:file:${t.id}`,
3299
3319
  ...n ?? {}
3300
3320
  })),
3301
- warn: (e, n) => S.logWarning(e).pipe(S.annotateLogs({
3321
+ warn: (e, n) => C.logWarning(e).pipe(C.annotateLogs({
3302
3322
  scope: `migrations:file:${t.id}`,
3303
3323
  ...n ?? {}
3304
3324
  }))
3305
3325
  },
3306
3326
  appliedAt: (/* @__PURE__ */ new Date()).toISOString()
3307
3327
  }, a = r.migration.down(n);
3308
- S.isEffect(a) ? yield* a : yield* S.tryPromise({
3328
+ C.isEffect(a) ? yield* a : yield* C.tryPromise({
3309
3329
  try: () => a,
3310
3330
  catch: (e) => e
3311
3331
  });
@@ -3315,19 +3335,19 @@ BEGIN
3315
3335
  durationMs: o
3316
3336
  };
3317
3337
  } finally {
3318
- yield* O(e, { schema: t.lockSchema }).pipe(S.orDie);
3338
+ yield* D(e, { schema: t.lockSchema }).pipe(C.orDie);
3319
3339
  }
3320
- }), ma = (e) => S.gen(function* () {
3321
- let t = yield* E.SqlClient, n = yield* t`
3340
+ }), va = (e) => C.gen(function* () {
3341
+ let t = yield* T.SqlClient, n = yield* t`
3322
3342
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
3323
3343
  WHERE source = 'auto-diff'
3324
3344
  AND squashedAt IS NULL
3325
3345
  AND appliedAt < ${e.before}
3326
3346
  ORDER BY appliedAt DESC
3327
3347
  `;
3328
- if (n.length === 0) return yield* S.fail(/* @__PURE__ */ Error(`squash: no rows applied before ${e.before}`));
3348
+ if (n.length === 0) return yield* C.fail(/* @__PURE__ */ Error(`squash: no rows applied before ${e.before}`));
3329
3349
  let r = n[0];
3330
- if (r.fingerprint !== e.fingerprint) return yield* S.fail(/* @__PURE__ */ Error(`squash: latest pre-squash fingerprint (${r.fingerprint.slice(0, 12)}…) differs from current declared-schema fingerprint (${e.fingerprint.slice(0, 12)}…). This means the working tree carries un-applied changes — squashing now would lock the drift in.\n\nFix: run \`voltro db apply\` first to align the live schema with the working tree, then re-squash.`));
3350
+ if (r.fingerprint !== e.fingerprint) return yield* C.fail(/* @__PURE__ */ Error(`squash: latest pre-squash fingerprint (${r.fingerprint.slice(0, 12)}…) differs from current declared-schema fingerprint (${e.fingerprint.slice(0, 12)}…). This means the working tree carries un-applied changes — squashing now would lock the drift in.\n\nFix: run \`voltro db apply\` first to align the live schema with the working tree, then re-squash.`));
3331
3351
  yield* t`
3332
3352
  UPDATE _voltro_migration_plans
3333
3353
  SET squashedAt = CURRENT_TIMESTAMP
@@ -3362,7 +3382,7 @@ BEGIN
3362
3382
  snapshotFingerprint: e.fingerprint,
3363
3383
  snapshotId: i
3364
3384
  };
3365
- }), ha = { safe: !0 }, ga = (e) => {
3385
+ }), ya = { safe: !0 }, ba = (e) => {
3366
3386
  switch (e.kind) {
3367
3387
  case "drop-column": return {
3368
3388
  safe: !1,
@@ -3389,7 +3409,7 @@ BEGIN
3389
3409
  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`,
3390
3410
  remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
3391
3411
  };
3392
- case "alter-column-nullability": return e.toNullable ? ha : {
3412
+ case "alter-column-nullability": return e.toNullable ? ya : {
3393
3413
  safe: !1,
3394
3414
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
3395
3415
  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)`
@@ -3419,12 +3439,12 @@ BEGIN
3419
3439
  case "drop-unique":
3420
3440
  case "drop-unique-composite":
3421
3441
  case "drop-foreign-key":
3422
- case "drop-check": return ha;
3442
+ case "drop-check": return ya;
3423
3443
  }
3424
- }, _a = (e) => {
3444
+ }, xa = (e) => {
3425
3445
  let t = [];
3426
3446
  for (let n of e) {
3427
- let e = ga(n.op);
3447
+ let e = ba(n.op);
3428
3448
  e.safe || t.push({
3429
3449
  op: n,
3430
3450
  reason: e.reason,
@@ -3432,7 +3452,7 @@ BEGIN
3432
3452
  });
3433
3453
  }
3434
3454
  return t;
3435
- }, va = (e) => {
3455
+ }, Sa = (e) => {
3436
3456
  if (!e.enabled || e.unsafeCount === 0) return {
3437
3457
  refuse: !1,
3438
3458
  warnForced: !1,
@@ -3448,18 +3468,18 @@ BEGIN
3448
3468
  warnForced: !1,
3449
3469
  message: `${t}. Old instances would break against the new schema mid-rollout. Split into expand → deploy → contract (see the ⚠ list above), deploy with no overlap (maintenance window / scale-to-zero), or pass --force to override.`
3450
3470
  };
3451
- }, ya = (e) => {
3471
+ }, Ca = (e) => {
3452
3472
  let t = e.table;
3453
3473
  if (typeof t == "string") return t;
3454
3474
  let n = e.from;
3455
3475
  return typeof n == "string" ? n : void 0;
3456
- }, ba = (e) => ({
3476
+ }, wa = (e) => ({
3457
3477
  kind: e.op.kind,
3458
- table: ya(e.op),
3478
+ table: Ca(e.op),
3459
3479
  classification: e.classification,
3460
3480
  reason: e.reason,
3461
3481
  blockedFix: e.blocked?.fix
3462
- }), xa = (e) => e.operations.map(ba), Sa = async (e) => {
3482
+ }), Ta = (e) => e.operations.map(wa), Ea = async (e) => {
3463
3483
  let t = e.log ?? (() => {}), n = {
3464
3484
  branchId: e.branchId,
3465
3485
  mechanism: e.mechanism,
@@ -3478,10 +3498,10 @@ BEGIN
3478
3498
  applied: !1,
3479
3499
  converged: !1,
3480
3500
  residual: r,
3481
- infidelity: xa(o)
3501
+ infidelity: Ta(o)
3482
3502
  };
3483
3503
  else {
3484
- let i = await e.plan(), o = xa(i), s = o.filter((e) => e.classification === "lossy"), c = Zi(i), l = c.operations.filter((e) => e.blocked !== void 0).map(ba);
3504
+ let i = await e.plan(), o = Ta(i), s = o.filter((e) => e.classification === "lossy"), c = ta(i), l = c.operations.filter((e) => e.blocked !== void 0).map(wa);
3485
3505
  if (l.length > 0) a = {
3486
3506
  ...n,
3487
3507
  outcome: "blocked",
@@ -3506,7 +3526,7 @@ BEGIN
3506
3526
  };
3507
3527
  else {
3508
3528
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
3509
- let i = xa(await e.replan());
3529
+ let i = Ta(await e.replan());
3510
3530
  a = {
3511
3531
  ...n,
3512
3532
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -3544,7 +3564,7 @@ BEGIN
3544
3564
  ...a,
3545
3565
  tornDown: o
3546
3566
  };
3547
- }, Ca = (e) => {
3567
+ }, Da = (e) => {
3548
3568
  switch (e.outcome) {
3549
3569
  case "clean": return 0;
3550
3570
  case "lossy": return 2;
@@ -3553,22 +3573,22 @@ BEGIN
3553
3573
  case "infidelity": return 1;
3554
3574
  case "failed": return 1;
3555
3575
  }
3556
- }, wa = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Ta = (e) => {
3576
+ }, Oa = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ka = (e) => {
3557
3577
  let t = [];
3558
3578
  if (t.push(`branch rehearsal · ${e.branchId} · mechanism ${e.mechanism}`), t.push(` branched ${e.branchedTables} table(s), replayed ${e.replayedForeignKeys} foreign key(s)`), e.outcome === "failed") t.push(` FAILED: ${e.error ?? "unknown error"}`);
3559
3579
  else if (e.outcome === "infidelity") {
3560
3580
  t.push(" BRANCH IS NOT A FAITHFUL COPY of the parent — the rehearsal proves nothing about your migration."), t.push(" The parent's own schema still differs from the branch by:");
3561
- for (let n of e.infidelity) t.push(wa(n));
3581
+ for (let n of e.infidelity) t.push(Oa(n));
3562
3582
  } else {
3563
3583
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
3564
- for (let n of e.operations) t.push(wa(n));
3565
- if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(wa(n));
3584
+ for (let n of e.operations) t.push(Oa(n));
3585
+ if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(Oa(n));
3566
3586
  }
3567
3587
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
3568
- }, Ea = (e, ...t) => ({
3588
+ }, Aa = (e, ...t) => ({
3569
3589
  _tag: "RawSqlFragment",
3570
3590
  strings: [...e],
3571
3591
  values: [...t]
3572
- }), Da = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3592
+ }), ja = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3573
3593
  //#endregion
3574
- export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN, sa as FileMigrationLedgerError, qe as REACTIVE_TRIGGER_PREFIX, de as VOLTRO_MIGRATION_LOCK_KEY, je as acquireMigrationLock, W as appliedAtValue, It as applyNamespacedSchema, Bi as applyPlan, Et as applySchema, va as assessRollingDeployGate, Ca as branchRehearsalExitCode, Vn as chunkTables, ga as classifyRollingDeploySafety, I as declaredSnapshot, $e as defaultArrayClause, Qe as defaultClause, N as defaultJsonClause, ta as describeOutcome, Yi as destructiveScope, Xt as detectReactiveTriggerDrift, ni as emitAddIndexMysql, Lr as emitCreateTableMysql, _r as emitDropColumnDdl, vr as emitDropColumnDdlMysql, Tt as emitFrameworkBootstrapSql, Ct as emitNamespaceProvisionDdl, wt as emitNamespacedSchemaSql, St as emitSchemaSql, er as engineFromVersion, Wt as fingerprintSchema, _e as fnv1a64, Ta as formatBranchRehearsal, Zt as formatReactiveTriggerDrift, Ji as ignoreTablesFromEnv, $n as introspectSchema, ar as isAlreadySatisfied, g as isFileMigration, Da as isRawSqlFragment, Ot as isReRunSafeDdl, Fn as mapPgType, o as migration, ve as migrationLockKeyForSchema, ye as migrationLockNameForSchema, Qr as mysqlIndexPrefixFor, Ye as notifyFunctionName, P as numericIdSql, Pn as parseEnumCheck, ua as pendingFileMigrationIds, Nn as planMigrations, Lt as provisionTenantNamespace, Je as reactiveTriggerName, pt as reactiveTriggerRepairSql, Ui as recordUpToDate, Sa as rehearseMigrationOnBranch, ba as rehearsedOperation, O as releaseMigrationLock, Fr as renderColumnMysql, Ar as renderColumnPg, pe as resolveMigrationLockSchema, U as resolveMysqlEngine, pa as rollbackFileBasedMigration, _a as rollingDeployUnsafeOps, da as runFileBasedMigrations, Rt as runFrameworkBootstrap, Ft as runMigrate, ea as runPlannedMigrations, Gt as shortFingerprint, Kt as snapshotColumn, Ea as sql, M as sqlType, ma as squashMigrationPlans, Zi as unblockLossy, Me as withMigrationLock };
3594
+ export { k as DEFAULT_CDC_CHANNEL, S as FILE_MIGRATION_PATTERN, da as FileMigrationLedgerError, Xe as REACTIVE_TRIGGER_PREFIX, me as VOLTRO_MIGRATION_LOCK_KEY, Pe as acquireMigrationLock, U as appliedAtValue, Bt as applyNamespacedSchema, Wi as applyPlan, At as applySchema, Sa as assessRollingDeployGate, Da as branchRehearsalExitCode, Gn as chunkTables, ba as classifyRollingDeploySafety, F as declaredSnapshot, rt as defaultArrayClause, nt as defaultClause, M as defaultJsonClause, aa as describeOutcome, $i as destructiveScope, en as detectReactiveTriggerDrift, oi as emitAddIndexMysql, Hr as emitCreateTableMysql, Sr as emitDropColumnDdl, Cr as emitDropColumnDdlMysql, kt as emitFrameworkBootstrapSql, Dt as emitNamespaceProvisionDdl, Ot as emitNamespacedSchemaSql, Et as emitSchemaSql, ar as engineFromVersion, Jt as fingerprintSchema, be as fnv1a64, ka as formatBranchRehearsal, tn as formatReactiveTriggerDrift, Qi as ignoreTablesFromEnv, ir as introspectSchema, ur as isAlreadySatisfied, u as isFileMigration, ja as isRawSqlFragment, Mt as isReRunSafeDdl, zn as mapPgType, d as migration, xe as migrationLockKeyForSchema, Se as migrationLockNameForSchema, ni as mysqlIndexPrefixFor, Qe as notifyFunctionName, N as numericIdSql, Rn as parseEnumCheck, ma as pendingFileMigrationIds, Ln as planMigrations, Vt as provisionTenantNamespace, Ze as reactiveTriggerName, _t as reactiveTriggerRepairSql, qi as recordUpToDate, Ea as rehearseMigrationOnBranch, wa as rehearsedOperation, D as releaseMigrationLock, Br as renderColumnMysql, Fr as renderColumnPg, ge as resolveMigrationLockSchema, H as resolveMysqlEngine, _a as rollbackFileBasedMigration, xa as rollingDeployUnsafeOps, ha as runFileBasedMigrations, Ht as runFrameworkBootstrap, zt as runMigrate, ia as runPlannedMigrations, Yt as shortFingerprint, Xt as snapshotColumn, Aa as sql, j as sqlType, va as squashMigrationPlans, ta as unblockLossy, Fe as withMigrationLock };