@voltro/database 0.70.0 → 0.71.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sql.js CHANGED
@@ -1,13 +1,48 @@
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 C } from "./frameworkLiveTables-CWbTSnjk.js";
2
- import { Effect as w, Exit as T, Schedule as ee, Scope as te } from "effect";
3
- import { createHash as ne } from "node:crypto";
4
- import { createLogger as re } from "@voltro/logger";
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 C } from "./frameworkLiveTables-D53uncZH.js";
2
+ import { Cause as w, Effect as T, Equal as ee, Exit as te, Schedule as ne, Scope as re } from "effect";
3
+ import { createHash as ie } from "node:crypto";
4
+ import { createLogger as ae } from "@voltro/logger";
5
5
  import { SqlClient as E } from "@effect/sql";
6
- import { promises as ie } from "node:fs";
7
- import { join as ae } from "node:path";
8
- import { pathToFileURL as oe } from "node:url";
9
- //#region src/migrations/ddlError.ts
10
- var se = (e, t, n, r = 400) => {
6
+ import { promises as oe } from "node:fs";
7
+ import { join as se } from "node:path";
8
+ import { pathToFileURL as ce } from "node:url";
9
+ //#region src/indexStorage.ts
10
+ var le = (e, t = "float32") => {
11
+ let n = e?.hnsw, r = n?.m ?? 16, i = n?.efConstruction ?? 64;
12
+ for (let [e, t] of Object.entries({
13
+ m: r,
14
+ efConstruction: i
15
+ })) if (!Number.isSafeInteger(t) || t <= 0) throw Error(`HNSW ${e} must be a positive safe integer`);
16
+ let a = n?.opclass ?? h(n?.distance, t);
17
+ if (!/^[a-z_][a-z0-9_$]*(?:\.[a-z_][a-z0-9_$]*)?$/i.test(a)) throw Error("HNSW opclass must be an unquoted, optionally schema-qualified identifier");
18
+ return {
19
+ m: r,
20
+ efConstruction: i,
21
+ opclass: a.toLowerCase().replace(/^public\./, "")
22
+ };
23
+ }, ue = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree", de = (e, t) => ({
24
+ ...e !== void 0 && e !== "btree" ? { kind: e } : {},
25
+ ...e === "hnsw" ? { kindOptions: { hnsw: le(t) } } : {}
26
+ }), fe = (e, t, n = "float32") => {
27
+ if (e === void 0 || e === "btree") return {
28
+ using: "",
29
+ withSuffix: "",
30
+ skip: !1
31
+ };
32
+ if (!/^[a-z_][a-z0-9_]*$/i.test(e)) throw Error("Index kind must be an SQL access-method identifier");
33
+ if (e !== "hnsw") return {
34
+ using: ` USING ${e.toUpperCase()}`,
35
+ withSuffix: "",
36
+ skip: !1
37
+ };
38
+ let r = le(t, n);
39
+ return {
40
+ using: " USING hnsw",
41
+ withSuffix: ` WITH (m = ${r.m}, ef_construction = ${r.efConstruction})`,
42
+ opclass: r.opclass,
43
+ skip: !1
44
+ };
45
+ }, pe = (e, t, n, r = 400) => {
11
46
  let i = n, a = i.cause ?? {}, o = (e) => {
12
47
  let t = a[e];
13
48
  return t == null || t === "" ? void 0 : String(t);
@@ -38,21 +73,21 @@ var se = (e, t, n, r = 400) => {
38
73
  let t = o(e);
39
74
  t !== void 0 && s.push(`db.${e}: ${t}`);
40
75
  }
41
- let c = ce(o("code"));
76
+ let c = me(o("code"));
42
77
  return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
43
- }, ce = (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, le = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, ue = (e) => e.replace(/"/g, "`"), de = (e) => typeof e == "string" ? e : e.name ?? String(e), fe = (e, t) => `_ua_${t}_${e}`.slice(0, 64), pe = (e, t) => {
44
- if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(le)) return e;
78
+ }, me = (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, he = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, ge = (e) => e.replace(/"/g, "`"), _e = (e) => typeof e == "string" ? e : e.name ?? String(e), ve = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ye = (e, t) => {
79
+ if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(he)) return e;
45
80
  let n = { ...e.fields }, r = [], i = [];
46
81
  for (let t of e.appliedIndexes) {
47
- if (!le(t)) {
82
+ if (!he(t)) {
48
83
  r.push(t);
49
84
  continue;
50
85
  }
51
- let a = ue(t.where), o = [];
86
+ let a = ge(t.where), o = [];
52
87
  for (let r of t.fields) {
53
- let i = de(r);
88
+ let i = _e(r);
54
89
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
55
- let s = fe(t.name, i);
90
+ let s = ve(t.name, i);
56
91
  o.push(s), n[s] = {
57
92
  type: "text",
58
93
  nullable: !0,
@@ -75,7 +110,7 @@ var se = (e, t, n, r = 400) => {
75
110
  appliedIndexes: r,
76
111
  appliedUniques: [...e.appliedUniques ?? [], ...i]
77
112
  };
78
- }, D = (e, t) => `${e}::${t}`, me = (e, t) => {
113
+ }, D = (e, t) => `${e}::${t}`, be = (e, t) => {
79
114
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
80
115
  n.add(e);
81
116
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
@@ -84,73 +119,73 @@ var se = (e, t, n, r = 400) => {
84
119
  };
85
120
  for (let t of [...e].sort()) r.has(t) || a(t);
86
121
  return i;
87
- }, O = (e, t) => e.executeUnprepared(t, [], void 0), he = 6322741009312437n, ge = (e) => {
122
+ }, O = (e, t) => e.executeUnprepared(t, [], void 0), xe = 6322741009312437n, Se = (e) => {
88
123
  let t = e?.trim();
89
124
  return t === void 0 || t === "" || t === "public" ? void 0 : t;
90
- }, _e = (e) => e?.schema === void 0 ? ge(process.env.DB_SCHEMA) : ge(e.schema), ve = 14695981039346656037n, ye = 1099511628211n, be = 18446744073709551615n, xe = (e) => {
91
- let t = ve;
92
- for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * ye & be;
125
+ }, Ce = (e) => e?.schema === void 0 ? Se(process.env.DB_SCHEMA) : Se(e.schema), we = 14695981039346656037n, Te = 1099511628211n, Ee = 18446744073709551615n, De = (e) => {
126
+ let t = we;
127
+ for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * Te & Ee;
93
128
  return t;
94
- }, Se = (e) => {
95
- let t = ge(e);
96
- return t === void 0 ? he : xe(`voltro_migration_lock:${t}`) & 9223372036854775807n;
97
- }, Ce = (e) => {
98
- let t = `voltro_migration_${he.toString(36)}`, n = ge(e);
129
+ }, Oe = (e) => {
130
+ let t = Se(e);
131
+ return t === void 0 ? xe : De(`voltro_migration_lock:${t}`) & 9223372036854775807n;
132
+ }, ke = (e) => {
133
+ let t = `voltro_migration_${xe.toString(36)}`, n = Se(e);
99
134
  if (n === void 0) return t;
100
135
  let r = `${t}_${n}`;
101
- return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(xe(`voltro_migration_lock:${n}`) & be).toString(16)}`;
102
- }, we = 250, Te = () => {
136
+ return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(De(`voltro_migration_lock:${n}`) & Ee).toString(16)}`;
137
+ }, Ae = 250, je = () => {
103
138
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
104
139
  return Number.isFinite(e) && e > 0 ? e : 3e4;
105
- }, Ee = (e, t) => w.gen(function* () {
106
- let n = Te(), r = Date.now();
140
+ }, Me = (e, t) => T.gen(function* () {
141
+ let n = je(), r = Date.now();
107
142
  for (;;) {
108
143
  if ((yield* O(e, `SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`))[0]?.got) return;
109
- Date.now() - r >= n && (yield* w.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* w.sleep(`${we} millis`);
144
+ Date.now() - r >= n && (yield* T.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* T.sleep(`${Ae} millis`);
110
145
  }
111
- }), De = (e, t) => w.asVoid(O(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Oe = 30, ke = (e, t) => w.gen(function* () {
112
- (yield* O(e, `SELECT GET_LOCK('${t}', ${String(Oe)}) AS got`))[0]?.got !== 1 && (yield* w.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Oe}s (another migration is in progress, or a prior one left it held).`)));
113
- }), Ae = (e, t) => w.asVoid(O(e, `SELECT RELEASE_LOCK('${t}')`)), je = 3e4, Me = (e, t) => w.gen(function* () {
146
+ }), Ne = (e, t) => T.asVoid(O(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Pe = 30, Fe = (e, t) => T.gen(function* () {
147
+ (yield* O(e, `SELECT GET_LOCK('${t}', ${String(Pe)}) AS got`))[0]?.got !== 1 && (yield* T.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Pe}s (another migration is in progress, or a prior one left it held).`)));
148
+ }), Ie = (e, t) => T.asVoid(O(e, `SELECT RELEASE_LOCK('${t}')`)), Le = 3e4, Re = (e, t) => T.gen(function* () {
114
149
  let n = yield* O(e, `
115
150
  DECLARE @res int;
116
151
  EXEC @res = sp_getapplock @Resource = '${t}', @LockMode = 'Exclusive',
117
- @LockOwner = 'Session', @LockTimeout = ${String(je)};
152
+ @LockOwner = 'Session', @LockTimeout = ${String(Le)};
118
153
  SELECT @res AS res`);
119
- (n[0]?.res ?? -999) < 0 && (yield* w.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
120
- }), Ne = (e, t) => w.asVoid(O(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), Pe = w.void, Fe = (e, t) => w.gen(function* () {
121
- let n = _e(t), r = Ce(n), i = Se(n);
154
+ (n[0]?.res ?? -999) < 0 && (yield* T.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
155
+ }), ze = (e, t) => T.asVoid(O(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), Be = T.void, Ve = (e, t) => T.gen(function* () {
156
+ let n = Ce(t), r = ke(n), i = Oe(n);
122
157
  if (!e.onDialectOrElse({
123
158
  mysql: () => !0,
124
159
  mssql: () => !0,
125
160
  sqlite: () => !1,
126
161
  orElse: () => !0
127
- })) return { release: Pe };
128
- let a = yield* te.make(), o = yield* w.provideService(e.reserve, te.Scope, a), s = te.close(a, T.void);
162
+ })) return { release: Be };
163
+ let a = yield* re.make(), o = yield* T.provideService(e.reserve, re.Scope, a), s = re.close(a, te.void);
129
164
  return yield* e.onDialectOrElse({
130
- mysql: () => ke(o, r),
131
- mssql: () => Me(o, r),
132
- sqlite: () => Pe,
133
- orElse: () => Ee(o, i)
134
- }).pipe(w.onExit((e) => T.isSuccess(e) ? w.void : s)), { release: e.onDialectOrElse({
135
- mysql: () => Ae(o, r),
136
- mssql: () => Ne(o, r),
137
- sqlite: () => Pe,
138
- orElse: () => De(o, i)
139
- }).pipe(w.ensuring(s)) };
140
- }), Ie = (e, t, n) => w.acquireUseRelease(Fe(e, n), () => t, (e) => e.release.pipe(w.orDie)), Le = (e) => e.onDialectOrElse({
165
+ mysql: () => Fe(o, r),
166
+ mssql: () => Re(o, r),
167
+ sqlite: () => Be,
168
+ orElse: () => Me(o, i)
169
+ }).pipe(T.onExit((e) => te.isSuccess(e) ? T.void : s)), { release: e.onDialectOrElse({
170
+ mysql: () => Ie(o, r),
171
+ mssql: () => ze(o, r),
172
+ sqlite: () => Be,
173
+ orElse: () => Ne(o, i)
174
+ }).pipe(T.ensuring(s)) };
175
+ }), He = (e, t, n) => T.acquireUseRelease(Ve(e, n), () => t, (e) => e.release.pipe(T.orDie)), Ue = (e) => e.onDialectOrElse({
141
176
  pg: () => "postgres",
142
177
  mysql: () => "mysql",
143
178
  mssql: () => "mssql",
144
179
  sqlite: () => "sqlite",
145
180
  orElse: () => "sqlite"
146
- }), Re = {
181
+ }), We = {
147
182
  postgres: "plan-transactional",
148
183
  mssql: "plan-transactional",
149
184
  mysql: "per-operation",
150
185
  mariadb: "per-operation",
151
186
  sqlite: "per-operation",
152
187
  turso: "per-operation"
153
- }, ze = (e) => Re[e], k = "_voltro_migration_ops", Be = l(k, {
188
+ }, Ge = (e) => We[e], k = "_voltro_migration_ops", Ke = l(k, {
154
189
  id: y({ prefix: "mop" }),
155
190
  runId: a(),
156
191
  planFingerprint: a(),
@@ -163,7 +198,7 @@ var se = (e, t, n, r = 400) => {
163
198
  appliedAt: v().nullable(),
164
199
  durationMs: t().nullable(),
165
200
  createdAt: v().default("now")
166
- }), Ve = (e) => {
201
+ }), qe = (e) => {
167
202
  switch (e.kind) {
168
203
  case "create-table": return /* @__PURE__ */ new Set([
169
204
  `table:${e.table}`,
@@ -183,18 +218,19 @@ var se = (e, t, n, r = 400) => {
183
218
  case "add-foreign-key":
184
219
  case "drop-foreign-key":
185
220
  case "add-check":
186
- case "drop-check": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column}`]);
221
+ case "drop-check":
222
+ case "reconcile-json-check": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column}`]);
187
223
  case "add-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index.name}`]);
188
224
  case "drop-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index}`]);
189
225
  case "rename-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.from}`, `index:${e.table}.${e.to}`]);
190
226
  case "add-unique-composite":
191
227
  case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
192
228
  }
193
- }, He = (e) => [...Ve(e)].join(" "), Ue = (e, t) => {
194
- let n = Ve(t);
195
- for (let t of Ve(e)) if (n.has(t)) return !0;
229
+ }, Je = (e) => [...qe(e)].join(" "), Ye = (e, t) => {
230
+ let n = qe(t);
231
+ for (let t of qe(e)) if (n.has(t)) return !0;
196
232
  return !1;
197
- }, We = (e, t) => e.operations.some((e) => Ue(e.op, t)), Ge = "__voltro_rebuild", Ke = "__shadow", qe = "__old", Je = /* @__PURE__ */ new Set([
233
+ }, Xe = (e, t) => e.operations.some((e) => Ye(e.op, t)), Ze = "__voltro_rebuild", Qe = "__shadow", $e = "__old", et = /* @__PURE__ */ new Set([
198
234
  "add-unique",
199
235
  "drop-unique",
200
236
  "add-unique-composite",
@@ -206,20 +242,58 @@ var se = (e, t, n, r = 400) => {
206
242
  "alter-column-nullability",
207
243
  "alter-column-type",
208
244
  "alter-column-default"
209
- ]), Ye = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Xe = (e, t, n) => {
245
+ ]), tt = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), nt = (e, t, n) => {
210
246
  let r = n === "sqlite" || n === "turso";
211
- return e.kind === "alter-column-type" && t === "online-required" || r && Je.has(e.kind) ? "artefact-repair" : Ye.has(e.kind) ? "idempotent" : "probe-then-replay";
247
+ return e.kind === "alter-column-type" && t === "online-required" || r && et.has(e.kind) ? "artefact-repair" : tt.has(e.kind) ? "idempotent" : "probe-then-replay";
212
248
  };
213
- Object.keys(Re);
249
+ Object.keys(We);
214
250
  //#endregion
215
- //#region src/migrations/reactiveTriggerName.ts
216
- var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "framework_changes" ? `${Ze}${e}` : `${Ze}${t}_${e}`, $e = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, et = "voltro:notify:v2", tt = (e, t) => {
251
+ //#region src/mssqlJsonValueCheck.ts
252
+ var rt = (e) => {
253
+ let t = `(N'{"v":' + ${e} + N'}')`, n = `ISJSON(${t}) = 1`, r = `JSON_MODIFY(CASE WHEN ${n} THEN ${t} ELSE N'{}' END, '$.v', NULL)`;
254
+ return `(${e} IS NULL OR (${n} AND ${[
255
+ 32,
256
+ 9,
257
+ 10,
258
+ 13
259
+ ].reduce((e, t) => `REPLACE(${e}, NCHAR(${t}), N'')`, r)} = N'{}'))`;
260
+ }, it = (e) => {
261
+ let t = [], n = /\s+|N?'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|[A-Za-z_][A-Za-z_0-9]*|[0-9]+|[()+,=]/giy, r = 0;
262
+ for (; r < e.length;) {
263
+ n.lastIndex = r;
264
+ let i = n.exec(e);
265
+ if (!i) return;
266
+ let a = i[0];
267
+ /^\s+$/.test(a) || t.push(/^(?:N?')|^\[/i.test(a) ? a.replace(/^n'/, "N'") : a.toLowerCase()), r = n.lastIndex;
268
+ }
269
+ return t;
270
+ }, at = (e, t) => {
271
+ let n = `[${e.replaceAll("]", "]]")}]`, r = `(N'{"v":'+${n})+N'}'`, i = `isjson(${r})=(1)`, a = `json_modify(case when ${i} then ${r} else N'{}' end,'$.v',NULL)`, o = [
272
+ 32,
273
+ 9,
274
+ 10,
275
+ 13
276
+ ].reduce((e, t) => `replace(${e},nchar((${t})),N'')`, a), s = [
277
+ ["value", rt(n)],
278
+ ["value", `(${n} IS NULL OR ${i} AND ${o}=N'{}')`],
279
+ ["container", `(${n} IS NULL OR ISJSON(${n}) = 1)`],
280
+ ["container", `(${n} IS NULL OR isjson(${n})=(1))`]
281
+ ], c = it(t);
282
+ if (c) return s.find(([, e]) => {
283
+ let t = it(e);
284
+ return t?.length === c.length && t.every((e, t) => e === c[t]);
285
+ })?.[0];
286
+ }, ot = (e) => {
287
+ if (e.length === 0) return;
288
+ let t = e.filter((e) => e.enabled);
289
+ return t.some((e) => e.validation === "container") ? t.some((e) => e.validation === "container" && e.trusted) ? "container" : "unverified" : t.some((e) => e.validation === "value" && e.trusted) ? "value" : "unverified";
290
+ }, A = "framework_changes", st = "framework_changes_", ct = (e, t) => t === "framework_changes" ? `${st}${e}` : `${st}${t}_${e}`, lt = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, ut = "voltro:notify:v2", dt = (e, t) => {
217
291
  if (e.type === "text" && e.generatedAs === void 0) {
218
292
  if (e.maxLength !== void 0) return e.maxLength;
219
293
  if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
220
294
  }
221
- }, nt = re({ scope: "voltro:migrate" }), j = (e) => {
222
- nt.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
295
+ }, ft = ae({ scope: "voltro:migrate" }), j = (e) => {
296
+ ft.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
223
297
  }, M = (e, t) => {
224
298
  let n = e.type;
225
299
  if (e.spatial) {
@@ -302,7 +376,7 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
302
376
  if (t === "mssql") switch (n) {
303
377
  case "id": return "NVARCHAR(64)";
304
378
  case "text": {
305
- let t = tt(e, !1);
379
+ let t = dt(e, !1);
306
380
  return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
307
381
  }
308
382
  case "integer": return "INT";
@@ -334,11 +408,11 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
334
408
  case "array": return "TEXT[]";
335
409
  case "interval": return "INTERVAL";
336
410
  }
337
- }, rt = (e, t) => {
411
+ }, pt = (e, t) => {
338
412
  if (!e.hasDefault || e.defaultFactory !== void 0) return null;
339
413
  let n = e.defaultValue;
340
- 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) ? it(n, e, t) : typeof n == "object" && n ? N(n, t) : null;
341
- }, it = (e, t, n) => {
414
+ 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) ? mt(n, e, t) : typeof n == "object" && n ? N(n, t) : null;
415
+ }, mt = (e, t, n) => {
342
416
  if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return N(e, n);
343
417
  let r = M({
344
418
  ...t,
@@ -366,18 +440,18 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
366
440
  case "setNull": return "SET NULL";
367
441
  case "noAction": return "NO ACTION";
368
442
  }
369
- }, at = (e, t, n) => n === null ? o(e, t) : `${o(n, t)}.${o(e, t)}`, ot = 191, st = (e, t) => {
443
+ }, ht = (e, t, n) => n === null ? o(e, t) : `${o(n, t)}.${o(e, t)}`, gt = 191, _t = (e, t) => {
370
444
  if (!e || t !== "mysql" && t !== "mariadb") return !1;
371
445
  let n = M(e, t).toUpperCase();
372
446
  return n.endsWith("TEXT") || n.endsWith("BLOB");
373
- }, ct = (e, t, n) => {
447
+ }, vt = (e, t, n) => {
374
448
  let r = o(e, n);
375
449
  if (n !== "mysql" && n !== "mariadb") return r;
376
450
  let i = t[e];
377
451
  if (!i) return r;
378
452
  let a = M(i, n).toUpperCase();
379
- return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${ot})` : r;
380
- }, lt = (e, t) => {
453
+ return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${gt})` : r;
454
+ }, yt = (e, t) => {
381
455
  if (!e.generatedAs) return null;
382
456
  let { expr: n, stored: r } = e.generatedAs;
383
457
  if (t === "postgres") return r || j("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
@@ -385,15 +459,15 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
385
459
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
386
460
  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.");
387
461
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
388
- }, ut = (e, t, n, r, i = !1, a = !1) => {
462
+ }, bt = (e, t, n, r, i = !1, a = !1) => {
389
463
  if (t.type === "id" && t.idScheme?.kind === "numeric") return P(e, n);
390
- let s = n === "mssql" ? tt(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? M(t, n) : `NVARCHAR(${s})`, l = [o(e, n), c];
464
+ let s = n === "mssql" ? dt(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? M(t, n) : `NVARCHAR(${s})`, l = [o(e, n), c];
391
465
  t.type === "id" && !a && l.push("PRIMARY KEY");
392
- let u = lt(t, n);
466
+ let u = yt(t, n);
393
467
  if (u) l.push(u);
394
468
  else {
395
- t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !st(t, n) && l.push("UNIQUE");
396
- let e = rt(t, n);
469
+ t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !_t(t, n) && l.push("UNIQUE");
470
+ let e = pt(t, n);
397
471
  e && l.push(e);
398
472
  }
399
473
  if (t.type === "reference" && t.references && !i && !b(n)) {
@@ -414,30 +488,30 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
414
488
  l.push(`CHECK (${o(e, n)} IN (${r}))`);
415
489
  }
416
490
  if (t.type === "json" || t.type === "array") {
417
- let t = o(e, n);
418
- m(n) ? l.push(`CHECK (${t} IS NULL OR json_valid(${t}))`) : n === "mssql" && l.push(`CHECK (${t} IS NULL OR ISJSON(${t}) = 1)`);
491
+ let r = o(e, n);
492
+ m(n) ? l.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : n === "mssql" && l.push(t.type === "json" ? `CHECK ${rt(r)}` : `CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
419
493
  }
420
494
  return l.join(" ");
421
- }, dt = (e, t, n = null, r) => {
495
+ }, xt = (e, t, n = null, r) => {
422
496
  let i = /* @__PURE__ */ new Set();
423
497
  for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
424
498
  for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
425
499
  for (let [t, n] of Object.entries(e.fields)) n.unique && i.add(t);
426
500
  let a = e.appliedPrimaryKey ?? [];
427
501
  for (let e of a) i.add(e);
428
- let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${ut(e, n, t, i, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
429
- let r = n.fields.map((n) => ct(n, e.fields, t)).join(", ");
502
+ let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${bt(e, n, t, i, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
503
+ let r = n.fields.map((n) => vt(n, e.fields, t)).join(", ");
430
504
  return ` CONSTRAINT ${o(n.name, t)} UNIQUE (${r})`;
431
- }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${o(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${a.map((n) => ct(n, e.fields, t)).join(", ")})`] : [], f = b(t) ? Object.entries(e.fields).flatMap(([i, a]) => {
505
+ }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${o(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${a.map((n) => vt(n, e.fields, t)).join(", ")})`] : [], f = b(t) ? Object.entries(e.fields).flatMap(([i, a]) => {
432
506
  if (a.type !== "reference" || !a.references || (r?.has(i) ?? !1)) return [];
433
507
  let s = a.references(), c = F(a.onDelete ?? "restrict", t), l = F(a.refOnUpdate ?? "noAction", t);
434
- return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${at(s.tableName, t, n)} (${o(a.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
508
+ return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${ht(s.tableName, t, n)} (${o(a.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
435
509
  }) : [], p = [
436
510
  ...d,
437
511
  ...l,
438
512
  ...u,
439
513
  ...f
440
- ], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = at(e.tableName, t, n);
514
+ ], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = ht(e.tableName, t, n);
441
515
  if (t === "mssql") {
442
516
  let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${h} (\n${m}\n)`;
443
517
  return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
@@ -447,56 +521,29 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
447
521
  m,
448
522
  ");"
449
523
  ].join("\n");
450
- }, ft = (e, t, n) => {
524
+ }, St = (e, t, n) => {
451
525
  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 = [];
452
526
  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;
453
- }, pt = (e, t, n = null) => {
454
- let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i) => {
455
- let a = {
527
+ }, Ct = (e, t, n = null) => {
528
+ let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i, a) => {
529
+ if (t === "postgres") return fe(r, i, a);
530
+ let o = {
456
531
  using: "",
457
532
  withSuffix: "",
458
533
  skip: !1
459
534
  };
460
- if (r === void 0 || r === "btree") return a;
461
- if (r === "gist") return t === "postgres" ? {
462
- using: " USING GIST",
463
- withSuffix: "",
464
- skip: !1
465
- } : (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.`), a);
466
- if (r === "gin") return t === "postgres" ? {
467
- using: " USING GIN",
468
- withSuffix: "",
469
- skip: !1
470
- } : 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(...).`), {
535
+ return r === void 0 || r === "btree" ? o : r === "gist" ? (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) : r === "gin" ? 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(...).`), {
471
536
  using: "",
472
537
  withSuffix: "",
473
538
  skip: !0
474
- }) : (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.`), a);
475
- if (r === "brin") return t === "postgres" ? {
476
- using: " USING BRIN",
539
+ }) : (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) : r === "brin" ? (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) : r === "hnsw" ? (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.`), {
540
+ using: "",
477
541
  withSuffix: "",
478
- skip: !1
479
- } : (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).`), a);
480
- if (r === "hnsw") {
481
- if (t === "postgres") {
482
- let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? h(i?.hnsw?.distance);
483
- return {
484
- using: " USING hnsw",
485
- withSuffix: ` WITH (m = ${e}, ef_construction = ${t})`,
486
- opclass: n,
487
- skip: !1
488
- };
489
- }
490
- 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.`), {
491
- using: "",
492
- withSuffix: "",
493
- skip: !0
494
- };
495
- }
496
- return a;
542
+ skip: !0
543
+ }) : o;
497
544
  }, c = (n, r) => {
498
545
  let i = n.map((n) => {
499
- if (typeof n == "string") return ct(n, e.fields, t);
546
+ if (typeof n == "string") return vt(n, e.fields, t);
500
547
  if ("jsonPath" in n) {
501
548
  let { column: e, path: r, numeric: i } = n.jsonPath;
502
549
  return `(${C(e, r, t, { numeric: i })})`;
@@ -504,14 +551,14 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
504
551
  return `(${n.expr})`;
505
552
  });
506
553
  return r !== void 0 && i.length === 1 ? `${i[0]} ${r}` : i.join(", ");
507
- }, l = (e, r, i, a, l, u = "", d = !1) => {
508
- let f = s(e, r, a, l);
509
- if (f.skip) return "";
510
- let p = c(i, f.opclass), m = `${f.withSuffix}${u}`, h = at(r, t, n), g = d ? "UNIQUE " : "";
511
- 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};`;
554
+ }, l = (r, i, a, l, u, d = "", f = !1) => {
555
+ let p = a[0], m = typeof p == "string" ? e.fields[p]?.vectorPrecision : void 0, h = s(r, i, l, u, m);
556
+ if (h.skip) return "";
557
+ let g = c(a, h.opclass), _ = `${h.withSuffix}${d}`, v = ht(i, t, n), y = f ? "UNIQUE " : "";
558
+ return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${r}') CREATE ${y}INDEX ${o(r, t)} ON ${v}${h.using} (${g})${_};` : t === "mysql" ? `CREATE ${y}INDEX ${o(r, t)} ON ${v}${h.using} (${g})${_};` : `CREATE ${y}INDEX IF NOT EXISTS ${o(r, t)} ON ${v}${h.using} (${g})${_};`;
512
559
  };
513
560
  if (t === "mysql" || t === "mariadb") for (let [n, i] of Object.entries(e.fields)) {
514
- if (!i.unique || i.type === "id" || !st(i, t)) continue;
561
+ if (!i.unique || i.type === "id" || !_t(i, t)) continue;
515
562
  let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
516
563
  a && r.push(a);
517
564
  }
@@ -525,7 +572,7 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
525
572
  let i = n.columns.map((e) => o(e, t)).join(", ");
526
573
  r.push(`CREATE FULLTEXT INDEX ${o(n.name, t)} ON ${o(e.tableName, t)} (${i});`);
527
574
  } 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.`);
528
- else t === "sqlite" ? r.push(...ft(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).`);
575
+ 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).`);
529
576
  for (let n of e.appliedIndexes) {
530
577
  if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
531
578
  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(...).`);
@@ -543,17 +590,17 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
543
590
  r.push(l(o, e.tableName, [t])), i.add(a([t]));
544
591
  }
545
592
  return r.join("\n");
546
- }, mt = (e, t, n = A) => {
593
+ }, wt = (e, t, n = A) => {
547
594
  if (t !== "postgres") return [];
548
595
  let r = e.filter((e) => e.isReactive !== !1);
549
- return r.length === 0 ? [] : [ht(n), ...r.map((e) => _t(e, n))];
550
- }, ht = (e) => `
551
- CREATE OR REPLACE FUNCTION ${$e(e)}() RETURNS trigger AS $$
596
+ return r.length === 0 ? [] : [Tt(n), ...r.map((e) => Dt(e, n))];
597
+ }, Tt = (e) => `
598
+ CREATE OR REPLACE FUNCTION ${lt(e)}() RETURNS trigger AS $$
552
599
  DECLARE
553
600
  payload TEXT;
554
601
  pk JSONB;
555
602
  BEGIN
556
- -- ${et}
603
+ -- ${ut}
557
604
  payload := json_build_object(
558
605
  'table', TG_TABLE_NAME,
559
606
  -- The schema the write landed in. Under namespace isolation this is
@@ -607,22 +654,22 @@ BEGIN
607
654
  RETURN COALESCE(NEW, OLD);
608
655
  END;
609
656
  $$ LANGUAGE plpgsql;
610
- `.trim(), gt = (e, t) => {
611
- let n = Qe(e.tableName, t);
657
+ `.trim(), Et = (e, t) => {
658
+ let n = ct(e.tableName, t);
612
659
  return [
613
660
  `ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
614
661
  `DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
615
- `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${$e(t)}()`
662
+ `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${lt(t)}()`
616
663
  ];
617
- }, _t = (e, t) => gt(e, t).map((e) => `${e};`).join("\n"), vt = (e) => {
664
+ }, Dt = (e, t) => Et(e, t).map((e) => `${e};`).join("\n"), Ot = (e) => {
618
665
  if (e.dialect !== "postgres") return [];
619
666
  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));
620
- (i.length > 0 || e.functionOutdated === !0) && r.push(ht(t));
621
- for (let e of i) r.push(...gt(n.get(e), t));
622
- for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Qe(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
667
+ (i.length > 0 || e.functionOutdated === !0) && r.push(Tt(t));
668
+ for (let e of i) r.push(...Et(n.get(e), t));
669
+ for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${ct(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
623
670
  return r;
624
- }, yt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), bt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), xt = (e) => {
625
- let t = new Map(e.map((e) => [e.tableName, e])), n = me(e.map((e) => e.tableName), (e) => {
671
+ }, kt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), At = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), jt = (e) => {
672
+ let t = new Map(e.map((e) => [e.tableName, e])), n = be(e.map((e) => e.tableName), (e) => {
626
673
  let n = t.get(e);
627
674
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
628
675
  if (n.type !== "reference" || !n.references) return [];
@@ -659,7 +706,7 @@ $$ LANGUAGE plpgsql;
659
706
  sorted: o,
660
707
  cyclic: r
661
708
  };
662
- }, St = (e, t, n = null) => {
709
+ }, Mt = (e, t, n = null) => {
663
710
  let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a = F(e.onDelete, t), s = F(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(e.targetColumn, t)})${c}`;
664
711
  switch (t) {
665
712
  case "postgres": return [
@@ -674,7 +721,7 @@ $$ LANGUAGE plpgsql;
674
721
  case "mariadb": return `ALTER TABLE ${r(e.table)} ${l(!0)};`;
675
722
  default: return `ALTER TABLE ${r(e.table)} ${l(!1)};`;
676
723
  }
677
- }, Ct = (e, t) => {
724
+ }, Nt = (e, t) => {
678
725
  let n = /* @__PURE__ */ new Map();
679
726
  if (m(t)) return n;
680
727
  for (let t of e) {
@@ -682,7 +729,7 @@ $$ LANGUAGE plpgsql;
682
729
  e.add(t.column), n.set(t.table, e);
683
730
  }
684
731
  return n;
685
- }, wt = (e, t) => {
732
+ }, Pt = (e, t) => {
686
733
  if (t !== "postgres") return "";
687
734
  let n = /* @__PURE__ */ new Map();
688
735
  for (let t of e) for (let e of Object.values(t.fields)) {
@@ -698,7 +745,7 @@ $$ LANGUAGE plpgsql;
698
745
  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 $$;`);
699
746
  }
700
747
  return r.join("\n\n");
701
- }, Tt = (e, t) => {
748
+ }, Ft = (e, t) => {
702
749
  if (t !== "postgres") return "";
703
750
  let r = /* @__PURE__ */ new Set();
704
751
  for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && r.add(e.enumName);
@@ -712,30 +759,30 @@ BEGIN
712
759
  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 $$;`);
713
760
  }
714
761
  return i.join("\n\n");
715
- }, Et = (e) => {
762
+ }, It = (e) => {
716
763
  let t = [], n = [];
717
764
  for (let r of e) s(r) ? n.push(r) : t.push(r);
718
765
  return {
719
766
  tables: t,
720
767
  views: n
721
768
  };
722
- }, Dt = (t, n, r = A) => {
723
- let { tables: i, views: a } = Et(t), { sorted: o, cyclic: s } = xt(i.map((e) => pe(e, n))), c = Ct(s, n), l = [];
724
- n === "postgres" && yt(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && bt(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
725
- let u = Tt(o, n);
769
+ }, Lt = (t, n, r = A) => {
770
+ let { tables: i, views: a } = It(t), { sorted: o, cyclic: s } = jt(i.map((e) => ye(e, n))), c = Nt(s, n), l = [];
771
+ n === "postgres" && kt(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && At(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
772
+ let u = Ft(o, n);
726
773
  u && l.push(u);
727
- let d = wt(o, n);
774
+ let d = Pt(o, n);
728
775
  d && l.push(d);
729
- for (let e of o) l.push(dt(e, n, null, c.get(e.tableName)));
730
- if (!m(n)) for (let e of s) l.push(St(e, n));
776
+ for (let e of o) l.push(xt(e, n, null, c.get(e.tableName)));
777
+ if (!m(n)) for (let e of s) l.push(Mt(e, n));
731
778
  for (let e of o) {
732
- let t = pt(e, n);
779
+ let t = Ct(e, n);
733
780
  t && l.push(t);
734
781
  }
735
- l.push(...mt(o, n, r));
782
+ l.push(...wt(o, n, r));
736
783
  for (let t of a) l.push(e(t, n));
737
784
  return l.join("\n\n") + "\n";
738
- }, Ot = (e, t, n) => {
785
+ }, Rt = (e, t, n) => {
739
786
  let r = o(e, t);
740
787
  switch (t) {
741
788
  case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
@@ -745,62 +792,62 @@ BEGIN
745
792
  case "turso":
746
793
  case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
747
794
  }
748
- }, kt = (e, t, n, r) => {
749
- let i = Ot(n, t, r), a = o(n, t);
750
- if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${Dt(e, t)}`;
751
- if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${Dt(e, t)}`;
752
- let { sorted: s, cyclic: c } = xt(e), l = Ct(c, t), u = [i];
753
- for (let e of s) u.push(dt(e, t, n, l.get(e.tableName)));
754
- if (!m(t)) for (let e of c) u.push(St(e, t, n));
795
+ }, zt = (e, t, n, r) => {
796
+ let i = Rt(n, t, r), a = o(n, t);
797
+ if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${Lt(e, t)}`;
798
+ if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${Lt(e, t)}`;
799
+ let { sorted: s, cyclic: c } = jt(e), l = Nt(c, t), u = [i];
800
+ for (let e of s) u.push(xt(e, t, n, l.get(e.tableName)));
801
+ if (!m(t)) for (let e of c) u.push(Mt(e, t, n));
755
802
  for (let e of s) {
756
- let r = pt(e, t, n);
803
+ let r = Ct(e, t, n);
757
804
  r && u.push(r);
758
805
  }
759
806
  return u.join("\n\n") + "\n";
760
- }, At = (e, t, n = A) => {
761
- let { sorted: r, cyclic: i } = xt(e), a = Ct(i, t), o = [], s = Tt(r, t);
807
+ }, Bt = (e, t, n = A) => {
808
+ let { sorted: r, cyclic: i } = jt(e), a = Nt(i, t), o = [], s = Ft(r, t);
762
809
  s && o.push(s);
763
- let c = wt(r, t);
810
+ let c = Pt(r, t);
764
811
  c && o.push(c);
765
- for (let e of r) o.push(dt(e, t, null, a.get(e.tableName)));
766
- for (let e of i) o.push(St(e, t));
767
- return o.push(...mt(r, t, n)), o.join("\n\n") + "\n";
768
- }, jt = (e, t = "postgres", n = A, r = {}) => w.gen(function* () {
812
+ for (let e of r) o.push(xt(e, t, null, a.get(e.tableName)));
813
+ for (let e of i) o.push(Mt(e, t));
814
+ return o.push(...wt(r, t, n)), o.join("\n\n") + "\n";
815
+ }, Vt = (e, t = "postgres", n = A, r = {}) => T.gen(function* () {
769
816
  let i = yield* E.SqlClient;
770
- yield* Ie(i, Rt(i, Dt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(w.orDie);
771
- }), Mt = (e, t) => {
817
+ yield* He(i, Jt(i, Lt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
818
+ }), Ht = (e, t) => {
772
819
  let n = t.cause ?? {};
773
820
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
774
- }, Nt = (e, t) => {
821
+ }, Ut = (e, t) => {
775
822
  let n = e.trimStart();
776
823
  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));
777
- }, Pt = () => {
824
+ }, Wt = () => {
778
825
  let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
779
826
  return Number.isInteger(e) && e >= 0 ? e : 4;
780
- }, Ft = (e) => ({
827
+ }, Gt = (e) => ({
781
828
  while: e,
782
- times: Pt(),
783
- schedule: ee.jittered(ee.exponential("50 millis"))
784
- }), It = class {
829
+ times: Wt(),
830
+ schedule: ne.jittered(ne.exponential("50 millis"))
831
+ }), Kt = class {
785
832
  statement;
786
833
  error;
787
834
  _tag = "DdlStatementFailed";
788
835
  constructor(e, t) {
789
836
  this.statement = e, this.error = t;
790
837
  }
791
- }, Lt = (e, t, n) => w.gen(function* () {
792
- let r = yield* E.SqlClient, i = n !== void 0 && ze(t) === "per-operation";
793
- for (let a of zt(e)) {
794
- process.env.VOLTRO_MIGRATE_DEBUG === "1" && nt.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
795
- let e = r.unsafe(a).pipe(w.catchIf((e) => Mt(a, e), () => w.succeed([])), w.tapError((e) => w.sync(() => {
796
- nt.error(se("migrate: statement failed", a, e, 200));
838
+ }, qt = (e, t, n) => T.gen(function* () {
839
+ let r = yield* E.SqlClient, i = n !== void 0 && Ge(t) === "per-operation";
840
+ for (let a of Yt(e)) {
841
+ process.env.VOLTRO_MIGRATE_DEBUG === "1" && ft.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
842
+ let e = r.unsafe(a).pipe(T.catchIf((e) => Ht(a, e), () => T.succeed([])), T.tapError((e) => T.sync(() => {
843
+ ft.error(pe("migrate: statement failed", a, e, 200));
797
844
  })));
798
- yield* (i && n !== void 0 && Nt(a, t) ? e.pipe(w.retry(Ft((e) => n(e) === "retry"))) : e).pipe(w.mapError((e) => new It(a, e)));
845
+ yield* (i && n !== void 0 && Ut(a, t) ? e.pipe(T.retry(Gt((e) => n(e) === "retry"))) : e).pipe(T.mapError((e) => new Kt(a, e)));
799
846
  }
800
- }), Rt = (e, t, n, r) => {
801
- let i = n === "turso" ? Lt(t, n, r) : e.withTransaction(Lt(t, n, r)), a = (e) => e instanceof It ? e.error : e;
802
- return (r !== void 0 && ze(n) === "plan-transactional" ? i.pipe(w.retry(Ft((e) => r(a(e)) === "retry"))) : i).pipe(w.orDieWith((e) => e instanceof It ? Error(se("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
803
- }, zt = (e) => {
847
+ }), Jt = (e, t, n, r) => {
848
+ let i = n === "turso" ? qt(t, n, r) : e.withTransaction(qt(t, n, r)), a = (e) => e instanceof Kt ? e.error : e;
849
+ return (r !== void 0 && Ge(n) === "plan-transactional" ? i.pipe(T.retry(Gt((e) => r(a(e)) === "retry"))) : i).pipe(T.orDieWith((e) => e instanceof Kt ? Error(pe("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
850
+ }, Yt = (e) => {
804
851
  let t = [], n = "", r = !1;
805
852
  for (let i = 0; i < e.length; i++) {
806
853
  if (e.slice(i, i + 2) === "$$") {
@@ -815,27 +862,27 @@ BEGIN
815
862
  }
816
863
  let i = n.trim();
817
864
  return i.length > 0 && t.push(i), t;
818
- }, Bt = async (e, t, n = "postgres", r = {}) => {
819
- await w.runPromise(jt(e, n, void 0, r).pipe(w.provide(t)));
820
- }, Vt = (e, t, n = "postgres", r = {}) => w.gen(function* () {
821
- let i = kt(e, n, t), a = yield* E.SqlClient;
822
- yield* Ie(a, Rt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(w.orDie);
823
- }), Ht = async (e, t, n, r = "postgres", i = {}) => {
824
- await w.runPromise(Vt(e, t, r, i).pipe(w.provide(n))), await f({
865
+ }, Xt = async (e, t, n = "postgres", r = {}) => {
866
+ await T.runPromise(Vt(e, n, void 0, r).pipe(T.provide(t)));
867
+ }, Zt = (e, t, n = "postgres", r = {}) => T.gen(function* () {
868
+ let i = zt(e, n, t), a = yield* E.SqlClient;
869
+ yield* He(a, Jt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
870
+ }), Qt = async (e, t, n, r = "postgres", i = {}) => {
871
+ await T.runPromise(Zt(e, t, r, i).pipe(T.provide(n))), await f({
825
872
  namespace: t,
826
873
  dialect: r
827
874
  });
828
- }, Ut = async (e, t, n = "postgres", r = {}) => {
829
- await w.runPromise(w.gen(function* () {
830
- let t = At(e, n), i = yield* E.SqlClient;
831
- yield* Ie(i, Rt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(w.orDie);
832
- }).pipe(w.provide(t)));
833
- }, I = (e) => {
875
+ }, $t = async (e, t, n = "postgres", r = {}) => {
876
+ await T.runPromise(T.gen(function* () {
877
+ let t = Bt(e, n), i = yield* E.SqlClient;
878
+ yield* He(i, Jt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
879
+ }).pipe(T.provide(t)));
880
+ }, en = (e, t) => t.name === "id" && e.primaryKey?.length === 1 && e.primaryKey[0] === "id", tn = (e, t, n) => n && t.type === "id" && (e.type === "text" || e.type === "id"), I = (e) => {
834
881
  if (typeof e != "object" || !e) return JSON.stringify(e);
835
882
  if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
836
883
  let t = e;
837
884
  return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
838
- }, Wt = (e) => {
885
+ }, nn = (e) => {
839
886
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
840
887
  let t = e.defaultValue;
841
888
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
@@ -855,10 +902,10 @@ BEGIN
855
902
  return I(JSON.parse(a));
856
903
  } catch {}
857
904
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
858
- }, Gt = (e) => {
859
- let t = Wt(e);
905
+ }, rn = (e) => {
906
+ let t = nn(e);
860
907
  return t === "1" || t === "true" ? "__BOOL_TRUE__" : t === "0" || t === "false" ? "__BOOL_FALSE__" : t;
861
- }, Kt = (e) => typeof e.defaultValue == "string" && /^nextval\(.+::regclass\)$/i.test(e.defaultValue.trim()), qt = (e) => {
908
+ }, an = (e) => typeof e.defaultValue == "string" && /^nextval\(.+::regclass\)$/i.test(e.defaultValue.trim()), L = (e) => {
862
909
  if (!e) return null;
863
910
  let t = (e) => e === "restrict" ? "noAction" : e;
864
911
  return {
@@ -867,9 +914,9 @@ BEGIN
867
914
  onDelete: t(e.onDelete),
868
915
  onUpdate: t(e.onUpdate)
869
916
  };
870
- }, Jt = (e, t, n) => {
917
+ }, on = (e, t, n) => {
871
918
  if (t === "mssql") {
872
- let t = tt(e, n);
919
+ let t = dt(e, n);
873
920
  if (t !== void 0) return t;
874
921
  }
875
922
  try {
@@ -878,15 +925,15 @@ BEGIN
878
925
  } catch {
879
926
  return;
880
927
  }
881
- }, Yt = /'(?:''|[^'])*'|"(?:""|[^"])*"|\[(?:\]\]|[^\]])*\]|`(?:``|[^`])*`|[A-Za-z_][A-Za-z_0-9$]*|\d+(?:\.\d+)?|::|<>|!=|<=|>=|\|\||[^\s]/g, Xt = (e) => {
928
+ }, sn = /'(?:''|[^'])*'|"(?:""|[^"])*"|\[(?:\]\]|[^\]])*\]|`(?:``|[^`])*`|[A-Za-z_][A-Za-z_0-9$]*|\d+(?:\.\d+)?|::|<>|!=|<=|>=|\|\||[^\s]/g, cn = (e) => {
882
929
  let t = 0;
883
- for (let n of e.matchAll(Yt)) if (n[0] === "(" && t++, n[0] === ")" && t--, t === 0 && n[0].toLowerCase() === "where") return e.slice(n.index + n[0].length).trim().replace(/;$/, "").trim();
884
- }, Zt = (e) => {
930
+ for (let n of e.matchAll(sn)) if (n[0] === "(" && t++, n[0] === ")" && t--, t === 0 && n[0].toLowerCase() === "where") return e.slice(n.index + n[0].length).trim().replace(/;$/, "").trim();
931
+ }, ln = (e) => {
885
932
  if (e === void 0) return;
886
- let t = e.match(Yt) ?? [], n = "(?:'(?:''|[^'])*'(?:\\s*::\\s*text)?|[0-9]+)", r = RegExp(`^\\s*${n}(?:\\s*,\\s*${n})*\\s*$`, "i");
933
+ let t = e.match(sn) ?? [], n = "(?:'(?:''|[^'])*'(?:\\s*::\\s*text)?|[0-9]+)", r = RegExp(`^\\s*${n}(?:\\s*,\\s*${n})*\\s*$`, "i");
887
934
  for (let e = 0; e < t.length - 5; e++) {
888
935
  let n = t[e + 4];
889
- t[e] === "=" && t[e + 1]?.toLowerCase() === "any" && t[e + 2] === "(" && t[e + 3]?.toLowerCase() === "array" && n.startsWith("[") && n.endsWith("]") && t[e + 5] === ")" && r.test(n.slice(1, -1)) && t.splice(e, 6, "in", "(", ...n.slice(1, -1).match(Yt) ?? [], ")");
936
+ t[e] === "=" && t[e + 1]?.toLowerCase() === "any" && t[e + 2] === "(" && t[e + 3]?.toLowerCase() === "array" && n.startsWith("[") && n.endsWith("]") && t[e + 5] === ")" && r.test(n.slice(1, -1)) && t.splice(e, 6, "in", "(", ...n.slice(1, -1).match(sn) ?? [], ")");
890
937
  }
891
938
  let i = t.filter((e, n) => !(e === "::" && t[n - 1]?.startsWith("'") && t[n + 1]?.toLowerCase() === "text" || e.toLowerCase() === "text" && t[n - 1] === "::" && t[n - 2]?.startsWith("'"))).map((e) => {
892
939
  if (e.startsWith("'")) return e;
@@ -924,22 +971,22 @@ BEGIN
924
971
  return r;
925
972
  };
926
973
  return JSON.stringify(a(i));
927
- }, Qt = (e) => {
974
+ }, un = (e) => {
928
975
  if (e == null) return e;
929
- if (Array.isArray(e)) return e.map(Qt);
976
+ if (Array.isArray(e)) return e.map(un);
930
977
  if (typeof e != "object") return e;
931
978
  let t = {};
932
979
  for (let n of Object.keys(e).sort()) {
933
980
  let r = e[n];
934
- r !== void 0 && (t[n] = Qt(r));
981
+ r !== void 0 && (t[n] = un(r));
935
982
  }
936
983
  return t;
937
- }, $t = (e) => {
938
- if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs) return e;
939
- let { idScheme: t, sensitive: n, safe: r, generatedAs: i, ...a } = e;
940
- return a;
941
- }, en = (e) => {
942
- let t = $t(e), { references: n, defaultValue: r, hasDefault: i, oneOf: a, ...o } = t, s = t.type === "id" && Kt(t) ? null : Gt(t), c = qt(t.references);
984
+ }, dn = (e) => {
985
+ if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs && !e.jsonChecks) return e;
986
+ let { idScheme: t, sensitive: n, safe: r, generatedAs: i, jsonChecks: a, ...o } = e;
987
+ return o;
988
+ }, fn = (e) => {
989
+ let t = dn(e), { references: n, defaultValue: r, hasDefault: i, oneOf: a, ...o } = t, s = t.type === "id" && an(t) ? null : rn(t), c = L(t.references);
943
990
  return {
944
991
  ...o,
945
992
  hasDefault: s !== null,
@@ -947,17 +994,22 @@ BEGIN
947
994
  ...c === null ? {} : { references: c },
948
995
  ...t.oneOf !== void 0 && t.oneOf.length > 0 ? { oneOf: [...t.oneOf].sort() } : {}
949
996
  };
950
- }, tn = (e) => e.filter((e) => !x(e.name)).map(en).sort((e, t) => e.name.localeCompare(t.name)), nn = (e) => [...e].map((e) => e.where === void 0 ? e : {
951
- ...e,
952
- where: Zt(e.where)
953
- }).sort((e, t) => e.name.localeCompare(t.name)), rn = (e) => [...e].map((e) => ({
997
+ }, pn = (e, t) => en(e, t) && (t.type === "text" || t.type === "id") ? {
998
+ ...t,
999
+ type: "id",
1000
+ unique: !0
1001
+ } : t, mn = (e) => e.columns.filter((e) => !x(e.name)).map((t) => fn(pn(e, t))).sort((e, t) => e.name.localeCompare(t.name)), hn = (e) => [...e].map(({ kind: e, kindOptions: t, ...n }) => ({
1002
+ ...n,
1003
+ ...de(e, t),
1004
+ ...n.where === void 0 ? {} : { where: ln(n.where) }
1005
+ })).sort((e, t) => e.name.localeCompare(t.name)), gn = (e) => [...e].map((e) => ({
954
1006
  name: e.name,
955
- columns: tn(e.columns),
956
- indexes: nn(e.indexes)
957
- })).sort((e, t) => e.name.localeCompare(t.name)), L = (e) => {
958
- let t = { tables: rn(e.tables) }, n = JSON.stringify(Qt(t));
959
- return ne("sha256").update(n).digest("hex");
960
- }, an = (e) => e.slice(0, 16), on = (e, t) => {
1007
+ columns: mn(e),
1008
+ indexes: hn(e.indexes)
1009
+ })).sort((e, t) => e.name.localeCompare(t.name)), R = (e) => {
1010
+ let t = { tables: gn(e.tables) }, n = JSON.stringify(un(t));
1011
+ return ie("sha256").update(n).digest("hex");
1012
+ }, _n = (e) => e.slice(0, 16), vn = (e, t) => {
961
1013
  let n = t.references ? {
962
1014
  table: t.references().tableName,
963
1015
  column: t.referenceColumn ?? "id",
@@ -997,105 +1049,111 @@ BEGIN
997
1049
  ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
998
1050
  ...t.spatial === void 0 ? {} : { spatial: t.spatial }
999
1051
  };
1000
- }, sn = (e) => {
1001
- let t = [], n = /* @__PURE__ */ new Set(), i = (e) => {
1002
- n.has(e.name) || (n.add(e.name), t.push(e));
1003
- }, a = e.appliedPrimaryKey ?? [];
1004
- a.length > 0 ? i({
1052
+ }, yn = (e, t) => {
1053
+ let n = [], i = /* @__PURE__ */ new Set(), a = (e) => {
1054
+ i.has(e.name) || (i.add(e.name), n.push(e));
1055
+ }, o = e.appliedPrimaryKey ?? [];
1056
+ o.length > 0 ? a({
1005
1057
  name: `${e.tableName}_pkey`,
1006
1058
  table: e.tableName,
1007
- columns: [...a],
1059
+ columns: [...o],
1008
1060
  unique: !0
1009
- }) : e.fields.id && i({
1061
+ }) : e.fields.id && a({
1010
1062
  name: `${e.tableName}_pkey`,
1011
1063
  table: e.tableName,
1012
1064
  columns: ["id"],
1013
1065
  unique: !0
1014
1066
  });
1015
- let o = e.appliedIndexes ?? [];
1016
- for (let t of o) {
1017
- 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");
1018
- i({
1019
- name: t.name,
1067
+ let s = e.appliedIndexes ?? [];
1068
+ for (let n of s) {
1069
+ let r = ue(n.kind, t);
1070
+ if (r === null) continue;
1071
+ let i = n.fields[0], o = typeof i == "string" ? e.fields[i]?.vectorPrecision : void 0, s = r === "hnsw" ? { hnsw: le(n.kindOptions, o) } : void 0, c = n.fields.map((e) => typeof e == "string" ? e : "jsonPath" in e ? `(json:${e.jsonPath.column}->${e.jsonPath.path.join(".")}${e.jsonPath.numeric ? "::num" : ""})` : `(${e.expr})`), l = n.fields.some((e) => typeof e != "string");
1072
+ a({
1073
+ name: n.name,
1020
1074
  table: e.tableName,
1021
- columns: n,
1022
- unique: t.unique ?? !1,
1023
- ...t.where === void 0 ? {} : { where: t.where },
1024
- ...r ? { expression: !0 } : {}
1075
+ columns: c,
1076
+ unique: n.unique ?? !1,
1077
+ ...de(r, s),
1078
+ ...n.where === void 0 ? {} : { where: n.where },
1079
+ ...l ? { expression: !0 } : {}
1025
1080
  });
1026
1081
  }
1027
- let s = e.appliedUniques ?? [];
1028
- for (let t of s) t.fields.length < 2 || i({
1082
+ let c = e.appliedUniques ?? [];
1083
+ for (let t of c) t.fields.length < 2 || a({
1029
1084
  name: t.name,
1030
1085
  table: e.tableName,
1031
1086
  columns: t.fields,
1032
1087
  unique: !0
1033
1088
  });
1034
- let c = /* @__PURE__ */ new Set();
1035
- for (let e of o) e.fields.every((e) => typeof e == "string") && c.add(e.fields.join("\0"));
1089
+ let l = /* @__PURE__ */ new Set();
1090
+ for (let e of s) e.fields.every((e) => typeof e == "string") && l.add(e.fields.join("\0"));
1036
1091
  for (let [t, n] of Object.entries(e.fields)) {
1037
- let a = n;
1038
- if (a.dropped || !a.references || a.fkAutoIndex === !1 || c.has(t)) continue;
1092
+ let i = n;
1093
+ if (i.dropped || !i.references || i.fkAutoIndex === !1 || l.has(t)) continue;
1039
1094
  let o = `${e.tableName}_${t}_idx`;
1040
- r(e.tableName, o, !0, [t]), i({
1095
+ r(e.tableName, o, !0, [t]), a({
1041
1096
  name: o,
1042
1097
  table: e.tableName,
1043
1098
  columns: [t],
1044
1099
  unique: !1
1045
1100
  });
1046
1101
  }
1047
- return t;
1048
- }, cn = (e) => {
1049
- let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
1050
- for (let [r, i] of Object.entries(e.fields)) {
1102
+ return n;
1103
+ }, bn = (e, t) => {
1104
+ let n = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), r = [];
1105
+ for (let [t, i] of Object.entries(e.fields)) {
1051
1106
  if (i.dropped) continue;
1052
- let e = on(r, i);
1053
- n.push(t.has(r) ? {
1107
+ let e = vn(t, i);
1108
+ r.push(n.has(t) ? {
1054
1109
  ...e,
1055
1110
  unique: !0
1056
1111
  } : e);
1057
1112
  }
1058
- let r = e.appliedPrimaryKey ?? [], i = e.previousTableName;
1113
+ let i = e.appliedPrimaryKey ?? [], a = e.previousTableName;
1059
1114
  return {
1060
1115
  name: e.tableName,
1061
- columns: n,
1062
- indexes: sn(e),
1063
- ...r.length > 0 ? { primaryKey: [...r] } : {},
1064
- ...i === void 0 ? {} : { renamedFrom: i }
1116
+ columns: r,
1117
+ indexes: yn(e, t),
1118
+ ...i.length > 0 ? { primaryKey: [...i] } : {},
1119
+ ...a === void 0 ? {} : { renamedFrom: a }
1065
1120
  };
1066
- }, ln = (e) => {
1121
+ }, xn = (e) => {
1067
1122
  let t = /* @__PURE__ */ new Map();
1068
1123
  for (let n of e) for (let e of n.indexes) {
1069
1124
  let r = t.get(e.name);
1070
1125
  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}').`);
1071
1126
  t.set(e.name, n.name);
1072
1127
  }
1073
- }, R = (e, t) => {
1074
- let n = e.filter((e) => !c(e.tableName)).map((e) => cn(pe(e, t)));
1128
+ }, z = (e, t) => {
1129
+ let n = e.filter((e) => !c(e.tableName)).map((e) => bn(ye(e, t), t));
1075
1130
  if (t === "mysql" || t === "mariadb") {
1076
1131
  for (let e of n) for (let n of e.indexes) if (n.where !== void 0) throw Error(`Partial index '${n.name}' on '${e.name}' is not supported by ${t}. Use uniqueActive for portable conditional uniqueness.`);
1077
1132
  }
1078
- return ln(n), { tables: t === void 0 ? n : n.map((e) => un(e, t)) };
1079
- }, un = (e, t) => {
1133
+ return xn(n), { tables: t === void 0 ? n : n.map((e) => Sn(e, t)) };
1134
+ }, Sn = (e, t) => {
1080
1135
  let n = new Set(e.indexes.flatMap((e) => e.columns));
1081
1136
  return {
1082
1137
  ...e,
1083
1138
  columns: e.columns.map((e) => {
1084
- if (e.maxLength !== void 0) return e;
1085
- let r = Jt(e, t, n.has(e.name) || e.unique);
1139
+ if (t === "mssql" && !e.generatedAs && (e.type === "json" || e.type === "array") && (e = {
1140
+ ...e,
1141
+ jsonValidation: e.type === "json" ? "value" : "container"
1142
+ }), e.maxLength !== void 0) return e;
1143
+ let r = on(e, t, n.has(e.name) || e.unique);
1086
1144
  return r === void 0 ? e : {
1087
1145
  ...e,
1088
1146
  maxLength: r
1089
1147
  };
1090
1148
  })
1091
1149
  };
1092
- }, dn = (e, t, n = A) => w.gen(function* () {
1150
+ }, Cn = (e, t, n = A) => T.gen(function* () {
1093
1151
  let r = (yield* e`
1094
1152
  SELECT p.prosrc
1095
1153
  FROM pg_proc p
1096
1154
  JOIN pg_namespace n ON n.oid = p.pronamespace
1097
1155
  WHERE n.nspname = current_schema()
1098
- AND p.proname = ${$e(n)}
1156
+ AND p.proname = ${lt(n)}
1099
1157
  `)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
1100
1158
  if (a.length === 0) return {
1101
1159
  missing: [],
@@ -1109,10 +1167,10 @@ BEGIN
1109
1167
  JOIN pg_namespace n ON n.oid = c.relnamespace
1110
1168
  WHERE NOT t.tgisinternal
1111
1169
  AND n.nspname = current_schema()
1112
- AND t.tgname LIKE ${`${Ze}%`}
1170
+ AND t.tgname LIKE ${`${st}%`}
1113
1171
  `, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
1114
1172
  for (let e of a) {
1115
- let t = s.has(Qe(e.tableName, n)), r = e.isReactive !== !1;
1173
+ let t = s.has(ct(e.tableName, n)), r = e.isReactive !== !1;
1116
1174
  r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
1117
1175
  }
1118
1176
  return {
@@ -1120,7 +1178,7 @@ BEGIN
1120
1178
  stale: l.sort(),
1121
1179
  functionOutdated: i
1122
1180
  };
1123
- }), fn = (e) => {
1181
+ }), wn = (e) => {
1124
1182
  let t = [];
1125
1183
  if (e.missing.length > 0) {
1126
1184
  let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
@@ -1131,19 +1189,19 @@ BEGIN
1131
1189
  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.`);
1132
1190
  }
1133
1191
  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;
1134
- }, pn = {
1192
+ }, Tn = {
1135
1193
  postgres: !0,
1136
1194
  mysql: !0,
1137
1195
  mariadb: !0,
1138
1196
  mssql: !0,
1139
1197
  sqlite: !0
1140
- }, mn = {
1198
+ }, En = {
1141
1199
  postgres: !0,
1142
1200
  mysql: !1,
1143
1201
  mariadb: !1,
1144
1202
  mssql: !0,
1145
1203
  sqlite: !0
1146
- }, hn = (e) => {
1204
+ }, Dn = (e) => {
1147
1205
  switch (e) {
1148
1206
  case "add-column":
1149
1207
  case "drop-column":
@@ -1153,43 +1211,43 @@ BEGIN
1153
1211
  case "add-foreign-key":
1154
1212
  case "add-unique":
1155
1213
  case "add-unique-composite":
1156
- case "add-check": return mn;
1157
- default: return pn;
1214
+ case "add-check": return En;
1215
+ default: return Tn;
1158
1216
  }
1159
- }, gn = (e, t) => {
1217
+ }, On = (e, t) => {
1160
1218
  let n = new Map(t.tables.map((e) => [e.name, e]));
1161
1219
  return new Map(e.map((e) => [e.tableName, {
1162
1220
  table: e,
1163
1221
  snapshot: n.get(e.tableName),
1164
1222
  columnDefs: e.fields
1165
1223
  }]));
1166
- }, _n = (e, t) => {
1167
- let n = Wt(e), r = Wt(t);
1224
+ }, kn = (e, t) => {
1225
+ let n = nn(e), r = nn(t);
1168
1226
  if (n === r) return !0;
1169
- let i = Kt, a = (e) => e.type === "id" && e.idScheme?.kind === "numeric";
1170
- return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 : Gt(e) === Gt(t);
1171
- }, vn = (e, t) => {
1227
+ let i = an, a = (e) => e.type === "id" && e.idScheme?.kind === "numeric";
1228
+ return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 : rn(e) === rn(t);
1229
+ }, An = (e, t) => {
1172
1230
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
1173
1231
  if (!n && !r) return !0;
1174
1232
  if (!n || !r || n.length !== r.length) return !1;
1175
1233
  let i = [...n].sort(), a = [...r].sort();
1176
1234
  return i.every((e, t) => e === a[t]);
1177
- }, yn = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || Jt(e, n, r) === t.maxLength, bn = (e, t, n, r) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && _n(e, t) && yn(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(qt(e.references)) === JSON.stringify(qt(t.references)) && vn(e.oneOf, t.oneOf), xn = (e, t) => t.oneOf && t.oneOf.length > 0 ? z({
1235
+ }, jn = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || on(e, n, r) === t.maxLength, Mn = (e, t, n, r, i = !1) => (e.type === t.type || tn(e, t, i)) && e.nullable === t.nullable && (e.unique === t.unique || tn(e, t, i)) && e.jsonValidation === t.jsonValidation && kn(e, t) && jn(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(L(e.references)) === JSON.stringify(L(t.references)) && An(e.oneOf, t.oneOf), Nn = (e, t) => t.oneOf && t.oneOf.length > 0 ? B({
1178
1236
  kind: "add-check",
1179
1237
  table: e,
1180
1238
  column: t.name,
1181
1239
  values: t.oneOf
1182
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Sn = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && Zt(e.where) === Zt(t.where) && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Cn = (e, t, n) => {
1240
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Pn = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && ln(e.where) === ln(t.where) && JSON.stringify(de(e.kind, e.kindOptions)) === JSON.stringify(de(t.kind, t.kindOptions)) && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Fn = (e, t, n) => {
1183
1241
  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));
1184
1242
  for (let t of e.columns) {
1185
- let e = r.get(t.name);
1186
- if (!e) {
1243
+ let i = r.get(t.name);
1244
+ if (!i) {
1187
1245
  a.push(t);
1188
1246
  continue;
1189
1247
  }
1190
- bn(t, e, n, c.has(t.name) || t.unique) || s.push({
1248
+ Mn(t, i, n, c.has(t.name) || t.unique, en(e, t)) || s.push({
1191
1249
  declared: t,
1192
- live: e
1250
+ live: i
1193
1251
  });
1194
1252
  }
1195
1253
  for (let e of t.columns) i.has(e.name) || o.push(e);
@@ -1198,50 +1256,50 @@ BEGIN
1198
1256
  removed: o,
1199
1257
  changed: s
1200
1258
  };
1201
- }, wn = (e, t, n) => {
1259
+ }, In = (e, t, n) => {
1202
1260
  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 = [];
1203
1261
  for (let t of e.indexes) {
1204
1262
  let e = i.get(r(t.name));
1205
- (!e || !Sn(t, e)) && o.push(t);
1263
+ (!e || !Pn(t, e)) && o.push(t);
1206
1264
  }
1207
1265
  for (let e of t.indexes) {
1208
1266
  let t = a.get(r(e.name));
1209
- (!t || (e.where !== void 0 || t.where !== void 0) && !Sn(t, e)) && s.push(e);
1267
+ (!t || !Pn(t, e)) && s.push(e);
1210
1268
  }
1211
1269
  return {
1212
1270
  added: o,
1213
1271
  removed: s
1214
1272
  };
1215
- }, z = (e, t, n, r) => ({
1273
+ }, B = (e, t, n, r) => ({
1216
1274
  op: e,
1217
1275
  classification: t,
1218
- atomicByDialect: hn(e.kind),
1276
+ atomicByDialect: Dn(e.kind),
1219
1277
  ...n ? { reason: n } : {},
1220
1278
  ...r ? { blocked: r } : {}
1221
- }), Tn = (e, t, n) => {
1279
+ }), Ln = (e, t, n) => {
1222
1280
  let r = {
1223
1281
  kind: "add-column",
1224
1282
  table: e,
1225
1283
  column: t
1226
1284
  };
1227
- return t.nullable ? z(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? z(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? z(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : z(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
1228
- }, En = (e, t, n) => {
1285
+ return t.nullable ? B(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? B(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? B(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : B(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` });
1286
+ }, Rn = (e, t, n) => {
1229
1287
  let r = {
1230
1288
  kind: "drop-column",
1231
1289
  table: e,
1232
1290
  column: t.name
1233
1291
  };
1234
- return n?.dropped ? z(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : z(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1235
- }, Dn = (e, t, n, r, i) => z({
1292
+ return n?.dropped ? B(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : B(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1293
+ }, zn = (e, t, n, r, i) => B({
1236
1294
  kind: "create-table",
1237
1295
  table: e,
1238
1296
  columns: t,
1239
1297
  indexes: n,
1240
1298
  ...r && r.length > 0 ? { primaryKey: r } : {}
1241
- }, "safe", i ?? "new table — no data to preserve"), On = (e) => z({
1299
+ }, "safe", i ?? "new table — no data to preserve"), Bn = (e) => B({
1242
1300
  kind: "drop-table",
1243
1301
  table: e
1244
- }, "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" }), kn = 5e4, An = (e, t, n, r) => {
1302
+ }, "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, Hn = (e, t, n, r) => {
1245
1303
  let i = (n ?? 0) >= r, a;
1246
1304
  return a = !t.unique || t.where !== void 0 ? {
1247
1305
  kind: "add-index",
@@ -1256,28 +1314,28 @@ BEGIN
1256
1314
  table: e,
1257
1315
  name: t.name,
1258
1316
  fields: t.columns
1259
- }, i ? z(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(a, "safe", t.where === void 0 ? t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index" : `add ${t.unique ? "unique " : ""}partial index`);
1260
- }, jn = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? z({
1317
+ }, i ? B(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : B(a, "safe", t.where === void 0 ? t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : `add ${t.kind === void 0 || t.kind === "btree" ? "B-tree" : t.kind.toUpperCase()} index` : `add ${t.unique ? "unique " : ""}partial index`);
1318
+ }, Un = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? B({
1261
1319
  kind: "drop-unique-composite",
1262
1320
  table: e,
1263
1321
  name: t.name
1264
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : z({
1322
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : B({
1265
1323
  kind: "drop-index",
1266
1324
  table: e,
1267
1325
  index: t.name
1268
- }, "safe", "drop index (no data loss — index is derived data)"), Mn = (e, t) => {
1326
+ }, "safe", "drop index (no data loss — index is derived data)"), Wn = (e, t) => {
1269
1327
  let n = e.type;
1270
1328
  if (n === "reference") return e.referenceStorage === "numeric" ? "bigint" : "text";
1271
1329
  switch (t) {
1272
1330
  case "sqlite":
1273
1331
  case "turso": return n === "timestamp" || n === "date" || n === "json" ? "text" : n === "boolean" ? "integer" : n === "decimal" ? "text" : n === "bigint" ? "integer" : n;
1274
- case "mssql": return n === "json" ? "text" : n;
1332
+ case "mssql": return n === "json" || n === "array" ? "text" : n;
1275
1333
  default: return n;
1276
1334
  }
1277
- }, Nn = (e, t, n) => {
1335
+ }, Gn = (e, t, n) => {
1278
1336
  let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
1279
1337
  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`;
1280
- }, Pn = (e, t, n, r, i, a) => {
1338
+ }, Kn = (e, t, n, r, i, a) => {
1281
1339
  let o = [];
1282
1340
  if (t.nullable !== n.nullable) {
1283
1341
  let n = {
@@ -1286,7 +1344,7 @@ BEGIN
1286
1344
  column: t.name,
1287
1345
  toNullable: t.nullable
1288
1346
  };
1289
- o.push(t.nullable ? z(n, "safe", `loosen ${e}.${t.name} to nullable`) : z(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1347
+ o.push(t.nullable ? B(n, "safe", `loosen ${e}.${t.name} to nullable`) : B(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1290
1348
  }
1291
1349
  if (t.unique !== n.unique) {
1292
1350
  if (t.unique) {
@@ -1295,14 +1353,14 @@ BEGIN
1295
1353
  table: e,
1296
1354
  column: t.name
1297
1355
  }, r = (i ?? 0) >= a;
1298
- o.push(r ? z(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1299
- } else o.push(z({
1356
+ o.push(r ? B(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : B(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1357
+ } else o.push(B({
1300
1358
  kind: "drop-unique",
1301
1359
  table: e,
1302
1360
  column: t.name
1303
1361
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
1304
1362
  }
1305
- if (Mn(t, r) !== Mn(n, r)) {
1363
+ if (Wn(t, r) !== Wn(n, r)) {
1306
1364
  let i = t.narrowedFrom;
1307
1365
  if (i && i.from === n.type) {
1308
1366
  let r = {
@@ -1313,7 +1371,7 @@ BEGIN
1313
1371
  to: t.type,
1314
1372
  ...i.using === void 0 ? {} : { using: i.using }
1315
1373
  };
1316
- o.push(z(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)")));
1374
+ o.push(B(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)")));
1317
1375
  } else {
1318
1376
  let i = {
1319
1377
  kind: "alter-column-type",
@@ -1322,12 +1380,12 @@ BEGIN
1322
1380
  from: n.type,
1323
1381
  to: t.type
1324
1382
  };
1325
- o.push(z(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Nn(n.type, t, r) }));
1383
+ o.push(B(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Gn(n.type, t, r) }));
1326
1384
  }
1327
1385
  }
1328
1386
  if (t.type === "text" && n.type === "text" && !m(r ?? "postgres") && t.maxLength !== n.maxLength) {
1329
1387
  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})`;
1330
- o.push(z({
1388
+ o.push(B({
1331
1389
  kind: "alter-column-type",
1332
1390
  table: e,
1333
1391
  column: t.name,
@@ -1335,7 +1393,7 @@ BEGIN
1335
1393
  to: "text"
1336
1394
  }, 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)}`));
1337
1395
  }
1338
- if (!_n(t, n)) {
1396
+ if (!kn(t, n)) {
1339
1397
  let n = {
1340
1398
  kind: "alter-column-default",
1341
1399
  table: e,
@@ -1343,23 +1401,34 @@ BEGIN
1343
1401
  hasDefault: t.hasDefault,
1344
1402
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
1345
1403
  };
1346
- o.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1404
+ o.push(B(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1347
1405
  }
1348
- if (!vn(t.oneOf, n.oneOf)) {
1349
- n.oneOf && n.oneOf.length > 0 && o.push(z({
1406
+ if (r === "mssql" && t.jsonValidation !== void 0 && t.jsonValidation !== "unverified" && t.jsonValidation !== n.jsonValidation) {
1407
+ let r = t.jsonValidation === "value" && n.jsonValidation === "container";
1408
+ o.push(B({
1409
+ kind: "reconcile-json-check",
1410
+ table: e,
1411
+ column: t.name,
1412
+ validation: t.jsonValidation,
1413
+ previousValidation: n.jsonValidation ?? "absent",
1414
+ dropConstraints: (n.jsonChecks ?? []).map((e) => e.name).sort()
1415
+ }, r ? "safe" : "needs-backfill", r ? `allow every JSON value on ${e}.${t.name}; preserve existing rows` : `validate existing JSON on ${e}.${t.name}; invalid rows refuse the migration without being rewritten`));
1416
+ }
1417
+ if (!An(t.oneOf, n.oneOf)) {
1418
+ n.oneOf && n.oneOf.length > 0 && o.push(B({
1350
1419
  kind: "drop-check",
1351
1420
  table: e,
1352
1421
  column: t.name
1353
1422
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
1354
- let r = xn(e, t);
1423
+ let r = Nn(e, t);
1355
1424
  r && o.push(r);
1356
1425
  }
1357
- return JSON.stringify(qt(t.references)) !== JSON.stringify(qt(n.references)) && (n.references && o.push(z({
1426
+ return JSON.stringify(L(t.references)) !== JSON.stringify(L(n.references)) && (n.references && o.push(B({
1358
1427
  kind: "drop-foreign-key",
1359
1428
  table: e,
1360
1429
  column: t.name
1361
- }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...Fn(e, t))), o;
1362
- }, Fn = (e, t) => {
1430
+ }, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...qn(e, t))), o;
1431
+ }, qn = (e, t) => {
1363
1432
  let n = [];
1364
1433
  if (!t.references) return n;
1365
1434
  let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
@@ -1371,15 +1440,15 @@ BEGIN
1371
1440
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1372
1441
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1373
1442
  };
1374
- return i === "null" && !t.nullable ? n.push(z(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(z({
1443
+ return i === "null" && !t.nullable ? n.push(B(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(B({
1375
1444
  ...a,
1376
1445
  orphanPolicy: i
1377
- }, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(z(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1378
- }, In = (e, t, n) => {
1446
+ }, "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(B(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1447
+ }, Jn = (e, t, n) => {
1379
1448
  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));
1380
1449
  for (let [n, c] of Object.entries(t)) {
1381
1450
  let t = c.renamedFrom;
1382
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(z({
1451
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(B({
1383
1452
  kind: "rename-column",
1384
1453
  table: e.tableName,
1385
1454
  from: t,
@@ -1391,30 +1460,30 @@ BEGIN
1391
1460
  consumedAddedNames: i,
1392
1461
  consumedRemovedNames: a
1393
1462
  };
1394
- }, Ln = /* @__PURE__ */ new Set([
1463
+ }, Yn = /* @__PURE__ */ new Set([
1395
1464
  "postgres",
1396
1465
  "mysql",
1397
1466
  "mariadb",
1398
1467
  "mssql"
1399
- ]), Rn = {
1468
+ ]), Xn = {
1400
1469
  ops: [],
1401
1470
  consumedAddedNames: /* @__PURE__ */ new Set(),
1402
1471
  consumedRemovedNames: /* @__PURE__ */ new Set()
1403
- }, zn = (e) => !e.unique && !e.expression && e.where === void 0, Bn = (e, t, n, r, i) => {
1404
- if (i === void 0 || !Ln.has(i)) return Rn;
1405
- let a = t.added.filter((e) => zn(e) && !r.has(e.name));
1406
- if (a.length === 0) return Rn;
1472
+ }, Zn = (e) => !e.unique && !e.expression && e.where === void 0 && (e.kind === void 0 || e.kind === "btree"), Qn = (e, t, n, r, i) => {
1473
+ if (i === void 0 || !Yn.has(i)) return Xn;
1474
+ let a = t.added.filter((e) => Zn(e) && !r.has(e.name));
1475
+ if (a.length === 0) return Xn;
1407
1476
  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();
1408
1477
  for (let n of t.removed) {
1409
- if (!zn(n)) continue;
1410
- let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
1411
- if (r.length !== 1) continue;
1412
- let i = r[0];
1413
- i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(z({
1478
+ if (!Zn(n) || t.added.some((e) => e.name === n.name)) continue;
1479
+ let r = o(n), i = a.filter((e) => !l.has(e.name) && s(e) === r);
1480
+ if (i.length !== 1) continue;
1481
+ let d = i[0];
1482
+ d.name !== n.name && (l.add(d.name), u.add(n.name), c.push(B({
1414
1483
  kind: "rename-index",
1415
1484
  table: e,
1416
1485
  from: n.name,
1417
- to: i.name
1486
+ to: d.name
1418
1487
  }, "safe", "rename index in place — catalog-only, no rebuild")));
1419
1488
  }
1420
1489
  return {
@@ -1422,7 +1491,7 @@ BEGIN
1422
1491
  consumedAddedNames: l,
1423
1492
  consumedRemovedNames: u
1424
1493
  };
1425
- }, Vn = (e, t, n) => {
1494
+ }, $n = (e, t, n) => {
1426
1495
  let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
1427
1496
  for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
1428
1497
  for (let c of e.tables) {
@@ -1433,7 +1502,7 @@ BEGIN
1433
1502
  continue;
1434
1503
  }
1435
1504
  if (t.has(c.name)) {
1436
- r.push(z({
1505
+ r.push(B({
1437
1506
  kind: "rename-table",
1438
1507
  from: e,
1439
1508
  to: c.name
@@ -1441,14 +1510,14 @@ BEGIN
1441
1510
  continue;
1442
1511
  }
1443
1512
  if ((s.get(e) ?? 0) !== 1) {
1444
- r.push(z({
1513
+ r.push(B({
1445
1514
  kind: "rename-table",
1446
1515
  from: e,
1447
1516
  to: c.name
1448
1517
  }, "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.` }));
1449
1518
  continue;
1450
1519
  }
1451
- i.set(c.name, e), a.add(e), r.push(z({
1520
+ i.set(c.name, e), a.add(e), r.push(B({
1452
1521
  kind: "rename-table",
1453
1522
  from: e,
1454
1523
  to: c.name
@@ -1462,19 +1531,19 @@ BEGIN
1462
1531
  claimedOldNames: c,
1463
1532
  refusals: o
1464
1533
  };
1465
- }, Hn = (e, t, n, r) => {
1534
+ }, er = (e, t, n, r) => {
1466
1535
  if (t === void 0) return {
1467
1536
  live: e,
1468
1537
  ops: []
1469
1538
  };
1470
- let i = r !== void 0 && Ln.has(r), a = [], o = e.indexes.map((e) => {
1539
+ let i = r !== void 0 && Yn.has(r), a = [], o = e.indexes.map((e) => {
1471
1540
  if (!e.name.startsWith(t)) return e;
1472
1541
  let r = `${n}${e.name.slice(t.length)}`;
1473
1542
  return r === e.name ? e : e.name === `${t}_pkey` ? {
1474
1543
  ...e,
1475
1544
  name: r,
1476
1545
  table: n
1477
- } : i ? (a.push(z({
1546
+ } : i ? (a.push(B({
1478
1547
  kind: "rename-index",
1479
1548
  table: n,
1480
1549
  from: e.name,
@@ -1493,7 +1562,7 @@ BEGIN
1493
1562
  },
1494
1563
  ops: a
1495
1564
  };
1496
- }, Un = (e) => {
1565
+ }, tr = (e) => {
1497
1566
  let t = {
1498
1567
  safe: 0,
1499
1568
  needsDefault: 0,
@@ -1526,13 +1595,13 @@ BEGIN
1526
1595
  case "multi-step": t.multiStep++;
1527
1596
  }
1528
1597
  return t;
1529
- }, Wn = (e) => {
1530
- let t = R(e.declared, e.dialect), n = gn(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? kn, a = [], o = Vn(t, r, n);
1598
+ }, nr = (e) => {
1599
+ let t = z(e.declared, e.dialect), n = On(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Vn, a = [], o = $n(t, r, n);
1531
1600
  a.push(...o.ops);
1532
1601
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1533
- a.push(Dn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1602
+ a.push(zn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
1534
1603
  for (let t of e.columns) {
1535
- let n = xn(e.name, t);
1604
+ let n = Nn(e.name, t);
1536
1605
  n && a.push(n);
1537
1606
  }
1538
1607
  }
@@ -1554,32 +1623,40 @@ BEGIN
1554
1623
  c.push(t.name);
1555
1624
  continue;
1556
1625
  }
1557
- a.push(On(t.name));
1626
+ a.push(Bn(t.name));
1558
1627
  }
1559
1628
  for (let s of t.tables) {
1560
1629
  let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
1561
1630
  if (!c) continue;
1562
- let l = Hn(c, t, s.name, e.dialect);
1631
+ let l = er(c, t, s.name, e.dialect);
1563
1632
  a.push(...l.ops);
1564
- let u = l.live, d = n.get(s.name), f = Cn(s, u, e.dialect), p = wn(s, u, e.dialect), m = In(d.table, d.columnDefs, f);
1633
+ let u = l.live, d = n.get(s.name), f = Fn(s, u, e.dialect), p = In(s, u, e.dialect), m = Jn(d.table, d.columnDefs, f);
1565
1634
  a.push(...m.ops);
1635
+ for (let { op: t } of m.ops) {
1636
+ if (t.kind !== "rename-column") continue;
1637
+ let n = s.columns.find((e) => e.name === t.to), r = u.columns.find((e) => e.name === t.from);
1638
+ n && r && a.push(...Kn(s.name, n, {
1639
+ ...r,
1640
+ name: t.to
1641
+ }, e.dialect, u.rowCount, i));
1642
+ }
1566
1643
  for (let e of f.removed) {
1567
1644
  if (m.consumedRemovedNames.has(e.name) || x(e.name)) continue;
1568
1645
  let t = d.columnDefs[e.name];
1569
- a.push(En(s.name, e, t));
1646
+ a.push(Rn(s.name, e, t));
1570
1647
  }
1571
1648
  for (let e of f.added) {
1572
1649
  if (m.consumedAddedNames.has(e.name)) continue;
1573
1650
  let t = d.columnDefs[e.name];
1574
- a.push(Tn(s.name, e, t));
1575
- let n = xn(s.name, e);
1576
- n && a.push(n), a.push(...Fn(s.name, e));
1651
+ a.push(Ln(s.name, e, t));
1652
+ let n = Nn(s.name, e);
1653
+ n && a.push(n), a.push(...qn(s.name, e));
1577
1654
  }
1578
- let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Bn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1655
+ let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Qn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
1579
1656
  a.push(...g.ops);
1580
- for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(An(s.name, e, u.rowCount, i));
1581
- for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(jn(s.name, e));
1582
- for (let { declared: t, live: n } of f.changed) a.push(...Pn(s.name, t, n, e.dialect, u.rowCount, i));
1657
+ for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(Hn(s.name, e, u.rowCount, i));
1658
+ for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(Un(s.name, e));
1659
+ for (let { declared: t, live: n } of f.changed) a.push(...Kn(s.name, t, n, e.dialect, u.rowCount, i));
1583
1660
  }
1584
1661
  let l = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), u = new Map(t.tables.map((e) => [e.name, e])), d = (e) => {
1585
1662
  let t = u.get(e);
@@ -1587,8 +1664,8 @@ BEGIN
1587
1664
  column: e.name,
1588
1665
  target: e.references.table
1589
1666
  }] : []) : [];
1590
- }, f = me([...l], d), p = [];
1591
- for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(D(e.name, t.name)) && p.push(z({
1667
+ }, f = be([...l], d), p = [];
1668
+ for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(D(e.name, t.name)) && p.push(B({
1592
1669
  kind: "add-foreign-key",
1593
1670
  table: e.name,
1594
1671
  column: t.name,
@@ -1647,7 +1724,8 @@ BEGIN
1647
1724
  "add-unique": 5,
1648
1725
  "add-unique-composite": 5,
1649
1726
  "add-foreign-key": 5,
1650
- "add-check": 5
1727
+ "add-check": 5,
1728
+ "reconcile-json-check": 5
1651
1729
  }, S = (e) => b[e] ?? 9, C = [...a].sort((e, t) => {
1652
1730
  let n = v(e.op.kind), r = v(t.op.kind);
1653
1731
  if (n !== r) return n - r;
@@ -1663,19 +1741,34 @@ BEGIN
1663
1741
  for (let e of t.tables) {
1664
1742
  if (w.has(e.name) || o.renamedInto.has(e.name)) continue;
1665
1743
  let t = r.get(e.name);
1666
- t !== void 0 && L({ tables: [t] }) !== L({ tables: [e] }) && T.push(e.name);
1744
+ t !== void 0 && R({ tables: [t] }) !== R({ tables: [e] }) && T.push(e.name);
1667
1745
  }
1668
1746
  return {
1669
1747
  operations: C,
1670
- fromFingerprint: L(e.live),
1671
- toFingerprint: L(t),
1672
- summary: Un(C),
1748
+ fromFingerprint: R(e.live),
1749
+ toFingerprint: R(t),
1750
+ summary: tr(C),
1673
1751
  fingerprintDivergence: {
1674
1752
  outsideDiff: c,
1675
1753
  diffEquivalent: T
1676
1754
  }
1677
1755
  };
1678
- }, Gn = (e) => {
1756
+ }, rr = (e, t) => {
1757
+ let n = (e.match(/'(?:''|[^'])*'|"(?:""|[^"])*"|::|[A-Za-z_][A-Za-z_0-9$]*|[^\s]/g) ?? []).filter((e) => e !== "(" && e !== ")"), r = 0, i = (e) => n[r]?.toLowerCase() === e && (r++, !0);
1758
+ if (!i("check")) return null;
1759
+ let a = n[r++];
1760
+ if (a === void 0 || (a.startsWith("\"") ? a.slice(1, -1).replace(/""/g, "\"") : a.toLowerCase()) !== t) return null;
1761
+ let o = () => !i("::") || i("text") || i("character") && i("varying");
1762
+ if (!o() || !i("=")) return null;
1763
+ let s = i("any");
1764
+ if (s && (!i("array") || !i("["))) return null;
1765
+ let c = [];
1766
+ do {
1767
+ let e = n[r++];
1768
+ if (e === void 0 || !/^'(?:''|[^'])*'$/.test(e) || (c.push(e.slice(1, -1).replace(/''/g, "'")), !o())) return null;
1769
+ } while (s && i(","));
1770
+ return s && (!i("]") || i("::") && (!i("text") || !i("[") || !i("]"))) ? null : r === n.length ? c : null;
1771
+ }, ir = (e) => {
1679
1772
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1680
1773
  if (!t) return null;
1681
1774
  let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
@@ -1683,8 +1776,8 @@ BEGIN
1683
1776
  column: t[1],
1684
1777
  values: n
1685
1778
  };
1686
- }, Kn = (e, t) => {
1687
- if (t === "vector") return "vector";
1779
+ }, ar = (e, t) => {
1780
+ if (t === "vector" || t === "halfvec") return "vector";
1688
1781
  switch (e) {
1689
1782
  case "text":
1690
1783
  case "character varying":
@@ -1710,10 +1803,10 @@ BEGIN
1710
1803
  case "USER-DEFINED": return "text";
1711
1804
  default: return "text";
1712
1805
  }
1713
- }, qn = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
1806
+ }, or = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
1714
1807
  expr: e,
1715
1808
  stored: t
1716
- } }, B = (e) => {
1809
+ } }, V = (e) => {
1717
1810
  switch (e.toUpperCase()) {
1718
1811
  case "CASCADE": return "cascade";
1719
1812
  case "RESTRICT": return "restrict";
@@ -1721,25 +1814,25 @@ BEGIN
1721
1814
  case "SET DEFAULT": return "noAction";
1722
1815
  default: return "noAction";
1723
1816
  }
1724
- }, Jn = (e, t) => {
1817
+ }, sr = (e, t) => {
1725
1818
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1726
1819
  return Number.isInteger(n) && n > 0 ? n : t;
1727
- }, Yn = () => Jn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Xn = 300, Zn = () => {
1820
+ }, cr = () => sr(process.env.VOLTRO_INTROSPECT_BATCH, 20), lr = 300, ur = () => {
1728
1821
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1729
- return e !== void 0 && e.trim() === "0" ? 0 : Jn(e, 3e4);
1730
- }, Qn = (e, t) => {
1822
+ return e !== void 0 && e.trim() === "0" ? 0 : sr(e, 3e4);
1823
+ }, dr = (e, t) => {
1731
1824
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1732
1825
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1733
1826
  return r;
1734
- }, $n = (e) => {
1735
- let t = Zn(), n = w.gen(function* () {
1827
+ }, fr = (e) => {
1828
+ let t = ur(), n = T.gen(function* () {
1736
1829
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1737
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Yn(), a = (e, t) => w.gen(function* () {
1830
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = cr(), a = (e, t) => T.gen(function* () {
1738
1831
  let r = [];
1739
- for (let a of Qn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1832
+ for (let a of dr(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1740
1833
  return r;
1741
1834
  }), o = [];
1742
- for (let t = 0;; t += Xn) {
1835
+ for (let t = 0;; t += lr) {
1743
1836
  let n = yield* e`
1744
1837
  SELECT c.relname AS table_name,
1745
1838
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1747,16 +1840,21 @@ BEGIN
1747
1840
  JOIN pg_namespace n ON n.oid = c.relnamespace
1748
1841
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1749
1842
  ORDER BY c.relname
1750
- LIMIT ${r(Xn)} OFFSET ${r(t)}
1843
+ LIMIT ${r(lr)} OFFSET ${r(t)}
1751
1844
  `;
1752
- if (o.push(...n), n.length < Xn) break;
1845
+ if (o.push(...n), n.length < lr) break;
1753
1846
  }
1754
1847
  let s = /* @__PURE__ */ new Set(), c = [];
1755
1848
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
1756
1849
  let l = c.map((e) => e.table_name), u = yield* a(l, (t) => e`
1757
1850
  SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,
1758
- character_maximum_length, is_generated, generation_expression
1759
- FROM information_schema.columns
1851
+ character_maximum_length, is_generated, generation_expression,
1852
+ (SELECT a.atttypmod FROM pg_attribute a
1853
+ JOIN pg_class c ON c.oid = a.attrelid
1854
+ JOIN pg_namespace n ON n.oid = c.relnamespace
1855
+ WHERE n.nspname = col.table_schema AND c.relname = col.table_name
1856
+ AND a.attname = col.column_name) AS type_modifier
1857
+ FROM information_schema.columns col
1760
1858
  WHERE table_schema = current_schema() AND table_name IN ${t}
1761
1859
  ORDER BY table_name, ordinal_position
1762
1860
  `), d = yield* a(l, (t) => e`
@@ -1786,8 +1884,8 @@ BEGIN
1786
1884
  AND rel.relname IN ${t}
1787
1885
  `), m = /* @__PURE__ */ new Map();
1788
1886
  for (let e of p) {
1789
- let t = [...e.def.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
1790
- t.length > 0 && m.set(`${e.table_name}.${e.column_name}`, t);
1887
+ let t = rr(e.def, e.column_name);
1888
+ t !== null && m.set(`${e.table_name}.${e.column_name}`, t);
1791
1889
  }
1792
1890
  let h = yield* a(l, (t) => e`
1793
1891
  SELECT
@@ -1820,6 +1918,10 @@ BEGIN
1820
1918
  c.relname AS table_name,
1821
1919
  i.relname AS index_name,
1822
1920
  ix2.indisunique AS is_unique,
1921
+ am.amname AS access_method,
1922
+ CASE WHEN opn.nspname IN ('public', 'pg_catalog') THEN opc.opcname
1923
+ ELSE opn.nspname || '.' || opc.opcname END AS operator_class,
1924
+ i.reloptions AS reloptions,
1823
1925
  pg_get_expr(ix2.indpred, ix2.indrelid) AS predicate,
1824
1926
  ix2.indisvalid AS is_valid,
1825
1927
  (0 = ANY (ix2.indkey::int[])) AS has_expression,
@@ -1827,6 +1929,9 @@ BEGIN
1827
1929
  array_position(ix2.indkey::int[], a.attnum) + 1 AS position
1828
1930
  FROM pg_index ix2
1829
1931
  JOIN pg_class i ON i.oid = ix2.indexrelid
1932
+ JOIN pg_am am ON am.oid = i.relam
1933
+ LEFT JOIN pg_opclass opc ON opc.oid = ix2.indclass[0]
1934
+ LEFT JOIN pg_namespace opn ON opn.oid = opc.opcnamespace
1830
1935
  JOIN pg_class c ON c.oid = ix2.indrelid
1831
1936
  JOIN pg_namespace n ON n.oid = c.relnamespace
1832
1937
  LEFT JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY (ix2.indkey)
@@ -1882,27 +1987,31 @@ BEGIN
1882
1987
  let n = t.get(e.index_name);
1883
1988
  n || (n = [], t.set(e.index_name, n)), n.push(e);
1884
1989
  }
1885
- let T = [];
1990
+ let w = [];
1886
1991
  for (let e of c) {
1887
1992
  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) => {
1888
- 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" : Kn(t.data_type, t.udt_name), c = a ? {
1993
+ 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" : ar(t.data_type, t.udt_name), c = a ? {
1889
1994
  table: a.target_table,
1890
1995
  column: a.target_column,
1891
- onDelete: B(a.delete_rule),
1892
- onUpdate: B(a.update_rule)
1996
+ onDelete: V(a.delete_rule),
1997
+ onUpdate: V(a.update_rule)
1893
1998
  } : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
1894
1999
  return {
1895
2000
  name: t.column_name,
1896
2001
  type: s,
1897
- ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
2002
+ ...s === "vector" ? {
2003
+ vectorPrecision: t.udt_name === "halfvec" ? "half" : "float32",
2004
+ ...t.type_modifier !== void 0 && t.type_modifier > 0 ? { vectorDim: t.type_modifier } : {}
2005
+ } : {},
2006
+ ...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
1898
2007
  nullable: t.is_nullable === "YES",
1899
2008
  unique: i.has(t.column_name) || n && t.column_name === "id",
1900
2009
  hasDefault: t.column_default !== null,
1901
2010
  ...t.column_default === null ? {} : { defaultValue: t.column_default },
1902
2011
  ...c ? { references: c } : {},
1903
- ...a ? { referenceStorage: ["integer", "bigint"].includes(Kn(t.data_type, t.udt_name)) ? "numeric" : "text" } : {},
2012
+ ...a ? { referenceStorage: ["integer", "bigint"].includes(ar(t.data_type, t.udt_name)) ? "numeric" : "text" } : {},
1904
2013
  ...l ? { oneOf: l } : {},
1905
- ...qn(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
2014
+ ...or(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
1906
2015
  };
1907
2016
  }), l = [], u = S.get(e.table_name);
1908
2017
  if (u) for (let [t, n] of u) {
@@ -1911,12 +2020,21 @@ BEGIN
1911
2020
  return !r.has(t) && (r.add(t), !0);
1912
2021
  });
1913
2022
  if (i.some((e) => s.has(e.column_name))) continue;
1914
- let a = n.some((e) => e.has_expression);
2023
+ let a = n.some((e) => e.has_expression), o = n[0], c = new Map((o?.reloptions ?? []).map((e) => {
2024
+ let [t, n] = e.split("=");
2025
+ return [t, Number(n)];
2026
+ }));
2027
+ if (o?.access_method === "hnsw" && !o.operator_class) throw Error(`Cannot read HNSW operator class for index ${t}`);
1915
2028
  l.push({
1916
2029
  name: t,
1917
2030
  table: e.table_name,
1918
2031
  columns: i.map((e) => e.column_name),
1919
2032
  unique: n[0]?.is_unique ?? !1,
2033
+ ...de(o?.access_method, o?.access_method === "hnsw" ? { hnsw: {
2034
+ opclass: o.operator_class,
2035
+ m: c.get("m") ?? 16,
2036
+ efConstruction: c.get("ef_construction") ?? 64
2037
+ } } : void 0),
1920
2038
  ...n[0]?.predicate == null ? {} : { where: n[0].predicate },
1921
2039
  ...n[0]?.is_valid === !1 ? { valid: !1 } : {},
1922
2040
  ...a ? { expression: !0 } : {}
@@ -1930,20 +2048,20 @@ BEGIN
1930
2048
  unique: !0
1931
2049
  });
1932
2050
  let d = Number(e.row_count ?? 0);
1933
- T.push({
2051
+ w.push({
1934
2052
  name: e.table_name,
1935
2053
  columns: c,
1936
2054
  indexes: l,
1937
2055
  ...d > 0 ? { rowCount: d } : {}
1938
2056
  });
1939
2057
  }
1940
- return { tables: T };
2058
+ return { tables: w };
1941
2059
  });
1942
- return (t > 0 ? e.withTransaction(n) : n).pipe(w.catchAll((e) => {
2060
+ return (t > 0 ? e.withTransaction(n) : n).pipe(T.catchAll((e) => {
1943
2061
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1944
- return n.includes("statement timeout") || n.includes("57014") ? w.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.`)) : w.fail(e);
2062
+ return n.includes("statement timeout") || n.includes("57014") ? T.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.`)) : T.fail(e);
1945
2063
  }));
1946
- }, er = (e, t) => {
2064
+ }, pr = (e, t) => {
1947
2065
  switch (e.toLowerCase()) {
1948
2066
  case "varchar":
1949
2067
  case "char":
@@ -1975,21 +2093,21 @@ BEGIN
1975
2093
  case "json": return "json";
1976
2094
  default: return "text";
1977
2095
  }
1978
- }, tr = (e) => e.map((e) => {
2096
+ }, mr = (e) => e.map((e) => {
1979
2097
  let t = e, n = {};
1980
2098
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1981
2099
  return n;
1982
- }), nr = (e) => w.gen(function* () {
1983
- let t = tr(yield* e`
2100
+ }), hr = (e) => T.gen(function* () {
2101
+ let t = mr(yield* e`
1984
2102
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1985
2103
  FROM information_schema.tables
1986
2104
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1987
- ORDER BY table_name`), n = tr(yield* e`
2105
+ ORDER BY table_name`), n = mr(yield* e`
1988
2106
  SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
1989
2107
  character_maximum_length, generation_expression, extra
1990
2108
  FROM information_schema.columns
1991
2109
  WHERE table_schema = DATABASE()
1992
- ORDER BY table_name, ordinal_position`), r = tr(yield* e`
2110
+ ORDER BY table_name, ordinal_position`), r = mr(yield* e`
1993
2111
  SELECT k.table_name AS source_table,
1994
2112
  k.column_name AS source_column,
1995
2113
  k.referenced_table_name AS target_table,
@@ -1999,7 +2117,7 @@ BEGIN
1999
2117
  JOIN information_schema.referential_constraints r
2000
2118
  ON k.constraint_name = r.constraint_name
2001
2119
  AND k.table_schema = r.constraint_schema
2002
- WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = tr(yield* e`
2120
+ WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = mr(yield* e`
2003
2121
  SELECT table_name, index_name, non_unique, column_name, seq_in_index
2004
2122
  FROM information_schema.statistics
2005
2123
  WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
@@ -2012,14 +2130,14 @@ BEGIN
2012
2130
  JOIN information_schema.table_constraints tc
2013
2131
  ON tc.constraint_schema = cc.constraint_schema
2014
2132
  AND tc.constraint_name = cc.constraint_name
2015
- WHERE cc.constraint_schema = DATABASE()`.unprepared, s = tr(yield* a.pipe(w.orElse(() => o), w.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
2133
+ WHERE cc.constraint_schema = DATABASE()`.unprepared, s = mr(yield* a.pipe(T.orElse(() => o), T.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
2016
2134
  for (let e of s) {
2017
2135
  let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
2018
2136
  if (t) {
2019
2137
  c.add(`${e.table_name}.${t[1]}`);
2020
2138
  continue;
2021
2139
  }
2022
- let n = Gn(e.check_clause);
2140
+ let n = ir(e.check_clause);
2023
2141
  n && l.set(`${e.table_name}.${n.column}`, n.values);
2024
2142
  }
2025
2143
  let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
@@ -2042,24 +2160,24 @@ BEGIN
2042
2160
  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);
2043
2161
  if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
2044
2162
  let s = t.map((t) => {
2045
- 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" : er(t.data_type, t.column_type), u = o ? {
2163
+ 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" : pr(t.data_type, t.column_type), u = o ? {
2046
2164
  table: o.target_table,
2047
2165
  column: o.target_column,
2048
- onDelete: B(o.delete_rule),
2049
- onUpdate: B(o.update_rule)
2166
+ onDelete: V(o.delete_rule),
2167
+ onUpdate: V(o.update_rule)
2050
2168
  } : 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}`);
2051
2169
  return {
2052
2170
  name: t.column_name,
2053
2171
  type: s,
2054
2172
  nullable: t.is_nullable === "YES",
2055
- ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
2173
+ ...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
2056
2174
  unique: d,
2057
2175
  hasDefault: f !== null,
2058
2176
  ...f === null ? {} : { defaultValue: f },
2059
2177
  ...u ? { references: u } : {},
2060
- ...o ? { referenceStorage: ["integer", "bigint"].includes(er(t.data_type, t.column_type)) ? "numeric" : "text" } : {},
2178
+ ...o ? { referenceStorage: ["integer", "bigint"].includes(pr(t.data_type, t.column_type)) ? "numeric" : "text" } : {},
2061
2179
  ...p ? { oneOf: p } : {},
2062
- ...qn(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
2180
+ ...or(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
2063
2181
  };
2064
2182
  }), m = new Set(n.map((e) => e.source_column)), h = [];
2065
2183
  if (o) for (let [t, n] of o) {
@@ -2086,10 +2204,10 @@ BEGIN
2086
2204
  });
2087
2205
  }
2088
2206
  return { tables: p };
2089
- }), rr = (e) => {
2207
+ }), gr = (e) => {
2090
2208
  let t = e.toUpperCase();
2091
2209
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
2092
- }, ir = (e) => e === 1 || e === !0, ar = (e) => w.gen(function* () {
2210
+ }, _r = (e) => e === 1 || e === !0, vr = (e) => T.gen(function* () {
2093
2211
  let t = yield* e`
2094
2212
  SELECT name, sql FROM sqlite_master
2095
2213
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -2103,18 +2221,18 @@ BEGIN
2103
2221
  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 Map(), m = /* @__PURE__ */ new Set();
2104
2222
  for (let t of c) {
2105
2223
  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);
2106
- if (f.set(t.name, r), t.partial !== void 0 && ir(t.partial)) {
2107
- let n = Xt((yield* e`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${t.name}`)[0]?.sql ?? "");
2224
+ if (f.set(t.name, r), t.partial !== void 0 && _r(t.partial)) {
2225
+ let n = cn((yield* e`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${t.name}`)[0]?.sql ?? "");
2108
2226
  n !== void 0 && p.set(t.name, n);
2109
2227
  }
2110
- !p.has(t.name) && ir(t.unique) && r.length === 1 && m.add(r[0]);
2228
+ !p.has(t.name) && _r(t.unique) && r.length === 1 && m.add(r[0]);
2111
2229
  }
2112
2230
  let h = o.map((e) => {
2113
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : rr(e.type), a = r ? {
2231
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : gr(e.type), a = r ? {
2114
2232
  table: r.table,
2115
2233
  column: r.to,
2116
- onDelete: B(r.on_delete),
2117
- onUpdate: B(r.on_update)
2234
+ onDelete: V(r.on_delete),
2235
+ onUpdate: V(r.on_update)
2118
2236
  } : void 0, o = t.get(e.name);
2119
2237
  return {
2120
2238
  name: e.name,
@@ -2124,19 +2242,19 @@ BEGIN
2124
2242
  hasDefault: e.dflt_value !== null,
2125
2243
  ...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
2126
2244
  ...a ? { references: a } : {},
2127
- ...r ? { referenceStorage: ["integer", "bigint"].includes(rr(e.type)) ? "numeric" : "text" } : {},
2245
+ ...r ? { referenceStorage: ["integer", "bigint"].includes(gr(e.type)) ? "numeric" : "text" } : {},
2128
2246
  ...o ? { oneOf: o } : {},
2129
- ...qn(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
2247
+ ...or(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
2130
2248
  };
2131
2249
  }), g = new Set(s.map((e) => e.from)), _ = [];
2132
2250
  for (let e of c) {
2133
2251
  if (e.origin === "pk") continue;
2134
2252
  let t = f.get(e.name) ?? [], n = p.get(e.name);
2135
- n === void 0 && t.length === 1 && ir(e.unique) || (n !== void 0 || t.length !== 1 || ir(e.unique) || !g.has(t[0]) || e.name === `${i}_${t[0]}_idx`) && _.push({
2253
+ n === void 0 && t.length === 1 && _r(e.unique) || (n !== void 0 || t.length !== 1 || _r(e.unique) || !g.has(t[0]) || e.name === `${i}_${t[0]}_idx`) && _.push({
2136
2254
  name: e.name,
2137
2255
  table: i,
2138
2256
  columns: t,
2139
- unique: ir(e.unique),
2257
+ unique: _r(e.unique),
2140
2258
  ...n === void 0 ? {} : { where: n }
2141
2259
  });
2142
2260
  }
@@ -2152,7 +2270,7 @@ BEGIN
2152
2270
  });
2153
2271
  }
2154
2272
  return { tables: r };
2155
- }), or = (e) => {
2273
+ }), yr = (e) => {
2156
2274
  switch (e.toLowerCase()) {
2157
2275
  case "int":
2158
2276
  case "smallint":
@@ -2174,14 +2292,14 @@ BEGIN
2174
2292
  case "image": return "bytes";
2175
2293
  default: return "text";
2176
2294
  }
2177
- }, V = (e) => e === !0 || e === 1, sr = (e) => w.gen(function* () {
2295
+ }, H = (e) => e === !0 || e === 1, br = (e) => T.gen(function* () {
2178
2296
  let t = yield* e`
2179
2297
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
2180
2298
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
2181
2299
  SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
2182
2300
  IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
2183
2301
  CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
2184
- FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* w.orElseSucceed(e`
2302
+ FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* T.orElseSucceed(e`
2185
2303
  SELECT t.name AS table_name, c.name AS column_name, cc.definition AS definition,
2186
2304
  cc.is_persisted AS is_persisted
2187
2305
  FROM sys.computed_columns cc
@@ -2206,14 +2324,14 @@ BEGIN
2206
2324
  JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
2207
2325
  WHERE i.type > 0 AND ic.is_included_column = 0
2208
2326
  ORDER BY t.name, i.name, ic.key_ordinal`, s = yield* e`
2209
- SELECT t.name AS table_name, c.name AS column_name, cc.definition AS def
2327
+ SELECT t.name AS table_name, c.name AS column_name, cc.definition AS def,
2328
+ cc.name AS constraint_name, cc.is_disabled, cc.is_not_trusted
2210
2329
  FROM sys.check_constraints cc
2211
2330
  JOIN sys.tables t ON t.object_id = cc.parent_object_id
2212
- JOIN sys.columns c ON c.object_id = cc.parent_object_id AND c.column_id = cc.parent_column_id
2213
- WHERE cc.parent_column_id <> 0`, c = /* @__PURE__ */ new Map();
2331
+ LEFT JOIN sys.columns c ON c.object_id = cc.parent_object_id AND c.column_id = cc.parent_column_id`, c = /* @__PURE__ */ new Map();
2214
2332
  for (let e of s) {
2215
- let t = [...e.def.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
2216
- t.length > 0 && c.set(`${e.table_name}.${e.column_name}`, t);
2333
+ let t = ir(e.def);
2334
+ t?.column === e.column_name && c.set(`${e.table_name}.${e.column_name}`, t.values);
2217
2335
  }
2218
2336
  let l = /* @__PURE__ */ new Map();
2219
2337
  for (let e of n) {
@@ -2234,141 +2352,173 @@ BEGIN
2234
2352
  }
2235
2353
  let f = [];
2236
2354
  for (let { table_name: e } of t) {
2237
- 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();
2355
+ 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), p = [], m = /* @__PURE__ */ new Set();
2238
2356
  if (o) for (let [, e] of o) {
2239
2357
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
2240
- if (V(t[0].is_primary)) for (let e of t) s.push(e.column_name);
2241
- else t[0].predicate == null && V(t[0].is_unique) && t.length === 1 && p.add(t[0].column_name);
2358
+ if (H(t[0].is_primary)) for (let e of t) p.push(e.column_name);
2359
+ else t[0].predicate == null && H(t[0].is_unique) && t.length === 1 && m.add(t[0].column_name);
2242
2360
  }
2243
- let m = t.map((t) => {
2244
- 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" : or(t.data_type), l = a ? {
2361
+ let h = t.map((t) => {
2362
+ let n = p.length === 1 && p[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : yr(t.data_type), l = a ? {
2245
2363
  table: a.target_table,
2246
2364
  column: a.target_column,
2247
- onDelete: cr(a.delete_rule),
2248
- onUpdate: cr(a.update_rule)
2249
- } : void 0, u = t.column_default === null ? null : lr(t.column_default), d = c.get(`${e}.${t.column_name}`);
2365
+ onDelete: xr(a.delete_rule),
2366
+ onUpdate: xr(a.update_rule)
2367
+ } : void 0, u = t.column_default === null ? null : Sr(t.column_default), d = c.get(`${e}.${t.column_name}`), f = s.flatMap((n) => {
2368
+ if (n.table_name !== e || n.column_name !== null && n.column_name !== t.column_name) return [];
2369
+ let r = at(t.column_name, n.def);
2370
+ return r ? [{
2371
+ name: n.constraint_name,
2372
+ validation: r,
2373
+ enabled: !H(n.is_disabled),
2374
+ trusted: !H(n.is_not_trusted)
2375
+ }] : [];
2376
+ }).sort((e, t) => e.name.localeCompare(t.name)), h = ot(f);
2250
2377
  return {
2251
2378
  name: t.column_name,
2252
2379
  type: o,
2253
2380
  nullable: t.is_nullable === "YES",
2254
- ...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
2255
- unique: p.has(t.column_name) || n && t.column_name === "id",
2381
+ ...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
2382
+ unique: m.has(t.column_name) || n && t.column_name === "id",
2256
2383
  hasDefault: u !== null,
2257
2384
  ...u === null ? {} : { defaultValue: u },
2258
2385
  ...l ? { references: l } : {},
2259
- ...a ? { referenceStorage: ["integer", "bigint"].includes(or(t.data_type)) ? "numeric" : "text" } : {},
2386
+ ...a ? { referenceStorage: ["integer", "bigint"].includes(yr(t.data_type)) ? "numeric" : "text" } : {},
2260
2387
  ...d ? { oneOf: d } : {},
2261
- ...qn(i.get(`${e}.${t.column_name}`)?.definition ?? null, V(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2388
+ ...f.length > 0 ? { jsonChecks: f } : {},
2389
+ ...h ? { jsonValidation: h } : {},
2390
+ ...or(i.get(`${e}.${t.column_name}`)?.definition ?? null, H(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2262
2391
  };
2263
- }), h = [];
2392
+ }), g = [];
2264
2393
  if (o) for (let [t, n] of o) {
2265
2394
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
2266
- if (V(r[0].is_primary)) continue;
2395
+ if (H(r[0].is_primary)) continue;
2267
2396
  let i = r[0].predicate ?? void 0;
2268
- i === void 0 && r.length === 1 && V(r[0].is_unique) || (i !== void 0 || r.length !== 1 || V(r[0].is_unique) || !a.has(r[0].column_name) || t === `${e}_${r[0].column_name}_idx`) && h.push({
2397
+ i === void 0 && r.length === 1 && H(r[0].is_unique) || (i !== void 0 || r.length !== 1 || H(r[0].is_unique) || !a.has(r[0].column_name) || t === `${e}_${r[0].column_name}_idx`) && g.push({
2269
2398
  name: t,
2270
2399
  table: e,
2271
2400
  columns: r.map((e) => e.column_name),
2272
- unique: V(r[0].is_unique),
2401
+ unique: H(r[0].is_unique),
2273
2402
  ...i === void 0 ? {} : { where: i }
2274
2403
  });
2275
2404
  }
2276
- s.length > 0 && h.push({
2405
+ p.length > 0 && g.push({
2277
2406
  name: `${e}_pkey`,
2278
2407
  table: e,
2279
- columns: s,
2408
+ columns: p,
2280
2409
  unique: !0
2281
2410
  }), f.push({
2282
2411
  name: e,
2283
- columns: m,
2284
- indexes: h
2412
+ columns: h,
2413
+ indexes: g
2285
2414
  });
2286
2415
  }
2287
2416
  return { tables: f };
2288
- }), cr = (e) => {
2417
+ }), xr = (e) => {
2289
2418
  switch (e.toUpperCase().replace(/_/g, " ")) {
2290
2419
  case "CASCADE": return "cascade";
2291
2420
  case "SET NULL": return "setNull";
2292
2421
  case "SET DEFAULT": return "noAction";
2293
2422
  default: return "noAction";
2294
2423
  }
2295
- }, lr = (e) => {
2424
+ }, Sr = (e) => {
2296
2425
  let t = e.trim();
2297
2426
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
2298
2427
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
2299
- }, ur = /* @__PURE__ */ new Set([
2428
+ }, Cr = /* @__PURE__ */ new Set([
2300
2429
  "character varying",
2301
2430
  "varchar",
2302
2431
  "nvarchar",
2303
2432
  "char",
2304
2433
  "character",
2305
2434
  "nchar"
2306
- ]), H = (e, t) => {
2307
- if (!ur.has(e.toLowerCase())) return;
2435
+ ]), U = (e, t) => {
2436
+ if (!Cr.has(e.toLowerCase())) return;
2308
2437
  let n = Number(t);
2309
2438
  if (!(!Number.isFinite(n) || n <= 0)) return n;
2310
- }, dr = /* @__PURE__ */ new Set([k]), fr = (e) => e.onDialectOrElse({
2311
- mysql: () => nr(e),
2312
- mssql: () => sr(e),
2313
- sqlite: () => ar(e),
2314
- orElse: () => $n(e)
2315
- }).pipe(w.map((e) => ({
2439
+ }, wr = /* @__PURE__ */ new Set([k]), Tr = (e) => e.onDialectOrElse({
2440
+ mysql: () => hr(e),
2441
+ mssql: () => br(e),
2442
+ sqlite: () => vr(e),
2443
+ orElse: () => fr(e)
2444
+ }).pipe(T.map((e) => ({
2316
2445
  ...e,
2317
- tables: e.tables.filter((e) => !dr.has(e.name))
2318
- }))), pr = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", mr = /* @__PURE__ */ new WeakMap(), hr = (e) => w.suspend(() => {
2319
- let t = mr.get(e);
2320
- return t === void 0 ? gr(e).pipe(w.tap((t) => w.sync(() => mr.set(e, t)))) : w.succeed(t);
2321
- }), gr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(w.map((e) => {
2446
+ tables: e.tables.filter((e) => !wr.has(e.name))
2447
+ }))), Er = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", Dr = /* @__PURE__ */ new WeakMap(), Or = (e) => T.suspend(() => {
2448
+ let t = Dr.get(e);
2449
+ return t === void 0 ? kr(e).pipe(T.tap((t) => T.sync(() => Dr.set(e, t)))) : T.succeed(t);
2450
+ }), kr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(T.map((e) => {
2322
2451
  let t = e[0]?.v;
2323
- return typeof t == "string" ? pr(t) : "mysql";
2324
- }), w.catchAll(() => w.succeed("mysql"))), _r = (e) => {
2452
+ return typeof t == "string" ? Er(t) : "mysql";
2453
+ }), T.catchAll(() => T.succeed("mysql"))), Ar = (e) => {
2325
2454
  let t = e;
2326
2455
  for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
2327
2456
  let e = t;
2328
2457
  if (typeof e.errno == "number") return e.errno;
2329
2458
  t = e.cause;
2330
2459
  }
2331
- }, vr = (e) => {
2460
+ }, jr = (e) => {
2332
2461
  let t = [], n = e;
2333
2462
  for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
2334
2463
  let e = n;
2335
2464
  typeof e.message == "string" && t.push(e.message), n = e.cause;
2336
2465
  }
2337
2466
  return t.join(" | ");
2338
- }, yr = (e, t) => {
2467
+ }, Mr = (e, t) => {
2339
2468
  if (t.length === 0) return !1;
2340
- let n = _r(e), r = vr(e);
2469
+ let n = Ar(e), r = jr(e);
2341
2470
  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)));
2342
- }, br = {
2471
+ }, Nr = {
2343
2472
  why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
2344
2473
  errno: [1061]
2345
- }, xr = {
2474
+ }, Pr = {
2346
2475
  why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
2347
2476
  errno: [1091]
2348
- }, Sr = {
2477
+ }, Fr = {
2349
2478
  why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
2350
2479
  messageIncludes: ["no such column"]
2351
- }, Cr = {
2480
+ }, Ir = {
2352
2481
  why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
2353
2482
  errno: [1091, 3940]
2354
- }, U = (e, t) => e.onDialectOrElse({
2355
- mysql: () => w.succeed(t.replace("T", " ").replace("Z", "")),
2356
- orElse: () => w.succeed(t)
2357
- }), wr = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Tr = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), Er = (e, t) => {
2358
- if ((e.type !== "text" || e.maxLength === void 0) && !Tr(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2483
+ }, Lr = (e, t) => T.suspend(() => {
2484
+ let n;
2485
+ return e.withTransaction(t.pipe(T.tapErrorCause((e) => T.sync(() => {
2486
+ n = e;
2487
+ })))).pipe(T.catchAllCause((e) => T.failCause(n !== void 0 && !ee.equals(n, e) ? w.sequential(n, e) : e)));
2488
+ }), Rr = (e, t, n) => {
2489
+ let r = e.match(/'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|\s+|[^'\[\s]+/g) ?? [];
2490
+ if (r.join("") !== e || r.some((e) => !e.startsWith("'") && !e.startsWith("[") && /"|\/\*|--/.test(e))) throw Error("Cannot safely rename CHECK: unsupported catalog SQL; use an explicit migration");
2491
+ let i = r.map((e, t) => ({
2492
+ value: e,
2493
+ index: t
2494
+ })).filter((e) => e.value.trim() !== ""), a = 0;
2495
+ for (let e = 0; e < i.length; e++) {
2496
+ let s = i[e];
2497
+ if (s.value !== o(t, "mssql")) continue;
2498
+ let c = i[e - 1]?.value ?? "", l = i[e + 1]?.value ?? "";
2499
+ if (c.endsWith(".") || l.startsWith(".") || l.startsWith("(")) throw Error(`Cannot safely rename CHECK reference '${t}': qualified or callable identifier; use an explicit migration`);
2500
+ r[s.index] = o(n, "mssql"), a++;
2501
+ }
2502
+ if (a === 0 || r.join("").length === 0) throw Error(`Cannot safely rename CHECK reference '${t}': no exact catalog column token; use an explicit migration`);
2503
+ return r.join("");
2504
+ }, W = (e, t) => e.onDialectOrElse({
2505
+ mysql: () => T.succeed(t.replace("T", " ").replace("Z", "")),
2506
+ orElse: () => T.succeed(t)
2507
+ }), zr = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Br = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), Vr = (e, t) => {
2508
+ if ((e.type !== "text" || e.maxLength === void 0) && !Br(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2359
2509
  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;
2360
2510
  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.`);
2361
2511
  return M(e, t);
2362
- }, Dr = (e) => {
2363
- let t = Er(e, "postgres");
2364
- return t === void 0 ? Or(e) : t;
2365
- }, Or = (e) => {
2512
+ }, Hr = (e) => {
2513
+ let t = Vr(e, "postgres");
2514
+ return t === void 0 ? Ur(e) : t;
2515
+ }, Ur = (e) => {
2366
2516
  switch (e.type) {
2367
2517
  case "id": return "text";
2368
2518
  case "text": return "text";
2369
2519
  case "integer": return "integer";
2370
2520
  case "real": return "double precision";
2371
- case "decimal": return wr(e, "NUMERIC");
2521
+ case "decimal": return zr(e, "NUMERIC");
2372
2522
  case "bigint": return "bigint";
2373
2523
  case "boolean": return "boolean";
2374
2524
  case "timestamp": return "timestamptz";
@@ -2382,15 +2532,15 @@ BEGIN
2382
2532
  case "interval": return "interval";
2383
2533
  case "raw": return e.rawDdl ?? "text";
2384
2534
  }
2385
- }, kr = (e) => {
2386
- let t = Er(e, "mariadb");
2535
+ }, Wr = (e) => {
2536
+ let t = Vr(e, "mariadb");
2387
2537
  if (t !== void 0) return t;
2388
2538
  switch (e.type) {
2389
2539
  case "id": return "VARCHAR(64)";
2390
2540
  case "text": return "LONGTEXT";
2391
2541
  case "integer": return "INT";
2392
2542
  case "real": return "DOUBLE";
2393
- case "decimal": return wr(e, "DECIMAL");
2543
+ case "decimal": return zr(e, "DECIMAL");
2394
2544
  case "bigint": return "BIGINT";
2395
2545
  case "boolean": return "TINYINT(1)";
2396
2546
  case "timestamp": return "DATETIME(6)";
@@ -2404,64 +2554,68 @@ BEGIN
2404
2554
  case "interval": return "BIGINT";
2405
2555
  case "raw": return e.rawDdl ?? "LONGTEXT";
2406
2556
  }
2407
- }, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, Ar = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", jr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Mr = (e, t = "mariadb") => `ALTER TABLE ${G(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${G(e.column)}, ALGORITHM=COPY;`, Nr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Pr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${li(t)}`)};`, Fr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Lr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Ir = (e, t) => {
2557
+ }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, Gr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", Kr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, qr = (e, t = "mariadb") => `ALTER TABLE ${K(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${K(e.column)}, ALGORITHM=COPY;`, Jr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Yr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Ti(t)}`)};`, Xr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Qr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Zr = (e, t) => {
2408
2558
  let { defaultFactory: n, ...r } = e;
2409
2559
  return M(e, t) !== M({
2410
2560
  ...r,
2411
2561
  hasDefault: !1
2412
2562
  }, t);
2413
- }, Lr = (e, t) => {
2563
+ }, Qr = (e, t) => {
2414
2564
  let n = t(e.defaultValue);
2415
2565
  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.`);
2416
2566
  return n;
2417
- }, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Rr = (e, t, n) => {
2418
- let r = K(e, t, n);
2419
- return r ? on(n, r) : void 0;
2420
- }, zr = (e, t, n) => {
2421
- let r = n ?? e.nullable, i = rt(e, "mariadb");
2567
+ }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], $r = (e, t, n) => {
2568
+ let r = q(e, t, n);
2569
+ return r ? vn(n, r) : void 0;
2570
+ }, ei = (e, t, n) => {
2571
+ let r = n ?? e.nullable, i = pt(e, "mariadb");
2422
2572
  return [
2423
- G(t),
2573
+ K(t),
2424
2574
  M(e, "mariadb"),
2425
2575
  r ? null : "NOT NULL",
2426
2576
  i
2427
2577
  ].filter(Boolean).join(" ");
2428
- }, Br = (e, t) => e == null ? null : Array.isArray(e) ? Vr(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, Vr = (e, t, n) => it(e, t ?? { type: "json" }, n), Hr = (e, t) => e == null ? null : Array.isArray(e) ? Vr(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, Ur = (e, t) => {
2578
+ }, ti = (e, t) => e == null ? null : Array.isArray(e) ? ni(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, ni = (e, t, n) => mt(e, t ?? { type: "json" }, n), ri = (e, t) => e == null ? null : Array.isArray(e) ? ni(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, ii = (e, t) => {
2429
2579
  if (!e.generatedAs) return null;
2430
2580
  let { expr: n, stored: r } = e.generatedAs;
2431
2581
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2432
- }, Wr = (e) => {
2582
+ }, ai = (e, t = !1) => {
2433
2583
  if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "postgres");
2434
- let t = Ur(e, "postgres");
2435
- if (t) return `${W(e.name)} ${Dr(e)} ${t}`;
2436
- let n = [W(e.name), Dr(e)];
2437
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2438
- let t = Hr(e.defaultValue, e);
2439
- t && n.push(t);
2440
- }
2441
- return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
2584
+ let n = ii(e, "postgres");
2585
+ if (n) return `${G(e.name)} ${Hr(e)} ${n}`;
2586
+ let r = [G(e.name), Hr(e)];
2587
+ if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && r.push("UNIQUE"), e.hasDefault) {
2588
+ let t = ri(e.defaultValue, e);
2589
+ t && r.push(t);
2590
+ }
2591
+ return e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
2442
2592
  cascade: "CASCADE",
2443
2593
  restrict: "RESTRICT",
2444
2594
  setNull: "SET NULL",
2445
2595
  noAction: "NO ACTION"
2446
- }[e.references.onDelete]}`)), n.join(" ");
2447
- }, Gr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Kr = (e) => {
2448
- let t = e.columns.map((e) => ` ${Wr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Gr(e, W)}\n)`];
2449
- 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(mi).join(", ")})${Y(t)}`);
2596
+ }[e.references.onDelete]}`)), r.join(" ");
2597
+ }, oi = (e) => (e.primaryKey?.length ?? 0) > 0, si = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", ci = (e) => {
2598
+ let t = e.columns.map((t) => ` ${ai(t, oi(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${si(e, G)}\n)`];
2599
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(Mi({
2600
+ kind: "add-index",
2601
+ table: e.table,
2602
+ index: t
2603
+ }, !1));
2450
2604
  return n;
2451
- }, qr = 191, Jr = (e) => {
2452
- let t = kr(e).toUpperCase();
2605
+ }, li = 191, ui = (e) => {
2606
+ let t = Wr(e).toUpperCase();
2453
2607
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2454
- }, Yr = (e) => {
2608
+ }, di = (e, t = !1) => {
2455
2609
  if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mariadb");
2456
- let t = Ur(e, "mariadb");
2457
- if (t) return `${G(e.name)} ${kr(e)} ${t}`;
2458
- let n = [G(e.name), kr(e)];
2459
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !Jr(e) && n.push("UNIQUE"), e.hasDefault) {
2460
- let t = Br(e.defaultValue, e);
2461
- t && n.push(t);
2462
- }
2463
- return n.join(" ");
2464
- }, Xr = (e) => e.columns.flatMap((t) => {
2610
+ let n = ii(e, "mariadb");
2611
+ if (n) return `${K(e.name)} ${Wr(e)} ${n}`;
2612
+ let r = [K(e.name), Wr(e)];
2613
+ if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && !ui(e) && r.push("UNIQUE"), e.hasDefault) {
2614
+ let t = ti(e.defaultValue, e);
2615
+ t && r.push(t);
2616
+ }
2617
+ return r.join(" ");
2618
+ }, fi = (e) => e.columns.flatMap((t) => {
2465
2619
  if (!t.references) return [];
2466
2620
  let n = t.references.onDelete ? ` ON DELETE ${{
2467
2621
  cascade: "CASCADE",
@@ -2469,28 +2623,28 @@ BEGIN
2469
2623
  setNull: "SET NULL",
2470
2624
  noAction: "NO ACTION"
2471
2625
  }[t.references.onDelete]}` : "";
2472
- return [` CONSTRAINT ${G(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${G(t.name)}) REFERENCES ${G(t.references.table)} (${G(t.references.column)})${n}`];
2473
- }), Zr = (e, t = "mariadb") => {
2474
- for (let n of e.indexes) _i(n, t);
2626
+ return [` CONSTRAINT ${K(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${K(t.name)}) REFERENCES ${K(t.references.table)} (${K(t.references.column)})${n}`];
2627
+ }), pi = (e, t = "mariadb") => {
2628
+ for (let n of e.indexes) Pi(n, t);
2475
2629
  let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
2476
- let t = fi(n.get(e));
2477
- return t === void 0 ? G(e) : `${G(e)}(${t})`;
2478
- }, i = e.columns.map((e) => ` ${Yr(e)}`).join(",\n"), a = Xr(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${o}${Gr(e, r)}\n)`];
2479
- for (let n of e.columns) n.unique && n.type !== "id" && Jr(n) && s.push(`CREATE UNIQUE INDEX ${Ar(t)}${G(`${e.table}_${n.name}_key`)} ON ${G(e.table)} (${r(n.name)})`);
2480
- for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Ar(t)}${G(n.name)} ON ${G(e.table)} (${n.columns.map(r).join(", ")})`);
2630
+ let t = Oi(n.get(e));
2631
+ return t === void 0 ? K(e) : `${K(e)}(${t})`;
2632
+ }, i = e.columns.map((t) => ` ${di(t, oi(e))}`).join(",\n"), a = fi(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${o}${si(e, r)}\n)`];
2633
+ for (let n of e.columns) n.unique && n.type !== "id" && ui(n) && s.push(`CREATE UNIQUE INDEX ${Gr(t)}${K(`${e.table}_${n.name}_key`)} ON ${K(e.table)} (${r(n.name)})`);
2634
+ 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(", ")})`);
2481
2635
  return s;
2482
- }, Qr = {
2636
+ }, mi = {
2483
2637
  cascade: "CASCADE",
2484
2638
  restrict: "RESTRICT",
2485
2639
  setNull: "SET NULL",
2486
2640
  noAction: "NO ACTION"
2487
- }, $r = {
2641
+ }, hi = {
2488
2642
  cascade: "CASCADE",
2489
2643
  restrict: "NO ACTION",
2490
2644
  setNull: "SET NULL",
2491
2645
  noAction: "NO ACTION"
2492
- }, ei = (e) => {
2493
- let t = Er(e, "sqlite");
2646
+ }, gi = (e) => {
2647
+ let t = Vr(e, "sqlite");
2494
2648
  if (t !== void 0) return t;
2495
2649
  switch (e.type) {
2496
2650
  case "integer":
@@ -2502,60 +2656,60 @@ BEGIN
2502
2656
  case "bytes": return "BLOB";
2503
2657
  default: return "TEXT";
2504
2658
  }
2505
- }, ti = (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, ni = (e) => {
2659
+ }, _i = (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, vi = (e, t = !1) => {
2506
2660
  if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "sqlite");
2507
- let t = Ur(e, "sqlite");
2508
- if (t) return `${W(e.name)} ${ei(e)} ${t}`;
2509
- let n = [W(e.name), ei(e)];
2510
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
2511
- let t = ti(e.defaultValue, "CURRENT_TIMESTAMP");
2512
- t && n.push(t);
2513
- }
2514
- if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Qr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2661
+ let n = ii(e, "sqlite");
2662
+ if (n) return `${G(e.name)} ${gi(e)} ${n}`;
2663
+ let r = [G(e.name), gi(e)];
2664
+ if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && r.push("UNIQUE"), e.hasDefault) {
2665
+ let t = _i(e.defaultValue, "CURRENT_TIMESTAMP");
2666
+ t && r.push(t);
2667
+ }
2668
+ if (e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${mi[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2515
2669
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2516
- n.push(`CHECK (${W(e.name)} IN (${t}))`);
2670
+ r.push(`CHECK (${G(e.name)} IN (${t}))`);
2517
2671
  }
2518
- return n.join(" ");
2519
- }, ri = (e) => {
2520
- let t = e.columns.map((e) => ` ${ni(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Gr(e, W)}\n)`];
2521
- 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(", ")})${Y(t)}`);
2672
+ return r.join(" ");
2673
+ }, yi = (e) => {
2674
+ let t = e.columns.map((t) => ` ${vi(t, oi(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${si(e, G)}\n)`];
2675
+ 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(", ")})${ji(t)}`);
2522
2676
  return n;
2523
- }, q = (e, t) => {
2677
+ }, J = (e, t) => {
2524
2678
  let n = t.find((t) => t.tableName === e);
2525
2679
  if (!n) return [];
2526
- let r = R([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
2527
- ...ri({
2680
+ let r = z([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
2681
+ ...yi({
2528
2682
  kind: "create-table",
2529
2683
  table: i,
2530
2684
  columns: r.columns,
2531
2685
  indexes: [],
2532
2686
  ...r.primaryKey ? { primaryKey: r.primaryKey } : {}
2533
2687
  }),
2534
- `INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
2535
- `DROP TABLE ${W(e)}`,
2536
- `ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
2688
+ `INSERT INTO ${G(i)} (${a}) SELECT ${a} FROM ${G(e)}`,
2689
+ `DROP TABLE ${G(e)}`,
2690
+ `ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
2537
2691
  ];
2538
- 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(", ")})${Y(t)}`);
2692
+ 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(", ")})${ji(t)}`);
2539
2693
  return o;
2540
- }, ii = (e, t, n, r) => {
2694
+ }, bi = (e, t, n, r) => {
2541
2695
  let i = r ?? e.nullable;
2542
- return `ALTER TABLE ${J(n)} ALTER COLUMN ${J(t)} ${M(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2543
- }, ai = (e, t) => {
2544
- 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 ${J(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
2696
+ return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${M(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2697
+ }, xi = (e, t) => {
2698
+ 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}` : "");
2545
2699
  if (!e.hasDefault) return n;
2546
- let r = ti(e.defaultValue, "SYSUTCDATETIME()");
2700
+ let r = _i(e.defaultValue, "SYSUTCDATETIME()");
2547
2701
  if (!r) return n;
2548
2702
  let i = r.replace(/^DEFAULT\s+/i, "");
2549
- return `${n} ALTER TABLE ${J(e.table)} ADD DEFAULT ${i} FOR ${J(e.column)};`;
2550
- }, J = (e) => `[${e.replace(/]/g, "]]")}]`, oi = (e) => {
2551
- let t = Er(e, "mssql");
2703
+ return `${n} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${i} FOR ${Y(e.column)};`;
2704
+ }, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Si = (e) => {
2705
+ let t = Vr(e, "mssql");
2552
2706
  if (t !== void 0) return t;
2553
2707
  switch (e.type) {
2554
2708
  case "id": return "NVARCHAR(64)";
2555
2709
  case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
2556
2710
  case "integer": return "INT";
2557
2711
  case "real": return "FLOAT";
2558
- case "decimal": return wr(e, "DECIMAL");
2712
+ case "decimal": return zr(e, "DECIMAL");
2559
2713
  case "bigint": return "BIGINT";
2560
2714
  case "boolean": return "BIT";
2561
2715
  case "timestamp": return "DATETIME2(6)";
@@ -2563,61 +2717,68 @@ BEGIN
2563
2717
  case "bytes": return "VARBINARY(MAX)";
2564
2718
  default: return "NVARCHAR(MAX)";
2565
2719
  }
2566
- }, si = (e, t) => {
2720
+ }, Ci = (e, t, n = !1) => {
2567
2721
  if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mssql");
2568
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : oi(e), r = Ur(e, "mssql");
2569
- if (r) return `${J(e.name)} ${r}`;
2570
- let i = [J(e.name), n];
2571
- if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2572
- let t = ti(e.defaultValue, "SYSUTCDATETIME()");
2573
- t && i.push(t);
2574
- }
2575
- return e.references && (i.push(`REFERENCES ${J(e.references.table)} (${J(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${$r[e.references.onDelete]}`)), i.join(" ");
2576
- }, ci = (e) => {
2577
- 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) => ` ${si(e, n)}`).join(",\n"), i = `CREATE TABLE ${J(e.table)} (\n${r}${Gr(e, J)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2722
+ let r = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Si(e), i = ii(e, "mssql");
2723
+ if (i) return `${Y(e.name)} ${i}`;
2724
+ let a = [Y(e.name), r];
2725
+ if (e.type === "json" && a.push(`CHECK ${rt(Y(e.name))}`), e.type === "array" && a.push(`CHECK (${Y(e.name)} IS NULL OR ISJSON(${Y(e.name)}) = 1)`), e.type === "id" && !n && a.push("PRIMARY KEY"), e.nullable || a.push("NOT NULL"), e.unique && e.type !== "id" && a.push("UNIQUE"), e.hasDefault) {
2726
+ let t = _i(e.defaultValue, "SYSUTCDATETIME()");
2727
+ t && a.push(t);
2728
+ }
2729
+ return e.references && (a.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${hi[e.references.onDelete]}`)), a.join(" ");
2730
+ }, wi = (e) => {
2731
+ 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((t) => ` ${Ci(t, n, oi(e))}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${si(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2578
2732
  for (let n of e.indexes) {
2579
2733
  if (n.name === `${e.table}_pkey`) continue;
2580
- let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${J(n.name)} ON ${J(e.table)} (${n.columns.map(J).join(", ")})${Y(n)}`;
2734
+ let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})${ji(n)}`;
2581
2735
  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)}')`);
2582
2736
  }
2583
2737
  return a;
2584
- }, li = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, ui = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, di = (e, t, n) => {
2585
- let r = `${e.table}${li(t)}`;
2738
+ }, Ti = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Ei = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Di = (e, t, n) => {
2739
+ let r = `${e.table}${Ti(t)}`;
2586
2740
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2587
- }, fi = (e) => {
2588
- if (e === void 0 || !Jr(e)) return;
2741
+ }, Oi = (e) => {
2742
+ if (e === void 0 || !ui(e)) return;
2589
2743
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
2590
- return t === void 0 ? qr : Math.min(qr, t);
2591
- }, pi = (e, t, n) => {
2592
- let r = fi(Rr(e, t, n));
2593
- return r === void 0 ? G(n) : `${G(n)}(${r})`;
2594
- }, mi = (e) => e.startsWith("(") ? e : W(e), Y = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, hi = (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(mi).join(", ")})${Y(e.index)};`, gi = (e, t, n = "mariadb") => (_i(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Ar(n)}${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => pi(t, e.table, n)).join(", ")});`), _i = (e, t) => {
2744
+ return t === void 0 ? li : Math.min(li, t);
2745
+ }, ki = (e, t, n) => {
2746
+ let r = Oi($r(e, t, n));
2747
+ return r === void 0 ? K(n) : `${K(n)}(${r})`;
2748
+ }, Ai = (e) => e.startsWith("(") ? e : G(e), ji = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, Mi = (e, t) => {
2749
+ let n = fe(e.index.kind, e.index.kindOptions), r = e.index.columns.map(Ai);
2750
+ if (n.opclass !== void 0) {
2751
+ if (r.length !== 1) throw Error("HNSW index requires exactly one column");
2752
+ r[0] = `${r[0]} ${n.opclass}`;
2753
+ }
2754
+ return `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)}${n.using} (${r.join(", ")})${n.withSuffix}${ji(e.index)};`;
2755
+ }, Ni = (e, t, n = "mariadb") => (Pi(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Gr(n)}${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => ki(t, e.table, n)).join(", ")});`), Pi = (e, t) => {
2595
2756
  if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
2596
- }, vi = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, yi = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, bi = (e) => `DROP INDEX IF EXISTS ${J(e.index)} ON ${J(e.table)};`, xi = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Si = (e) => {
2757
+ }, Fi = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Ii = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Li = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, Ri = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, zi = (e) => {
2597
2758
  let t = (e) => e.replace(/'/g, "''");
2598
2759
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
2599
- }, Ci = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, wi = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, Ti = (e) => {
2760
+ }, Bi = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, Vi = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, Hi = (e) => {
2600
2761
  let t = (e) => e.replace(/'/g, "''");
2601
2762
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2602
- }, Ei = (e) => {
2603
- let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${J(e.index.name)} ON ${J(e.table)} (${e.index.columns.map(J).join(", ")})${Y(e.index)}`;
2763
+ }, Ui = (e) => {
2764
+ 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(", ")})${ji(e.index)}`;
2604
2765
  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)}');`;
2605
- }, Di = (e, t, n) => {
2766
+ }, Wi = (e, t, n) => {
2606
2767
  let r = n.find((t) => t.tableName === e);
2607
2768
  if (!r) return [];
2608
2769
  let i = [];
2609
2770
  for (let n of t) {
2610
2771
  let t = r.fields[n];
2611
- t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${J(e)} ALTER COLUMN ${J(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2772
+ t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2612
2773
  }
2613
2774
  return i;
2614
- }, Oi = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, ki = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${pi(t, e.table, e.column)});`, Ai = (e) => {
2615
- let t = e.fields.map((e) => W(e)).join(", ");
2616
- return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
2617
- }, ji = (e, t) => {
2618
- let n = e.fields.map((n) => pi(t, e.table, n)).join(", ");
2619
- return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
2620
- }, Mi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, Ni = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, Pi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, Fi = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, Ii = (e, t) => {
2775
+ }, Gi = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, Ki = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${ki(t, e.table, e.column)});`, qi = (e) => {
2776
+ let t = e.fields.map((e) => G(e)).join(", ");
2777
+ return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
2778
+ }, Ji = (e, t) => {
2779
+ let n = e.fields.map((n) => ki(t, e.table, n)).join(", ");
2780
+ return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
2781
+ }, Yi = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Xi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Zi = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Qi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, $i = (e, t) => {
2621
2782
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2622
2783
  if (e.orphanPolicy) {
2623
2784
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2635,36 +2796,36 @@ BEGIN
2635
2796
  setNull: "SET NULL",
2636
2797
  noAction: "NO ACTION"
2637
2798
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2638
- }, Li = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, Ri = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, zi = (e, t) => {
2799
+ }, ea = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, ta = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, na = (e, t) => {
2639
2800
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2640
2801
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2641
- }, Bi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, Vi = (e, t) => w.gen(function* () {
2802
+ }, ra = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, ia = (e, t) => T.gen(function* () {
2642
2803
  let n = yield* e`
2643
2804
  SELECT cc.constraint_name AS n, cc.check_clause AS c
2644
2805
  FROM information_schema.check_constraints cc
2645
- WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(w.orElse(() => e`
2806
+ WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(T.orElse(() => e`
2646
2807
  SELECT cc.constraint_name AS n, cc.check_clause AS c
2647
2808
  FROM information_schema.check_constraints cc
2648
2809
  JOIN information_schema.table_constraints tc
2649
2810
  ON tc.constraint_schema = cc.constraint_schema
2650
2811
  AND tc.constraint_name = cc.constraint_name
2651
- WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), w.orElseSucceed(() => []));
2812
+ WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), T.orElseSucceed(() => []));
2652
2813
  for (let e of n) {
2653
2814
  let n = String(e.n ?? "");
2654
- if (n !== "" && Gn(String(e.c ?? ""))?.column === t.column) return n;
2815
+ if (n !== "" && ir(String(e.c ?? ""))?.column === t.column) return n;
2655
2816
  }
2656
- }), Hi = (e, t, n) => w.gen(function* () {
2657
- let r = yield* Vi(e, t);
2658
- r !== void 0 && (yield* X(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [Cr]));
2659
- let i = yield* Vi(e, t);
2817
+ }), aa = (e, t, n) => T.gen(function* () {
2818
+ let r = yield* ia(e, t);
2819
+ r !== void 0 && (yield* X(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [Ir]));
2820
+ let i = yield* ia(e, t);
2660
2821
  if (i === void 0) return;
2661
- let a = K(n, t.table, t.column);
2662
- if (!a) return yield* w.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.`));
2663
- yield* X(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${zr(a, t.column)};`, t.kind);
2664
- }), Ui = (e, t, n, r) => {
2665
- let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? J : W, s = a ? kr(i) : r === "mssql" ? oi(i) : r === "sqlite" ? ei(i) : Dr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? Br(e, i) : r === "mssql" ? ti(e, "SYSUTCDATETIME()") : r === "sqlite" ? ti(e, "CURRENT_TIMESTAMP") : Hr(e, i), u = Ur(i, r);
2666
- if (u) {
2667
- let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2822
+ let a = q(n, t.table, t.column);
2823
+ if (!a) return yield* T.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.`));
2824
+ yield* X(e, `ALTER TABLE ${K(t.table)} MODIFY COLUMN ${ei(a, t.column)};`, t.kind);
2825
+ }), oa = (e, t, n, r) => {
2826
+ let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Y : G, s = a ? Wr(i) : r === "mssql" ? Si(i) : r === "sqlite" ? gi(i) : Hr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${rt(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? ti(e, i) : r === "mssql" ? _i(e, "SYSUTCDATETIME()") : r === "sqlite" ? _i(e, "CURRENT_TIMESTAMP") : ri(e, i), d = ii(i, r);
2827
+ if (d) {
2828
+ let t = r === "mssql" ? `${o(i.name)} ${d}` : `${o(i.name)} ${s} ${d}`;
2668
2829
  return {
2669
2830
  pre: [`ALTER TABLE ${o(e.table)} ${c} ${t};`],
2670
2831
  post: []
@@ -2673,24 +2834,24 @@ BEGIN
2673
2834
  if (t.classification === "safe") {
2674
2835
  let t = [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s}`];
2675
2836
  return i.unique && t.push("UNIQUE"), {
2676
- pre: [`${t.join(" ")};`],
2837
+ pre: [`${t.join(" ")}${l};`],
2677
2838
  post: []
2678
2839
  };
2679
2840
  }
2680
2841
  if (t.classification === "needs-default") {
2681
- let t = l(i.defaultValue);
2842
+ let t = u(i.defaultValue);
2682
2843
  if (t === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${i.name}' (${JSON.stringify(i.defaultValue)}) while adding it NOT NULL to a populated table. This is a framework bug — report the column type + default.`);
2683
2844
  return {
2684
- pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t};`],
2845
+ pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t}${l};`],
2685
2846
  post: []
2686
2847
  };
2687
2848
  }
2688
- let d = n(e.table, i.name), f = a ? `ALTER TABLE ${o(e.table)} MODIFY COLUMN ${o(i.name)} ${s} NOT NULL;` : r === "mssql" ? `ALTER TABLE ${o(e.table)} ALTER COLUMN ${o(i.name)} ${s} NOT NULL;` : r === "sqlite" ? null : `ALTER TABLE ${o(e.table)} ALTER COLUMN ${o(i.name)} SET NOT NULL;`, p = {
2689
- pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s};`],
2690
- post: f ? [f] : []
2849
+ let f = n(e.table, i.name), p = a ? `ALTER TABLE ${o(e.table)} MODIFY COLUMN ${o(i.name)} ${s} NOT NULL;` : r === "mssql" ? `ALTER TABLE ${o(e.table)} ALTER COLUMN ${o(i.name)} ${s} NOT NULL;` : r === "sqlite" ? null : `ALTER TABLE ${o(e.table)} ALTER COLUMN ${o(i.name)} SET NOT NULL;`, m = {
2850
+ pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s}${l};`],
2851
+ post: p ? [p] : []
2691
2852
  };
2692
- 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;
2693
- }, Wi = (e) => {
2853
+ return f?.sql && (m.backfillKind = "sql", m.backfillSql = f.sql), f?.js && (m.backfillKind = "js", m.backfillJs = f.js), f?.batchSize !== void 0 && (m.batchSize = f.batchSize), f?.sleepMs !== void 0 && (m.sleepMs = f.sleepMs), m;
2854
+ }, sa = (e) => {
2694
2855
  let t = new Map(e.map((e) => [e.tableName, e]));
2695
2856
  return (e, n) => {
2696
2857
  let r = t.get(e);
@@ -2710,44 +2871,44 @@ BEGIN
2710
2871
  ...o
2711
2872
  };
2712
2873
  };
2713
- }, X = (e, t, n, r = []) => e.unsafe(t).pipe(w.catchIf((e) => yr(e, r), () => w.void), w.tapError((e) => w.sync(() => {
2714
- process.stderr.write(se(`applier: statement failed (op=${n})`, t, e, 400));
2715
- })), w.mapError((e) => {
2716
- let r = se(`applier: statement failed (op=${n})`, t, e, 400).trim();
2874
+ }, X = (e, t, n, r = []) => e.unsafe(t).pipe(T.catchIf((e) => Mr(e, r), () => T.void), T.tapError((e) => T.sync(() => {
2875
+ process.stderr.write(pe(`applier: statement failed (op=${n})`, t, e, 400));
2876
+ })), T.mapError((e) => {
2877
+ let r = pe(`applier: statement failed (op=${n})`, t, e, 400).trim();
2717
2878
  return Object.assign(e, { message: r });
2718
- }), w.map(() => void 0)), Z = (e, t, n) => w.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(w.as(!0), w.catchAll(() => w.succeed(!1))), Gi = (e, t) => w.gen(function* () {
2719
- let n = R([Be], t).tables[0];
2720
- if (!n) return yield* w.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2879
+ }), T.map(() => void 0)), Z = (e, t, n) => T.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(T.as(!0), T.catchAll(() => T.succeed(!1))), ca = (e, t) => T.gen(function* () {
2880
+ let n = z([Ke], t).tables[0];
2881
+ if (!n) return yield* T.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
2721
2882
  let r = {
2722
2883
  kind: "create-table",
2723
2884
  table: k,
2724
2885
  columns: n.columns,
2725
2886
  indexes: []
2726
2887
  }, i = yield* e.onDialectOrElse({
2727
- mysql: () => hr(e).pipe(w.map((e) => Zr(r, e))),
2728
- mssql: () => w.succeed(ci(r)),
2729
- sqlite: () => w.succeed(ri(r)),
2730
- orElse: () => w.succeed(Kr(r))
2888
+ mysql: () => Or(e).pipe(T.map((e) => pi(r, e))),
2889
+ mssql: () => T.succeed(wi(r)),
2890
+ sqlite: () => T.succeed(yi(r)),
2891
+ orElse: () => T.succeed(ci(r))
2731
2892
  });
2732
- yield* w.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2733
- }), Ki = (e) => e`
2893
+ yield* T.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
2894
+ }), la = (e) => e`
2734
2895
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2735
2896
  ${e("status")}, ${e("payload")}
2736
2897
  FROM ${e(k)}
2737
- `, qi = (e, t, n, r) => w.gen(function* () {
2738
- let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2739
- yield* w.forEach(r, ({ index: r, planned: a }) => e`
2898
+ `, ua = (e, t, n, r) => T.gen(function* () {
2899
+ let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
2900
+ yield* T.forEach(r, ({ index: r, planned: a }) => e`
2740
2901
  INSERT INTO ${e(k)}
2741
2902
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
2742
2903
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
2743
2904
  ${e("createdAt")})
2744
2905
  VALUES
2745
2906
  (${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
2746
- ${a.op.kind}, ${He(a.op)}, ${"pending"},
2907
+ ${a.op.kind}, ${Je(a.op)}, ${"pending"},
2747
2908
  ${JSON.stringify(a)}, ${i})
2748
2909
  `, { discard: !0 });
2749
- }), Ji = (e, t, n, r, i) => w.gen(function* () {
2750
- let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2910
+ }), da = (e, t, n, r, i) => T.gen(function* () {
2911
+ let a = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
2751
2912
  if (r === "applied") {
2752
2913
  yield* e`
2753
2914
  UPDATE ${e(k)}
@@ -2762,8 +2923,8 @@ BEGIN
2762
2923
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
2763
2924
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
2764
2925
  `;
2765
- }), Yi = (e, t, n, r) => w.gen(function* () {
2766
- let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
2926
+ }), fa = (e, t, n, r) => T.gen(function* () {
2927
+ let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
2767
2928
  r.length > 0 && (yield* e`
2768
2929
  UPDATE ${e(k)}
2769
2930
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
@@ -2773,280 +2934,307 @@ BEGIN
2773
2934
  SET ${e("status")} = ${"pending"}
2774
2935
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
2775
2936
  `);
2776
- }), Xi = (e, t) => t === void 0 ? e`DELETE FROM ${e(k)}`.pipe(w.asVoid) : e`DELETE FROM ${e(k)} WHERE ${e("runId")} = ${t}`.pipe(w.asVoid), Zi = (e, t, n) => w.gen(function* () {
2777
- if (Xe(n.op, n.classification, t) !== "artefact-repair") return "clean";
2937
+ }), pa = (e, t) => t === void 0 ? e`DELETE FROM ${e(k)}`.pipe(T.asVoid) : e`DELETE FROM ${e(k)} WHERE ${e("runId")} = ${t}`.pipe(T.asVoid), ma = (e, t, n) => T.gen(function* () {
2938
+ if (nt(n.op, n.classification, t) !== "artefact-repair") return "clean";
2778
2939
  let r = n.op, i = (e) => o(e, t);
2779
2940
  if (t === "sqlite" || t === "turso") {
2780
2941
  if (!("table" in r)) return "clean";
2781
- let n = `${r.table}${Ge}`;
2782
- 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* w.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
2942
+ let n = `${r.table}${Ze}`;
2943
+ 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* T.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
2783
2944
  }
2784
2945
  if (r.kind !== "alter-column-type") return "clean";
2785
- let a = `${r.column}${Ke}`, s = `${r.column}${qe}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, a), u = yield* $(e, t, r.table, s), d = (e) => w.logWarning(`migration resume: ${e}`).pipe(w.annotateLogs({ scope: "voltro:migrate" }));
2786
- 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* w.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.`));
2787
- }), Qi = (e, t, n, r = "fresh") => w.gen(function* () {
2788
- let i = process.hrtime.bigint(), a = Wi(n.declared), o = t.op;
2789
- switch (o.kind) {
2946
+ let a = `${r.column}${Qe}`, s = `${r.column}${$e}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, a), u = yield* $(e, t, r.table, s), d = (e) => T.logWarning(`migration resume: ${e}`).pipe(T.annotateLogs({ scope: "voltro:migrate" }));
2947
+ 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* T.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.`));
2948
+ }), ha = (e, t, n, r = "fresh") => T.gen(function* () {
2949
+ let i = process.hrtime.bigint(), a = sa(n.declared), s = t.op;
2950
+ switch (s.kind) {
2790
2951
  case "create-table": {
2791
2952
  let t = yield* e.onDialectOrElse({
2792
- mysql: () => hr(e).pipe(w.map((e) => Zr(o, e))),
2793
- mssql: () => w.succeed(ci(o)),
2794
- sqlite: () => w.succeed(ri(o)),
2795
- orElse: () => w.succeed(Kr(o))
2953
+ mysql: () => Or(e).pipe(T.map((e) => pi(s, e))),
2954
+ mssql: () => T.succeed(wi(s)),
2955
+ sqlite: () => T.succeed(yi(s)),
2956
+ orElse: () => T.succeed(ci(s))
2796
2957
  }), n = yield* e.onDialectOrElse({
2797
- mysql: () => w.succeed([br]),
2798
- orElse: () => w.succeed([])
2958
+ mysql: () => T.succeed([Nr]),
2959
+ orElse: () => T.succeed([])
2799
2960
  });
2800
- for (let r of t) yield* X(e, r, o.kind, n);
2961
+ for (let r of t) yield* X(e, r, s.kind, n);
2801
2962
  break;
2802
2963
  }
2803
2964
  case "drop-table": {
2804
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? di(o, n, e) : ui(o, e);
2965
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Di(s, n, e) : Ei(s, e);
2805
2966
  yield* e.onDialectOrElse({
2806
- mysql: () => X(e, r(G), o.kind),
2807
- orElse: () => X(e, r(W), o.kind)
2967
+ mysql: () => X(e, r(K), s.kind),
2968
+ orElse: () => X(e, r(G), s.kind)
2808
2969
  });
2809
2970
  break;
2810
2971
  }
2811
2972
  case "drop-column": {
2812
2973
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2813
2974
  yield* e.onDialectOrElse({
2814
- mysql: () => hr(e).pipe(w.flatMap((r) => X(e, t ? Pr(o, n, G) : Mr(o, r), o.kind, t ? [] : [xr]))),
2815
- sqlite: () => X(e, t ? Pr(o, n, W) : jr(o, W, !1), o.kind, t ? [] : [Sr]),
2816
- orElse: () => X(e, t ? Pr(o, n, W) : jr(o, W), o.kind)
2975
+ mysql: () => Or(e).pipe(T.flatMap((r) => X(e, t ? Yr(s, n, K) : qr(s, r), s.kind, t ? [] : [Pr]))),
2976
+ sqlite: () => X(e, t ? Yr(s, n, G) : Kr(s, G, !1), s.kind, t ? [] : [Fr]),
2977
+ orElse: () => X(e, t ? Yr(s, n, G) : Kr(s, G), s.kind)
2817
2978
  });
2818
2979
  break;
2819
2980
  }
2820
2981
  case "rename-column":
2821
2982
  yield* e.onDialectOrElse({
2822
- mysql: () => X(e, Nr(o, G), o.kind),
2823
- mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
2824
- orElse: () => X(e, Nr(o, W), o.kind)
2983
+ mysql: () => X(e, Jr(s, K), s.kind),
2984
+ mssql: () => T.gen(function* () {
2985
+ let t = (yield* e`
2986
+ SELECT ck.name, ck.definition, ck.is_disabled AS disabled,
2987
+ ck.is_not_trusted AS untrusted, ck.is_not_for_replication AS notForReplication
2988
+ FROM sys.check_constraints ck
2989
+ WHERE ck.parent_object_id = OBJECT_ID(${s.table}) AND EXISTS (
2990
+ SELECT 1 FROM sys.sql_expression_dependencies dep
2991
+ JOIN sys.columns col ON col.object_id = dep.referenced_id AND col.column_id = dep.referenced_minor_id
2992
+ WHERE dep.referencing_id = ck.object_id AND col.object_id = ck.parent_object_id AND col.name = ${s.from}
2993
+ ) ORDER BY ck.name
2994
+ `).map((e) => ({
2995
+ ...e,
2996
+ definition: Rr(e.definition, s.from, s.to)
2997
+ })), n = (e) => o(e, "mssql"), r = (e) => e.replace(/'/g, "''");
2998
+ return yield* Z(e, [
2999
+ ...t.map((e) => `ALTER TABLE ${n(s.table)} DROP CONSTRAINT ${n(e.name)}`),
3000
+ `EXEC sp_rename N'${r(`${n(s.table)}.${n(s.from)}`)}', N'${r(s.to)}', 'COLUMN';`,
3001
+ ...t.flatMap((e) => [`ALTER TABLE ${n(s.table)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${n(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${n(s.table)} NOCHECK CONSTRAINT ${n(e.name)}`] : []])
3002
+ ], s.kind);
3003
+ }),
3004
+ orElse: () => X(e, Jr(s, G), s.kind)
2825
3005
  });
2826
3006
  break;
2827
3007
  case "add-index":
2828
3008
  yield* e.onDialectOrElse({
2829
- sqlite: () => X(e, hi(o, !1), o.kind),
2830
- mysql: () => hr(e).pipe(w.flatMap((t) => X(e, gi(o, n.declared, t), o.kind, [br]))),
2831
- mssql: () => Z(e, [...Di(o.table, o.index.columns, n.declared), Ei(o)], o.kind),
2832
- orElse: () => X(e, hi(o, t.classification === "online-required"), o.kind)
3009
+ sqlite: () => X(e, Mi(s, !1), s.kind),
3010
+ mysql: () => Or(e).pipe(T.flatMap((t) => X(e, Ni(s, n.declared, t), s.kind, [Nr]))),
3011
+ mssql: () => Z(e, [...Wi(s.table, s.index.columns, n.declared), Ui(s)], s.kind),
3012
+ orElse: () => X(e, Mi(s, t.classification === "online-required"), s.kind)
2833
3013
  });
2834
3014
  break;
2835
3015
  case "drop-index":
2836
3016
  yield* e.onDialectOrElse({
2837
- mysql: () => X(e, yi(o), o.kind),
2838
- mssql: () => X(e, bi(o), o.kind),
2839
- orElse: () => X(e, vi(o), o.kind)
3017
+ mysql: () => X(e, Ii(s), s.kind),
3018
+ mssql: () => X(e, Li(s), s.kind),
3019
+ orElse: () => X(e, Fi(s), s.kind)
2840
3020
  });
2841
3021
  break;
2842
3022
  case "rename-table":
2843
3023
  yield* e.onDialectOrElse({
2844
- mysql: () => X(e, xi(o, G), o.kind),
2845
- mssql: () => X(e, Si(o), o.kind),
2846
- orElse: () => X(e, xi(o, W), o.kind)
3024
+ mysql: () => X(e, Ri(s, K), s.kind),
3025
+ mssql: () => X(e, zi(s), s.kind),
3026
+ orElse: () => X(e, Ri(s, G), s.kind)
2847
3027
  });
2848
3028
  break;
2849
3029
  case "rename-index":
2850
3030
  yield* e.onDialectOrElse({
2851
- mysql: () => X(e, wi(o), o.kind),
2852
- mssql: () => X(e, Ti(o), o.kind),
2853
- orElse: () => X(e, Ci(o), o.kind)
3031
+ mysql: () => X(e, Vi(s), s.kind),
3032
+ mssql: () => X(e, Hi(s), s.kind),
3033
+ orElse: () => X(e, Bi(s), s.kind)
2854
3034
  });
2855
3035
  break;
2856
3036
  case "add-unique":
2857
3037
  yield* e.onDialectOrElse({
2858
- mysql: () => X(e, ki(o, n.declared), o.kind),
2859
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2860
- mssql: () => Z(e, [...Di(o.table, [o.column], n.declared), Oi(o)], o.kind),
2861
- orElse: () => X(e, Oi(o), o.kind)
3038
+ mysql: () => X(e, Ki(s, n.declared), s.kind),
3039
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3040
+ mssql: () => Z(e, [...Wi(s.table, [s.column], n.declared), Gi(s)], s.kind),
3041
+ orElse: () => X(e, Gi(s), s.kind)
2862
3042
  });
2863
3043
  break;
2864
3044
  case "drop-unique":
2865
3045
  yield* e.onDialectOrElse({
2866
- mysql: () => X(e, Fi(o), o.kind),
2867
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2868
- orElse: () => X(e, Pi(o), o.kind)
3046
+ mysql: () => X(e, Qi(s), s.kind),
3047
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3048
+ orElse: () => X(e, Zi(s), s.kind)
2869
3049
  });
2870
3050
  break;
2871
3051
  case "add-unique-composite":
2872
3052
  yield* e.onDialectOrElse({
2873
- mysql: () => X(e, ji(o, n.declared), o.kind),
2874
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2875
- mssql: () => Z(e, [...Di(o.table, o.fields, n.declared), Ai(o)], o.kind),
2876
- orElse: () => X(e, Ai(o), o.kind)
3053
+ mysql: () => X(e, Ji(s, n.declared), s.kind),
3054
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3055
+ mssql: () => Z(e, [...Wi(s.table, s.fields, n.declared), qi(s)], s.kind),
3056
+ orElse: () => X(e, qi(s), s.kind)
2877
3057
  });
2878
3058
  break;
2879
3059
  case "drop-unique-composite":
2880
3060
  yield* e.onDialectOrElse({
2881
- mysql: () => X(e, Ni(o), o.kind),
2882
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2883
- orElse: () => X(e, Mi(o), o.kind)
3061
+ mysql: () => X(e, Xi(s), s.kind),
3062
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3063
+ orElse: () => X(e, Yi(s), s.kind)
2884
3064
  });
2885
3065
  break;
2886
3066
  case "add-foreign-key":
2887
3067
  yield* e.onDialectOrElse({
2888
- mysql: () => Z(e, Ii(o, G), o.kind),
2889
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2890
- orElse: () => Z(e, Ii(o, W), o.kind)
3068
+ mysql: () => Z(e, $i(s, K), s.kind),
3069
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3070
+ orElse: () => Z(e, $i(s, G), s.kind)
2891
3071
  });
2892
3072
  break;
2893
3073
  case "add-column": {
2894
- let n = Ui(o, t, a, yield* e.onDialectOrElse({
2895
- mysql: () => w.succeed("mariadb"),
2896
- mssql: () => w.succeed("mssql"),
2897
- sqlite: () => w.succeed("sqlite"),
2898
- orElse: () => w.succeed("postgres")
3074
+ let n = oa(s, t, a, yield* e.onDialectOrElse({
3075
+ mysql: () => T.succeed("mariadb"),
3076
+ mssql: () => T.succeed("mssql"),
3077
+ sqlite: () => T.succeed("sqlite"),
3078
+ orElse: () => T.succeed("postgres")
2899
3079
  }));
2900
- if (!(r === "resume" && (yield* $(e, Le(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
3080
+ if (!(r === "resume" && (yield* $(e, Ue(e), s.table, s.column.name)))) for (let t of n.pre) yield* X(e, t, s.kind);
2901
3081
  if (n.backfillKind === "sql" && n.backfillSql) {
2902
- if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
3082
+ if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${n.backfillSql}`;
2903
3083
  else {
2904
3084
  let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
2905
3085
  for (;;) {
2906
- 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)}`;
2907
- if (s.length === 0) break;
2908
- let c = s.map((e) => e.id);
2909
- yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += s.length, yield* w.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows`).pipe(w.annotateLogs({
3086
+ let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
3087
+ if (o.length === 0) break;
3088
+ let c = o.map((e) => e.id);
3089
+ yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += o.length, yield* T.logInfo(`backfill ${s.table}.${s.column.name}: ${a} rows`).pipe(T.annotateLogs({
2910
3090
  scope: "voltro:migrate",
2911
3091
  mode: "sql-batched"
2912
- })), i = s[s.length - 1].id, r > 0 && (yield* w.sleep(`${r} millis`));
3092
+ })), i = o[o.length - 1].id, r > 0 && (yield* T.sleep(`${r} millis`));
2913
3093
  }
2914
3094
  }
2915
3095
  } else if (n.backfillKind === "js" && n.backfillJs) {
2916
3096
  let t = n.batchSize ?? 1e3, r = n.sleepMs ?? 0, i, a = 0;
2917
3097
  for (;;) {
2918
- 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)}`;
2919
- if (s.length === 0) break;
2920
- for (let t of s) {
2921
- let r = yield* w.tryPromise({
3098
+ let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
3099
+ if (o.length === 0) break;
3100
+ for (let t of o) {
3101
+ let r = yield* T.tryPromise({
2922
3102
  try: () => Promise.resolve(n.backfillJs({ id: t.id })),
2923
3103
  catch: (e) => e
2924
- }).pipe(w.orDie);
2925
- yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${r} WHERE ${e("id")} = ${t.id}`;
3104
+ }).pipe(T.orDie);
3105
+ yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${r} WHERE ${e("id")} = ${t.id}`;
2926
3106
  }
2927
- a += s.length, yield* w.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows processed`).pipe(w.annotateLogs({
3107
+ a += o.length, yield* T.logInfo(`backfill ${s.table}.${s.column.name}: ${a} rows processed`).pipe(T.annotateLogs({
2928
3108
  scope: "voltro:migrate",
2929
- table: o.table,
2930
- column: o.column.name
2931
- })), i = s[s.length - 1].id, r > 0 && (yield* w.sleep(`${r} millis`));
3109
+ table: s.table,
3110
+ column: s.column.name
3111
+ })), i = o[o.length - 1].id, r > 0 && (yield* T.sleep(`${r} millis`));
2932
3112
  }
2933
3113
  }
2934
- for (let t of n.post) yield* X(e, t, o.kind);
3114
+ for (let t of n.post) yield* X(e, t, s.kind);
2935
3115
  break;
2936
3116
  }
2937
3117
  case "alter-column-nullability":
2938
3118
  yield* e.onDialectOrElse({
2939
3119
  mysql: () => {
2940
- let t = K(n.declared, o.table, o.column);
2941
- return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${zr(t, o.column, o.toNullable)};`, o.kind) : w.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.`));
3120
+ let t = q(n.declared, s.table, s.column);
3121
+ return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${ei(t, s.column, s.toNullable)};`, s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${s.table}.${s.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2942
3122
  },
2943
3123
  mssql: () => {
2944
- let t = K(n.declared, o.table, o.column);
2945
- return t ? X(e, ii(t, o.column, o.table, o.toNullable), o.kind) : w.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
3124
+ let t = q(n.declared, s.table, s.column);
3125
+ return t ? X(e, bi(t, s.column, s.table, s.toNullable), s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${s.table}.${s.column}'.`));
2946
3126
  },
2947
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2948
- orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
3127
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3128
+ orElse: () => X(e, `ALTER TABLE ${G(s.table)} ALTER COLUMN ${G(s.column)} ${s.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, s.kind)
2949
3129
  });
2950
3130
  break;
2951
3131
  case "alter-column-default": {
2952
- let t = Rr(n.declared, o.table, o.column), r = K(n.declared, o.table, o.column), i = (e) => o.hasDefault && r !== void 0 && Ir(r, e) ? r : void 0;
3132
+ let t = $r(n.declared, s.table, s.column), r = q(n.declared, s.table, s.column), i = (e) => s.hasDefault && r !== void 0 && Zr(r, e) ? r : void 0;
2953
3133
  yield* e.onDialectOrElse({
2954
3134
  mysql: () => {
2955
3135
  let n = i("mariadb");
2956
- return X(e, n ? `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${zr(n, o.column)};` : Fr(o, G, (e) => Br(e, t)), o.kind);
3136
+ return X(e, n ? `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${ei(n, s.column)};` : Xr(s, K, (e) => ti(e, t)), s.kind);
2957
3137
  },
2958
3138
  mssql: () => {
2959
3139
  let t = i("mssql");
2960
- return X(e, ai(o, t ? ii(t, o.column, o.table) : void 0), o.kind);
3140
+ return X(e, xi(s, t ? bi(t, s.column, s.table) : void 0), s.kind);
2961
3141
  },
2962
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2963
- orElse: () => X(e, Fr(o, W, (e) => Hr(e, t)), o.kind)
3142
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3143
+ orElse: () => X(e, Xr(s, G, (e) => ri(e, t)), s.kind)
2964
3144
  });
2965
3145
  break;
2966
3146
  }
2967
3147
  case "alter-column-type": {
2968
- let r = Dr(Rr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
3148
+ let r = Hr($r(n.declared, s.table, s.column) ?? { type: s.to }), i = s.using ? ` USING ${s.using}` : "";
2969
3149
  if (t.classification !== "online-required") {
2970
3150
  yield* e.onDialectOrElse({
2971
3151
  mysql: () => {
2972
- let t = K(n.declared, o.table, o.column);
2973
- return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${zr(t, o.column)};`, o.kind) : w.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.`));
3152
+ let t = q(n.declared, s.table, s.column);
3153
+ return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${ei(t, s.column)};`, s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${s.table}.${s.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2974
3154
  },
2975
3155
  mssql: () => {
2976
- let t = K(n.declared, o.table, o.column);
2977
- return t ? X(e, ii(t, o.column, o.table), o.kind) : w.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
3156
+ let t = q(n.declared, s.table, s.column);
3157
+ return t ? X(e, bi(t, s.column, s.table), s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${s.table}.${s.column}'.`));
2978
3158
  },
2979
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
2980
- orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
3159
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3160
+ orElse: () => X(e, `ALTER TABLE ${G(s.table)} ALTER COLUMN ${G(s.column)} TYPE ${r}${i};`, s.kind)
2981
3161
  });
2982
3162
  break;
2983
3163
  }
2984
3164
  yield* e.onDialectOrElse({
2985
- mysql: () => w.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.`)),
2986
- orElse: () => w.void
3165
+ mysql: () => T.die(/* @__PURE__ */ Error(`online-required alter-column-type on ${s.table}.${s.column} is not supported on mariadb (the shadow-swap path is postgres-only). Use a smaller-table window or an external online-DDL tool.`)),
3166
+ orElse: () => T.void
2987
3167
  });
2988
- let a = `${o.column}__shadow`, s = `${o.column}__old`;
2989
- yield* e.unsafe(`ALTER TABLE ${W(o.table)} ADD COLUMN ${W(a)} ${r}`);
2990
- let c = o.using ?? W(o.column), l;
3168
+ let a = `${s.column}__shadow`, o = `${s.column}__old`;
3169
+ yield* e.unsafe(`ALTER TABLE ${G(s.table)} ADD COLUMN ${G(a)} ${r}`);
3170
+ let c = s.using ?? G(s.column), l;
2991
3171
  for (;;) {
2992
- 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)}`;
3172
+ let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Q(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Q(e, 5e3)}`;
2993
3173
  if (t.length === 0) break;
2994
- 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;
3174
+ yield* e.unsafe(`UPDATE ${G(s.table)} SET ${G(a)} = ${c} WHERE ${G(s.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;
2995
3175
  }
2996
- yield* w.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(w.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)}`);
3176
+ yield* T.logInfo(`alter-column-type shadow ${s.table}.${s.column}: shadow populated`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${G(s.table)} RENAME COLUMN ${G(s.column)} TO ${G(o)}`), yield* e.unsafe(`ALTER TABLE ${G(s.table)} RENAME COLUMN ${G(a)} TO ${G(s.column)}`), yield* e.unsafe(`ALTER TABLE ${G(s.table)} DROP COLUMN ${G(o)}`);
2997
3177
  break;
2998
3178
  }
2999
3179
  case "drop-foreign-key":
3000
3180
  yield* e.onDialectOrElse({
3001
- mysql: () => X(e, Ri(o), o.kind),
3002
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
3003
- orElse: () => X(e, Li(o), o.kind)
3181
+ mysql: () => X(e, ta(s), s.kind),
3182
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3183
+ orElse: () => X(e, ea(s), s.kind)
3004
3184
  });
3005
3185
  break;
3006
3186
  case "add-check":
3007
3187
  yield* e.onDialectOrElse({
3008
- mysql: () => X(e, zi(o, G), o.kind),
3009
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
3010
- orElse: () => X(e, zi(o, W), o.kind)
3188
+ mysql: () => X(e, na(s, K), s.kind),
3189
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3190
+ orElse: () => X(e, na(s, G), s.kind)
3011
3191
  });
3012
3192
  break;
3193
+ case "reconcile-json-check": {
3194
+ let t = Y(s.column), n = s.validation === "value" ? rt(t) : `(${t} IS NULL OR ISJSON(${t}) = 1)`;
3195
+ yield* e.onDialectOrElse({
3196
+ mssql: () => Z(e, [...s.dropConstraints.map((e) => `ALTER TABLE ${Y(s.table)} DROP CONSTRAINT ${Y(e)}`), `ALTER TABLE ${Y(s.table)} WITH CHECK ADD CHECK ${n}`], s.kind),
3197
+ orElse: () => T.dieMessage("reconcile-json-check requires SQL Server")
3198
+ });
3199
+ break;
3200
+ }
3013
3201
  case "drop-check": yield* e.onDialectOrElse({
3014
- mysql: () => Hi(e, o, n.declared),
3015
- sqlite: () => Z(e, q(o.table, n.declared), o.kind),
3016
- orElse: () => X(e, Bi(o), o.kind)
3202
+ mysql: () => aa(e, s, n.declared),
3203
+ sqlite: () => Z(e, J(s.table, n.declared), s.kind),
3204
+ orElse: () => X(e, ra(s), s.kind)
3017
3205
  });
3018
3206
  }
3019
3207
  return {
3020
- op: o,
3208
+ op: s,
3021
3209
  status: "applied",
3022
3210
  durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
3023
3211
  };
3024
- }), $i = (e, t, n, r) => w.gen(function* () {
3212
+ }), ga = (e, t, n, r) => T.gen(function* () {
3025
3213
  let i = [...new Set(r.map((e) => e.runId))];
3026
- if (i.length > 1) return yield* w.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.`));
3214
+ if (i.length > 1) return yield* T.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.`));
3027
3215
  let a = i[0], o = [...r].map((e) => ({
3028
3216
  index: Number(e.opIndex),
3029
3217
  status: e.status,
3030
3218
  planned: JSON.parse(e.payload)
3031
3219
  })).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
3032
- if (c > 1) return yield* w.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.`));
3033
- if (yield* w.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} ${He(s.planned.op)}` : ""}`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
3220
+ if (c > 1) return yield* T.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.`));
3221
+ if (yield* T.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} ${Je(s.planned.op)}` : ""}`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
3034
3222
  kind: "discard",
3035
3223
  runId: a,
3036
3224
  why: "no operation had started — no DDL ran"
3037
3225
  };
3038
- let l = s ? yield* Zi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
3226
+ let l = s ? yield* ma(e, t, s.planned) : "clean", u = r[0].planFingerprint;
3039
3227
  if (u !== n.toFingerprint) return {
3040
3228
  kind: "discard",
3041
3229
  runId: a,
3042
3230
  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`
3043
3231
  };
3044
- let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : We(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
3232
+ let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Xe(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
3045
3233
  return f.length === 0 ? {
3046
3234
  kind: "discard",
3047
3235
  runId: a,
3048
3236
  why: "every recorded operation had already taken effect"
3049
- } : (yield* Yi(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* w.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), {
3237
+ } : (yield* fa(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* T.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), {
3050
3238
  kind: "resume",
3051
3239
  runId: a,
3052
3240
  ops: f.map((e) => ({
@@ -3054,7 +3242,7 @@ BEGIN
3054
3242
  planned: e.planned
3055
3243
  }))
3056
3244
  });
3057
- }), ea = (e, t, n) => w.gen(function* () {
3245
+ }), _a = (e, t, n) => T.gen(function* () {
3058
3246
  for (let r of t.operations) {
3059
3247
  let i = r.op;
3060
3248
  if (i.kind !== "add-index" || !i.index.unique || i.index.where === void 0 || t.operations.some((e) => e.op.kind === "rename-table" ? e.op.to === i.table : e.op.table === i.table && [
@@ -3063,9 +3251,9 @@ BEGIN
3063
3251
  "rename-column"
3064
3252
  ].includes(e.op.kind))) continue;
3065
3253
  let a = i.index.columns.map((e) => e.startsWith("(") ? e : o(e, n)), s = n === "mssql" ? "" : a.map((e) => ` AND ${e} IS NOT NULL`).join(""), c = n === "mssql" ? "SELECT TOP (1) 1" : "SELECT 1", l = n === "mssql" ? "" : " LIMIT 1";
3066
- if ((yield* e.unsafe(`${c} FROM ${o(i.table, n)} WHERE (${i.index.where})${s} GROUP BY ${a.join(", ")} HAVING COUNT(*) > 1${l}`)).length > 0) return yield* w.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${i.index.name}' on '${i.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
3254
+ if ((yield* e.unsafe(`${c} FROM ${o(i.table, n)} WHERE (${i.index.where})${s} GROUP BY ${a.join(", ")} HAVING COUNT(*) > 1${l}`)).length > 0) return yield* T.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${i.index.name}' on '${i.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
3067
3255
  }
3068
- }), ta = (e) => {
3256
+ }), va = (e) => {
3069
3257
  let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
3070
3258
  return [
3071
3259
  t.kind,
@@ -3074,45 +3262,45 @@ BEGIN
3074
3262
  n("name"),
3075
3263
  n("to")
3076
3264
  ].join("\0");
3077
- }, na = (e, t, n) => w.acquireUseRelease(Fe(e, { schema: n.lockSchema }), () => ra(e, t, n), (e) => e.release.pipe(w.orDie)), ra = (e, t, n) => w.gen(function* () {
3265
+ }, ya = (e, t, n) => T.acquireUseRelease(Ve(e, { schema: n.lockSchema }), () => ba(e, t, n), (e) => e.release.pipe(T.orDie)), ba = (e, t, n) => T.gen(function* () {
3078
3266
  let r = t.operations.filter((e) => e.blocked);
3079
- if (r.length > 0) return yield* w.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
3080
- let i = Date.now(), a = [], o = Le(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => ta(e))), l = {
3267
+ if (r.length > 0) return yield* T.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
3268
+ let i = Date.now(), a = [], o = Ue(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => va(e))), l = {
3081
3269
  ...s,
3082
3270
  operations: s.operations.map((e) => {
3083
- if (!e.blocked || !c.has(ta(e))) return e;
3271
+ if (!e.blocked || !c.has(va(e))) return e;
3084
3272
  let { blocked: t, ...n } = e;
3085
3273
  return n;
3086
3274
  })
3087
3275
  };
3088
- (l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* w.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(w.annotateLogs({ scope: "voltro:migrate" })));
3276
+ (l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* T.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(T.annotateLogs({ scope: "voltro:migrate" })));
3089
3277
  let u = l.operations.filter((e) => e.blocked);
3090
- if (u.length > 0) return yield* w.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.`));
3091
- let d = ze(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) => ({
3278
+ if (u.length > 0) return yield* T.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.`));
3279
+ let d = Ge(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) => ({
3092
3280
  index: t,
3093
3281
  planned: e
3094
3282
  })), _ = "fresh";
3095
- yield* ea(e, l, o), yield* Gi(e, o);
3096
- let v = yield* Ki(e);
3283
+ yield* _a(e, l, o), yield* ca(e, o);
3284
+ let v = yield* la(e);
3097
3285
  if (v.length > 0) {
3098
- let t = yield* $i(e, o, l, v);
3099
- t.kind === "resume" ? (m = t.runId, h = t.ops, _ = "resume") : (yield* w.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), yield* Xi(e, t.runId));
3286
+ let t = yield* ga(e, o, l, v);
3287
+ t.kind === "resume" ? (m = t.runId, h = t.ops, _ = "resume") : (yield* T.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), yield* pa(e, t.runId));
3100
3288
  }
3101
- _ === "fresh" && h.length > 0 && (yield* qi(e, m, l.toFingerprint, h)), f.length > 0 && (yield* e.withTransaction(w.gen(function* () {
3289
+ _ === "fresh" && h.length > 0 && (yield* ua(e, m, l.toFingerprint, h)), f.length > 0 && (yield* Lr(e, T.gen(function* () {
3102
3290
  let e = yield* E.SqlClient;
3103
- for (let t of f) a.push(yield* Qi(e, t, n));
3291
+ for (let t of f) a.push(yield* ha(e, t, n));
3104
3292
  })));
3105
3293
  for (let { index: t, planned: r } of h) {
3106
- yield* Ji(e, m, t, "started");
3107
- let i = a.length, o = yield* Qi(e, r, n, _).pipe(w.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`) })));
3108
- a.push(o), yield* Ji(e, m, t, "applied", o.durationMs);
3294
+ yield* da(e, m, t, "started");
3295
+ let i = a.length, o = yield* ha(e, r, n, _).pipe(T.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`) })));
3296
+ a.push(o), yield* da(e, m, t, "applied", o.durationMs);
3109
3297
  }
3110
3298
  let y = yield* n.replan(e);
3111
3299
  if (y.operations.length > 0) {
3112
3300
  let e = y.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");
3113
- return yield* w.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 ${y.operations.length}:\n${e}${y.operations.length > 10 ? `\n … and ${y.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.`));
3301
+ return yield* T.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 ${y.operations.length}:\n${e}${y.operations.length > 10 ? `\n … and ${y.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.`));
3114
3302
  }
3115
- let b = a.filter((e) => e.status === "applied").length, x = Date.now() - i, S = m, C = (/* @__PURE__ */ new Date()).toISOString(), T = yield* U(e, C), ee = [...f, ...h.map((e) => e.planned)];
3303
+ let b = a.filter((e) => e.status === "applied").length, x = Date.now() - i, S = m, C = (/* @__PURE__ */ new Date()).toISOString(), w = yield* W(e, C), ee = [...f, ...h.map((e) => e.planned)];
3116
3304
  yield* e`
3117
3305
  INSERT INTO ${e("_voltro_migration_plans")}
3118
3306
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -3121,10 +3309,10 @@ BEGIN
3121
3309
  VALUES
3122
3310
  (${S}, ${l.toFingerprint}, ${y.fromFingerprint}, ${JSON.stringify(ee)},
3123
3311
  ${n.appliedBy}, ${n.environment}, ${n.source},
3124
- ${x}, ${T}, ${n.notes ?? null})
3125
- `, yield* Xi(e, m);
3312
+ ${x}, ${w}, ${n.notes ?? null})
3313
+ `, yield* pa(e, m);
3126
3314
  let te = [...new Set(ee.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
3127
- return yield* w.promise(() => g({ changedTables: te }).catch(() => {})), {
3315
+ return yield* T.promise(() => g({ changedTables: te }).catch(() => {})), {
3128
3316
  id: S,
3129
3317
  appliedAt: C,
3130
3318
  fingerprint: l.toFingerprint,
@@ -3136,14 +3324,14 @@ BEGIN
3136
3324
  source: n.source,
3137
3325
  ...n.notes ? { notes: n.notes } : {}
3138
3326
  };
3139
- }), ia = (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"), aa = (e) => e`
3327
+ }), xa = (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"), Sa = (e) => e`
3140
3328
  SELECT fingerprint
3141
3329
  FROM _voltro_migration_plans
3142
3330
  ORDER BY ${e("appliedAt")} DESC
3143
3331
  LIMIT 1
3144
- `.pipe(w.map((e) => e.length > 0 ? e[0].fingerprint : void 0), w.catchAll(() => w.succeed(void 0))), oa = (e, t, n) => w.gen(function* () {
3145
- if ((yield* aa(e)) === t.toFingerprint) return "already-current";
3146
- let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
3332
+ `.pipe(T.map((e) => e.length > 0 ? e[0].fingerprint : void 0), T.catchAll(() => T.succeed(void 0))), Ca = (e, t, n) => T.gen(function* () {
3333
+ if ((yield* Sa(e)) === t.toFingerprint) return "already-current";
3334
+ let r = `plan_${Date.now().toString(36)}`, i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
3147
3335
  return yield* e`
3148
3336
  INSERT INTO ${e("_voltro_migration_plans")}
3149
3337
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
@@ -3154,8 +3342,8 @@ BEGIN
3154
3342
  ${n.appliedBy}, ${n.environment}, ${n.source},
3155
3343
  ${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
3156
3344
  `, "recorded";
3157
- }).pipe(w.catchAll(() => w.succeed("already-current"))), sa = (e, t) => w.gen(function* () {
3158
- let n = L(R(t, Le(e))), r = yield* aa(e);
3345
+ }).pipe(T.catchAll(() => T.succeed("already-current"))), wa = (e, t) => T.gen(function* () {
3346
+ let n = R(z(t, Ue(e))), r = yield* Sa(e);
3159
3347
  return r === n ? {
3160
3348
  kind: "up-to-date",
3161
3349
  fingerprint: n
@@ -3164,23 +3352,23 @@ BEGIN
3164
3352
  expected: n,
3165
3353
  ...r === void 0 ? {} : { actual: r }
3166
3354
  };
3167
- }), ca = [
3355
+ }), Ta = [
3168
3356
  "pgeagertest_",
3169
3357
  "mig_e2e_",
3170
3358
  "mig_test_",
3171
3359
  "mysqleagertest_",
3172
3360
  "mssqleagertest_",
3173
3361
  "sqliteeagertest_"
3174
- ], la = (e) => ca.some((t) => e.startsWith(t)), ua = (e, t) => w.gen(function* () {
3362
+ ], Ea = (e) => Ta.some((t) => e.startsWith(t)), Da = (e, t) => T.gen(function* () {
3175
3363
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
3176
- let n = t.filter((e) => la(e.name)).map((e) => e.name);
3364
+ let n = t.filter((e) => Ea(e.name)).map((e) => e.name);
3177
3365
  if (n.length === 0) return [];
3178
- for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(w.catchAll(() => w.void));
3366
+ for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(T.catchAll(() => T.void));
3179
3367
  return n;
3180
- }), da = () => {
3368
+ }), Oa = () => {
3181
3369
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
3182
3370
  return e.length > 0 ? { ignoreTables: e } : {};
3183
- }, fa = (e) => {
3371
+ }, ka = (e) => {
3184
3372
  if (e === void 0) return;
3185
3373
  let t = e.trim();
3186
3374
  if (t === "") return;
@@ -3190,55 +3378,55 @@ BEGIN
3190
3378
  kind: "tables",
3191
3379
  tables: new Set(n)
3192
3380
  } : void 0;
3193
- }, pa = (e) => typeof e.table == "string" ? e.table : void 0, ma = (e, t = { kind: "all" }) => ({
3381
+ }, Aa = (e) => typeof e.table == "string" ? e.table : void 0, ja = (e, t = { kind: "all" }) => ({
3194
3382
  ...e,
3195
3383
  operations: e.operations.map((e) => {
3196
3384
  if (!e.blocked || e.classification !== "lossy") return e;
3197
3385
  if (t?.kind === "tables") {
3198
- let n = pa(e.op);
3386
+ let n = Aa(e.op);
3199
3387
  if (n === void 0 || !t.tables.has(n)) return e;
3200
3388
  }
3201
3389
  let { blocked: n, ...r } = e;
3202
3390
  return r;
3203
3391
  })
3204
- }), ha = (e, t, n) => t === "postgres" ? dn(e, n).pipe(w.flatMap((e) => {
3205
- let t = fn(e);
3206
- return t === void 0 ? w.void : w.logWarning(`auto-migrate: ${t}`).pipe(w.annotateLogs({ scope: "voltro:migrate" }));
3207
- }), w.catchAll(() => w.void)) : w.void, ga = (e, t, n) => w.gen(function* () {
3208
- let r = Le(e), a = t;
3392
+ }), Ma = (e, t, n) => t === "postgres" ? Cn(e, n).pipe(T.flatMap((e) => {
3393
+ let t = wn(e);
3394
+ return t === void 0 ? T.void : T.logWarning(`auto-migrate: ${t}`).pipe(T.annotateLogs({ scope: "voltro:migrate" }));
3395
+ }), T.catchAll(() => T.void)) : T.void, Na = (e, t, n) => T.gen(function* () {
3396
+ let r = Ue(e), a = t;
3209
3397
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
3210
- let t = L(R(a, r));
3211
- if ((yield* aa(e)) === t) return yield* ha(e, r, a), {
3398
+ let t = R(z(a, r));
3399
+ if ((yield* Sa(e)) === t) return yield* Ma(e, r, a), {
3212
3400
  kind: "up-to-date",
3213
3401
  fingerprint: t
3214
3402
  };
3215
3403
  }
3216
- let o = yield* fr(e), s = yield* ua(e, o.tables);
3217
- s.length > 0 && (yield* w.logInfo(`auto-migrate: reaped ${s.length} test-fixture leftover(s)`).pipe(w.annotateLogs({
3404
+ let o = yield* Tr(e), s = yield* Da(e, o.tables);
3405
+ s.length > 0 && (yield* T.logInfo(`auto-migrate: reaped ${s.length} test-fixture leftover(s)`).pipe(T.annotateLogs({
3218
3406
  scope: "voltro:migrate",
3219
3407
  count: s.length
3220
- })), o = yield* fr(e));
3408
+ })), o = yield* Tr(e));
3221
3409
  {
3222
3410
  let e = n.softDropRetentionDays ?? 7, t = p(o, { retentionDays: e });
3223
- t.length > 0 && (yield* w.logWarning(`auto-migrate: ${i(t, e)}`).pipe(w.annotateLogs({
3411
+ t.length > 0 && (yield* T.logWarning(`auto-migrate: ${i(t, e)}`).pipe(T.annotateLogs({
3224
3412
  scope: "voltro:migrate",
3225
3413
  snapshots: t.map((e) => e.name)
3226
3414
  })));
3227
3415
  }
3228
- let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u = Wn({
3416
+ let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u = nr({
3229
3417
  declared: a,
3230
3418
  live: { tables: l(o.tables) },
3231
3419
  dialect: r,
3232
- ...da()
3420
+ ...Oa()
3233
3421
  });
3234
3422
  if (u.summary.blocked > 0) {
3235
- let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = fa(process.env.VOLTRO_DESTRUCTIVE_OK);
3236
- if (t === void 0 || !e || (u = ma(u, t), u.operations.some((e) => e.blocked))) return {
3423
+ let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = ka(process.env.VOLTRO_DESTRUCTIVE_OK);
3424
+ if (t === void 0 || !e || (u = ja(u, t), u.operations.some((e) => e.blocked))) return {
3237
3425
  kind: "refused-blocked",
3238
3426
  plan: u
3239
3427
  };
3240
3428
  }
3241
- return u.operations.length === 0 ? (yield* oa(e, u, {
3429
+ return u.operations.length === 0 ? (yield* Ca(e, u, {
3242
3430
  appliedBy: n.appliedBy,
3243
3431
  environment: n.environment === "prod" ? "dev" : n.environment,
3244
3432
  source: "auto-diff"
@@ -3247,37 +3435,37 @@ BEGIN
3247
3435
  fingerprint: u.toFingerprint
3248
3436
  }) : {
3249
3437
  kind: "applied",
3250
- applied: yield* na(e, u, {
3438
+ applied: yield* ya(e, u, {
3251
3439
  declared: t,
3252
3440
  appliedBy: n.appliedBy,
3253
3441
  environment: n.environment === "prod" ? "dev" : n.environment,
3254
3442
  source: "auto-diff",
3255
- replan: (e) => w.gen(function* () {
3256
- let t = yield* fr(e);
3257
- return Wn({
3443
+ replan: (e) => T.gen(function* () {
3444
+ let t = yield* Tr(e);
3445
+ return nr({
3258
3446
  declared: a,
3259
3447
  live: { tables: l(t.tables) },
3260
3448
  dialect: r,
3261
- ...da()
3449
+ ...Oa()
3262
3450
  });
3263
3451
  })
3264
3452
  }),
3265
3453
  plan: u
3266
3454
  };
3267
- }), _a = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? w.succeed({
3455
+ }), Pa = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? T.succeed({
3268
3456
  kind: "skipped",
3269
3457
  reason: "VOLTRO_AUTO_MIGRATE=0"
3270
- }) : n.environment === "prod" ? sa(e, t) : ga(e, t, n), va = (e, t) => {
3458
+ }) : n.environment === "prod" ? wa(e, t) : Na(e, t, n), Fa = (e, t) => {
3271
3459
  switch (e.kind) {
3272
3460
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
3273
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${an(e.fingerprint)})`;
3461
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${_n(e.fingerprint)})`;
3274
3462
  case "applied": {
3275
3463
  let t = e.plan.summary;
3276
- 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=${an(e.applied.fingerprint)}`;
3464
+ return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${_n(e.applied.fingerprint)}`;
3277
3465
  }
3278
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${an(e.expected)}` + (e.actual ? ` live=${an(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3466
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${_n(e.expected)}` + (e.actual ? ` live=${_n(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3279
3467
  case "refused-blocked": {
3280
- 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` + ia(e.plan), c = [""];
3468
+ 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` + xa(e.plan), c = [""];
3281
3469
  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) {
3282
3470
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
3283
3471
  for (let r of e.plan.operations) {
@@ -3294,7 +3482,7 @@ BEGIN
3294
3482
  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");
3295
3483
  }
3296
3484
  }
3297
- }, ya = re({ scope: "voltro:migrate" }), ba = /* @__PURE__ */ new Set([
3485
+ }, Ia = ae({ scope: "voltro:migrate" }), La = /* @__PURE__ */ new Set([
3298
3486
  "node_modules",
3299
3487
  "dist",
3300
3488
  "build",
@@ -3303,12 +3491,12 @@ BEGIN
3303
3491
  ".next",
3304
3492
  ".git",
3305
3493
  ".framework"
3306
- ]), xa = async (e) => {
3494
+ ]), Ra = async (e) => {
3307
3495
  let t = [], n = async (e) => {
3308
- let r = await ie.readdir(e, { withFileTypes: !0 }).catch(() => []);
3496
+ let r = await oe.readdir(e, { withFileTypes: !0 }).catch(() => []);
3309
3497
  for (let i of r) {
3310
- if (ba.has(i.name)) continue;
3311
- let r = ae(e, i.name);
3498
+ if (La.has(i.name)) continue;
3499
+ let r = se(e, i.name);
3312
3500
  i.isDirectory() ? await n(r) : i.isFile() && S.test(i.name) && t.push(r);
3313
3501
  }
3314
3502
  };
@@ -3316,12 +3504,12 @@ BEGIN
3316
3504
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
3317
3505
  return n.localeCompare(r);
3318
3506
  });
3319
- }, Sa = async (e) => {
3507
+ }, za = async (e) => {
3320
3508
  let t = [];
3321
3509
  for (let n of e) {
3322
- let e = (await import(oe(n).href)).default;
3510
+ let e = (await import(ce(n).href)).default;
3323
3511
  if (!u(e)) {
3324
- ya.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
3512
+ Ia.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
3325
3513
  continue;
3326
3514
  }
3327
3515
  t.push({
@@ -3330,11 +3518,11 @@ BEGIN
3330
3518
  });
3331
3519
  }
3332
3520
  return t;
3333
- }, Ca = (e) => e`
3521
+ }, Ba = (e) => e`
3334
3522
  SELECT ${e("id")}
3335
3523
  FROM ${e("_voltro_migration_plans")}
3336
3524
  WHERE ${e("source")} = 'file'
3337
- `.pipe(w.map((e) => e.map((e) => e.id)), w.catchAll(() => w.succeed([]))), wa = class extends Error {
3525
+ `.pipe(T.map((e) => e.map((e) => e.id)), T.catchAll(() => T.succeed([]))), Va = class extends Error {
3338
3526
  migrationId;
3339
3527
  file;
3340
3528
  cause;
@@ -3342,28 +3530,28 @@ BEGIN
3342
3530
  constructor(e, t, n) {
3343
3531
  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";
3344
3532
  }
3345
- }, Ta = (e, t, n, r) => w.gen(function* () {
3533
+ }, Ha = (e, t, n, r) => T.gen(function* () {
3346
3534
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
3347
3535
  sql: e,
3348
3536
  log: {
3349
- info: (e, n) => w.logInfo(e).pipe(w.annotateLogs({
3537
+ info: (e, n) => T.logInfo(e).pipe(T.annotateLogs({
3350
3538
  scope: `migrations:file:${t.migration.id}`,
3351
3539
  ...n ?? {}
3352
3540
  })),
3353
- warn: (e, n) => w.logWarning(e).pipe(w.annotateLogs({
3541
+ warn: (e, n) => T.logWarning(e).pipe(T.annotateLogs({
3354
3542
  scope: `migrations:file:${t.migration.id}`,
3355
3543
  ...n ?? {}
3356
3544
  }))
3357
3545
  },
3358
3546
  appliedAt: a
3359
3547
  }, s = t.migration.up(o);
3360
- w.isEffect(s) ? yield* s : yield* w.tryPromise({
3548
+ T.isEffect(s) ? yield* s : yield* T.tryPromise({
3361
3549
  try: () => s,
3362
3550
  catch: (e) => e
3363
3551
  });
3364
3552
  let c = Date.now() - i;
3365
- !w.isEffect(s) && c < 2 && (yield* w.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(w.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
3366
- let l = yield* U(e, a);
3553
+ !T.isEffect(s) && c < 2 && (yield* T.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(T.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
3554
+ let l = yield* W(e, a);
3367
3555
  return yield* e`
3368
3556
  INSERT INTO ${e("_voltro_migration_plans")}
3369
3557
  (${e("id")}, ${e("fingerprint")}, ${e("operations")},
@@ -3376,87 +3564,87 @@ BEGIN
3376
3564
  }])},
3377
3565
  ${r}, ${n}, ${"file"},
3378
3566
  ${c}, ${l}, ${t.migration.description})
3379
- `.pipe(w.mapError((e) => new wa(t.migration.id, t.file, e))), { durationMs: c };
3380
- }), Ea = (e, t) => w.gen(function* () {
3381
- let n = yield* w.tryPromise({
3382
- try: () => xa(ae(t, "migrations")),
3567
+ `.pipe(T.mapError((e) => new Va(t.migration.id, t.file, e))), { durationMs: c };
3568
+ }), Ua = (e, t) => T.gen(function* () {
3569
+ let n = yield* T.tryPromise({
3570
+ try: () => Ra(se(t, "migrations")),
3383
3571
  catch: (e) => e
3384
3572
  });
3385
3573
  if (n.length === 0) return {
3386
3574
  pending: [],
3387
3575
  skipped: []
3388
3576
  };
3389
- let r = yield* w.tryPromise({
3390
- try: () => Sa(n),
3577
+ let r = yield* T.tryPromise({
3578
+ try: () => za(n),
3391
3579
  catch: (e) => e
3392
3580
  });
3393
3581
  if (r.length === 0) return {
3394
3582
  pending: [],
3395
3583
  skipped: []
3396
3584
  };
3397
- let i = new Set(yield* Ca(e));
3585
+ let i = new Set(yield* Ba(e));
3398
3586
  return {
3399
3587
  pending: r.filter((e) => !i.has(e.migration.id)),
3400
3588
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
3401
3589
  };
3402
- }), Da = (e, t) => Ea(e, t).pipe(w.map((e) => e.pending.map((e) => e.migration.id))), Oa = (e, t) => w.gen(function* () {
3403
- let { pending: n, skipped: r } = yield* Ea(e, t.projectRoot);
3590
+ }), Wa = (e, t) => Ua(e, t).pipe(T.map((e) => e.pending.map((e) => e.migration.id))), Ga = (e, t) => T.gen(function* () {
3591
+ let { pending: n, skipped: r } = yield* Ua(e, t.projectRoot);
3404
3592
  return n.length === 0 ? {
3405
3593
  applied: [],
3406
3594
  skipped: r
3407
3595
  } : {
3408
- applied: yield* w.acquireUseRelease(Fe(e, { schema: t.lockSchema }), () => w.gen(function* () {
3596
+ applied: yield* T.acquireUseRelease(Ve(e, { schema: t.lockSchema }), () => T.gen(function* () {
3409
3597
  let r = [];
3410
3598
  for (let i of n) {
3411
- yield* w.logInfo("file-based migration applying").pipe(w.annotateLogs({
3599
+ yield* T.logInfo("file-based migration applying").pipe(T.annotateLogs({
3412
3600
  scope: "voltro:migrate",
3413
3601
  id: i.migration.id,
3414
3602
  file: i.file
3415
3603
  }));
3416
- let { durationMs: n } = yield* Ta(e, i, t.env, t.appliedBy);
3604
+ let { durationMs: n } = yield* Ha(e, i, t.env, t.appliedBy);
3417
3605
  r.push({
3418
3606
  id: i.migration.id,
3419
3607
  durationMs: n
3420
- }), yield* w.logInfo("file-based migration applied").pipe(w.annotateLogs({
3608
+ }), yield* T.logInfo("file-based migration applied").pipe(T.annotateLogs({
3421
3609
  scope: "voltro:migrate",
3422
3610
  id: i.migration.id,
3423
3611
  durationMs: n
3424
3612
  }));
3425
3613
  }
3426
3614
  return r;
3427
- }), (e) => e.release.pipe(w.orDie)),
3615
+ }), (e) => e.release.pipe(T.orDie)),
3428
3616
  skipped: r
3429
3617
  };
3430
- }), ka = (e, t) => e`
3618
+ }), Ka = (e, t) => e`
3431
3619
  SELECT ${e("id")}
3432
3620
  FROM ${e("_voltro_migration_plans")}
3433
3621
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
3434
3622
  LIMIT 1
3435
- `, Aa = (e, t) => w.gen(function* () {
3436
- if (!(yield* ka(e, t.id))[0]) return yield* w.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3437
- let n = yield* w.tryPromise({
3438
- try: () => xa(ae(t.projectRoot, "migrations")),
3623
+ `, qa = (e, t) => T.gen(function* () {
3624
+ if (!(yield* Ka(e, t.id))[0]) return yield* T.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
3625
+ let n = yield* T.tryPromise({
3626
+ try: () => Ra(se(t.projectRoot, "migrations")),
3439
3627
  catch: (e) => e
3440
- }), r = (yield* w.tryPromise({
3441
- try: () => Sa(n),
3628
+ }), r = (yield* T.tryPromise({
3629
+ try: () => za(n),
3442
3630
  catch: (e) => e
3443
3631
  })).find((e) => e.migration.id === t.id);
3444
- return r ? yield* w.acquireUseRelease(Fe(e, { schema: t.lockSchema }), () => w.gen(function* () {
3632
+ return r ? yield* T.acquireUseRelease(Ve(e, { schema: t.lockSchema }), () => T.gen(function* () {
3445
3633
  let n = Date.now(), i = {
3446
3634
  sql: e,
3447
3635
  log: {
3448
- info: (e, n) => w.logInfo(e).pipe(w.annotateLogs({
3636
+ info: (e, n) => T.logInfo(e).pipe(T.annotateLogs({
3449
3637
  scope: `migrations:file:${t.id}`,
3450
3638
  ...n ?? {}
3451
3639
  })),
3452
- warn: (e, n) => w.logWarning(e).pipe(w.annotateLogs({
3640
+ warn: (e, n) => T.logWarning(e).pipe(T.annotateLogs({
3453
3641
  scope: `migrations:file:${t.id}`,
3454
3642
  ...n ?? {}
3455
3643
  }))
3456
3644
  },
3457
3645
  appliedAt: (/* @__PURE__ */ new Date()).toISOString()
3458
3646
  }, a = r.migration.down(i);
3459
- w.isEffect(a) ? yield* a : yield* w.tryPromise({
3647
+ T.isEffect(a) ? yield* a : yield* T.tryPromise({
3460
3648
  try: () => a,
3461
3649
  catch: (e) => e
3462
3650
  });
@@ -3465,8 +3653,8 @@ BEGIN
3465
3653
  id: t.id,
3466
3654
  durationMs: o
3467
3655
  };
3468
- }), (e) => e.release.pipe(w.orDie)) : yield* w.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3469
- }), ja = (e) => w.gen(function* () {
3656
+ }), (e) => e.release.pipe(T.orDie)) : yield* T.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
3657
+ }), Ja = (e) => T.gen(function* () {
3470
3658
  let t = yield* E.SqlClient, n = yield* t`
3471
3659
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
3472
3660
  WHERE source = 'auto-diff'
@@ -3474,9 +3662,9 @@ BEGIN
3474
3662
  AND appliedAt < ${e.before}
3475
3663
  ORDER BY appliedAt DESC
3476
3664
  `;
3477
- if (n.length === 0) return yield* w.fail(/* @__PURE__ */ Error(`squash: no rows applied before ${e.before}`));
3665
+ if (n.length === 0) return yield* T.fail(/* @__PURE__ */ Error(`squash: no rows applied before ${e.before}`));
3478
3666
  let r = n[0];
3479
- if (r.fingerprint !== e.fingerprint) return yield* w.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.`));
3667
+ if (r.fingerprint !== e.fingerprint) return yield* T.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.`));
3480
3668
  yield* t`
3481
3669
  UPDATE _voltro_migration_plans
3482
3670
  SET squashedAt = CURRENT_TIMESTAMP
@@ -3511,7 +3699,7 @@ BEGIN
3511
3699
  snapshotFingerprint: e.fingerprint,
3512
3700
  snapshotId: i
3513
3701
  };
3514
- }), Ma = { safe: !0 }, Na = (e) => {
3702
+ }), Ya = { safe: !0 }, Xa = (e) => {
3515
3703
  switch (e.kind) {
3516
3704
  case "drop-column": return {
3517
3705
  safe: !1,
@@ -3538,7 +3726,7 @@ BEGIN
3538
3726
  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`,
3539
3727
  remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
3540
3728
  };
3541
- case "alter-column-nullability": return e.toNullable ? Ma : {
3729
+ case "alter-column-nullability": return e.toNullable ? Ya : {
3542
3730
  safe: !1,
3543
3731
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
3544
3732
  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)`
@@ -3549,6 +3737,11 @@ BEGIN
3549
3737
  reason: `old instances still write "${e.table}" without honouring the new uniqueness; a colliding insert now fails mid-rollout`,
3550
3738
  remedy: "make code enforce uniqueness first and deploy that; add the constraint in a LATER deploy once no old writer remains"
3551
3739
  };
3740
+ case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ? Ya : {
3741
+ safe: !1,
3742
+ reason: `writes to "${e.table}"."${e.column}" must satisfy the new JSON validation`,
3743
+ remedy: "ensure all writers supply valid JSON in the required domain before enabling this check"
3744
+ };
3552
3745
  case "add-check": return {
3553
3746
  safe: !1,
3554
3747
  reason: `old instances may write values to "${e.table}" the new CHECK rejects`,
@@ -3568,12 +3761,12 @@ BEGIN
3568
3761
  case "drop-unique":
3569
3762
  case "drop-unique-composite":
3570
3763
  case "drop-foreign-key":
3571
- case "drop-check": return Ma;
3764
+ case "drop-check": return Ya;
3572
3765
  }
3573
- }, Pa = (e) => {
3766
+ }, Za = (e) => {
3574
3767
  let t = [];
3575
3768
  for (let n of e) {
3576
- let e = Na(n.op);
3769
+ let e = Xa(n.op);
3577
3770
  e.safe || t.push({
3578
3771
  op: n,
3579
3772
  reason: e.reason,
@@ -3581,7 +3774,7 @@ BEGIN
3581
3774
  });
3582
3775
  }
3583
3776
  return t;
3584
- }, Fa = (e) => {
3777
+ }, Qa = (e) => {
3585
3778
  if (!e.enabled || e.unsafeCount === 0) return {
3586
3779
  refuse: !1,
3587
3780
  warnForced: !1,
@@ -3597,18 +3790,18 @@ BEGIN
3597
3790
  warnForced: !1,
3598
3791
  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.`
3599
3792
  };
3600
- }, Ia = (e) => {
3793
+ }, $a = (e) => {
3601
3794
  let t = e.table;
3602
3795
  if (typeof t == "string") return t;
3603
3796
  let n = e.from;
3604
3797
  return typeof n == "string" ? n : void 0;
3605
- }, La = (e) => ({
3798
+ }, eo = (e) => ({
3606
3799
  kind: e.op.kind,
3607
- table: Ia(e.op),
3800
+ table: $a(e.op),
3608
3801
  classification: e.classification,
3609
3802
  reason: e.reason,
3610
3803
  blockedFix: e.blocked?.fix
3611
- }), Ra = (e) => e.operations.map(La), za = async (e) => {
3804
+ }), to = (e) => e.operations.map(eo), no = async (e) => {
3612
3805
  let t = e.log ?? (() => {}), n = {
3613
3806
  branchId: e.branchId,
3614
3807
  mechanism: e.mechanism,
@@ -3627,10 +3820,10 @@ BEGIN
3627
3820
  applied: !1,
3628
3821
  converged: !1,
3629
3822
  residual: r,
3630
- infidelity: Ra(o)
3823
+ infidelity: to(o)
3631
3824
  };
3632
3825
  else {
3633
- let i = await e.plan(), o = Ra(i), s = o.filter((e) => e.classification === "lossy"), c = ma(i), l = c.operations.filter((e) => e.blocked !== void 0).map(La);
3826
+ let i = await e.plan(), o = to(i), s = o.filter((e) => e.classification === "lossy"), c = ja(i), l = c.operations.filter((e) => e.blocked !== void 0).map(eo);
3634
3827
  if (l.length > 0) a = {
3635
3828
  ...n,
3636
3829
  outcome: "blocked",
@@ -3655,7 +3848,7 @@ BEGIN
3655
3848
  };
3656
3849
  else {
3657
3850
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
3658
- let i = Ra(await e.replan());
3851
+ let i = to(await e.replan());
3659
3852
  a = {
3660
3853
  ...n,
3661
3854
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -3693,7 +3886,7 @@ BEGIN
3693
3886
  ...a,
3694
3887
  tornDown: o
3695
3888
  };
3696
- }, Ba = (e) => {
3889
+ }, ro = (e) => {
3697
3890
  switch (e.outcome) {
3698
3891
  case "clean": return 0;
3699
3892
  case "lossy": return 2;
@@ -3702,22 +3895,22 @@ BEGIN
3702
3895
  case "infidelity": return 1;
3703
3896
  case "failed": return 1;
3704
3897
  }
3705
- }, Va = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Ha = (e) => {
3898
+ }, io = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ao = (e) => {
3706
3899
  let t = [];
3707
3900
  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"}`);
3708
3901
  else if (e.outcome === "infidelity") {
3709
3902
  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:");
3710
- for (let n of e.infidelity) t.push(Va(n));
3903
+ for (let n of e.infidelity) t.push(io(n));
3711
3904
  } else {
3712
3905
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
3713
- for (let n of e.operations) t.push(Va(n));
3714
- 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(Va(n));
3906
+ for (let n of e.operations) t.push(io(n));
3907
+ 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(io(n));
3715
3908
  }
3716
3909
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
3717
- }, Ua = (e, ...t) => ({
3910
+ }, oo = (e, ...t) => ({
3718
3911
  _tag: "RawSqlFragment",
3719
3912
  strings: [...e],
3720
3913
  values: [...t]
3721
- }), Wa = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3914
+ }), so = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
3722
3915
  //#endregion
3723
- export { A as DEFAULT_CDC_CHANNEL, S as FILE_MIGRATION_PATTERN, wa as FileMigrationLedgerError, Ze as REACTIVE_TRIGGER_PREFIX, he as VOLTRO_MIGRATION_LOCK_KEY, Fe as acquireMigrationLock, U as appliedAtValue, Vt as applyNamespacedSchema, na as applyPlan, jt as applySchema, Fa as assessRollingDeployGate, Ba as branchRehearsalExitCode, Qn as chunkTables, Na as classifyRollingDeploySafety, R as declaredSnapshot, it as defaultArrayClause, rt as defaultClause, N as defaultJsonClause, va as describeOutcome, fa as destructiveScope, dn as detectReactiveTriggerDrift, gi as emitAddIndexMysql, Zr as emitCreateTableMysql, jr as emitDropColumnDdl, Mr as emitDropColumnDdlMysql, At as emitFrameworkBootstrapSql, Ot as emitNamespaceProvisionDdl, kt as emitNamespacedSchemaSql, Dt as emitSchemaSql, pr as engineFromVersion, L as fingerprintSchema, xe as fnv1a64, Ha as formatBranchRehearsal, fn as formatReactiveTriggerDrift, da as ignoreTablesFromEnv, fr as introspectSchema, yr as isAlreadySatisfied, u as isFileMigration, Wa as isRawSqlFragment, Nt as isReRunSafeDdl, Kn as mapPgType, d as migration, Se as migrationLockKeyForSchema, Ce as migrationLockNameForSchema, fi as mysqlIndexPrefixFor, $e as notifyFunctionName, P as numericIdSql, Gn as parseEnumCheck, Da as pendingFileMigrationIds, Wn as planMigrations, Ht as provisionTenantNamespace, Qe as reactiveTriggerName, vt as reactiveTriggerRepairSql, oa as recordUpToDate, za as rehearseMigrationOnBranch, La as rehearsedOperation, Yr as renderColumnMysql, Wr as renderColumnPg, _e as resolveMigrationLockSchema, hr as resolveMysqlEngine, Aa as rollbackFileBasedMigration, Pa as rollingDeployUnsafeOps, Oa as runFileBasedMigrations, Ut as runFrameworkBootstrap, Bt as runMigrate, _a as runPlannedMigrations, an as shortFingerprint, on as snapshotColumn, Ua as sql, M as sqlType, ja as squashMigrationPlans, ma as unblockLossy, Ie as withMigrationLock };
3916
+ export { A as DEFAULT_CDC_CHANNEL, S as FILE_MIGRATION_PATTERN, Va as FileMigrationLedgerError, st as REACTIVE_TRIGGER_PREFIX, xe as VOLTRO_MIGRATION_LOCK_KEY, Ve as acquireMigrationLock, W as appliedAtValue, Zt as applyNamespacedSchema, ya as applyPlan, Vt as applySchema, Qa as assessRollingDeployGate, ro as branchRehearsalExitCode, dr as chunkTables, Xa as classifyRollingDeploySafety, z as declaredSnapshot, mt as defaultArrayClause, pt as defaultClause, N as defaultJsonClause, Fa as describeOutcome, ka as destructiveScope, Cn as detectReactiveTriggerDrift, Ni as emitAddIndexMysql, wi as emitCreateTableMssql, pi as emitCreateTableMysql, ci as emitCreateTablePg, yi as emitCreateTableSqlite, Kr as emitDropColumnDdl, qr as emitDropColumnDdlMysql, Bt as emitFrameworkBootstrapSql, Rt as emitNamespaceProvisionDdl, zt as emitNamespacedSchemaSql, Lt as emitSchemaSql, Er as engineFromVersion, R as fingerprintSchema, De as fnv1a64, ao as formatBranchRehearsal, wn as formatReactiveTriggerDrift, Oa as ignoreTablesFromEnv, Tr as introspectSchema, Mr as isAlreadySatisfied, u as isFileMigration, so as isRawSqlFragment, Ut as isReRunSafeDdl, ar as mapPgType, d as migration, Oe as migrationLockKeyForSchema, ke as migrationLockNameForSchema, Oi as mysqlIndexPrefixFor, lt as notifyFunctionName, P as numericIdSql, ir as parseEnumCheck, Wa as pendingFileMigrationIds, nr as planMigrations, Qt as provisionTenantNamespace, ct as reactiveTriggerName, Ot as reactiveTriggerRepairSql, Ca as recordUpToDate, no as rehearseMigrationOnBranch, eo as rehearsedOperation, di as renderColumnMysql, ai as renderColumnPg, Ce as resolveMigrationLockSchema, Or as resolveMysqlEngine, qa as rollbackFileBasedMigration, Za as rollingDeployUnsafeOps, Ga as runFileBasedMigrations, $t as runFrameworkBootstrap, Xt as runMigrate, Pa as runPlannedMigrations, _n as shortFingerprint, vn as snapshotColumn, oo as sql, M as sqlType, Ja as squashMigrationPlans, ja as unblockLossy, He as withMigrationLock };