@voltro/database 0.70.0 → 0.71.0

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