@voltro/database 0.73.0 → 0.74.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,29 +1,29 @@
1
- import { B as e, D as t, Gn as n, Gt as r, I as i, Jt as a, Kn as o, Ln as s, N as c, Nn as l, Pn as u, S as d, Ut as f, V as p, Wt as m, Yt as h, _ as g, a as _, c as v, cn as y, d as b, f as x, g as S, h as C, i as ee, lt as w, m as T, mn as te, o as ne, ot as E, p as re, rt as ie, s as ae, tt as oe, u as se, v as ce, x as le, y as ue } from "./frameworkLiveTables-C1WjQ_uI.js";
2
- import { Cause as de, Effect as D, Equal as fe, Exit as pe, Schedule as me, Scope as he } from "effect";
3
- import { createHash as ge } from "node:crypto";
4
- import { createLogger as _e } from "@voltro/logger";
1
+ import { D as e, Gn as t, Gt as n, I as r, Jt as i, Kn as a, Ln as o, N as s, Nn as c, Pn as l, S as u, Ut as d, V as f, Wt as p, Yt as m, _ as h, a as g, c as _, cn as v, d as y, f as b, g as x, h as S, i as C, lt as ee, m as w, mn as te, o as T, ot as ne, p as E, rt as re, s as ie, tt as ae, u as oe, v as se, x as ce, y as le } from "./frameworkLiveTables-C1WjQ_uI.js";
2
+ import { Cause as ue, Effect as D, Equal as de, Exit as fe, Schedule as pe, Scope as me } from "effect";
3
+ import { createHash as he } from "node:crypto";
4
+ import { createLogger as ge } from "@voltro/logger";
5
5
  import { SqlClient as O } from "@effect/sql";
6
- import { promises as ve } from "node:fs";
7
- import { join as ye } from "node:path";
8
- import { pathToFileURL as be } from "node:url";
6
+ import { promises as _e } from "node:fs";
7
+ import { join as ve } from "node:path";
8
+ import { pathToFileURL as ye } from "node:url";
9
9
  //#region src/indexStorage.ts
10
- var xe = (e, t = "float32") => {
10
+ var be = (e, t = "float32") => {
11
11
  let n = e?.hnsw, r = n?.m ?? 16, i = n?.efConstruction ?? 64;
12
12
  for (let [e, t] of Object.entries({
13
13
  m: r,
14
14
  efConstruction: i
15
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);
16
+ let a = n?.opclass ?? m(n?.distance, t);
17
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
18
  return {
19
19
  m: r,
20
20
  efConstruction: i,
21
21
  opclass: a.toLowerCase().replace(/^public\./, "")
22
22
  };
23
- }, Se = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree", Ce = (e, t) => ({
23
+ }, xe = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree", Se = (e, t) => ({
24
24
  ...e !== void 0 && e !== "btree" ? { kind: e } : {},
25
- ...e === "hnsw" ? { kindOptions: { hnsw: xe(t) } } : {}
26
- }), we = (e, t, n = "float32") => {
25
+ ...e === "hnsw" ? { kindOptions: { hnsw: be(t) } } : {}
26
+ }), Ce = (e, t, n = "float32") => {
27
27
  if (e === void 0 || e === "btree") return {
28
28
  using: "",
29
29
  withSuffix: "",
@@ -35,14 +35,14 @@ var xe = (e, t = "float32") => {
35
35
  withSuffix: "",
36
36
  skip: !1
37
37
  };
38
- let r = xe(t, n);
38
+ let r = be(t, n);
39
39
  return {
40
40
  using: " USING hnsw",
41
41
  withSuffix: ` WITH (m = ${r.m}, ef_construction = ${r.efConstruction})`,
42
42
  opclass: r.opclass,
43
43
  skip: !1
44
44
  };
45
- }, Te = (e, t, n, r = 400) => {
45
+ }, we = (e, t, n, r = 400) => {
46
46
  let i = n, a = i.cause ?? {}, o = (e) => {
47
47
  let t = a[e];
48
48
  return t == null || t === "" ? void 0 : String(t);
@@ -73,21 +73,21 @@ var xe = (e, t = "float32") => {
73
73
  let t = o(e);
74
74
  t !== void 0 && s.push(`db.${e}: ${t}`);
75
75
  }
76
- let c = Ee(o("code"));
76
+ let c = Te(o("code"));
77
77
  return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
78
- }, Ee = (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, De = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, Oe = (e) => e.replace(/"/g, "`"), ke = (e) => typeof e == "string" ? e : e.name ?? String(e), Ae = (e, t) => `_ua_${t}_${e}`.slice(0, 64), je = (e, t) => {
79
- if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(De)) return e;
78
+ }, Te = (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, Ee = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, De = (e) => e.replace(/"/g, "`"), Oe = (e) => typeof e == "string" ? e : e.name ?? String(e), ke = (e, t) => `_ua_${t}_${e}`.slice(0, 64), Ae = (e, t) => {
79
+ if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(Ee)) return e;
80
80
  let n = { ...e.fields }, r = [], i = [];
81
81
  for (let t of e.appliedIndexes) {
82
- if (!De(t)) {
82
+ if (!Ee(t)) {
83
83
  r.push(t);
84
84
  continue;
85
85
  }
86
- let a = Oe(t.where), o = [];
86
+ let a = De(t.where), o = [];
87
87
  for (let r of t.fields) {
88
- let i = ke(r);
88
+ let i = Oe(r);
89
89
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
90
- let s = Ae(t.name, i);
90
+ let s = ke(t.name, i);
91
91
  o.push(s), n[s] = {
92
92
  type: "text",
93
93
  nullable: !0,
@@ -110,7 +110,7 @@ var xe = (e, t = "float32") => {
110
110
  appliedIndexes: r,
111
111
  appliedUniques: [...e.appliedUniques ?? [], ...i]
112
112
  };
113
- }, k = (e, t) => `${e}::${t}`, Me = (e, t) => {
113
+ }, k = (e, t) => `${e}::${t}`, je = (e, t) => {
114
114
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
115
115
  n.add(e);
116
116
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
@@ -119,7 +119,7 @@ var xe = (e, t = "float32") => {
119
119
  };
120
120
  for (let t of [...e].sort()) r.has(t) || a(t);
121
121
  return i;
122
- }, A = (e, t) => e.executeUnprepared(t, [], void 0), Ne = 6322741009312437n, Pe = (e) => {
122
+ }, Me = (e, t) => e.executeUnprepared(t, [], void 0), Ne = 6322741009312437n, Pe = (e) => {
123
123
  let t = e?.trim();
124
124
  return t === void 0 || t === "" || t === "public" ? void 0 : t;
125
125
  }, Fe = (e) => e?.schema === void 0 ? Pe(process.env.DB_SCHEMA) : Pe(e.schema), Ie = 14695981039346656037n, Le = 1099511628211n, Re = 18446744073709551615n, ze = (e) => {
@@ -140,19 +140,19 @@ var xe = (e, t = "float32") => {
140
140
  }, We = (e, t) => D.gen(function* () {
141
141
  let n = Ue(), r = Date.now();
142
142
  for (;;) {
143
- if ((yield* A(e, `SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`))[0]?.got) return;
143
+ if ((yield* Me(e, `SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`))[0]?.got) return;
144
144
  Date.now() - r >= n && (yield* D.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* D.sleep(`${He} millis`);
145
145
  }
146
- }), Ge = (e, t) => D.asVoid(A(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Ke = 30, qe = (e, t) => D.gen(function* () {
147
- (yield* A(e, `SELECT GET_LOCK('${t}', ${String(Ke)}) AS got`))[0]?.got !== 1 && (yield* D.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Ke}s (another migration is in progress, or a prior one left it held).`)));
148
- }), Je = (e, t) => D.asVoid(A(e, `SELECT RELEASE_LOCK('${t}')`)), Ye = 3e4, Xe = (e, t) => D.gen(function* () {
149
- let n = yield* A(e, `
146
+ }), Ge = (e, t) => D.asVoid(Me(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Ke = 30, qe = (e, t) => D.gen(function* () {
147
+ (yield* Me(e, `SELECT GET_LOCK('${t}', ${String(Ke)}) AS got`))[0]?.got !== 1 && (yield* D.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Ke}s (another migration is in progress, or a prior one left it held).`)));
148
+ }), Je = (e, t) => D.asVoid(Me(e, `SELECT RELEASE_LOCK('${t}')`)), Ye = 3e4, Xe = (e, t) => D.gen(function* () {
149
+ let n = yield* Me(e, `
150
150
  DECLARE @res int;
151
151
  EXEC @res = sp_getapplock @Resource = '${t}', @LockMode = 'Exclusive',
152
152
  @LockOwner = 'Session', @LockTimeout = ${String(Ye)};
153
153
  SELECT @res AS res`);
154
154
  (n[0]?.res ?? -999) < 0 && (yield* D.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
155
- }), Ze = (e, t) => D.asVoid(A(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), Qe = D.void, $e = (e, t) => D.gen(function* () {
155
+ }), Ze = (e, t) => D.asVoid(Me(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), Qe = D.void, $e = (e, t) => D.gen(function* () {
156
156
  let n = Fe(t), r = Ve(n), i = Be(n);
157
157
  if (!e.onDialectOrElse({
158
158
  mysql: () => !0,
@@ -160,19 +160,19 @@ var xe = (e, t = "float32") => {
160
160
  sqlite: () => !1,
161
161
  orElse: () => !0
162
162
  })) return { release: Qe };
163
- let a = yield* he.make(), o = yield* D.provideService(e.reserve, he.Scope, a), s = he.close(a, pe.void);
163
+ let a = yield* me.make(), o = yield* D.provideService(e.reserve, me.Scope, a), s = me.close(a, fe.void);
164
164
  return yield* e.onDialectOrElse({
165
165
  mysql: () => qe(o, r),
166
166
  mssql: () => Xe(o, r),
167
167
  sqlite: () => Qe,
168
168
  orElse: () => We(o, i)
169
- }).pipe(D.onExit((e) => pe.isSuccess(e) ? D.void : s)), { release: e.onDialectOrElse({
169
+ }).pipe(D.onExit((e) => fe.isSuccess(e) ? D.void : s)), { release: e.onDialectOrElse({
170
170
  mysql: () => Je(o, r),
171
171
  mssql: () => Ze(o, r),
172
172
  sqlite: () => Qe,
173
173
  orElse: () => Ge(o, i)
174
174
  }).pipe(D.ensuring(s)) };
175
- }), et = "a migration needs 2 connections: one holds the migration lock for the whole apply, the other runs the statements. The pool could not hand out the second one — raise its size (DB_POOL_MAX / maxConnections) to at least 2 for the migrating process; behind a pooler (PgBouncer, Supavisor) point the migration at the database directly (DB_DIRECT_URL / DB_MIGRATE_URL).", tt = (e) => /acquire connection/i.test(String(e?.message ?? e)), nt = (e, t, n) => D.acquireUseRelease($e(e, n), () => t.pipe(D.tapError((e) => tt(e) ? D.logError(`migrate: ${et}`).pipe(D.annotateLogs({ scope: "voltro:migrate" })) : D.void)), (e) => e.release.pipe(D.orDie)), j = (e) => e.onDialectOrElse({
175
+ }), et = "a migration needs 2 connections: one holds the migration lock for the whole apply, the other runs the statements. The pool could not hand out the second one — raise its size (DB_POOL_MAX / maxConnections) to at least 2 for the migrating process; behind a pooler (PgBouncer, Supavisor) point the migration at the database directly (DB_DIRECT_URL / DB_MIGRATE_URL).", tt = (e) => /acquire connection/i.test(String(e?.message ?? e)), nt = (e, t, n) => D.acquireUseRelease($e(e, n), () => t.pipe(D.tapError((e) => tt(e) ? D.logError(`migrate: ${et}`).pipe(D.annotateLogs({ scope: "voltro:migrate" })) : D.void)), (e) => e.release.pipe(D.orDie)), A = (e) => e.onDialectOrElse({
176
176
  pg: () => "postgres",
177
177
  mysql: () => "mysql",
178
178
  mssql: () => "mssql",
@@ -185,19 +185,19 @@ var xe = (e, t = "float32") => {
185
185
  mariadb: "per-operation",
186
186
  sqlite: "per-operation",
187
187
  turso: "per-operation"
188
- }, it = (e) => rt[e], M = "_voltro_migration_ops", at = a(M, {
189
- id: l({ prefix: "mop" }),
190
- runId: n(),
191
- planFingerprint: n(),
192
- opIndex: u(),
193
- opKind: n(),
194
- opTarget: n(),
195
- status: n(),
196
- payload: n(),
197
- startedAt: o().nullable(),
198
- appliedAt: o().nullable(),
199
- durationMs: u().nullable(),
200
- createdAt: o().default("now")
188
+ }, it = (e) => rt[e], j = "_voltro_migration_ops", at = i(j, {
189
+ id: c({ prefix: "mop" }),
190
+ runId: t(),
191
+ planFingerprint: t(),
192
+ opIndex: l(),
193
+ opKind: t(),
194
+ opTarget: t(),
195
+ status: t(),
196
+ payload: t(),
197
+ startedAt: a().nullable(),
198
+ appliedAt: a().nullable(),
199
+ durationMs: l().nullable(),
200
+ createdAt: a().default("now")
201
201
  }), ot = (e) => {
202
202
  switch (e.kind) {
203
203
  case "create-table": return /* @__PURE__ */ new Set([
@@ -288,14 +288,17 @@ var gt = (e) => {
288
288
  if (e.length === 0) return;
289
289
  let t = e.filter((e) => e.enabled);
290
290
  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";
291
- }, bt = "framework_changes", xt = "framework_changes_", St = (e, t) => t === "framework_changes" ? `${xt}${e}` : `${xt}${t}_${e}`, Ct = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, wt = "voltro:notify:v2", Tt = (e, t) => {
291
+ }, bt = "framework_changes", xt = "framework_changes_", St = (e, t) => t === "framework_changes" ? `${xt}${e}` : `${xt}${t}_${e}`, Ct = (e, t) => Tt(St(e, t).replace(/[A-Z]/g, (e) => e.toLowerCase())), wt = 63, Tt = (e) => {
292
+ let t = new TextEncoder().encode(e);
293
+ return t.length <= wt ? e : new TextDecoder().decode(t.subarray(0, wt)).replace(/�+$/u, "");
294
+ }, Et = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Dt = "voltro:notify:v2", Ot = (e, t) => {
292
295
  if (e.type === "text" && e.generatedAs === void 0) {
293
296
  if (e.maxLength !== void 0) return e.maxLength;
294
297
  if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
295
298
  }
296
- }, Et = _e({ scope: "voltro:migrate" }), N = (e) => {
297
- Et.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
298
- }, P = (e, t) => {
299
+ }, kt = ge({ scope: "voltro:migrate" }), M = (e) => {
300
+ kt.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
301
+ }, N = (e, t) => {
299
302
  let n = e.type;
300
303
  if (e.spatial) {
301
304
  if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
@@ -306,14 +309,14 @@ var gt = (e) => {
306
309
  return e.rawDdl;
307
310
  }
308
311
  if (n === "array" && e.arrayElement) {
309
- if (t === "postgres") return `${P({
312
+ if (t === "postgres") return `${N({
310
313
  ...e,
311
314
  type: e.arrayElement,
312
315
  arrayElement: void 0
313
316
  }, t)}[]`;
314
317
  if (t === "mysql" || t === "mariadb") return "JSON";
315
318
  if (t === "mssql") return "NVARCHAR(MAX)";
316
- if (m(t)) return "TEXT";
319
+ if (p(t)) return "TEXT";
317
320
  }
318
321
  if (n === "vector") {
319
322
  let n = e.vectorDim;
@@ -322,27 +325,27 @@ var gt = (e) => {
322
325
  if (t === "postgres") return r ? `HALFVEC(${n})` : `VECTOR(${n})`;
323
326
  if (t === "mysql" || t === "mariadb") return `VECTOR(${n})`;
324
327
  if (t === "mssql") return "VARBINARY(MAX)";
325
- if (m(t)) return "BLOB";
328
+ if (p(t)) return "BLOB";
326
329
  }
327
330
  if (n === "interval") {
328
331
  if (t === "postgres") return "INTERVAL";
329
332
  if (t === "mysql" || t === "mariadb" || t === "mssql") return "BIGINT";
330
- if (m(t)) return "INTEGER";
333
+ if (p(t)) return "INTEGER";
331
334
  }
332
335
  if (n === "decimal") {
333
336
  let n = e.precision, r = e.scale ?? 0;
334
337
  if (n === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
335
- return m(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
338
+ return p(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
336
339
  }
337
- if (n === "bigint") return m(t) ? "INTEGER" : "BIGINT";
340
+ if (n === "bigint") return p(t) ? "INTEGER" : "BIGINT";
338
341
  if (n === "enum") {
339
342
  if (t === "postgres") return e.enumName ?? "TEXT";
340
343
  if (t === "mysql" || t === "mariadb") return `ENUM(${(e.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
341
344
  if (t === "mssql") return "NVARCHAR(255)";
342
- if (m(t)) return "TEXT";
345
+ if (p(t)) return "TEXT";
343
346
  }
344
- if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : m(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
345
- if (m(t)) switch (n) {
347
+ if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : p(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
348
+ if (p(t)) switch (n) {
346
349
  case "id": return "TEXT";
347
350
  case "text": return "TEXT";
348
351
  case "integer": return "INTEGER";
@@ -377,7 +380,7 @@ var gt = (e) => {
377
380
  if (t === "mssql") switch (n) {
378
381
  case "id": return "NVARCHAR(64)";
379
382
  case "text": {
380
- let t = Tt(e, !1);
383
+ let t = Ot(e, !1);
381
384
  return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
382
385
  }
383
386
  case "integer": return "INT";
@@ -409,22 +412,22 @@ var gt = (e) => {
409
412
  case "array": return "TEXT[]";
410
413
  case "interval": return "INTERVAL";
411
414
  }
412
- }, Dt = (e, t) => {
415
+ }, At = (e, t) => {
413
416
  if (!e.hasDefault || e.defaultFactory !== void 0) return null;
414
417
  let n = e.defaultValue;
415
- 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) ? Ot(n, e, t) : typeof n == "object" && n ? kt(n, t) : null;
416
- }, Ot = (e, t, n) => {
417
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return kt(e, n);
418
- let r = P({
418
+ return n === "now" ? p(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) ? jt(n, e, t) : typeof n == "object" && n ? P(n, t) : null;
419
+ }, jt = (e, t, n) => {
420
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return P(e, n);
421
+ let r = N({
419
422
  ...t,
420
423
  type: t.arrayElement,
421
424
  arrayElement: void 0
422
425
  }, n);
423
426
  return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
424
- }, kt = (e, t) => {
427
+ }, P = (e, t) => {
425
428
  let n = JSON.stringify(e).replace(/'/g, "''");
426
429
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
427
- }, At = (e, t) => {
430
+ }, F = (e, t) => {
428
431
  switch (t) {
429
432
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
430
433
  case "mysql":
@@ -433,7 +436,7 @@ var gt = (e) => {
433
436
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
434
437
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
435
438
  }
436
- }, jt = (e, t) => {
439
+ }, I = (e, t) => {
437
440
  if (e === "restrict" && t === "mssql") return "NO ACTION";
438
441
  switch (e) {
439
442
  case "cascade": return "CASCADE";
@@ -441,103 +444,103 @@ var gt = (e) => {
441
444
  case "setNull": return "SET NULL";
442
445
  case "noAction": return "NO ACTION";
443
446
  }
444
- }, Mt = (e, t, n) => n === null ? r(e, t) : `${r(n, t)}.${r(e, t)}`, Nt = 191, Pt = (e, t) => {
447
+ }, Mt = (e, t, r) => r === null ? n(e, t) : `${n(r, t)}.${n(e, t)}`, Nt = 191, Pt = (e, t) => {
445
448
  if (!e || t !== "mysql" && t !== "mariadb") return !1;
446
- let n = P(e, t).toUpperCase();
449
+ let n = N(e, t).toUpperCase();
447
450
  return n.endsWith("TEXT") || n.endsWith("BLOB");
448
- }, Ft = (e, t, n) => {
449
- let i = r(e, n);
450
- if (n !== "mysql" && n !== "mariadb") return i;
451
+ }, Ft = (e, t, r) => {
452
+ let i = n(e, r);
453
+ if (r !== "mysql" && r !== "mariadb") return i;
451
454
  let a = t[e];
452
455
  if (!a) return i;
453
- let o = P(a, n).toUpperCase();
456
+ let o = N(a, r).toUpperCase();
454
457
  return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${Nt})` : i;
455
458
  }, It = (e, t) => {
456
459
  if (!e.generatedAs) return null;
457
460
  let { expr: n, stored: r } = e.generatedAs;
458
- if (t === "postgres") return r || N("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
461
+ if (t === "postgres") return r || M("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
459
462
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
460
463
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
461
464
  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.");
462
465
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
463
- }, Lt = (e, t, n, i, a = !1, o = !1) => {
464
- if (t.type === "id" && t.idScheme?.kind === "numeric") return At(e, n);
465
- let s = n === "mssql" ? Tt(t, i?.has(e) ?? !1) : void 0, c = s === void 0 ? P(t, n) : `NVARCHAR(${s})`, l = [r(e, n), c];
466
+ }, Lt = (e, t, r, i, a = !1, o = !1) => {
467
+ if (t.type === "id" && t.idScheme?.kind === "numeric") return F(e, r);
468
+ let s = r === "mssql" ? Ot(t, i?.has(e) ?? !1) : void 0, c = s === void 0 ? N(t, r) : `NVARCHAR(${s})`, l = [n(e, r), c];
466
469
  t.type === "id" && !o && l.push("PRIMARY KEY");
467
- let u = It(t, n);
470
+ let u = It(t, r);
468
471
  if (u) l.push(u);
469
472
  else {
470
- t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !Pt(t, n) && l.push("UNIQUE");
471
- let e = Dt(t, n);
473
+ t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !Pt(t, r) && l.push("UNIQUE");
474
+ let e = At(t, r);
472
475
  e && l.push(e);
473
476
  }
474
- if (t.type === "reference" && t.references && !a && !f(n)) {
477
+ if (t.type === "reference" && t.references && !a && !d(r)) {
475
478
  let e = t.references();
476
- l.push(`REFERENCES ${r(e.tableName, n)} (${r(t.referenceColumn ?? "id", n)})`);
477
- let i = jt(t.onDelete ?? "restrict", n);
479
+ l.push(`REFERENCES ${n(e.tableName, r)} (${n(t.referenceColumn ?? "id", r)})`);
480
+ let i = I(t.onDelete ?? "restrict", r);
478
481
  l.push(`ON DELETE ${i}`);
479
- let a = jt(t.refOnUpdate ?? "noAction", n);
482
+ let a = I(t.refOnUpdate ?? "noAction", r);
480
483
  a !== "NO ACTION" && l.push(`ON UPDATE ${a}`);
481
484
  }
482
485
  if (t.oneOf && t.oneOf.length > 0) {
483
486
  let i = t.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
484
- l.push(`CHECK (${r(e, n)} IN (${i}))`);
487
+ l.push(`CHECK (${n(e, r)} IN (${i}))`);
485
488
  }
486
489
  if (t.checks && t.checks.length > 0) for (let e of t.checks) l.push(`CHECK (${e})`);
487
- if (t.type === "enum" && t.enumValues && t.enumValues.length > 0 && (n === "mssql" || m(n))) {
490
+ if (t.type === "enum" && t.enumValues && t.enumValues.length > 0 && (r === "mssql" || p(r))) {
488
491
  let i = t.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
489
- l.push(`CHECK (${r(e, n)} IN (${i}))`);
492
+ l.push(`CHECK (${n(e, r)} IN (${i}))`);
490
493
  }
491
494
  if (t.type === "json" || t.type === "array") {
492
- let i = r(e, n);
493
- m(n) ? l.push(`CHECK (${i} IS NULL OR json_valid(${i}))`) : n === "mssql" && l.push(t.type === "json" ? `CHECK ${gt(i)}` : `CHECK (${i} IS NULL OR ISJSON(${i}) = 1)`);
495
+ let i = n(e, r);
496
+ p(r) ? l.push(`CHECK (${i} IS NULL OR json_valid(${i}))`) : r === "mssql" && l.push(t.type === "json" ? `CHECK ${gt(i)}` : `CHECK (${i} IS NULL OR ISJSON(${i}) = 1)`);
494
497
  }
495
498
  return l.join(" ");
496
- }, Rt = (e, t, n = null, i) => {
499
+ }, Rt = (e, t, r = null, i) => {
497
500
  let a = /* @__PURE__ */ new Set();
498
501
  for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
499
502
  for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
500
503
  for (let [t, n] of Object.entries(e.fields)) n.unique && a.add(t);
501
504
  let o = e.appliedPrimaryKey ?? [];
502
505
  for (let e of o) a.add(e);
503
- let s = o.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${Lt(e, n, t, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
504
- let i = n.fields.map((n) => Ft(n, e.fields, t)).join(", ");
505
- return ` CONSTRAINT ${r(n.name, t)} UNIQUE (${i})`;
506
- }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${r(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${o.map((n) => Ft(n, e.fields, t)).join(", ")})`] : [], p = f(t) ? Object.entries(e.fields).flatMap(([a, o]) => {
506
+ let s = o.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${Lt(e, n, t, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((r) => {
507
+ let i = r.fields.map((n) => Ft(n, e.fields, t)).join(", ");
508
+ return ` CONSTRAINT ${n(r.name, t)} UNIQUE (${i})`;
509
+ }), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${n(e.name, t)} CHECK (${e.expr})`), f = s ? [` PRIMARY KEY (${o.map((n) => Ft(n, e.fields, t)).join(", ")})`] : [], p = d(t) ? Object.entries(e.fields).flatMap(([a, o]) => {
507
510
  if (o.type !== "reference" || !o.references || (i?.has(a) ?? !1)) return [];
508
- let s = o.references(), c = jt(o.onDelete ?? "restrict", t), l = jt(o.refOnUpdate ?? "noAction", t);
509
- return [` CONSTRAINT ${r(`${e.tableName}_${a}_fkey`, t)} FOREIGN KEY (${r(a, t)}) REFERENCES ${Mt(s.tableName, t, n)} (${r(o.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
511
+ let s = o.references(), c = I(o.onDelete ?? "restrict", t), l = I(o.refOnUpdate ?? "noAction", t);
512
+ return [` CONSTRAINT ${n(`${e.tableName}_${a}_fkey`, t)} FOREIGN KEY (${n(a, t)}) REFERENCES ${Mt(s.tableName, t, r)} (${n(o.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
510
513
  }) : [], m = [
511
- ...d,
514
+ ...f,
512
515
  ...l,
513
516
  ...u,
514
517
  ...p
515
- ], h = m.length > 0 ? `${c},\n${m.join(",\n")}` : c, g = Mt(e.tableName, t, n);
518
+ ], h = m.length > 0 ? `${c},\n${m.join(",\n")}` : c, g = Mt(e.tableName, t, r);
516
519
  if (t === "mssql") {
517
- let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${g} (\n${h}\n)`;
518
- return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
520
+ let t = r === null ? e.tableName : `${r}.${e.tableName}`, n = `CREATE TABLE ${g} (\n${h}\n)`;
521
+ return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
519
522
  }
520
523
  return [
521
524
  `CREATE TABLE IF NOT EXISTS ${g} (`,
522
525
  h,
523
526
  ");"
524
527
  ].join("\n");
525
- }, zt = (e, t, n) => {
526
- let i = `${e}_${t.name}_fts`, a = (e) => r(e, n), o = t.columns.map(a).join(", "), s = t.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
528
+ }, zt = (e, t, r) => {
529
+ let i = `${e}_${t.name}_fts`, a = (e) => n(e, r), o = t.columns.map(a).join(", "), s = t.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
527
530
  return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(i)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ai`)} AFTER INSERT ON ${a(e)} BEGIN\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ad`)} AFTER DELETE ON ${a(e)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_au`)} AFTER UPDATE ON ${a(e)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
528
- }, Bt = (e, t, n = null) => {
531
+ }, Bt = (e, t, r = null) => {
529
532
  let i = [], a = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, n, r, i, a) => {
530
- if (t === "postgres") return we(r, i, a);
533
+ if (t === "postgres") return Ce(r, i, a);
531
534
  let o = {
532
535
  using: "",
533
536
  withSuffix: "",
534
537
  skip: !1
535
538
  };
536
- return r === void 0 || r === "btree" ? o : r === "gist" ? (N(`[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" ? (N(`[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(...).`), {
539
+ 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(...).`), {
537
540
  using: "",
538
541
  withSuffix: "",
539
542
  skip: !0
540
- }) : (N(`[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" ? (N(`[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" ? (N(`[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.`), {
543
+ }) : (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.`), {
541
544
  using: "",
542
545
  withSuffix: "",
543
546
  skip: !0
@@ -547,7 +550,7 @@ var gt = (e) => {
547
550
  if (typeof n == "string") return Ft(n, e.fields, t);
548
551
  if ("jsonPath" in n) {
549
552
  let { column: e, path: r, numeric: i } = n.jsonPath;
550
- return `(${oe(e, r, t, { numeric: i })})`;
553
+ return `(${ae(e, r, t, { numeric: i })})`;
551
554
  }
552
555
  return `(${n.expr})`;
553
556
  });
@@ -555,33 +558,33 @@ var gt = (e) => {
555
558
  }, l = (i, a, o, l, u, d = "", f = !1) => {
556
559
  let p = o[0], m = typeof p == "string" ? e.fields[p]?.vectorPrecision : void 0, h = s(i, a, l, u, m);
557
560
  if (h.skip) return "";
558
- let g = c(o, h.opclass), _ = `${h.withSuffix}${d}`, v = Mt(a, t, n), y = f ? "UNIQUE " : "";
559
- return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${i}') CREATE ${y}INDEX ${r(i, t)} ON ${v}${h.using} (${g})${_};` : t === "mysql" ? `CREATE ${y}INDEX ${r(i, t)} ON ${v}${h.using} (${g})${_};` : `CREATE ${y}INDEX IF NOT EXISTS ${r(i, t)} ON ${v}${h.using} (${g})${_};`;
561
+ let g = c(o, h.opclass), _ = `${h.withSuffix}${d}`, v = Mt(a, t, r), y = f ? "UNIQUE " : "";
562
+ return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${i}') CREATE ${y}INDEX ${n(i, t)} ON ${v}${h.using} (${g})${_};` : t === "mysql" ? `CREATE ${y}INDEX ${n(i, t)} ON ${v}${h.using} (${g})${_};` : `CREATE ${y}INDEX IF NOT EXISTS ${n(i, t)} ON ${v}${h.using} (${g})${_};`;
560
563
  };
561
564
  if (t === "mysql" || t === "mariadb") for (let [n, r] of Object.entries(e.fields)) {
562
565
  if (!r.unique || r.type === "id" || !Pt(r, t)) continue;
563
566
  let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
564
567
  a && i.push(a);
565
568
  }
566
- for (let n of e.appliedFullText ?? []) if (t === "postgres") {
567
- let a = n.config ?? "english", o = `${n.name}_tsv`, s = n.columns.map((e) => {
568
- let i = n.weights?.[e] ?? "A";
569
- return `setweight(to_tsvector('${a}', coalesce(${r(e, t)}, '')), '${i}')`;
569
+ for (let r of e.appliedFullText ?? []) if (t === "postgres") {
570
+ let a = r.config ?? "english", o = `${r.name}_tsv`, s = r.columns.map((e) => {
571
+ let i = r.weights?.[e] ?? "A";
572
+ return `setweight(to_tsvector('${a}', coalesce(${n(e, t)}, '')), '${i}')`;
570
573
  }).join(" || ");
571
- i.push(`ALTER TABLE ${r(e.tableName, t)} ADD COLUMN IF NOT EXISTS ${r(o, t)} tsvector GENERATED ALWAYS AS (${s}) STORED;`), i.push(`CREATE INDEX IF NOT EXISTS ${r(n.name, t)} ON ${r(e.tableName, t)} USING GIN (${r(o, t)});`);
574
+ i.push(`ALTER TABLE ${n(e.tableName, t)} ADD COLUMN IF NOT EXISTS ${n(o, t)} tsvector GENERATED ALWAYS AS (${s}) STORED;`), i.push(`CREATE INDEX IF NOT EXISTS ${n(r.name, t)} ON ${n(e.tableName, t)} USING GIN (${n(o, t)});`);
572
575
  } else if (t === "mysql" || t === "mariadb") {
573
- let a = n.columns.map((e) => r(e, t)).join(", ");
574
- i.push(`CREATE FULLTEXT INDEX ${r(n.name, t)} ON ${r(e.tableName, t)} (${a});`);
575
- } 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.`);
576
- else t === "sqlite" ? i.push(...zt(e.tableName, n, t)) : N(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
576
+ let a = r.columns.map((e) => n(e, t)).join(", ");
577
+ i.push(`CREATE FULLTEXT INDEX ${n(r.name, t)} ON ${n(e.tableName, t)} (${a});`);
578
+ } else if (t === "turso") throw Error(`@voltro/sql-turso: full-text index '${r.name}' on '${e.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
579
+ else t === "sqlite" ? i.push(...zt(e.tableName, r, t)) : M(`[voltro:migrate] full-text index '${r.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
577
580
  for (let n of e.appliedIndexes) {
578
581
  if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
579
- N(`[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(...).`);
582
+ 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(...).`);
580
583
  continue;
581
584
  }
582
585
  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.`);
583
586
  let r = "";
584
- n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? N(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : r = ` WHERE ${n.where}`);
587
+ 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`) : r = ` WHERE ${n.where}`);
585
588
  let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, r, n.unique === !0);
586
589
  s !== "" && i.push(s), n.fields.every((e) => typeof e == "string") && a.add(o(n.fields));
587
590
  }
@@ -596,12 +599,12 @@ var gt = (e) => {
596
599
  let r = e.filter((e) => e.isReactive !== !1);
597
600
  return r.length === 0 ? [] : [Ht(n), ...r.map((e) => Wt(e, n))];
598
601
  }, Ht = (e) => `
599
- CREATE OR REPLACE FUNCTION ${Ct(e)}() RETURNS trigger AS $$
602
+ CREATE OR REPLACE FUNCTION ${Et(e)}() RETURNS trigger AS $$
600
603
  DECLARE
601
604
  payload TEXT;
602
605
  pk JSONB;
603
606
  BEGIN
604
- -- ${wt}
607
+ -- ${Dt}
605
608
  payload := json_build_object(
606
609
  'table', TG_TABLE_NAME,
607
610
  -- The schema the write landed in. Under namespace isolation this is
@@ -660,7 +663,7 @@ $$ LANGUAGE plpgsql;
660
663
  return [
661
664
  `ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
662
665
  `DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
663
- `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Ct(t)}()`
666
+ `CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Et(t)}()`
664
667
  ];
665
668
  }, Wt = (e, t) => Ut(e, t).map((e) => `${e};`).join("\n"), Gt = (e) => {
666
669
  if (e.dialect !== "postgres") return [];
@@ -674,7 +677,7 @@ $$ LANGUAGE plpgsql;
674
677
  let n = [];
675
678
  return qt(e) && n.push("CREATE EXTENSION IF NOT EXISTS vector;"), Jt(e) && n.push("CREATE EXTENSION IF NOT EXISTS postgis;"), n.length === 0 ? void 0 : n.join("\n");
676
679
  }, qt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Jt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Yt = (e) => {
677
- let t = new Map(e.map((e) => [e.tableName, e])), n = Me(e.map((e) => e.tableName), (e) => {
680
+ let t = new Map(e.map((e) => [e.tableName, e])), n = je(e.map((e) => e.tableName), (e) => {
678
681
  let n = t.get(e);
679
682
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
680
683
  if (n.type !== "reference" || !n.references) return [];
@@ -711,13 +714,13 @@ $$ LANGUAGE plpgsql;
711
714
  sorted: o,
712
715
  cyclic: r
713
716
  };
714
- }, Xt = (e, t, n = null) => {
715
- let i = (e) => n ? `${r(n, t)}.${r(e, t)}` : r(e, t), a = `${e.table}_${e.column}_fkey`, o = jt(e.onDelete, t), s = jt(e.onUpdate, t), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (n) => `ADD CONSTRAINT ${r(a, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${r(e.column, t)}) REFERENCES ${i(e.targetTable)} (${r(e.targetColumn, t)})${c}`;
717
+ }, Xt = (e, t, r = null) => {
718
+ let i = (e) => r ? `${n(r, t)}.${n(e, t)}` : n(e, t), a = `${e.table}_${e.column}_fkey`, o = I(e.onDelete, t), s = I(e.onUpdate, t), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${n(a, t)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${n(e.column, t)}) REFERENCES ${i(e.targetTable)} (${n(e.targetColumn, t)})${c}`;
716
719
  switch (t) {
717
720
  case "postgres": return [
718
721
  "DO $$ BEGIN",
719
722
  " IF NOT EXISTS (SELECT 1 FROM pg_constraint",
720
- ` WHERE conname = '${a}' AND conrelid = '${n ? `${n}.` : ""}${e.table}'::regclass) THEN`,
723
+ ` WHERE conname = '${a}' AND conrelid = '${r ? `${r}.` : ""}${e.table}'::regclass) THEN`,
721
724
  ` ALTER TABLE ${i(e.table)} ${l(!1)};`,
722
725
  " END IF;",
723
726
  "END $$;"
@@ -728,7 +731,7 @@ $$ LANGUAGE plpgsql;
728
731
  }
729
732
  }, Zt = (e, t) => {
730
733
  let n = /* @__PURE__ */ new Map();
731
- if (m(t)) return n;
734
+ if (p(t)) return n;
732
735
  for (let t of e) {
733
736
  let e = n.get(t.table) ?? /* @__PURE__ */ new Set();
734
737
  e.add(t.column), n.set(t.table, e);
@@ -766,47 +769,47 @@ BEGIN
766
769
  return r.join("\n\n");
767
770
  }, en = (e) => {
768
771
  let t = [], n = [];
769
- for (let r of e) E(r) ? n.push(r) : t.push(r);
772
+ for (let r of e) ne(r) ? n.push(r) : t.push(r);
770
773
  return {
771
774
  tables: t,
772
775
  views: n
773
776
  };
774
777
  }, tn = (e, t, n = bt) => {
775
- let { tables: r, views: i } = en(e), { sorted: a, cyclic: o } = Yt(r.map((e) => je(e, t))), s = Zt(o, t), c = [], l = Kt(a, t);
778
+ let { tables: r, views: i } = en(e), { sorted: a, cyclic: o } = Yt(r.map((e) => Ae(e, t))), s = Zt(o, t), c = [], l = Kt(a, t);
776
779
  l && c.push(l);
777
780
  let u = $t(a, t);
778
781
  u && c.push(u);
779
782
  let d = Qt(a, t);
780
783
  d && c.push(d);
781
784
  for (let e of a) c.push(Rt(e, t, null, s.get(e.tableName)));
782
- if (!m(t)) for (let e of o) c.push(Xt(e, t));
785
+ if (!p(t)) for (let e of o) c.push(Xt(e, t));
783
786
  for (let e of a) {
784
787
  let n = Bt(e, t);
785
788
  n && c.push(n);
786
789
  }
787
790
  c.push(...Vt(a, t, n));
788
- for (let e of i) c.push(w(e, t));
791
+ for (let e of i) c.push(ee(e, t));
789
792
  return c.join("\n\n") + "\n";
790
- }, nn = (e, t, n) => {
791
- let i = r(e, t);
793
+ }, nn = (e, t, r) => {
794
+ let i = n(e, t);
792
795
  switch (t) {
793
796
  case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
794
797
  case "mysql":
795
798
  case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${i};`;
796
799
  case "mssql": return `IF SCHEMA_ID('${e.replace(/'/g, "''")}') IS NULL EXEC(N'CREATE SCHEMA ${i.replace(/'/g, "''")}');`;
797
800
  case "turso":
798
- case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${i};`;
801
+ case "sqlite": return `ATTACH DATABASE '${(r ?? `${e}.db`).replace(/'/g, "''")}' AS ${i};`;
799
802
  }
800
- }, rn = (e, t, n, i) => {
801
- let a = nn(n, t, i), o = r(n, t);
803
+ }, rn = (e, t, r, i) => {
804
+ let a = nn(r, t, i), o = n(r, t);
802
805
  if (t === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${tn(e, t)}`;
803
806
  if (t === "mysql" || t === "mariadb") return `${a}\n\nUSE ${o};\n\n${tn(e, t)}`;
804
807
  let { sorted: s, cyclic: c } = Yt(e), l = Zt(c, t), u = [a];
805
- for (let e of s) u.push(Rt(e, t, n, l.get(e.tableName)));
806
- if (!m(t)) for (let e of c) u.push(Xt(e, t, n));
808
+ for (let e of s) u.push(Rt(e, t, r, l.get(e.tableName)));
809
+ if (!p(t)) for (let e of c) u.push(Xt(e, t, r));
807
810
  for (let e of s) {
808
- let r = Bt(e, t, n);
809
- r && u.push(r);
811
+ let n = Bt(e, t, r);
812
+ n && u.push(n);
810
813
  }
811
814
  return u.join("\n\n") + "\n";
812
815
  }, an = (e, t, n = bt) => {
@@ -832,7 +835,7 @@ BEGIN
832
835
  }, un = (e) => ({
833
836
  while: e,
834
837
  times: ln(),
835
- schedule: me.jittered(me.exponential("50 millis"))
838
+ schedule: pe.jittered(pe.exponential("50 millis"))
836
839
  }), dn = class {
837
840
  statement;
838
841
  error;
@@ -843,15 +846,15 @@ BEGIN
843
846
  }, fn = (e, t, n) => D.gen(function* () {
844
847
  let r = yield* O.SqlClient, i = n !== void 0 && it(t) === "per-operation";
845
848
  for (let a of mn(e)) {
846
- process.env.VOLTRO_MIGRATE_DEBUG === "1" && Et.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
849
+ process.env.VOLTRO_MIGRATE_DEBUG === "1" && kt.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
847
850
  let e = r.unsafe(a).pipe(D.catchIf((e) => sn(a, e), () => D.succeed([])), D.tapError((e) => D.sync(() => {
848
- Et.error(Te("migrate: statement failed", a, e, 200));
851
+ kt.error(we("migrate: statement failed", a, e, 200));
849
852
  })));
850
853
  yield* (i && n !== void 0 && cn(a, t) ? e.pipe(D.retry(un((e) => n(e) === "retry"))) : e).pipe(D.mapError((e) => new dn(a, e)));
851
854
  }
852
855
  }), pn = (e, t, n, r) => {
853
856
  let i = n === "turso" ? fn(t, n, r) : e.withTransaction(fn(t, n, r)), a = (e) => e instanceof dn ? e.error : e;
854
- return (r !== void 0 && it(n) === "plan-transactional" ? i.pipe(D.retry(un((e) => r(a(e)) === "retry"))) : i).pipe(D.orDieWith((e) => e instanceof dn ? Error(Te("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
857
+ return (r !== void 0 && it(n) === "plan-transactional" ? i.pipe(D.retry(un((e) => r(a(e)) === "retry"))) : i).pipe(D.orDieWith((e) => e instanceof dn ? Error(we("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
855
858
  }, mn = (e) => {
856
859
  let t = [], n = "", r = !1;
857
860
  for (let i = 0; i < e.length; i++) {
@@ -873,7 +876,7 @@ BEGIN
873
876
  let i = rn(e, n, t), a = yield* O.SqlClient;
874
877
  yield* nt(a, pn(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(D.orDie);
875
878
  }), _n = async (e, t, n, r = "postgres", i = {}) => {
876
- await D.runPromise(gn(e, t, r, i).pipe(D.provide(n))), await d({
879
+ await D.runPromise(gn(e, t, r, i).pipe(D.provide(n))), await u({
877
880
  namespace: t,
878
881
  dialect: r
879
882
  });
@@ -950,36 +953,36 @@ BEGIN
950
953
  }, Pn = (e) => {
951
954
  let { kind: t, kindOptions: n, ...r } = e, i = {
952
955
  ...r,
953
- ...Ce(t, n),
956
+ ...Se(t, n),
954
957
  ...e.where === void 0 ? {} : { where: xn(e.where) }
955
958
  };
956
959
  return e.expression ? {
957
960
  ...i,
958
961
  columns: []
959
962
  } : i;
960
- }, F = (e) => {
963
+ }, L = (e) => {
961
964
  if (typeof e != "object" || !e) return JSON.stringify(e);
962
- if (Array.isArray(e)) return `[${e.map(F).join(",")}]`;
965
+ if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
963
966
  let t = e;
964
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${F(t[e])}`).join(",")}}`;
967
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
965
968
  }, Fn = (e) => {
966
969
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
967
970
  let t = e.defaultValue;
968
971
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
969
972
  if (typeof t == "number") return String(t);
970
- if (typeof t != "string") return F(t);
973
+ if (typeof t != "string") return L(t);
971
974
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
972
975
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
973
976
  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);
974
977
  if (o) try {
975
- return F(JSON.parse(o[1]));
978
+ return L(JSON.parse(o[1]));
976
979
  } catch {}
977
980
  let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
978
981
  if (s) try {
979
- return F(JSON.parse(s[1]));
982
+ return L(JSON.parse(s[1]));
980
983
  } catch {}
981
984
  if (a.startsWith("{") || a.startsWith("[")) try {
982
- return F(JSON.parse(a));
985
+ return L(JSON.parse(a));
983
986
  } catch {}
984
987
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
985
988
  }, In = (e) => {
@@ -996,11 +999,11 @@ BEGIN
996
999
  };
997
1000
  }, zn = (e, t, n) => {
998
1001
  if (t === "mssql") {
999
- let t = Tt(e, n);
1002
+ let t = Ot(e, n);
1000
1003
  if (t !== void 0) return t;
1001
1004
  }
1002
1005
  try {
1003
- let n = /^N?VARCHAR\((\d+)\)$/i.exec(P(e, t).trim());
1006
+ let n = /^N?VARCHAR\((\d+)\)$/i.exec(N(e, t).trim());
1004
1007
  return n ? Number(n[1]) : void 0;
1005
1008
  } catch {
1006
1009
  return;
@@ -1037,13 +1040,13 @@ BEGIN
1037
1040
  ...t.spatial === void 0 ? {} : { spatial: Mn(t.spatial) },
1038
1041
  ...t.enumValues === void 0 ? {} : { enumValues: [...t.enumValues].sort() }
1039
1042
  };
1040
- }, Un = (e) => e.columns.filter((e) => !ae(e.name)).map((t) => Hn(kn(t, Sn(e, t)))).sort((e, t) => e.name.localeCompare(t.name)), Wn = (e) => [...e].map(Pn).sort((e, t) => e.name.localeCompare(t.name)), Gn = (e) => [...e].filter((e) => !ae(e.name)).map((e) => ({
1043
+ }, Un = (e) => e.columns.filter((e) => !ie(e.name)).map((t) => Hn(kn(t, Sn(e, t)))).sort((e, t) => e.name.localeCompare(t.name)), Wn = (e) => [...e].map(Pn).sort((e, t) => e.name.localeCompare(t.name)), Gn = (e) => [...e].filter((e) => !ie(e.name)).map((e) => ({
1041
1044
  name: e.name,
1042
1045
  columns: Un(e),
1043
1046
  indexes: Wn(e.indexes)
1044
- })).sort((e, t) => e.name.localeCompare(t.name)), I = (e) => {
1047
+ })).sort((e, t) => e.name.localeCompare(t.name)), R = (e) => {
1045
1048
  let t = { tables: Gn(e.tables) }, n = JSON.stringify(Bn(t));
1046
- return ge("sha256").update(n).digest("hex");
1049
+ return he("sha256").update(n).digest("hex");
1047
1050
  }, Kn = (e) => e.slice(0, 16), qn = (e, t, n) => {
1048
1051
  let r = t.references ? {
1049
1052
  table: t.references().tableName,
@@ -1104,15 +1107,15 @@ BEGIN
1104
1107
  });
1105
1108
  let o = e.appliedIndexes ?? [];
1106
1109
  for (let n of o) {
1107
- let r = Se(n.kind, t);
1110
+ let r = xe(n.kind, t);
1108
1111
  if (r === null) continue;
1109
- let a = n.fields[0], o = typeof a == "string" ? e.fields[a]?.vectorPrecision : void 0, s = r === "hnsw" ? { hnsw: xe(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");
1112
+ let a = n.fields[0], o = typeof a == "string" ? e.fields[a]?.vectorPrecision : void 0, s = r === "hnsw" ? { hnsw: be(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");
1110
1113
  i({
1111
1114
  name: n.name,
1112
1115
  table: e.tableName,
1113
1116
  columns: c,
1114
1117
  unique: n.unique ?? !1,
1115
- ...Ce(r, s),
1118
+ ...Se(r, s),
1116
1119
  ...n.where === void 0 ? {} : { where: n.where },
1117
1120
  ...l ? { expression: !0 } : {}
1118
1121
  });
@@ -1130,7 +1133,7 @@ BEGIN
1130
1133
  let r = n;
1131
1134
  if (r.dropped || !r.references || r.fkAutoIndex === !1 || c.has(t)) continue;
1132
1135
  let a = `${e.tableName}_${t}_idx`;
1133
- y(e.tableName, a, !0, [t]), i({
1136
+ v(e.tableName, a, !0, [t]), i({
1134
1137
  name: a,
1135
1138
  table: e.tableName,
1136
1139
  columns: [t],
@@ -1163,8 +1166,8 @@ BEGIN
1163
1166
  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}').`);
1164
1167
  t.set(e.name, n.name);
1165
1168
  }
1166
- }, L = (e, t) => {
1167
- let n = e.filter((e) => !v(e.tableName)).map((e) => Yn(je(e, t), t));
1169
+ }, z = (e, t) => {
1170
+ let n = e.filter((e) => !_(e.tableName)).map((e) => Yn(Ae(e, t), t));
1168
1171
  if (t === "mysql" || t === "mariadb") {
1169
1172
  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.`);
1170
1173
  }
@@ -1177,7 +1180,7 @@ BEGIN
1177
1180
  if (t === "mssql" && !e.generatedAs && (e.type === "json" || e.type === "array") && (e = {
1178
1181
  ...e,
1179
1182
  jsonValidation: e.type === "json" ? "value" : "container"
1180
- }), m(t)) {
1183
+ }), p(t)) {
1181
1184
  if (e.maxLength === void 0) return e;
1182
1185
  let { maxLength: t, ...n } = e;
1183
1186
  return n;
@@ -1196,7 +1199,7 @@ BEGIN
1196
1199
  FROM pg_proc p
1197
1200
  JOIN pg_namespace n ON n.oid = p.pronamespace
1198
1201
  WHERE n.nspname = current_schema()
1199
- AND p.proname = ${Ct(n)}
1202
+ AND p.proname = ${Et(n)}
1200
1203
  `)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = (yield* e`SELECT current_schema() AS schema`)[0]?.schema ?? "", o = t.filter((e) => !e.tableName.startsWith("_voltro_"));
1201
1204
  if (o.length === 0) return {
1202
1205
  missing: [],
@@ -1209,26 +1212,26 @@ BEGIN
1209
1212
  }
1210
1213
  };
1211
1214
  let s = yield* e`
1212
- SELECT t.tgname
1215
+ SELECT t.tgname, c.relname
1213
1216
  FROM pg_trigger t
1214
1217
  JOIN pg_class c ON c.oid = t.tgrelid
1215
1218
  JOIN pg_namespace n ON n.oid = c.relnamespace
1216
1219
  WHERE NOT t.tgisinternal
1217
1220
  AND n.nspname = current_schema()
1218
1221
  AND t.tgname LIKE ${`${xt}%`}
1219
- `, c = new Set(s.map((e) => e.tgname)), l = [], u = [];
1222
+ `, c = (e, t) => `${e}\u0000${t}`, l = new Set(s.map((e) => c(e.relname, e.tgname))), u = [], d = [];
1220
1223
  for (let e of o) {
1221
- let t = c.has(St(e.tableName, n)), r = e.isReactive !== !1;
1222
- r && !t && l.push(e.tableName), !r && t && u.push(e.tableName);
1224
+ let t = l.has(c(e.tableName, Ct(e.tableName, n))), r = e.isReactive !== !1;
1225
+ r && !t && u.push(e.tableName), !r && t && d.push(e.tableName);
1223
1226
  }
1224
1227
  return {
1225
- missing: l.sort(),
1226
- stale: u.sort(),
1228
+ missing: u.sort(),
1229
+ stale: d.sort(),
1227
1230
  functionOutdated: i,
1228
1231
  compared: {
1229
1232
  schema: a,
1230
1233
  channel: n,
1231
- present: c.size
1234
+ present: l.size
1232
1235
  }
1233
1236
  };
1234
1237
  }), $n = (e) => {
@@ -1285,12 +1288,12 @@ BEGIN
1285
1288
  if (!n || !r || n.length !== r.length) return !1;
1286
1289
  let i = [...n].sort(), a = [...r].sort();
1287
1290
  return i.every((e, t) => e === a[t]);
1288
- }, or = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || !On(t) || zn(e, n, r) === t.maxLength, sr = (e, t, n, r, i = !1) => (!jn(e) || e.type === t.type || An(e, t, i)) && kn(e, i).idStorage === kn(t, !1).idStorage && e.nullable === t.nullable && (e.unique === t.unique || An(e, t, i)) && e.jsonValidation === t.jsonValidation && (t.enumValues === void 0 || e.enumValues === void 0 || e.enumValues.length === t.enumValues.length && e.enumValues.every((e) => t.enumValues.includes(e))) && (t.precision === void 0 || e.precision === t.precision && (e.scale ?? 0) === (t.scale ?? 0)) && Nn(e.spatial, t.spatial) && (e.storageType !== void 0 || t.storageType !== void 0 || t.arrayElement === void 0 || e.arrayElement === void 0 || e.arrayElement === t.arrayElement) && (t.vectorDim === void 0 || e.vectorDim === t.vectorDim) && (e.vectorPrecision ?? "float32") === (t.vectorPrecision ?? "float32") && ir(e, t) && or(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(Rn(e.references)) === JSON.stringify(Rn(t.references)) && ar(e.oneOf, t.oneOf), cr = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
1291
+ }, or = (e, t, n, r) => n === void 0 || p(n) ? !0 : e.type !== "text" || !On(t) || zn(e, n, r) === t.maxLength, sr = (e, t, n, r, i = !1) => (!jn(e) || e.type === t.type || An(e, t, i)) && kn(e, i).idStorage === kn(t, !1).idStorage && e.nullable === t.nullable && (e.unique === t.unique || An(e, t, i)) && e.jsonValidation === t.jsonValidation && (t.enumValues === void 0 || e.enumValues === void 0 || e.enumValues.length === t.enumValues.length && e.enumValues.every((e) => t.enumValues.includes(e))) && (t.precision === void 0 || e.precision === t.precision && (e.scale ?? 0) === (t.scale ?? 0)) && Nn(e.spatial, t.spatial) && (e.storageType !== void 0 || t.storageType !== void 0 || t.arrayElement === void 0 || e.arrayElement === void 0 || e.arrayElement === t.arrayElement) && (t.vectorDim === void 0 || e.vectorDim === t.vectorDim) && (e.vectorPrecision ?? "float32") === (t.vectorPrecision ?? "float32") && ir(e, t) && or(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(Rn(e.references)) === JSON.stringify(Rn(t.references)) && ar(e.oneOf, t.oneOf), cr = (e, t) => t.oneOf && t.oneOf.length > 0 ? B({
1289
1292
  kind: "add-check",
1290
1293
  table: e,
1291
1294
  column: t.name,
1292
1295
  values: t.oneOf
1293
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, lr = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && xn(e.where) === xn(t.where) && JSON.stringify(Ce(e.kind, e.kindOptions)) === JSON.stringify(Ce(t.kind, t.kindOptions)) && (e.expression ?? !1) === (t.expression ?? !1) && (e.expression === !0 && t.expression === !0 || e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), ur = (e, t, n) => {
1296
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, lr = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && xn(e.where) === xn(t.where) && JSON.stringify(Se(e.kind, e.kindOptions)) === JSON.stringify(Se(t.kind, t.kindOptions)) && (e.expression ?? !1) === (t.expression ?? !1) && (e.expression === !0 && t.expression === !0 || e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), ur = (e, t, n) => {
1294
1297
  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));
1295
1298
  for (let t of e.columns) {
1296
1299
  let i = r.get(t.name);
@@ -1323,7 +1326,7 @@ BEGIN
1323
1326
  added: o,
1324
1327
  removed: s
1325
1328
  };
1326
- }, R = (e, t, n, r) => ({
1329
+ }, B = (e, t, n, r) => ({
1327
1330
  op: e,
1328
1331
  classification: t,
1329
1332
  atomicByDialect: nr(e.kind),
@@ -1335,21 +1338,21 @@ BEGIN
1335
1338
  table: e,
1336
1339
  column: t
1337
1340
  };
1338
- return t.nullable ? R(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? R(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? R(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : R(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
1341
+ 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` });
1339
1342
  }, pr = (e, t, n) => {
1340
1343
  let r = {
1341
1344
  kind: "drop-column",
1342
1345
  table: e,
1343
1346
  column: t.name
1344
1347
  };
1345
- return n?.dropped ? R(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : R(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
1346
- }, mr = (e, t, n, r, i) => R({
1348
+ 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` });
1349
+ }, mr = (e, t, n, r, i) => B({
1347
1350
  kind: "create-table",
1348
1351
  table: e,
1349
1352
  columns: t,
1350
1353
  indexes: n,
1351
1354
  ...r && r.length > 0 ? { primaryKey: r } : {}
1352
- }, "safe", i ?? "new table — no data to preserve"), hr = (e) => R({
1355
+ }, "safe", i ?? "new table — no data to preserve"), hr = (e) => B({
1353
1356
  kind: "drop-table",
1354
1357
  table: e
1355
1358
  }, "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" }), gr = 5e4, _r = (e, t, n, r) => {
@@ -1367,12 +1370,12 @@ BEGIN
1367
1370
  table: e,
1368
1371
  name: t.name,
1369
1372
  fields: t.columns
1370
- }, i ? R(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(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`);
1371
- }, vr = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? R({
1373
+ }, 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`);
1374
+ }, vr = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? B({
1372
1375
  kind: "drop-unique-composite",
1373
1376
  table: e,
1374
1377
  name: t.name
1375
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : R({
1378
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : B({
1376
1379
  kind: "drop-index",
1377
1380
  table: e,
1378
1381
  index: t.name
@@ -1380,7 +1383,7 @@ BEGIN
1380
1383
  let n = e.type;
1381
1384
  if (n === "id") return Dn(e) === "numeric" ? "bigint" : "text";
1382
1385
  if (n === "array") return t === void 0 || t === "postgres" ? "array" : t === "mysql" || t === "mariadb" ? "json" : "text";
1383
- if (n === "enum") return t === "mssql" || m(t ?? "postgres") ? "text" : "enum";
1386
+ if (n === "enum") return t === "mssql" || p(t ?? "postgres") ? "text" : "enum";
1384
1387
  if (n === "reference") return e.referenceStorage === "numeric" ? "bigint" : "text";
1385
1388
  switch (t) {
1386
1389
  case "sqlite":
@@ -1400,7 +1403,7 @@ BEGIN
1400
1403
  column: t.name,
1401
1404
  toNullable: t.nullable
1402
1405
  };
1403
- o.push(t.nullable ? R(n, "safe", `loosen ${e}.${t.name} to nullable`) : R(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
1406
+ 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`));
1404
1407
  }
1405
1408
  if (t.unique !== n.unique) {
1406
1409
  if (t.unique) {
@@ -1409,8 +1412,8 @@ BEGIN
1409
1412
  table: e,
1410
1413
  column: t.name
1411
1414
  }, r = (i ?? 0) >= a;
1412
- o.push(r ? R(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
1413
- } else o.push(R({
1415
+ 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)`));
1416
+ } else o.push(B({
1414
1417
  kind: "drop-unique",
1415
1418
  table: e,
1416
1419
  column: t.name
@@ -1427,7 +1430,7 @@ BEGIN
1427
1430
  to: t.type,
1428
1431
  ...i.using === void 0 ? {} : { using: i.using }
1429
1432
  };
1430
- o.push(R(r, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${i.from}') declared` + (i.using ? ` with USING ${i.using}` : " (implicit cast)")));
1433
+ 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)")));
1431
1434
  } else {
1432
1435
  let i = {
1433
1436
  kind: "alter-column-type",
@@ -1436,12 +1439,12 @@ BEGIN
1436
1439
  from: n.type,
1437
1440
  to: t.type
1438
1441
  };
1439
- o.push(R(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: br(n.type, t, r) }));
1442
+ o.push(B(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: br(n.type, t, r) }));
1440
1443
  }
1441
1444
  }
1442
- if (t.type === "text" && On(n) && !m(r ?? "postgres") && t.maxLength !== n.maxLength) {
1445
+ if (t.type === "text" && On(n) && !p(r ?? "postgres") && t.maxLength !== n.maxLength) {
1443
1446
  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})`;
1444
- o.push(R({
1447
+ o.push(B({
1445
1448
  kind: "alter-column-type",
1446
1449
  table: e,
1447
1450
  column: t.name,
@@ -1452,7 +1455,7 @@ BEGIN
1452
1455
  if (t.type === "enum" && n.type === "enum" && n.enumValues !== void 0 && t.enumValues !== void 0) {
1453
1456
  let r = new Set(n.enumValues);
1454
1457
  new Set(t.enumValues);
1455
- for (let n of t.enumValues) r.has(n) || o.push(R({
1458
+ for (let n of t.enumValues) r.has(n) || o.push(B({
1456
1459
  kind: "add-enum-value",
1457
1460
  table: e,
1458
1461
  column: t.name,
@@ -1462,7 +1465,7 @@ BEGIN
1462
1465
  }
1463
1466
  if (!Nn(t.spatial, n.spatial)) {
1464
1467
  let r = t.spatial, i = n.spatial, a = (e) => e === void 0 ? "plain text" : `${e.kind}(${e.geomKind},${String(e.srid)})`, s = r !== void 0 && i !== void 0 && r.kind === i.kind && r.geomKind.toUpperCase() === i.geomKind.toUpperCase() && r.srid !== i.srid, c = r === void 0 ? void 0 : r.kind === "geography" ? `ST_Transform("${t.name}"::geometry, ${String(r.srid)})::geography` : `ST_Transform("${t.name}", ${String(r.srid)})`, l = t.narrowedFrom, u = l !== void 0 && l.from === n.type, d = s ? c : u ? l.using : void 0;
1465
- o.push(R({
1468
+ o.push(B({
1466
1469
  kind: "alter-column-type",
1467
1470
  table: e,
1468
1471
  column: t.name,
@@ -1473,7 +1476,7 @@ BEGIN
1473
1476
  }
1474
1477
  if (t.type === "array" && n.type === "array" && n.arrayElement !== void 0 && t.arrayElement !== void 0 && t.arrayElement !== n.arrayElement) {
1475
1478
  let r = t.narrowedFrom, i = r !== void 0 && r.from === n.type;
1476
- o.push(R({
1479
+ o.push(B({
1477
1480
  kind: "alter-column-type",
1478
1481
  table: e,
1479
1482
  column: t.name,
@@ -1484,7 +1487,7 @@ BEGIN
1484
1487
  }
1485
1488
  if (t.type === "vector" && n.type === "vector" && (n.vectorDim !== void 0 && t.vectorDim !== n.vectorDim || (t.vectorPrecision ?? "float32") !== (n.vectorPrecision ?? "float32"))) {
1486
1489
  let r = (e) => `${e.vectorPrecision === "half" ? "halfvec" : "vector"}(${String(e.vectorDim ?? "?")})`, i = t.narrowedFrom, a = i !== void 0 && i.from === n.type;
1487
- o.push(R({
1490
+ o.push(B({
1488
1491
  kind: "alter-column-type",
1489
1492
  table: e,
1490
1493
  column: t.name,
@@ -1495,7 +1498,7 @@ BEGIN
1495
1498
  }
1496
1499
  if (t.type === "decimal" && n.type === "decimal" && n.precision !== void 0 && (t.precision !== n.precision || (t.scale ?? 0) !== (n.scale ?? 0))) {
1497
1500
  let r = (e) => `${String(e.precision)},${String(e.scale ?? 0)}`, i = t.precision !== void 0 && n.precision !== void 0 && t.precision - (t.scale ?? 0) >= n.precision - (n.scale ?? 0) && (t.scale ?? 0) >= (n.scale ?? 0);
1498
- o.push(R({
1501
+ o.push(B({
1499
1502
  kind: "alter-column-type",
1500
1503
  table: e,
1501
1504
  column: t.name,
@@ -1511,11 +1514,11 @@ BEGIN
1511
1514
  hasDefault: t.hasDefault,
1512
1515
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
1513
1516
  };
1514
- o.push(R(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1517
+ o.push(B(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1515
1518
  }
1516
1519
  if (r === "mssql" && t.jsonValidation !== void 0 && t.jsonValidation !== "unverified" && t.jsonValidation !== n.jsonValidation) {
1517
1520
  let r = t.jsonValidation === "value" && n.jsonValidation === "container";
1518
- o.push(R({
1521
+ o.push(B({
1519
1522
  kind: "reconcile-json-check",
1520
1523
  table: e,
1521
1524
  column: t.name,
@@ -1525,7 +1528,7 @@ BEGIN
1525
1528
  }, 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`));
1526
1529
  }
1527
1530
  if (!ar(t.oneOf, n.oneOf)) {
1528
- n.oneOf && n.oneOf.length > 0 && o.push(R({
1531
+ n.oneOf && n.oneOf.length > 0 && o.push(B({
1529
1532
  kind: "drop-check",
1530
1533
  table: e,
1531
1534
  column: t.name
@@ -1533,7 +1536,7 @@ BEGIN
1533
1536
  let r = cr(e, t);
1534
1537
  r && o.push(r);
1535
1538
  }
1536
- return JSON.stringify(Rn(t.references)) !== JSON.stringify(Rn(n.references)) && (n.references && o.push(R({
1539
+ return JSON.stringify(Rn(t.references)) !== JSON.stringify(Rn(n.references)) && (n.references && o.push(B({
1537
1540
  kind: "drop-foreign-key",
1538
1541
  table: e,
1539
1542
  column: t.name
@@ -1550,15 +1553,15 @@ BEGIN
1550
1553
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1551
1554
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1552
1555
  };
1553
- return i === "null" && !t.nullable ? n.push(R(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(R({
1556
+ 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({
1554
1557
  ...a,
1555
1558
  orphanPolicy: i
1556
- }, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(R(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
1559
+ }, "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;
1557
1560
  }, Cr = (e, t, n) => {
1558
1561
  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));
1559
1562
  for (let [n, c] of Object.entries(t)) {
1560
1563
  let t = c.renamedFrom;
1561
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(R({
1564
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(B({
1562
1565
  kind: "rename-column",
1563
1566
  table: e.tableName,
1564
1567
  from: t,
@@ -1589,7 +1592,7 @@ BEGIN
1589
1592
  let r = o(n), i = a.filter((e) => !l.has(e.name) && s(e) === r);
1590
1593
  if (i.length !== 1) continue;
1591
1594
  let d = i[0];
1592
- d.name !== n.name && (l.add(d.name), u.add(n.name), c.push(R({
1595
+ d.name !== n.name && (l.add(d.name), u.add(n.name), c.push(B({
1593
1596
  kind: "rename-index",
1594
1597
  table: e,
1595
1598
  from: n.name,
@@ -1612,7 +1615,7 @@ BEGIN
1612
1615
  continue;
1613
1616
  }
1614
1617
  if (t.has(c.name)) {
1615
- r.push(R({
1618
+ r.push(B({
1616
1619
  kind: "rename-table",
1617
1620
  from: e,
1618
1621
  to: c.name
@@ -1620,14 +1623,14 @@ BEGIN
1620
1623
  continue;
1621
1624
  }
1622
1625
  if ((s.get(e) ?? 0) !== 1) {
1623
- r.push(R({
1626
+ r.push(B({
1624
1627
  kind: "rename-table",
1625
1628
  from: e,
1626
1629
  to: c.name
1627
1630
  }, "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.` }));
1628
1631
  continue;
1629
1632
  }
1630
- i.set(c.name, e), a.add(e), r.push(R({
1633
+ i.set(c.name, e), a.add(e), r.push(B({
1631
1634
  kind: "rename-table",
1632
1635
  from: e,
1633
1636
  to: c.name
@@ -1653,7 +1656,7 @@ BEGIN
1653
1656
  ...e,
1654
1657
  name: r,
1655
1658
  table: n
1656
- } : i ? (a.push(R({
1659
+ } : i ? (a.push(B({
1657
1660
  kind: "rename-index",
1658
1661
  table: n,
1659
1662
  from: e.name,
@@ -1706,7 +1709,7 @@ BEGIN
1706
1709
  }
1707
1710
  return t;
1708
1711
  }, jr = (e) => {
1709
- let t = L(e.declared, e.dialect), n = rr(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? gr, a = [], o = Or(t, r, n);
1712
+ let t = z(e.declared, e.dialect), n = rr(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? gr, a = [], o = Or(t, r, n);
1710
1713
  a.push(...o.ops);
1711
1714
  for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
1712
1715
  a.push(mr(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
@@ -1721,11 +1724,11 @@ BEGIN
1721
1724
  c.push(t.name);
1722
1725
  continue;
1723
1726
  }
1724
- if (ne(t.name)) {
1727
+ if (T(t.name)) {
1725
1728
  c.push(t.name);
1726
1729
  continue;
1727
1730
  }
1728
- if (ae(t.name)) {
1731
+ if (ie(t.name)) {
1729
1732
  c.push(t.name);
1730
1733
  continue;
1731
1734
  }
@@ -1751,10 +1754,10 @@ BEGIN
1751
1754
  }, e.dialect, u.rowCount, i));
1752
1755
  }
1753
1756
  for (let e of f.removed) {
1754
- if (m.consumedRemovedNames.has(e.name) || ae(e.name)) continue;
1757
+ if (m.consumedRemovedNames.has(e.name) || ie(e.name)) continue;
1755
1758
  let t = d.columnDefs[e.name], n = pr(s.name, e, t);
1756
1759
  e.references !== void 0 && a.push({
1757
- ...R({
1760
+ ...B({
1758
1761
  kind: "drop-foreign-key",
1759
1762
  table: s.name,
1760
1763
  column: e.name,
@@ -1782,8 +1785,8 @@ BEGIN
1782
1785
  column: e.name,
1783
1786
  target: e.references.table
1784
1787
  }] : []) : [];
1785
- }, f = Me([...l], d), p = [];
1786
- for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(k(e.name, t.name)) && p.push(R({
1788
+ }, f = je([...l], d), p = [];
1789
+ for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(k(e.name, t.name)) && p.push(B({
1787
1790
  kind: "add-foreign-key",
1788
1791
  table: e.name,
1789
1792
  column: t.name,
@@ -1859,12 +1862,12 @@ BEGIN
1859
1862
  for (let e of t.tables) {
1860
1863
  if (S.has(e.name) || o.renamedInto.has(e.name)) continue;
1861
1864
  let t = r.get(e.name);
1862
- t !== void 0 && I({ tables: [t] }) !== I({ tables: [e] }) && C.push(e.name);
1865
+ t !== void 0 && R({ tables: [t] }) !== R({ tables: [e] }) && C.push(e.name);
1863
1866
  }
1864
1867
  return {
1865
1868
  operations: x,
1866
- fromFingerprint: I(e.live),
1867
- toFingerprint: I(t),
1869
+ fromFingerprint: R(e.live),
1870
+ toFingerprint: R(t),
1868
1871
  summary: Ar(x),
1869
1872
  fingerprintDivergence: {
1870
1873
  outsideDiff: c,
@@ -1941,7 +1944,7 @@ BEGIN
1941
1944
  }, Ir = (e) => e === void 0 ? void 0 : Fr[e], Lr = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
1942
1945
  expr: e,
1943
1946
  stored: t
1944
- } }, z = (e) => {
1947
+ } }, V = (e) => {
1945
1948
  switch (e.toUpperCase()) {
1946
1949
  case "CASCADE": return "cascade";
1947
1950
  case "RESTRICT": return "restrict";
@@ -2110,7 +2113,7 @@ BEGIN
2110
2113
  AND c.relname IN ${t}
2111
2114
  )
2112
2115
  SELECT * FROM ix ORDER BY table_name, index_name, position
2113
- `), S = /* @__PURE__ */ new Map(), C = /* @__PURE__ */ new Map(), ee = /* @__PURE__ */ new Map(), w = /* @__PURE__ */ new Map(), T = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map();
2116
+ `), S = /* @__PURE__ */ new Map(), C = /* @__PURE__ */ new Map(), ee = /* @__PURE__ */ new Map(), w = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map(), T = /* @__PURE__ */ new Map();
2114
2117
  for (let e of u) {
2115
2118
  let t = S.get(e.table_name);
2116
2119
  t || (t = [], S.set(e.table_name, t)), t.push(e);
@@ -2146,23 +2149,23 @@ BEGIN
2146
2149
  }
2147
2150
  }
2148
2151
  for (let e of b) {
2149
- let t = T.get(e.source_table);
2150
- t || (t = [], T.set(e.source_table, t)), t.push(e);
2152
+ let t = te.get(e.source_table);
2153
+ t || (t = [], te.set(e.source_table, t)), t.push(e);
2151
2154
  }
2152
2155
  for (let e of x) {
2153
- let t = te.get(e.table_name);
2154
- t || (t = /* @__PURE__ */ new Map(), te.set(e.table_name, t));
2156
+ let t = T.get(e.table_name);
2157
+ t || (t = /* @__PURE__ */ new Map(), T.set(e.table_name, t));
2155
2158
  let n = t.get(e.index_name);
2156
2159
  n || (n = [], t.set(e.index_name, n)), n.push(e);
2157
2160
  }
2158
2161
  let E = [];
2159
2162
  for (let e of c) {
2160
- let t = /* @__PURE__ */ new Set(), n = (S.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = C.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = ee.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = T.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) => {
2163
+ let t = /* @__PURE__ */ new Set(), n = (S.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = C.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = ee.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = te.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) => {
2161
2164
  let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = t.data_type === "USER-DEFINED" && t.udt_name !== void 0 && g.has(t.udt_name), c = s ? "enum" : Pr(t.data_type, t.udt_name), l = !a && n && t.column_name === "id", u = a ? "reference" : l ? "id" : c, d = a ? {
2162
2165
  table: a.target_table,
2163
2166
  column: a.target_column,
2164
- onDelete: z(a.delete_rule),
2165
- onUpdate: z(a.update_rule),
2167
+ onDelete: V(a.delete_rule),
2168
+ onUpdate: V(a.update_rule),
2166
2169
  constraintName: a.constraint_name
2167
2170
  } : void 0, f = y.get(`${e.table_name}.${t.column_name}`);
2168
2171
  return {
@@ -2179,7 +2182,7 @@ BEGIN
2179
2182
  vectorPrecision: t.udt_name === "halfvec" ? "half" : "float32",
2180
2183
  ...t.type_modifier !== void 0 && t.type_modifier > 0 ? { vectorDim: t.type_modifier } : {}
2181
2184
  } : {},
2182
- ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
2185
+ ...ti(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: ti(t.data_type, t.character_maximum_length) },
2183
2186
  ...c === "decimal" && typeof t.numeric_precision == "number" ? {
2184
2187
  precision: t.numeric_precision,
2185
2188
  ...typeof t.numeric_scale == "number" ? { scale: t.numeric_scale } : {}
@@ -2193,7 +2196,7 @@ BEGIN
2193
2196
  ...f ? { oneOf: f } : {},
2194
2197
  ...Lr(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
2195
2198
  };
2196
- }), l = [], u = te.get(e.table_name);
2199
+ }), l = [], u = T.get(e.table_name);
2197
2200
  if (u) for (let [t, n] of u) {
2198
2201
  let r = /* @__PURE__ */ new Set(), i = [...n].filter((e) => e.column_name !== null && e.position !== null).sort((e, t) => (e.position ?? 0) - (t.position ?? 0)).filter((e) => {
2199
2202
  let t = e.position;
@@ -2210,7 +2213,7 @@ BEGIN
2210
2213
  table: e.table_name,
2211
2214
  columns: i.map((e) => e.column_name),
2212
2215
  unique: n[0]?.is_unique ?? !1,
2213
- ...Ce(o?.access_method, o?.access_method === "hnsw" ? { hnsw: {
2216
+ ...Se(o?.access_method, o?.access_method === "hnsw" ? { hnsw: {
2214
2217
  opclass: o.operator_class,
2215
2218
  m: c.get("m") ?? 16,
2216
2219
  efConstruction: c.get("ef_construction") ?? 64
@@ -2345,8 +2348,8 @@ BEGIN
2345
2348
  let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = c.has(`${e.table_name}.${t.column_name}`) ? "json" : Wr(t.data_type, t.column_type), u = !o && n && t.column_name === "id", d = o ? "reference" : u ? "id" : s, f = o ? {
2346
2349
  table: o.target_table,
2347
2350
  column: o.target_column,
2348
- onDelete: z(o.delete_rule),
2349
- onUpdate: z(o.update_rule),
2351
+ onDelete: V(o.delete_rule),
2352
+ onUpdate: V(o.update_rule),
2350
2353
  constraintName: o.constraint_name
2351
2354
  } : void 0, p = a.has(t.column_name) || n && t.column_name === "id", m = t.column_default === "NULL" ? null : t.column_default, h = l.get(`${e.table_name}.${t.column_name}`), g = t.data_type.toLowerCase() === "enum" ? [...t.column_type.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")) : void 0;
2352
2355
  return {
@@ -2355,7 +2358,7 @@ BEGIN
2355
2358
  ...u ? { idStorage: wn(s) } : {},
2356
2359
  ...d === "enum" && g !== void 0 ? { enumValues: g } : {},
2357
2360
  nullable: t.is_nullable === "YES",
2358
- ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
2361
+ ...ti(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: ti(t.data_type, t.character_maximum_length) },
2359
2362
  ...s === "decimal" && typeof t.numeric_precision == "number" ? {
2360
2363
  precision: t.numeric_precision,
2361
2364
  ...typeof t.numeric_scale == "number" ? { scale: t.numeric_scale } : {}
@@ -2420,8 +2423,8 @@ BEGIN
2420
2423
  let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = qr(e.type), a = !r && n && e.name === "id", o = r ? "reference" : a ? "id" : i, s = r ? {
2421
2424
  table: r.table,
2422
2425
  column: r.to,
2423
- onDelete: z(r.on_delete),
2424
- onUpdate: z(r.on_update)
2426
+ onDelete: V(r.on_delete),
2427
+ onUpdate: V(r.on_update)
2425
2428
  } : void 0, c = t.get(e.name);
2426
2429
  return {
2427
2430
  name: e.name,
@@ -2482,7 +2485,7 @@ BEGIN
2482
2485
  case "image": return "bytes";
2483
2486
  default: return "text";
2484
2487
  }
2485
- }, B = (e) => e === !0 || e === 1, Zr = (e) => D.gen(function* () {
2488
+ }, H = (e) => e === !0 || e === 1, Zr = (e) => D.gen(function* () {
2486
2489
  let t = yield* e`
2487
2490
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
2488
2491
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
@@ -2547,8 +2550,8 @@ BEGIN
2547
2550
  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();
2548
2551
  if (o) for (let [, e] of o) {
2549
2552
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
2550
- if (B(t[0].is_primary)) for (let e of t) p.push(e.column_name);
2551
- else t[0].predicate == null && B(t[0].is_unique) && t.length === 1 && m.add(t[0].column_name);
2553
+ if (H(t[0].is_primary)) for (let e of t) p.push(e.column_name);
2554
+ else t[0].predicate == null && H(t[0].is_unique) && t.length === 1 && m.add(t[0].column_name);
2552
2555
  }
2553
2556
  let h = t.map((t) => {
2554
2557
  let n = p.length === 1 && p[0] === t.column_name, a = r.get(t.column_name), o = Xr(t.data_type), l = !a && n && t.column_name === "id", u = a ? "reference" : l ? "id" : o, d = a ? {
@@ -2563,8 +2566,8 @@ BEGIN
2563
2566
  return r ? [{
2564
2567
  name: n.constraint_name,
2565
2568
  validation: r,
2566
- enabled: !B(n.is_disabled),
2567
- trusted: !B(n.is_not_trusted)
2569
+ enabled: !H(n.is_disabled),
2570
+ trusted: !H(n.is_not_trusted)
2568
2571
  }] : [];
2569
2572
  }).sort((e, t) => e.name.localeCompare(t.name)), _ = yt(g);
2570
2573
  return {
@@ -2572,7 +2575,7 @@ BEGIN
2572
2575
  type: u,
2573
2576
  ...l ? { idStorage: wn(o) } : {},
2574
2577
  nullable: t.is_nullable === "YES",
2575
- ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
2578
+ ...ti(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: ti(t.data_type, t.character_maximum_length) },
2576
2579
  ...o === "decimal" && typeof t.numeric_precision == "number" ? {
2577
2580
  precision: t.numeric_precision,
2578
2581
  ...typeof t.numeric_scale == "number" ? { scale: t.numeric_scale } : {}
@@ -2585,18 +2588,18 @@ BEGIN
2585
2588
  ...h ? { oneOf: h } : {},
2586
2589
  ...g.length > 0 ? { jsonChecks: g } : {},
2587
2590
  ..._ ? { jsonValidation: _ } : {},
2588
- ...Lr(i.get(`${e}.${t.column_name}`)?.definition ?? null, B(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2591
+ ...Lr(i.get(`${e}.${t.column_name}`)?.definition ?? null, H(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
2589
2592
  };
2590
2593
  }), g = [];
2591
2594
  if (o) for (let [t, n] of o) {
2592
2595
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
2593
- if (B(r[0].is_primary)) continue;
2596
+ if (H(r[0].is_primary)) continue;
2594
2597
  let i = r[0].predicate ?? void 0;
2595
- i === void 0 && r.length === 1 && B(r[0].is_unique) || (i !== void 0 || r.length !== 1 || B(r[0].is_unique) || !a.has(r[0].column_name) || t === `${e}_${r[0].column_name}_idx`) && g.push({
2598
+ 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({
2596
2599
  name: t,
2597
2600
  table: e,
2598
2601
  columns: r.map((e) => e.column_name),
2599
- unique: B(r[0].is_unique),
2602
+ unique: H(r[0].is_unique),
2600
2603
  ...i === void 0 ? {} : { where: i }
2601
2604
  });
2602
2605
  }
@@ -2630,72 +2633,72 @@ BEGIN
2630
2633
  "char",
2631
2634
  "character",
2632
2635
  "nchar"
2633
- ]), V = (e, t) => {
2636
+ ]), ti = (e, t) => {
2634
2637
  if (!ei.has(e.toLowerCase())) return;
2635
2638
  let n = Number(t);
2636
2639
  if (!(!Number.isFinite(n) || n <= 0)) return n;
2637
- }, ti = /* @__PURE__ */ new Set([M]), ni = (e) => e.onDialectOrElse({
2640
+ }, ni = /* @__PURE__ */ new Set([j]), ri = (e) => e.onDialectOrElse({
2638
2641
  mysql: () => Kr(e),
2639
2642
  mssql: () => Zr(e),
2640
2643
  sqlite: () => Yr(e),
2641
2644
  orElse: () => Ur(e)
2642
2645
  }).pipe(D.map((e) => ({
2643
2646
  ...e,
2644
- tables: e.tables.filter((e) => !ti.has(e.name))
2645
- }))), ri = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", ii = /* @__PURE__ */ new WeakMap(), H = (e) => D.suspend(() => {
2646
- let t = ii.get(e);
2647
- return t === void 0 ? ai(e).pipe(D.tap((t) => D.sync(() => ii.set(e, t)))) : D.succeed(t);
2648
- }), ai = (e) => e.unsafe("SELECT VERSION() AS v").pipe(D.map((e) => {
2647
+ tables: e.tables.filter((e) => !ni.has(e.name))
2648
+ }))), ii = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", ai = /* @__PURE__ */ new WeakMap(), oi = (e) => D.suspend(() => {
2649
+ let t = ai.get(e);
2650
+ return t === void 0 ? si(e).pipe(D.tap((t) => D.sync(() => ai.set(e, t)))) : D.succeed(t);
2651
+ }), si = (e) => e.unsafe("SELECT VERSION() AS v").pipe(D.map((e) => {
2649
2652
  let t = e[0]?.v;
2650
- return typeof t == "string" ? ri(t) : "mysql";
2651
- }), D.catchAll(() => D.succeed("mysql"))), U = "_voltro_deploys", oi = a(U, {
2652
- id: l({ prefix: "dpl" }),
2653
- status: n(),
2654
- dialect: n(),
2655
- appliedBy: n(),
2656
- startedAt: n(),
2657
- baseline: n(),
2658
- report: n().nullable()
2659
- }), si = (e, t) => e`INSERT INTO ${e(U)} (${e("id")}, ${e("status")}, ${e("dialect")}, ${e("appliedBy")}, ${e("startedAt")}, ${e("baseline")}, ${e("report")})
2660
- VALUES (${t.id}, ${"running"}, ${t.dialect}, ${t.appliedBy}, ${(/* @__PURE__ */ new Date()).toISOString()}, ${t.baseline}, ${null})`.pipe(D.asVoid), ci = (e, t) => e`DELETE FROM ${e(U)} WHERE ${e("id")} = ${t}`.pipe(D.asVoid), li = (e, t, n) => e`UPDATE ${e(U)} SET ${e("status")} = ${"failed"}, ${e("report")} = ${n} WHERE ${e("id")} = ${t}`.pipe(D.asVoid), ui = (e) => e`SELECT ${e("id")}, ${e("status")}, ${e("dialect")}, ${e("appliedBy")}, ${e("startedAt")}, ${e("baseline")}, ${e("report")} FROM ${e(U)}`.pipe(D.map((e) => e.map((e) => ({
2653
+ return typeof t == "string" ? ii(t) : "mysql";
2654
+ }), D.catchAll(() => D.succeed("mysql"))), U = "_voltro_deploys", ci = i(U, {
2655
+ id: c({ prefix: "dpl" }),
2656
+ status: t(),
2657
+ dialect: t(),
2658
+ appliedBy: t(),
2659
+ startedAt: t(),
2660
+ baseline: t(),
2661
+ report: t().nullable()
2662
+ }), li = (e, t) => e`INSERT INTO ${e(U)} (${e("id")}, ${e("status")}, ${e("dialect")}, ${e("appliedBy")}, ${e("startedAt")}, ${e("baseline")}, ${e("report")})
2663
+ VALUES (${t.id}, ${"running"}, ${t.dialect}, ${t.appliedBy}, ${(/* @__PURE__ */ new Date()).toISOString()}, ${t.baseline}, ${null})`.pipe(D.asVoid), ui = (e, t) => e`DELETE FROM ${e(U)} WHERE ${e("id")} = ${t}`.pipe(D.asVoid), di = (e, t, n) => e`UPDATE ${e(U)} SET ${e("status")} = ${"failed"}, ${e("report")} = ${n} WHERE ${e("id")} = ${t}`.pipe(D.asVoid), fi = (e) => e`SELECT ${e("id")}, ${e("status")}, ${e("dialect")}, ${e("appliedBy")}, ${e("startedAt")}, ${e("baseline")}, ${e("report")} FROM ${e(U)}`.pipe(D.map((e) => e.map((e) => ({
2661
2664
  ...e,
2662
2665
  startedAt: String(e.startedAt)
2663
- }))), D.catchAll(() => D.succeed([]))), di = (e) => {
2666
+ }))), D.catchAll(() => D.succeed([]))), pi = (e) => {
2664
2667
  let t = e;
2665
2668
  for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
2666
2669
  let e = t;
2667
2670
  if (typeof e.errno == "number") return e.errno;
2668
2671
  t = e.cause;
2669
2672
  }
2670
- }, fi = (e) => {
2673
+ }, mi = (e) => {
2671
2674
  let t = [], n = e;
2672
2675
  for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
2673
2676
  let e = n;
2674
2677
  typeof e.message == "string" && t.push(e.message), n = e.cause;
2675
2678
  }
2676
2679
  return t.join(" | ");
2677
- }, pi = (e, t) => {
2680
+ }, hi = (e, t) => {
2678
2681
  if (t.length === 0) return !1;
2679
- let n = di(e), r = fi(e);
2682
+ let n = pi(e), r = mi(e);
2680
2683
  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)));
2681
- }, mi = {
2684
+ }, gi = {
2682
2685
  why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
2683
2686
  errno: [1061]
2684
- }, hi = {
2687
+ }, _i = {
2685
2688
  why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
2686
2689
  errno: [1091]
2687
- }, gi = {
2690
+ }, vi = {
2688
2691
  why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
2689
2692
  messageIncludes: ["no such column"]
2690
- }, _i = {
2693
+ }, yi = {
2691
2694
  why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
2692
2695
  errno: [1091, 3940]
2693
- }, vi = (e, t) => D.suspend(() => {
2696
+ }, bi = (e, t) => D.suspend(() => {
2694
2697
  let n;
2695
2698
  return e.withTransaction(t.pipe(D.tapErrorCause((e) => D.sync(() => {
2696
2699
  n = e;
2697
- })))).pipe(D.catchAllCause((e) => D.failCause(n !== void 0 && !fe.equals(n, e) ? de.sequential(n, e) : e)));
2698
- }), yi = (e, t, n) => {
2700
+ })))).pipe(D.catchAllCause((e) => D.failCause(n !== void 0 && !de.equals(n, e) ? ue.sequential(n, e) : e)));
2701
+ }), xi = (e, t, r) => {
2699
2702
  let i = e.match(/'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|\s+|[^'\[\s]+/g) ?? [];
2700
2703
  if (i.join("") !== e || i.some((e) => !e.startsWith("'") && !e.startsWith("[") && /"|\/\*|--/.test(e))) throw Error("Cannot safely rename CHECK: unsupported catalog SQL; use an explicit migration");
2701
2704
  let a = i.map((e, t) => ({
@@ -2704,31 +2707,31 @@ BEGIN
2704
2707
  })).filter((e) => e.value.trim() !== ""), o = 0;
2705
2708
  for (let e = 0; e < a.length; e++) {
2706
2709
  let s = a[e];
2707
- if (s.value !== r(t, "mssql")) continue;
2710
+ if (s.value !== n(t, "mssql")) continue;
2708
2711
  let c = a[e - 1]?.value ?? "", l = a[e + 1]?.value ?? "";
2709
2712
  if (c.endsWith(".") || l.startsWith(".") || l.startsWith("(")) throw Error(`Cannot safely rename CHECK reference '${t}': qualified or callable identifier; use an explicit migration`);
2710
- i[s.index] = r(n, "mssql"), o++;
2713
+ i[s.index] = n(r, "mssql"), o++;
2711
2714
  }
2712
2715
  if (o === 0 || i.join("").length === 0) throw Error(`Cannot safely rename CHECK reference '${t}': no exact catalog column token; use an explicit migration`);
2713
2716
  return i.join("");
2714
2717
  }, W = (e, t) => e.onDialectOrElse({
2715
2718
  mysql: () => D.succeed(t.replace("T", " ").replace("Z", "")),
2716
2719
  orElse: () => D.succeed(t)
2717
- }), bi = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, xi = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), Si = (e, t) => {
2718
- if ((e.type !== "text" || e.maxLength === void 0) && !xi(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2720
+ }), Si = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Ci = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), wi = (e, t) => {
2721
+ if ((e.type !== "text" || e.maxLength === void 0) && !Ci(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
2719
2722
  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;
2720
2723
  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.`);
2721
- return P(e, t);
2722
- }, Ci = (e) => {
2723
- let t = Si(e, "postgres");
2724
- return t === void 0 ? wi(e) : t;
2725
- }, wi = (e) => {
2724
+ return N(e, t);
2725
+ }, Ti = (e) => {
2726
+ let t = wi(e, "postgres");
2727
+ return t === void 0 ? Ei(e) : t;
2728
+ }, Ei = (e) => {
2726
2729
  switch (e.type) {
2727
2730
  case "id": return "text";
2728
2731
  case "text": return "text";
2729
2732
  case "integer": return "integer";
2730
2733
  case "real": return "double precision";
2731
- case "decimal": return bi(e, "NUMERIC");
2734
+ case "decimal": return Si(e, "NUMERIC");
2732
2735
  case "bigint": return "bigint";
2733
2736
  case "boolean": return "boolean";
2734
2737
  case "timestamp": return "timestamptz";
@@ -2742,15 +2745,15 @@ BEGIN
2742
2745
  case "interval": return "interval";
2743
2746
  case "raw": return e.rawDdl ?? "text";
2744
2747
  }
2745
- }, Ti = (e) => {
2746
- let t = Si(e, "mariadb");
2748
+ }, Di = (e) => {
2749
+ let t = wi(e, "mariadb");
2747
2750
  if (t !== void 0) return t;
2748
2751
  switch (e.type) {
2749
2752
  case "id": return "VARCHAR(64)";
2750
2753
  case "text": return "LONGTEXT";
2751
2754
  case "integer": return "INT";
2752
2755
  case "real": return "DOUBLE";
2753
- case "decimal": return bi(e, "DECIMAL");
2756
+ case "decimal": return Si(e, "DECIMAL");
2754
2757
  case "bigint": return "BIGINT";
2755
2758
  case "boolean": return "TINYINT(1)";
2756
2759
  case "timestamp": return "DATETIME(6)";
@@ -2764,38 +2767,38 @@ BEGIN
2764
2767
  case "interval": return "BIGINT";
2765
2768
  case "raw": return e.rawDdl ?? "LONGTEXT";
2766
2769
  }
2767
- }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, Ei = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", Di = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Oi = (e, t = "mariadb") => `ALTER TABLE ${K(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${K(e.column)}, ALGORITHM=COPY;`, ki = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Ai = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${ca(t)}`)};`, ji = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Ni(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Mi = (e, t) => {
2770
+ }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, Oi = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", ki = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Ai = (e, t = "mariadb") => `ALTER TABLE ${K(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${K(e.column)}, ALGORITHM=COPY;`, ji = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Mi = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${ua(t)}`)};`, Ni = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Fi(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Pi = (e, t) => {
2768
2771
  let { defaultFactory: n, ...r } = e;
2769
- return P(e, t) !== P({
2772
+ return N(e, t) !== N({
2770
2773
  ...r,
2771
2774
  hasDefault: !1
2772
2775
  }, t);
2773
- }, Ni = (e, t) => {
2776
+ }, Fi = (e, t) => {
2774
2777
  let n = t(e.defaultValue);
2775
2778
  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.`);
2776
2779
  return n;
2777
- }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Pi = (e, t, n) => {
2780
+ }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Ii = (e, t, n) => {
2778
2781
  let r = q(e, t, n);
2779
2782
  return r ? qn(n, r) : void 0;
2780
- }, Fi = (e, t, n) => {
2781
- let r = n ?? e.nullable, i = Dt(e, "mariadb");
2783
+ }, Li = (e, t, n) => {
2784
+ let r = n ?? e.nullable, i = At(e, "mariadb");
2782
2785
  return [
2783
2786
  K(t),
2784
- P(e, "mariadb"),
2787
+ N(e, "mariadb"),
2785
2788
  r ? null : "NOT NULL",
2786
2789
  i
2787
2790
  ].filter(Boolean).join(" ");
2788
- }, Ii = (e, t) => e == null ? null : Array.isArray(e) ? Li(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" ? kt(e, "mariadb") : null, Li = (e, t, n) => Ot(e, t ?? { type: "json" }, n), Ri = (e, t) => e == null ? null : Array.isArray(e) ? Li(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" ? kt(e, "postgres") : null, zi = (e, t) => {
2791
+ }, Ri = (e, t) => e == null ? null : Array.isArray(e) ? zi(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, zi = (e, t, n) => jt(e, t ?? { type: "json" }, n), Bi = (e, t) => e == null ? null : Array.isArray(e) ? zi(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, Vi = (e, t) => {
2789
2792
  if (!e.generatedAs) return null;
2790
2793
  let { expr: n, stored: r } = e.generatedAs;
2791
2794
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
2792
- }, Bi = (e, t = !1) => {
2793
- if (e.type === "id" && e.idScheme?.kind === "numeric") return At(e.name, "postgres");
2794
- let n = zi(e, "postgres");
2795
- if (n) return `${G(e.name)} ${Ci(e)} ${n}`;
2796
- let r = [G(e.name), Ci(e)];
2795
+ }, Hi = (e, t = !1) => {
2796
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "postgres");
2797
+ let n = Vi(e, "postgres");
2798
+ if (n) return `${G(e.name)} ${Ti(e)} ${n}`;
2799
+ let r = [G(e.name), Ti(e)];
2797
2800
  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) {
2798
- let t = Ri(e.defaultValue, e);
2801
+ let t = Bi(e.defaultValue, e);
2799
2802
  t && r.push(t);
2800
2803
  }
2801
2804
  return e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
@@ -2804,28 +2807,28 @@ BEGIN
2804
2807
  setNull: "SET NULL",
2805
2808
  noAction: "NO ACTION"
2806
2809
  }[e.references.onDelete]}`)), r.join(" ");
2807
- }, Vi = (e) => (e.primaryKey?.length ?? 0) > 0, Hi = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Ui = (e) => {
2808
- let t = e.columns.map((t) => ` ${Bi(t, Vi(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${Hi(e, G)}\n)`];
2809
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(ha({
2810
+ }, Ui = (e) => (e.primaryKey?.length ?? 0) > 0, Wi = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Gi = (e) => {
2811
+ let t = e.columns.map((t) => ` ${Hi(t, Ui(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${Wi(e, G)}\n)`];
2812
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(_a({
2810
2813
  kind: "add-index",
2811
2814
  table: e.table,
2812
2815
  index: t
2813
2816
  }, !1));
2814
2817
  return n;
2815
- }, Wi = 191, Gi = (e) => {
2816
- let t = Ti(e).toUpperCase();
2818
+ }, Ki = 191, qi = (e) => {
2819
+ let t = Di(e).toUpperCase();
2817
2820
  return t.endsWith("TEXT") || t.endsWith("BLOB");
2818
- }, Ki = (e, t = !1) => {
2819
- if (e.type === "id" && e.idScheme?.kind === "numeric") return At(e.name, "mariadb");
2820
- let n = zi(e, "mariadb");
2821
- if (n) return `${K(e.name)} ${Ti(e)} ${n}`;
2822
- let r = [K(e.name), Ti(e)];
2823
- if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && !Gi(e) && r.push("UNIQUE"), e.hasDefault) {
2824
- let t = Ii(e.defaultValue, e);
2821
+ }, Ji = (e, t = !1) => {
2822
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "mariadb");
2823
+ let n = Vi(e, "mariadb");
2824
+ if (n) return `${K(e.name)} ${Di(e)} ${n}`;
2825
+ let r = [K(e.name), Di(e)];
2826
+ if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && !qi(e) && r.push("UNIQUE"), e.hasDefault) {
2827
+ let t = Ri(e.defaultValue, e);
2825
2828
  t && r.push(t);
2826
2829
  }
2827
2830
  return r.join(" ");
2828
- }, qi = (e) => e.columns.flatMap((t) => {
2831
+ }, Yi = (e) => e.columns.flatMap((t) => {
2829
2832
  if (!t.references) return [];
2830
2833
  let n = t.references.onDelete ? ` ON DELETE ${{
2831
2834
  cascade: "CASCADE",
@@ -2834,27 +2837,27 @@ BEGIN
2834
2837
  noAction: "NO ACTION"
2835
2838
  }[t.references.onDelete]}` : "";
2836
2839
  return [` CONSTRAINT ${K(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${K(t.name)}) REFERENCES ${K(t.references.table)} (${K(t.references.column)})${n}`];
2837
- }), Ji = (e, t = "mariadb") => {
2838
- for (let n of e.indexes) _a(n, t);
2840
+ }), Xi = (e, t = "mariadb") => {
2841
+ for (let n of e.indexes) ya(n, t);
2839
2842
  let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
2840
- let t = da(n.get(e));
2843
+ let t = pa(n.get(e));
2841
2844
  return t === void 0 ? K(e) : `${K(e)}(${t})`;
2842
- }, i = e.columns.map((t) => ` ${Ki(t, Vi(e))}`).join(",\n"), a = qi(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${o}${Hi(e, r)}\n)`];
2843
- for (let n of e.columns) n.unique && n.type !== "id" && Gi(n) && s.push(`CREATE UNIQUE INDEX ${Ei(t)}${K(`${e.table}_${n.name}_key`)} ON ${K(e.table)} (${r(n.name)})`);
2844
- for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Ei(t)}${K(n.name)} ON ${K(e.table)} (${n.columns.map(r).join(", ")})`);
2845
+ }, i = e.columns.map((t) => ` ${Ji(t, Ui(e))}`).join(",\n"), a = Yi(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${o}${Wi(e, r)}\n)`];
2846
+ for (let n of e.columns) n.unique && n.type !== "id" && qi(n) && s.push(`CREATE UNIQUE INDEX ${Oi(t)}${K(`${e.table}_${n.name}_key`)} ON ${K(e.table)} (${r(n.name)})`);
2847
+ for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Oi(t)}${K(n.name)} ON ${K(e.table)} (${n.columns.map(r).join(", ")})`);
2845
2848
  return s;
2846
- }, Yi = {
2849
+ }, Zi = {
2847
2850
  cascade: "CASCADE",
2848
2851
  restrict: "RESTRICT",
2849
2852
  setNull: "SET NULL",
2850
2853
  noAction: "NO ACTION"
2851
- }, Xi = {
2854
+ }, Qi = {
2852
2855
  cascade: "CASCADE",
2853
2856
  restrict: "NO ACTION",
2854
2857
  setNull: "SET NULL",
2855
2858
  noAction: "NO ACTION"
2856
- }, Zi = (e) => {
2857
- let t = Si(e, "sqlite");
2859
+ }, $i = (e) => {
2860
+ let t = wi(e, "sqlite");
2858
2861
  if (t !== void 0) return t;
2859
2862
  switch (e.type) {
2860
2863
  case "integer":
@@ -2866,30 +2869,30 @@ BEGIN
2866
2869
  case "bytes": return "BLOB";
2867
2870
  default: return "TEXT";
2868
2871
  }
2869
- }, Qi = (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" ? kt(e, "sqlite") : null, $i = (e, t = !1) => {
2870
- if (e.type === "id" && e.idScheme?.kind === "numeric") return At(e.name, "sqlite");
2871
- let n = zi(e, "sqlite");
2872
- if (n) return `${G(e.name)} ${Zi(e)} ${n}`;
2873
- let r = [G(e.name), Zi(e)];
2872
+ }, ea = (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, ta = (e, t = !1) => {
2873
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "sqlite");
2874
+ let n = Vi(e, "sqlite");
2875
+ if (n) return `${G(e.name)} ${$i(e)} ${n}`;
2876
+ let r = [G(e.name), $i(e)];
2874
2877
  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) {
2875
- let t = Qi(e.defaultValue, "CURRENT_TIMESTAMP");
2878
+ let t = ea(e.defaultValue, "CURRENT_TIMESTAMP");
2876
2879
  t && r.push(t);
2877
2880
  }
2878
- if (e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${Yi[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2881
+ if (e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${Zi[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
2879
2882
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2880
2883
  r.push(`CHECK (${G(e.name)} IN (${t}))`);
2881
2884
  }
2882
2885
  return r.join(" ");
2883
- }, ea = (e) => {
2884
- let t = e.columns.map((t) => ` ${$i(t, Vi(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${Hi(e, G)}\n)`];
2885
- 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(", ")})${ma(t)}`);
2886
+ }, na = (e) => {
2887
+ let t = e.columns.map((t) => ` ${ta(t, Ui(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${Wi(e, G)}\n)`];
2888
+ 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(", ")})${ga(t)}`);
2886
2889
  return n;
2887
- }, ta = (e, t) => {
2890
+ }, ra = (e, t) => {
2888
2891
  let n = t.find((t) => t.tableName === e);
2889
- return n ? na(L([n], "sqlite").tables[0]) : [];
2890
- }, na = (e) => {
2892
+ return n ? ia(z([n], "sqlite").tables[0]) : [];
2893
+ }, ia = (e) => {
2891
2894
  let t = e.name, n = `${t}__voltro_rebuild`, r = e.columns.map((e) => G(e.name)).join(", "), i = [
2892
- ...ea({
2895
+ ...na({
2893
2896
  kind: "create-table",
2894
2897
  table: n,
2895
2898
  columns: e.columns,
@@ -2900,27 +2903,27 @@ BEGIN
2900
2903
  `DROP TABLE ${G(t)}`,
2901
2904
  `ALTER TABLE ${G(n)} RENAME TO ${G(t)}`
2902
2905
  ];
2903
- for (let n of e.indexes) n.name !== `${t}_pkey` && i.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(n.name)} ON ${G(t)} (${n.columns.map(G).join(", ")})${ma(n)}`);
2906
+ for (let n of e.indexes) n.name !== `${t}_pkey` && i.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(n.name)} ON ${G(t)} (${n.columns.map(G).join(", ")})${ga(n)}`);
2904
2907
  return i;
2905
- }, ra = (e, t, n, r) => {
2908
+ }, aa = (e, t, n, r) => {
2906
2909
  let i = r ?? e.nullable;
2907
- return `ALTER TABLE ${J(n)} ALTER COLUMN ${J(t)} ${P(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2908
- }, ia = (e, t) => {
2910
+ return `ALTER TABLE ${J(n)} ALTER COLUMN ${J(t)} ${N(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
2911
+ }, oa = (e, t) => {
2909
2912
  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}` : "");
2910
2913
  if (!e.hasDefault) return n;
2911
- let r = Qi(e.defaultValue, "SYSUTCDATETIME()");
2914
+ let r = ea(e.defaultValue, "SYSUTCDATETIME()");
2912
2915
  if (!r) return n;
2913
2916
  let i = r.replace(/^DEFAULT\s+/i, "");
2914
2917
  return `${n} ALTER TABLE ${J(e.table)} ADD DEFAULT ${i} FOR ${J(e.column)};`;
2915
- }, J = (e) => `[${e.replace(/]/g, "]]")}]`, aa = (e) => {
2916
- let t = Si(e, "mssql");
2918
+ }, J = (e) => `[${e.replace(/]/g, "]]")}]`, sa = (e) => {
2919
+ let t = wi(e, "mssql");
2917
2920
  if (t !== void 0) return t;
2918
2921
  switch (e.type) {
2919
2922
  case "id": return "NVARCHAR(64)";
2920
2923
  case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
2921
2924
  case "integer": return "INT";
2922
2925
  case "real": return "FLOAT";
2923
- case "decimal": return bi(e, "DECIMAL");
2926
+ case "decimal": return Si(e, "DECIMAL");
2924
2927
  case "bigint": return "BIGINT";
2925
2928
  case "boolean": return "BIT";
2926
2929
  case "timestamp": return "DATETIME2(6)";
@@ -2928,53 +2931,53 @@ BEGIN
2928
2931
  case "bytes": return "VARBINARY(MAX)";
2929
2932
  default: return "NVARCHAR(MAX)";
2930
2933
  }
2931
- }, oa = (e, t, n = !1) => {
2932
- if (e.type === "id" && e.idScheme?.kind === "numeric") return At(e.name, "mssql");
2933
- let r = e.type === "text" && t?.has(e.name) ? `NVARCHAR(${Math.min(e.maxLength ?? 450, 450)})` : aa(e), i = zi(e, "mssql");
2934
+ }, ca = (e, t, n = !1) => {
2935
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "mssql");
2936
+ let r = e.type === "text" && t?.has(e.name) ? `NVARCHAR(${Math.min(e.maxLength ?? 450, 450)})` : sa(e), i = Vi(e, "mssql");
2934
2937
  if (i) return `${J(e.name)} ${i}`;
2935
2938
  let a = [J(e.name), r];
2936
2939
  if (e.type === "json" && a.push(`CHECK ${gt(J(e.name))}`), e.type === "array" && a.push(`CHECK (${J(e.name)} IS NULL OR ISJSON(${J(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) {
2937
- let t = Qi(e.defaultValue, "SYSUTCDATETIME()");
2940
+ let t = ea(e.defaultValue, "SYSUTCDATETIME()");
2938
2941
  t && a.push(t);
2939
2942
  }
2940
- return e.references && (a.push(`REFERENCES ${J(e.references.table)} (${J(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${Xi[e.references.onDelete]}`)), a.join(" ");
2941
- }, sa = (e) => {
2942
- 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) => ` ${oa(t, n, Vi(e))}`).join(",\n"), i = `CREATE TABLE ${J(e.table)} (\n${r}${Hi(e, J)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2943
+ return e.references && (a.push(`REFERENCES ${J(e.references.table)} (${J(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${Qi[e.references.onDelete]}`)), a.join(" ");
2944
+ }, la = (e) => {
2945
+ 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) => ` ${ca(t, n, Ui(e))}`).join(",\n"), i = `CREATE TABLE ${J(e.table)} (\n${r}${Wi(e, J)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2943
2946
  for (let n of e.indexes) {
2944
2947
  if (n.name === `${e.table}_pkey`) continue;
2945
- let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${J(n.name)} ON ${J(e.table)} (${n.columns.map(J).join(", ")})${ma(n)}`;
2948
+ let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${J(n.name)} ON ${J(e.table)} (${n.columns.map(J).join(", ")})${ga(n)}`;
2946
2949
  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)}')`);
2947
2950
  }
2948
2951
  return a;
2949
- }, ca = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, la = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, ua = (e, t, n) => {
2950
- let r = `${e.table}${ca(t)}`;
2952
+ }, ua = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, da = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, fa = (e, t, n) => {
2953
+ let r = `${e.table}${ua(t)}`;
2951
2954
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2952
- }, da = (e) => {
2953
- if (e === void 0 || !Gi(e)) return;
2955
+ }, pa = (e) => {
2956
+ if (e === void 0 || !qi(e)) return;
2954
2957
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
2955
- return t === void 0 ? Wi : Math.min(Wi, t);
2956
- }, fa = (e, t, n) => {
2957
- let r = da(Pi(e, t, n));
2958
+ return t === void 0 ? Ki : Math.min(Ki, t);
2959
+ }, ma = (e, t, n) => {
2960
+ let r = pa(Ii(e, t, n));
2958
2961
  return r === void 0 ? K(n) : `${K(n)}(${r})`;
2959
- }, pa = (e) => e.startsWith("(") ? e : G(e), ma = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, ha = (e, t) => {
2960
- let n = we(e.index.kind, e.index.kindOptions), r = e.index.columns.map(pa);
2962
+ }, ha = (e) => e.startsWith("(") ? e : G(e), ga = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, _a = (e, t) => {
2963
+ let n = Ce(e.index.kind, e.index.kindOptions), r = e.index.columns.map(ha);
2961
2964
  if (n.opclass !== void 0) {
2962
2965
  if (r.length !== 1) throw Error("HNSW index requires exactly one column");
2963
2966
  r[0] = `${r[0]} ${n.opclass}`;
2964
2967
  }
2965
- 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}${ma(e.index)};`;
2966
- }, ga = (e, t, n = "mariadb") => (_a(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Ei(n)}${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => fa(t, e.table, n)).join(", ")});`), _a = (e, t) => {
2968
+ 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}${ga(e.index)};`;
2969
+ }, va = (e, t, n = "mariadb") => (ya(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Oi(n)}${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => ma(t, e.table, n)).join(", ")});`), ya = (e, t) => {
2967
2970
  if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
2968
- }, va = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, ya = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, ba = (e) => `DROP INDEX IF EXISTS ${J(e.index)} ON ${J(e.table)};`, xa = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Sa = (e) => {
2971
+ }, ba = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, xa = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Sa = (e) => `DROP INDEX IF EXISTS ${J(e.index)} ON ${J(e.table)};`, Ca = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, wa = (e) => {
2969
2972
  let t = (e) => e.replace(/'/g, "''");
2970
2973
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
2971
- }, Ca = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, wa = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, Ta = (e) => {
2974
+ }, Ta = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, Ea = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, Da = (e) => {
2972
2975
  let t = (e) => e.replace(/'/g, "''");
2973
2976
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
2974
- }, Ea = (e) => {
2975
- 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(", ")})${ma(e.index)}`;
2977
+ }, Oa = (e) => {
2978
+ 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(", ")})${ga(e.index)}`;
2976
2979
  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)}');`;
2977
- }, Da = (e, t, n) => {
2980
+ }, ka = (e, t, n) => {
2978
2981
  let r = n.find((t) => t.tableName === e);
2979
2982
  if (!r) return [];
2980
2983
  let i = [];
@@ -2986,13 +2989,13 @@ BEGIN
2986
2989
  }
2987
2990
  }
2988
2991
  return i;
2989
- }, Oa = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, ka = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${fa(t, e.table, e.column)});`, Aa = (e) => {
2992
+ }, Aa = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, ja = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${ma(t, e.table, e.column)});`, Ma = (e) => {
2990
2993
  let t = e.fields.map((e) => G(e)).join(", ");
2991
2994
  return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
2992
- }, ja = (e, t) => {
2993
- let n = e.fields.map((n) => fa(t, e.table, n)).join(", ");
2995
+ }, Na = (e, t) => {
2996
+ let n = e.fields.map((n) => ma(t, e.table, n)).join(", ");
2994
2997
  return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
2995
- }, Ma = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Na = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Pa = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Fa = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, Ia = (e, t, n = Yi) => {
2998
+ }, Pa = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Fa = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Ia = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, La = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, Ra = (e, t, n = Zi) => {
2996
2999
  let r = [], i = t(e.table), a = t(e.column), o = t(e.targetTable), s = t(e.targetColumn);
2997
3000
  if (e.orphanPolicy) {
2998
3001
  let t = `${a} IS NOT NULL AND ${a} NOT IN (SELECT ${s} FROM ${o})`;
@@ -3005,10 +3008,10 @@ BEGIN
3005
3008
  `REFERENCES ${o} (${s})`
3006
3009
  ];
3007
3010
  return e.onDelete && c.push(`ON DELETE ${n[e.onDelete]}`), r.push(c.join(" ") + ";"), r;
3008
- }, La = (e) => e.name ?? `${e.table}_${e.column}_fkey`, Ra = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(La(e))};`, za = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(La(e))};`, Ba = (e, t) => {
3011
+ }, za = (e) => e.name ?? `${e.table}_${e.column}_fkey`, Ba = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(za(e))};`, Va = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(za(e))};`, Ha = (e, t) => {
3009
3012
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
3010
3013
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
3011
- }, Va = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, Ha = (e, t) => D.gen(function* () {
3014
+ }, Ua = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, Wa = (e, t) => D.gen(function* () {
3012
3015
  let n = yield* e`
3013
3016
  SELECT cc.constraint_name AS n, cc.check_clause AS c
3014
3017
  FROM information_schema.check_constraints cc
@@ -3023,16 +3026,16 @@ BEGIN
3023
3026
  let n = String(e.n ?? "");
3024
3027
  if (n !== "" && Nr(String(e.c ?? ""))?.column === t.column) return n;
3025
3028
  }
3026
- }), Ua = (e, t, n) => D.gen(function* () {
3027
- let r = yield* Ha(e, t);
3028
- r !== void 0 && (yield* Y(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [_i]));
3029
- let i = yield* Ha(e, t);
3029
+ }), Ga = (e, t, n) => D.gen(function* () {
3030
+ let r = yield* Wa(e, t);
3031
+ r !== void 0 && (yield* Y(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [yi]));
3032
+ let i = yield* Wa(e, t);
3030
3033
  if (i === void 0) return;
3031
3034
  let a = q(n, t.table, t.column);
3032
3035
  if (!a) return yield* D.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.`));
3033
- yield* Y(e, `ALTER TABLE ${K(t.table)} MODIFY COLUMN ${Fi(a, t.column)};`, t.kind);
3034
- }), Wa = (e, t, n, r) => {
3035
- let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? J : G, s = a ? Ti(i) : r === "mssql" ? aa(i) : r === "sqlite" ? Zi(i) : Ci(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${gt(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? Ii(e, i) : r === "mssql" ? Qi(e, "SYSUTCDATETIME()") : r === "sqlite" ? Qi(e, "CURRENT_TIMESTAMP") : Ri(e, i), d = zi(i, r);
3036
+ yield* Y(e, `ALTER TABLE ${K(t.table)} MODIFY COLUMN ${Li(a, t.column)};`, t.kind);
3037
+ }), Ka = (e, t, n, r) => {
3038
+ let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? J : G, s = a ? Di(i) : r === "mssql" ? sa(i) : r === "sqlite" ? $i(i) : Ti(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${gt(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? Ri(e, i) : r === "mssql" ? ea(e, "SYSUTCDATETIME()") : r === "sqlite" ? ea(e, "CURRENT_TIMESTAMP") : Bi(e, i), d = Vi(i, r);
3036
3039
  if (d) {
3037
3040
  let t = r === "mssql" ? `${o(i.name)} ${d}` : `${o(i.name)} ${s} ${d}`;
3038
3041
  return {
@@ -3052,15 +3055,16 @@ BEGIN
3052
3055
  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.`);
3053
3056
  return {
3054
3057
  pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t}${l};`],
3055
- post: []
3058
+ post: [],
3059
+ ...i.unique && i.type !== "id" ? { uniquePending: !0 } : {}
3056
3060
  };
3057
3061
  }
3058
3062
  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 = {
3059
3063
  pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s}${l};`],
3060
3064
  post: p ? [p] : []
3061
3065
  };
3062
- 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;
3063
- }, Ga = /* @__PURE__ */ new Set([
3066
+ return i.unique && i.type !== "id" && (m.uniquePending = !0), 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;
3067
+ }, qa = /* @__PURE__ */ new Set([
3064
3068
  "drop-index",
3065
3069
  "drop-check",
3066
3070
  "drop-unique",
@@ -3068,7 +3072,7 @@ BEGIN
3068
3072
  "drop-foreign-key",
3069
3073
  "drop-column",
3070
3074
  "drop-table"
3071
- ]), Ka = (e) => {
3075
+ ]), Ja = (e) => {
3072
3076
  let t = new Map(e.map((e) => [e.tableName, e]));
3073
3077
  return (e, n) => {
3074
3078
  let r = t.get(e);
@@ -3088,15 +3092,15 @@ BEGIN
3088
3092
  ...o
3089
3093
  };
3090
3094
  };
3091
- }, Y = (e, t, n, r = []) => e.unsafe(t).pipe(D.catchIf((e) => pi(e, r), () => D.void), D.tapError((e) => D.sync(() => {
3092
- process.stderr.write(Te(`applier: statement failed (op=${n})`, t, e, 400));
3095
+ }, Y = (e, t, n, r = []) => e.unsafe(t).pipe(D.catchIf((e) => hi(e, r), () => D.void), D.tapError((e) => D.sync(() => {
3096
+ process.stderr.write(we(`applier: statement failed (op=${n})`, t, e, 400));
3093
3097
  })), D.mapError((e) => {
3094
- let r = Te(`applier: statement failed (op=${n})`, t, e, 400).trim();
3098
+ let r = we(`applier: statement failed (op=${n})`, t, e, 400).trim();
3095
3099
  return Object.assign(e, { message: r });
3096
- }), D.map(() => void 0)), X = (e, t, n, r) => qa(e, t, ta(t, n), r), qa = (e, t, n, r) => {
3100
+ }), D.map(() => void 0)), X = (e, t, n, r) => Ya(e, t, ra(t, n), r), Ya = (e, t, n, r) => {
3097
3101
  if (n.length === 0) return D.void;
3098
3102
  let i = (e) => (n) => {
3099
- let i = Te(`applier: statement failed (op=${r}, sqlite rebuild of ${t})`, e, n, 400).trim();
3103
+ let i = we(`applier: statement failed (op=${r}, sqlite rebuild of ${t})`, e, n, 400).trim();
3100
3104
  return process.stderr.write(`${i}\n`), Object.assign(n, { message: i });
3101
3105
  };
3102
3106
  return D.scoped(D.gen(function* () {
@@ -3110,8 +3114,8 @@ BEGIN
3110
3114
  }
3111
3115
  }), D.ignore(a("PRAGMA foreign_keys = ON")));
3112
3116
  }));
3113
- }, Ja = (e, t) => D.gen(function* () {
3114
- let n = (yield* e`
3117
+ }, Xa = (e, t) => D.gen(function* () {
3118
+ let r = (yield* e`
3115
3119
  SELECT ck.name, ck.definition, ck.is_disabled AS disabled,
3116
3120
  ck.is_not_trusted AS untrusted, ck.is_not_for_replication AS notForReplication
3117
3121
  FROM sys.check_constraints ck
@@ -3122,18 +3126,18 @@ BEGIN
3122
3126
  ) ORDER BY ck.name
3123
3127
  `).map((e) => ({
3124
3128
  ...e,
3125
- definition: yi(e.definition, t.from, t.to)
3126
- })), i = (e) => r(e, "mssql"), a = (e) => e.replace(/'/g, "''");
3129
+ definition: xi(e.definition, t.from, t.to)
3130
+ })), i = (e) => n(e, "mssql"), a = (e) => e.replace(/'/g, "''");
3127
3131
  return yield* Z(e, [
3128
- ...n.map((e) => `ALTER TABLE ${i(t.table)} DROP CONSTRAINT ${i(e.name)}`),
3132
+ ...r.map((e) => `ALTER TABLE ${i(t.table)} DROP CONSTRAINT ${i(e.name)}`),
3129
3133
  `EXEC sp_rename N'${a(`${i(t.table)}.${i(t.from)}`)}', N'${a(t.to)}', 'COLUMN';`,
3130
- ...n.flatMap((e) => [`ALTER TABLE ${i(t.table)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${i(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${i(t.table)} NOCHECK CONSTRAINT ${i(e.name)}`] : []])
3134
+ ...r.flatMap((e) => [`ALTER TABLE ${i(t.table)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${i(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${i(t.table)} NOCHECK CONSTRAINT ${i(e.name)}`] : []])
3131
3135
  ], t.kind);
3132
- }), Ya = (e, t, n) => e == null ? e : t.type === "json" ? JSON.stringify(e) : (t.type === "array" || t.type === "vector") && n !== "postgres" ? typeof e == "string" ? e : JSON.stringify(e) : e, Z = (e, t, n) => D.forEach(t, (t) => Y(e, t, n), { discard: !0 }), Xa = (e, t) => {
3136
+ }), Za = (e, t, n) => e == null ? e : t.type === "json" ? JSON.stringify(e) : (t.type === "array" || t.type === "vector") && n !== "postgres" ? typeof e == "string" ? e : JSON.stringify(e) : e, Z = (e, t, n) => D.forEach(t, (t) => Y(e, t, n), { discard: !0 }), Qa = (e, t) => {
3133
3137
  let n = Math.max(1, Math.floor(Number.isFinite(t) ? t : 1));
3134
- return e.literal(j(e) === "mssql" ? `OFFSET 0 ROWS FETCH NEXT ${n} ROWS ONLY` : `LIMIT ${n}`);
3135
- }, Za = (e, t, n, i) => e.unsafe(`SELECT ${i === void 0 ? "*" : r(i, t)} FROM ${r(n, t)} WHERE 1=0`).pipe(D.as(!0), D.catchAll(() => D.succeed(!1))), Qa = (e, t) => eo(e, t, at, M), $a = (e, t) => eo(e, t, oi, U), eo = (e, t, n, r) => D.gen(function* () {
3136
- let i = L([n], t).tables[0];
3138
+ return e.literal(A(e) === "mssql" ? `OFFSET 0 ROWS FETCH NEXT ${n} ROWS ONLY` : `LIMIT ${n}`);
3139
+ }, $a = (e, t, r, i) => e.unsafe(`SELECT ${i === void 0 ? "*" : n(i, t)} FROM ${n(r, t)} WHERE 1=0`).pipe(D.as(!0), D.catchAll(() => D.succeed(!1))), eo = (e, t) => no(e, t, at, j), to = (e, t) => no(e, t, ci, U), no = (e, t, n, r) => D.gen(function* () {
3140
+ let i = z([n], t).tables[0];
3137
3141
  if (!i) return yield* D.die(/* @__PURE__ */ Error(`migration applier: the ${r} table descriptor produced no snapshot. This is a framework bug.`));
3138
3142
  let a = {
3139
3143
  kind: "create-table",
@@ -3141,20 +3145,20 @@ BEGIN
3141
3145
  columns: i.columns,
3142
3146
  indexes: []
3143
3147
  }, o = yield* e.onDialectOrElse({
3144
- mysql: () => H(e).pipe(D.map((e) => Ji(a, e))),
3145
- mssql: () => D.succeed(sa(a)),
3146
- sqlite: () => D.succeed(ea(a)),
3147
- orElse: () => D.succeed(Ui(a))
3148
+ mysql: () => oi(e).pipe(D.map((e) => Xi(a, e))),
3149
+ mssql: () => D.succeed(la(a)),
3150
+ sqlite: () => D.succeed(na(a)),
3151
+ orElse: () => D.succeed(Gi(a))
3148
3152
  });
3149
3153
  yield* D.forEach(o, (t) => Y(e, t, "resume-ledger-bootstrap"), { discard: !0 });
3150
- }), to = (e) => e`
3154
+ }), ro = (e) => e`
3151
3155
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
3152
3156
  ${e("status")}, ${e("payload")}
3153
- FROM ${e(M)}
3154
- `, no = (e, t, n, r) => D.gen(function* () {
3157
+ FROM ${e(j)}
3158
+ `, io = (e, t, n, r) => D.gen(function* () {
3155
3159
  let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
3156
3160
  yield* D.forEach(r, ({ index: r, planned: a }) => e`
3157
- INSERT INTO ${e(M)}
3161
+ INSERT INTO ${e(j)}
3158
3162
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
3159
3163
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
3160
3164
  ${e("createdAt")})
@@ -3163,11 +3167,11 @@ BEGIN
3163
3167
  ${a.op.kind}, ${st(a.op)}, ${"pending"},
3164
3168
  ${JSON.stringify(a)}, ${i})
3165
3169
  `, { discard: !0 });
3166
- }), ro = (e, t, n, r, i) => D.gen(function* () {
3170
+ }), ao = (e, t, n, r, i) => D.gen(function* () {
3167
3171
  let a = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
3168
3172
  if (r === "applied") {
3169
3173
  yield* e`
3170
- UPDATE ${e(M)}
3174
+ UPDATE ${e(j)}
3171
3175
  SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
3172
3176
  ${e("durationMs")} = ${i ?? null}
3173
3177
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
@@ -3175,50 +3179,50 @@ BEGIN
3175
3179
  return;
3176
3180
  }
3177
3181
  yield* e`
3178
- UPDATE ${e(M)}
3182
+ UPDATE ${e(j)}
3179
3183
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
3180
3184
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
3181
3185
  `;
3182
- }), io = (e, t, n, r) => D.gen(function* () {
3186
+ }), oo = (e, t, n, r) => D.gen(function* () {
3183
3187
  let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
3184
3188
  r.length > 0 && (yield* e`
3185
- UPDATE ${e(M)}
3189
+ UPDATE ${e(j)}
3186
3190
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
3187
3191
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
3188
3192
  `), n.length > 0 && (yield* e`
3189
- UPDATE ${e(M)}
3193
+ UPDATE ${e(j)}
3190
3194
  SET ${e("status")} = ${"pending"}
3191
3195
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
3192
3196
  `);
3193
- }), ao = (e, t) => t === void 0 ? e`DELETE FROM ${e(M)}`.pipe(D.asVoid) : e`DELETE FROM ${e(M)} WHERE ${e("runId")} = ${t}`.pipe(D.asVoid), oo = (e) => to(e).pipe(D.map((e) => e.filter((e) => e.status === "started" || e.status === "added" || e.status === "applied").map((e) => JSON.parse(e.payload))), D.catchAll(() => D.succeed([]))), so = (e) => ao(e).pipe(D.catchAll(() => D.void)), co = (e, t, n) => D.gen(function* () {
3194
- if (ht(n.op, n.classification, t) !== "artefact-repair") return "clean";
3195
- let i = n.op, a = (e) => r(e, t);
3197
+ }), so = (e, t) => t === void 0 ? e`DELETE FROM ${e(j)}`.pipe(D.asVoid) : e`DELETE FROM ${e(j)} WHERE ${e("runId")} = ${t}`.pipe(D.asVoid), co = (e) => ro(e).pipe(D.map((e) => e.filter((e) => e.status === "started" || e.status === "added" || e.status === "applied").map((e) => JSON.parse(e.payload))), D.catchAll(() => D.succeed([]))), lo = (e) => so(e).pipe(D.catchAll(() => D.void)), uo = (e, t, r) => D.gen(function* () {
3198
+ if (ht(r.op, r.classification, t) !== "artefact-repair") return "clean";
3199
+ let i = r.op, a = (e) => n(e, t);
3196
3200
  if (t === "sqlite" || t === "turso") {
3197
3201
  if (!("table" in i)) return "clean";
3198
3202
  let n = `${i.table}${ut}`;
3199
- return (yield* Za(e, t, n)) ? ((yield* Za(e, t, i.table)) ? yield* Y(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* Y(e, `ALTER TABLE ${a(n)} RENAME TO ${a(i.table)}`, "resume-repair"), yield* D.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${i.table}' — replaying the operation`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
3203
+ return (yield* $a(e, t, n)) ? ((yield* $a(e, t, i.table)) ? yield* Y(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* Y(e, `ALTER TABLE ${a(n)} RENAME TO ${a(i.table)}`, "resume-repair"), yield* D.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${i.table}' — replaying the operation`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
3200
3204
  }
3201
3205
  if (i.kind !== "alter-column-type") return "clean";
3202
- let o = `${i.column}${dt}`, s = `${i.column}${ft}`, c = yield* Za(e, t, i.table, i.column), l = yield* Za(e, t, i.table, o), u = yield* Za(e, t, i.table, s), d = (e) => D.logWarning(`migration resume: ${e}`).pipe(D.annotateLogs({ scope: "voltro:migrate" }));
3206
+ let o = `${i.column}${dt}`, s = `${i.column}${ft}`, c = yield* $a(e, t, i.table, i.column), l = yield* $a(e, t, i.table, o), u = yield* $a(e, t, i.table, s), d = (e) => D.logWarning(`migration resume: ${e}`).pipe(D.annotateLogs({ scope: "voltro:migrate" }));
3203
3207
  return !l && !u ? "clean" : c && l && !u ? (yield* Y(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${i.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* Y(e, `ALTER TABLE ${a(i.table)} RENAME COLUMN ${a(o)} TO ${a(i.column)}`, "resume-repair"), yield* Y(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${i.table}.${i.column}'`), "applied") : c && !l && u ? (yield* Y(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${i.table}.${s}'`), "applied") : yield* D.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${i.table}.${i.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${o}=${l}, ${s}=${u}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
3204
- }), lo = (e, t, n, i = "fresh", a) => D.gen(function* () {
3205
- let o = process.hrtime.bigint(), s = Ka(n.declared), c = t.op, l = j(e);
3208
+ }), fo = (e, t, r, i = "fresh", a) => D.gen(function* () {
3209
+ let o = process.hrtime.bigint(), s = Ja(r.declared), c = t.op, l = A(e);
3206
3210
  switch (c.kind) {
3207
3211
  case "create-table": {
3208
3212
  let t = yield* e.onDialectOrElse({
3209
- mysql: () => H(e).pipe(D.map((e) => Ji(c, e))),
3210
- mssql: () => D.succeed(sa(c)),
3211
- sqlite: () => D.succeed(ea(c)),
3212
- orElse: () => D.succeed(Ui(c))
3213
+ mysql: () => oi(e).pipe(D.map((e) => Xi(c, e))),
3214
+ mssql: () => D.succeed(la(c)),
3215
+ sqlite: () => D.succeed(na(c)),
3216
+ orElse: () => D.succeed(Gi(c))
3213
3217
  }), n = yield* e.onDialectOrElse({
3214
- mysql: () => D.succeed([mi]),
3218
+ mysql: () => D.succeed([gi]),
3215
3219
  orElse: () => D.succeed([])
3216
3220
  });
3217
3221
  for (let r of t) yield* Y(e, r, c.kind, n);
3218
3222
  break;
3219
3223
  }
3220
3224
  case "drop-table": {
3221
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? ua(c, n, e) : la(c, e);
3225
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? fa(c, n, e) : da(c, e);
3222
3226
  yield* e.onDialectOrElse({
3223
3227
  mysql: () => Y(e, r(K), c.kind),
3224
3228
  orElse: () => Y(e, r(G), c.kind)
@@ -3228,131 +3232,131 @@ BEGIN
3228
3232
  case "drop-column": {
3229
3233
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
3230
3234
  yield* e.onDialectOrElse({
3231
- mysql: () => H(e).pipe(D.flatMap((r) => Y(e, t ? Ai(c, n, K) : Oi(c, r), c.kind, t ? [] : [hi]))),
3232
- sqlite: () => Y(e, t ? Ai(c, n, G) : Di(c, G, !1), c.kind, t ? [] : [gi]),
3233
- orElse: () => Y(e, t ? Ai(c, n, G) : Di(c, G), c.kind)
3235
+ mysql: () => oi(e).pipe(D.flatMap((r) => Y(e, t ? Mi(c, n, K) : Ai(c, r), c.kind, t ? [] : [_i]))),
3236
+ sqlite: () => Y(e, t ? Mi(c, n, G) : ki(c, G, !1), c.kind, t ? [] : [vi]),
3237
+ orElse: () => Y(e, t ? Mi(c, n, G) : ki(c, G), c.kind)
3234
3238
  });
3235
3239
  break;
3236
3240
  }
3237
3241
  case "rename-column":
3238
3242
  yield* e.onDialectOrElse({
3239
- mysql: () => Y(e, ki(c, K), c.kind),
3240
- mssql: () => Ja(e, c),
3241
- orElse: () => Y(e, ki(c, G), c.kind)
3243
+ mysql: () => Y(e, ji(c, K), c.kind),
3244
+ mssql: () => Xa(e, c),
3245
+ orElse: () => Y(e, ji(c, G), c.kind)
3242
3246
  });
3243
3247
  break;
3244
3248
  case "add-index":
3245
3249
  yield* e.onDialectOrElse({
3246
- sqlite: () => Y(e, ha(c, !1), c.kind),
3247
- mysql: () => H(e).pipe(D.flatMap((t) => Y(e, ga(c, n.declared, t), c.kind, [mi]))),
3248
- mssql: () => Z(e, [...Da(c.table, c.index.columns, n.declared), Ea(c)], c.kind),
3249
- orElse: () => Y(e, ha(c, t.classification === "online-required"), c.kind)
3250
+ sqlite: () => Y(e, _a(c, !1), c.kind),
3251
+ mysql: () => oi(e).pipe(D.flatMap((t) => Y(e, va(c, r.declared, t), c.kind, [gi]))),
3252
+ mssql: () => Z(e, [...ka(c.table, c.index.columns, r.declared), Oa(c)], c.kind),
3253
+ orElse: () => Y(e, _a(c, t.classification === "online-required"), c.kind)
3250
3254
  });
3251
3255
  break;
3252
3256
  case "drop-index":
3253
3257
  yield* e.onDialectOrElse({
3254
- mysql: () => Y(e, ya(c), c.kind),
3255
- mssql: () => Y(e, ba(c), c.kind),
3256
- orElse: () => Y(e, va(c), c.kind)
3258
+ mysql: () => Y(e, xa(c), c.kind),
3259
+ mssql: () => Y(e, Sa(c), c.kind),
3260
+ orElse: () => Y(e, ba(c), c.kind)
3257
3261
  });
3258
3262
  break;
3259
3263
  case "rename-table":
3260
3264
  yield* e.onDialectOrElse({
3261
- mysql: () => Y(e, xa(c, K), c.kind),
3262
- mssql: () => Y(e, Sa(c), c.kind),
3263
- orElse: () => Y(e, xa(c, G), c.kind)
3265
+ mysql: () => Y(e, Ca(c, K), c.kind),
3266
+ mssql: () => Y(e, wa(c), c.kind),
3267
+ orElse: () => Y(e, Ca(c, G), c.kind)
3264
3268
  });
3265
3269
  break;
3266
3270
  case "rename-index":
3267
3271
  yield* e.onDialectOrElse({
3268
- mysql: () => Y(e, wa(c), c.kind),
3269
- mssql: () => Y(e, Ta(c), c.kind),
3270
- orElse: () => Y(e, Ca(c), c.kind)
3272
+ mysql: () => Y(e, Ea(c), c.kind),
3273
+ mssql: () => Y(e, Da(c), c.kind),
3274
+ orElse: () => Y(e, Ta(c), c.kind)
3271
3275
  });
3272
3276
  break;
3273
3277
  case "add-unique":
3274
3278
  yield* e.onDialectOrElse({
3275
- mysql: () => Y(e, ka(c, n.declared), c.kind),
3276
- sqlite: () => X(e, c.table, n.declared, c.kind),
3277
- mssql: () => Z(e, [...Da(c.table, [c.column], n.declared), Oa(c)], c.kind),
3278
- orElse: () => Y(e, Oa(c), c.kind)
3279
+ mysql: () => Y(e, ja(c, r.declared), c.kind),
3280
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3281
+ mssql: () => Z(e, [...ka(c.table, [c.column], r.declared), Aa(c)], c.kind),
3282
+ orElse: () => Y(e, Aa(c), c.kind)
3279
3283
  });
3280
3284
  break;
3281
3285
  case "drop-unique":
3282
3286
  yield* e.onDialectOrElse({
3283
- mysql: () => Y(e, Fa(c), c.kind),
3284
- sqlite: () => X(e, c.table, n.declared, c.kind),
3285
- orElse: () => Y(e, Pa(c), c.kind)
3287
+ mysql: () => Y(e, La(c), c.kind),
3288
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3289
+ orElse: () => Y(e, Ia(c), c.kind)
3286
3290
  });
3287
3291
  break;
3288
3292
  case "add-enum-value":
3289
3293
  yield* e.onDialectOrElse({
3290
- pg: () => c.enumName === void 0 ? D.die(/* @__PURE__ */ Error(`add-enum-value on postgres needs the type name for ${c.table}.${c.column}; the plan carries none.`)) : Y(e, `ALTER TYPE ${r(c.enumName, "postgres")} ADD VALUE IF NOT EXISTS '${c.value.replace(/'/g, "''")}'`, c.kind),
3294
+ pg: () => c.enumName === void 0 ? D.die(/* @__PURE__ */ Error(`add-enum-value on postgres needs the type name for ${c.table}.${c.column}; the plan carries none.`)) : Y(e, `ALTER TYPE ${n(c.enumName, "postgres")} ADD VALUE IF NOT EXISTS '${c.value.replace(/'/g, "''")}'`, c.kind),
3291
3295
  mysql: () => {
3292
- let t = q(n.declared, c.table, c.column);
3293
- return t === void 0 || t.enumValues === void 0 || t.enumValues.length === 0 ? D.die(/* @__PURE__ */ Error(`add-enum-value on the mysql family needs the declared column ${c.table}.${c.column} and its labels; the declaration carries none.`)) : Y(e, `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Fi(t, c.column)}`, c.kind);
3296
+ let t = q(r.declared, c.table, c.column);
3297
+ return t === void 0 || t.enumValues === void 0 || t.enumValues.length === 0 ? D.die(/* @__PURE__ */ Error(`add-enum-value on the mysql family needs the declared column ${c.table}.${c.column} and its labels; the declaration carries none.`)) : Y(e, `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Li(t, c.column)}`, c.kind);
3294
3298
  },
3295
3299
  orElse: () => D.void
3296
3300
  });
3297
3301
  break;
3298
3302
  case "add-unique-composite":
3299
3303
  yield* e.onDialectOrElse({
3300
- mysql: () => Y(e, ja(c, n.declared), c.kind),
3301
- sqlite: () => X(e, c.table, n.declared, c.kind),
3302
- mssql: () => Z(e, [...Da(c.table, c.fields, n.declared), Aa(c)], c.kind),
3303
- orElse: () => Y(e, Aa(c), c.kind)
3304
+ mysql: () => Y(e, Na(c, r.declared), c.kind),
3305
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3306
+ mssql: () => Z(e, [...ka(c.table, c.fields, r.declared), Ma(c)], c.kind),
3307
+ orElse: () => Y(e, Ma(c), c.kind)
3304
3308
  });
3305
3309
  break;
3306
3310
  case "drop-unique-composite":
3307
3311
  yield* e.onDialectOrElse({
3308
- mysql: () => Y(e, Na(c), c.kind),
3309
- sqlite: () => X(e, c.table, n.declared, c.kind),
3310
- orElse: () => Y(e, Ma(c), c.kind)
3312
+ mysql: () => Y(e, Fa(c), c.kind),
3313
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3314
+ orElse: () => Y(e, Pa(c), c.kind)
3311
3315
  });
3312
3316
  break;
3313
3317
  case "add-foreign-key":
3314
3318
  yield* e.onDialectOrElse({
3315
- mysql: () => Z(e, Ia(c, K), c.kind),
3316
- sqlite: () => X(e, c.table, n.declared, c.kind),
3317
- mssql: () => Z(e, Ia(c, J, Xi), c.kind),
3318
- orElse: () => Z(e, Ia(c, G), c.kind)
3319
+ mysql: () => Z(e, Ra(c, K), c.kind),
3320
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3321
+ mssql: () => Z(e, Ra(c, J, Qi), c.kind),
3322
+ orElse: () => Z(e, Ra(c, G), c.kind)
3319
3323
  });
3320
3324
  break;
3321
3325
  case "add-column": {
3322
- let r = Wa(c, t, s, yield* e.onDialectOrElse({
3326
+ let n = Ka(c, t, s, yield* e.onDialectOrElse({
3323
3327
  mysql: () => D.succeed("mariadb"),
3324
3328
  mssql: () => D.succeed("mssql"),
3325
3329
  sqlite: () => D.succeed("sqlite"),
3326
3330
  orElse: () => D.succeed("postgres")
3327
3331
  }));
3328
- if (!(i === "resume" && (yield* Za(e, j(e), c.table, c.column.name)))) for (let t of r.pre) yield* Y(e, t, c.kind);
3329
- let u = t.classification === "online-required" || r.batchSize !== void 0 || r.sleepMs !== void 0, d = D.gen(function* () {
3330
- if (r.backfillKind === "sql" && r.backfillSql) {
3331
- if (t.classification !== "online-required" && r.batchSize === void 0) yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${r.backfillSql}`;
3332
+ if (!(i === "resume" && (yield* $a(e, A(e), c.table, c.column.name)))) for (let t of n.pre) yield* Y(e, t, c.kind);
3333
+ let u = t.classification === "online-required" || n.batchSize !== void 0 || n.sleepMs !== void 0, d = D.gen(function* () {
3334
+ if (n.backfillKind === "sql" && n.backfillSql) {
3335
+ if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${n.backfillSql}`;
3332
3336
  else {
3333
- let t = r.batchSize ?? 5e3, n = r.sleepMs ?? 0, i, a = 0;
3337
+ let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
3334
3338
  for (;;) {
3335
- let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${Xa(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Xa(e, t)}`;
3339
+ let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${Qa(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Qa(e, t)}`;
3336
3340
  if (o.length === 0) break;
3337
3341
  let s = o.map((e) => e.id);
3338
- yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${r.backfillSql} WHERE ${e("id")} IN ${e.in(s)}`, a += o.length, yield* D.logInfo(`backfill ${c.table}.${c.column.name}: ${a} rows`).pipe(D.annotateLogs({
3342
+ yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(s)}`, a += o.length, yield* D.logInfo(`backfill ${c.table}.${c.column.name}: ${a} rows`).pipe(D.annotateLogs({
3339
3343
  scope: "voltro:migrate",
3340
3344
  mode: "sql-batched"
3341
- })), i = o[o.length - 1].id, n > 0 && (yield* D.sleep(`${n} millis`));
3345
+ })), i = o[o.length - 1].id, r > 0 && (yield* D.sleep(`${r} millis`));
3342
3346
  }
3343
3347
  }
3344
- } else if (r.backfillKind === "js" && r.backfillJs) {
3345
- let t = r.batchSize ?? 1e3, i = r.sleepMs ?? 0, a = n.declared.find((e) => e.tableName === c.table), o, s = 0;
3348
+ } else if (n.backfillKind === "js" && n.backfillJs) {
3349
+ let t = n.batchSize ?? 1e3, i = n.sleepMs ?? 0, a = r.declared.find((e) => e.tableName === c.table), o, s = 0;
3346
3350
  for (;;) {
3347
- let n = o === void 0 ? yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${Xa(e, t)}` : yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL AND ${e("id")} > ${o} ORDER BY ${e("id")} ${Xa(e, t)}`;
3348
- if (n.length === 0) break;
3349
- let u = a === void 0 ? n : ie(n, a, l);
3351
+ let r = o === void 0 ? yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${Qa(e, t)}` : yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL AND ${e("id")} > ${o} ORDER BY ${e("id")} ${Qa(e, t)}`;
3352
+ if (r.length === 0) break;
3353
+ let u = a === void 0 ? r : re(r, a, l);
3350
3354
  for (let t of u) {
3351
- let n = yield* D.tryPromise({
3352
- try: () => Promise.resolve(r.backfillJs(t)),
3355
+ let r = yield* D.tryPromise({
3356
+ try: () => Promise.resolve(n.backfillJs(t)),
3353
3357
  catch: (e) => e
3354
3358
  }).pipe(D.orDie);
3355
- yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${Ya(n, c.column, l)} WHERE ${e("id")} = ${t.id}`;
3359
+ yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${Za(r, c.column, l)} WHERE ${e("id")} = ${t.id}`;
3356
3360
  }
3357
3361
  s += u.length, yield* D.logInfo(`backfill ${c.table}.${c.column.name}: ${s} rows processed`).pipe(D.annotateLogs({
3358
3362
  scope: "voltro:migrate",
@@ -3362,10 +3366,22 @@ BEGIN
3362
3366
  }
3363
3367
  }
3364
3368
  }), f = D.gen(function* () {
3365
- for (let t of r.post) yield* Y(e, t, c.kind);
3366
- m(l) && r.backfillKind !== void 0 && !c.column.nullable && (yield* X(e, c.table, n.declared, c.kind));
3369
+ for (let t of n.post) yield* Y(e, t, c.kind);
3370
+ if (p(l) && (n.uniquePending === !0 || n.backfillKind !== void 0 && !c.column.nullable)) yield* X(e, c.table, r.declared, c.kind);
3371
+ else if (n.uniquePending === !0) {
3372
+ let t = {
3373
+ kind: "add-unique",
3374
+ table: c.table,
3375
+ column: c.column.name
3376
+ };
3377
+ yield* e.onDialectOrElse({
3378
+ mysql: () => Y(e, ja(t, r.declared), c.kind),
3379
+ mssql: () => Z(e, [...ka(c.table, [c.column.name], r.declared), Aa(t)], c.kind),
3380
+ orElse: () => Y(e, Aa(t), c.kind)
3381
+ });
3382
+ }
3367
3383
  });
3368
- if (a !== void 0 && r.backfillKind !== void 0 && !u) return a({
3384
+ if (a !== void 0 && n.backfillKind !== void 0 && !u) return a({
3369
3385
  table: c.table,
3370
3386
  op: c,
3371
3387
  data: d,
@@ -3382,47 +3398,47 @@ BEGIN
3382
3398
  case "alter-column-nullability":
3383
3399
  yield* e.onDialectOrElse({
3384
3400
  mysql: () => {
3385
- let t = q(n.declared, c.table, c.column);
3386
- return t ? Y(e, `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Fi(t, c.column, c.toNullable)};`, c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${c.table}.${c.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
3401
+ let t = q(r.declared, c.table, c.column);
3402
+ return t ? Y(e, `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Li(t, c.column, c.toNullable)};`, c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${c.table}.${c.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
3387
3403
  },
3388
3404
  mssql: () => {
3389
- let t = q(n.declared, c.table, c.column);
3390
- return t ? Y(e, ra(t, c.column, c.table, c.toNullable), c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${c.table}.${c.column}'.`));
3405
+ let t = q(r.declared, c.table, c.column);
3406
+ return t ? Y(e, aa(t, c.column, c.table, c.toNullable), c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${c.table}.${c.column}'.`));
3391
3407
  },
3392
- sqlite: () => X(e, c.table, n.declared, c.kind),
3408
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3393
3409
  orElse: () => Y(e, `ALTER TABLE ${G(c.table)} ALTER COLUMN ${G(c.column)} ${c.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, c.kind)
3394
3410
  });
3395
3411
  break;
3396
3412
  case "alter-column-default": {
3397
- let t = Pi(n.declared, c.table, c.column), r = q(n.declared, c.table, c.column), i = (e) => c.hasDefault && r !== void 0 && Mi(r, e) ? r : void 0;
3413
+ let t = Ii(r.declared, c.table, c.column), n = q(r.declared, c.table, c.column), i = (e) => c.hasDefault && n !== void 0 && Pi(n, e) ? n : void 0;
3398
3414
  yield* e.onDialectOrElse({
3399
3415
  mysql: () => {
3400
3416
  let n = i("mariadb");
3401
- return Y(e, n ? `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Fi(n, c.column)};` : ji(c, K, (e) => Ii(e, t)), c.kind);
3417
+ return Y(e, n ? `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Li(n, c.column)};` : Ni(c, K, (e) => Ri(e, t)), c.kind);
3402
3418
  },
3403
3419
  mssql: () => {
3404
3420
  let t = i("mssql");
3405
- return Y(e, ia(c, t ? ra(t, c.column, c.table) : void 0), c.kind);
3421
+ return Y(e, oa(c, t ? aa(t, c.column, c.table) : void 0), c.kind);
3406
3422
  },
3407
- sqlite: () => X(e, c.table, n.declared, c.kind),
3408
- orElse: () => Y(e, ji(c, G, (e) => Ri(e, t)), c.kind)
3423
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3424
+ orElse: () => Y(e, Ni(c, G, (e) => Bi(e, t)), c.kind)
3409
3425
  });
3410
3426
  break;
3411
3427
  }
3412
3428
  case "alter-column-type": {
3413
- let r = Ci(Pi(n.declared, c.table, c.column) ?? { type: c.to }), i = c.using ? ` USING ${c.using}` : "";
3429
+ let n = Ti(Ii(r.declared, c.table, c.column) ?? { type: c.to }), i = c.using ? ` USING ${c.using}` : "";
3414
3430
  if (t.classification !== "online-required") {
3415
3431
  yield* e.onDialectOrElse({
3416
3432
  mysql: () => {
3417
- let t = q(n.declared, c.table, c.column);
3418
- return t ? Y(e, `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Fi(t, c.column)};`, c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${c.table}.${c.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
3433
+ let t = q(r.declared, c.table, c.column);
3434
+ return t ? Y(e, `ALTER TABLE ${K(c.table)} MODIFY COLUMN ${Li(t, c.column)};`, c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${c.table}.${c.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
3419
3435
  },
3420
3436
  mssql: () => {
3421
- let t = q(n.declared, c.table, c.column);
3422
- return t ? Y(e, ra(t, c.column, c.table), c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${c.table}.${c.column}'.`));
3437
+ let t = q(r.declared, c.table, c.column);
3438
+ return t ? Y(e, aa(t, c.column, c.table), c.kind) : D.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${c.table}.${c.column}'.`));
3423
3439
  },
3424
- sqlite: () => X(e, c.table, n.declared, c.kind),
3425
- orElse: () => Y(e, `ALTER TABLE ${G(c.table)} ALTER COLUMN ${G(c.column)} TYPE ${r}${i};`, c.kind)
3440
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3441
+ orElse: () => Y(e, `ALTER TABLE ${G(c.table)} ALTER COLUMN ${G(c.column)} TYPE ${n}${i};`, c.kind)
3426
3442
  });
3427
3443
  break;
3428
3444
  }
@@ -3431,10 +3447,10 @@ BEGIN
3431
3447
  orElse: () => D.void
3432
3448
  });
3433
3449
  let a = `${c.column}__shadow`, o = `${c.column}__old`;
3434
- yield* e.unsafe(`ALTER TABLE ${G(c.table)} ADD COLUMN ${G(a)} ${r}`);
3450
+ yield* e.unsafe(`ALTER TABLE ${G(c.table)} ADD COLUMN ${G(a)} ${n}`);
3435
3451
  let s = c.using ?? G(c.column), l;
3436
3452
  for (;;) {
3437
- let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Xa(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Xa(e, 5e3)}`;
3453
+ let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Qa(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Qa(e, 5e3)}`;
3438
3454
  if (t.length === 0) break;
3439
3455
  yield* e.unsafe(`UPDATE ${G(c.table)} SET ${G(a)} = ${s} WHERE ${G(c.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;
3440
3456
  }
@@ -3443,16 +3459,16 @@ BEGIN
3443
3459
  }
3444
3460
  case "drop-foreign-key":
3445
3461
  yield* e.onDialectOrElse({
3446
- mysql: () => Y(e, za(c), c.kind),
3447
- sqlite: () => X(e, c.table, n.declared, c.kind),
3448
- orElse: () => Y(e, Ra(c), c.kind)
3462
+ mysql: () => Y(e, Va(c), c.kind),
3463
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3464
+ orElse: () => Y(e, Ba(c), c.kind)
3449
3465
  });
3450
3466
  break;
3451
3467
  case "add-check":
3452
3468
  yield* e.onDialectOrElse({
3453
- mysql: () => Y(e, Ba(c, K), c.kind),
3454
- sqlite: () => X(e, c.table, n.declared, c.kind),
3455
- orElse: () => Y(e, Ba(c, G), c.kind)
3469
+ mysql: () => Y(e, Ha(c, K), c.kind),
3470
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3471
+ orElse: () => Y(e, Ha(c, G), c.kind)
3456
3472
  });
3457
3473
  break;
3458
3474
  case "reconcile-json-check": {
@@ -3464,9 +3480,9 @@ BEGIN
3464
3480
  break;
3465
3481
  }
3466
3482
  case "drop-check": yield* e.onDialectOrElse({
3467
- mysql: () => Ua(e, c, n.declared),
3468
- sqlite: () => X(e, c.table, n.declared, c.kind),
3469
- orElse: () => Y(e, Va(c), c.kind)
3483
+ mysql: () => Ga(e, c, r.declared),
3484
+ sqlite: () => X(e, c.table, r.declared, c.kind),
3485
+ orElse: () => Y(e, Ua(c), c.kind)
3470
3486
  });
3471
3487
  }
3472
3488
  return {
@@ -3474,22 +3490,22 @@ BEGIN
3474
3490
  status: "applied",
3475
3491
  durationMs: Number((process.hrtime.bigint() - o) / 1000000n)
3476
3492
  };
3477
- }), uo = (e, t, n, r) => D.gen(function* () {
3493
+ }), po = (e, t, n, r) => D.gen(function* () {
3478
3494
  let i = [...new Set(r.map((e) => e.runId))];
3479
- if (i.length > 1) return yield* D.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 \`${M}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
3495
+ if (i.length > 1) return yield* D.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 \`${j}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
3480
3496
  let a = i[0], o = [...r].map((e) => ({
3481
3497
  index: Number(e.opIndex),
3482
3498
  status: e.status,
3483
3499
  planned: JSON.parse(e.payload)
3484
3500
  })).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
3485
- if (c > 1) return yield* D.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 \`${M}\` by hand before re-running.`));
3501
+ if (c > 1) return yield* D.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 \`${j}\` by hand before re-running.`));
3486
3502
  let l = o.filter((e) => e.status === "added");
3487
3503
  if (yield* D.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} ${st(s.planned.op)}` : ""}${l.length > 0 ? `, ${l.length} column(s) added with the backfill still owed` : ""}`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
3488
3504
  kind: "discard",
3489
3505
  runId: a,
3490
3506
  why: "no operation had started — no DDL ran"
3491
3507
  };
3492
- let u = s ? yield* co(e, t, s.planned) : "clean", d = r[0].planFingerprint;
3508
+ let u = s ? yield* uo(e, t, s.planned) : "clean", d = r[0].planFingerprint;
3493
3509
  if (d !== n.toFingerprint) return {
3494
3510
  kind: "discard",
3495
3511
  runId: a,
@@ -3500,7 +3516,7 @@ BEGIN
3500
3516
  kind: "discard",
3501
3517
  runId: a,
3502
3518
  why: "every recorded operation had already taken effect"
3503
- } : (yield* io(e, a, p.map((e) => e.index), m.map((e) => e.index)), yield* D.logWarning(`migration resume: continuing run ${a} — replaying ${p.length} operation(s), ${o.length - p.length} already applied`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), {
3519
+ } : (yield* oo(e, a, p.map((e) => e.index), m.map((e) => e.index)), yield* D.logWarning(`migration resume: continuing run ${a} — replaying ${p.length} operation(s), ${o.length - p.length} already applied`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), {
3504
3520
  kind: "resume",
3505
3521
  runId: a,
3506
3522
  ops: p.map((e) => ({
@@ -3508,7 +3524,7 @@ BEGIN
3508
3524
  planned: e.planned
3509
3525
  }))
3510
3526
  });
3511
- }), fo = (e, t, n) => D.gen(function* () {
3527
+ }), mo = (e, t, r) => D.gen(function* () {
3512
3528
  for (let i of t.operations) {
3513
3529
  let a = i.op;
3514
3530
  if (a.kind !== "add-index" || !a.index.unique || a.index.where === void 0 || t.operations.some((e) => e.op.kind === "rename-table" ? e.op.to === a.table : e.op.table === a.table && [
@@ -3516,10 +3532,10 @@ BEGIN
3516
3532
  "add-column",
3517
3533
  "rename-column"
3518
3534
  ].includes(e.op.kind))) continue;
3519
- let o = a.index.columns.map((e) => e.startsWith("(") ? e : r(e, n)), s = n === "mssql" ? "" : o.map((e) => ` AND ${e} IS NOT NULL`).join(""), c = n === "mssql" ? "SELECT TOP (1) 1" : "SELECT 1", l = n === "mssql" ? "" : " LIMIT 1";
3520
- if ((yield* e.unsafe(`${c} FROM ${r(a.table, n)} WHERE (${a.index.where})${s} GROUP BY ${o.join(", ")} HAVING COUNT(*) > 1${l}`)).length > 0) return yield* D.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${a.index.name}' on '${a.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
3535
+ let o = a.index.columns.map((e) => e.startsWith("(") ? e : n(e, r)), s = r === "mssql" ? "" : o.map((e) => ` AND ${e} IS NOT NULL`).join(""), c = r === "mssql" ? "SELECT TOP (1) 1" : "SELECT 1", l = r === "mssql" ? "" : " LIMIT 1";
3536
+ if ((yield* e.unsafe(`${c} FROM ${n(a.table, r)} WHERE (${a.index.where})${s} GROUP BY ${o.join(", ")} HAVING COUNT(*) > 1${l}`)).length > 0) return yield* D.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${a.index.name}' on '${a.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
3521
3537
  }
3522
- }), po = (e) => {
3538
+ }), ho = (e) => {
3523
3539
  let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
3524
3540
  return [
3525
3541
  t.kind,
@@ -3528,13 +3544,13 @@ BEGIN
3528
3544
  n("name"),
3529
3545
  n("to")
3530
3546
  ].join("\0");
3531
- }, mo = (e, t, n) => D.acquireUseRelease($e(e, { schema: n.lockSchema }), () => ho(e, t, n), (e) => e.release.pipe(D.orDie)), ho = (e, t, n) => D.gen(function* () {
3547
+ }, go = (e, t, n) => D.acquireUseRelease($e(e, { schema: n.lockSchema }), () => _o(e, t, n), (e) => e.release.pipe(D.orDie)), _o = (e, t, n) => D.gen(function* () {
3532
3548
  let r = t.operations.filter((e) => e.blocked);
3533
3549
  if (r.length > 0) return yield* D.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
3534
- let i = Date.now(), a = [], o = j(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => po(e))), l = {
3550
+ let i = Date.now(), a = [], o = A(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => ho(e))), l = {
3535
3551
  ...s,
3536
3552
  operations: s.operations.map((e) => {
3537
- if (!e.blocked || !c.has(po(e))) return e;
3553
+ if (!e.blocked || !c.has(ho(e))) return e;
3538
3554
  let { blocked: t, ...n } = e;
3539
3555
  return n;
3540
3556
  })
@@ -3552,66 +3568,66 @@ BEGIN
3552
3568
  index: t,
3553
3569
  planned: e
3554
3570
  })), y = "fresh";
3555
- yield* fo(e, l, o), yield* Qa(e, o);
3556
- let b = yield* to(e);
3571
+ yield* mo(e, l, o), yield* eo(e, o);
3572
+ let b = yield* ro(e);
3557
3573
  if (b.length > 0) {
3558
- let t = yield* uo(e, o, l, b);
3559
- t.kind === "resume" ? (_ = t.runId, v = t.ops, y = "resume") : (yield* D.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), yield* ao(e, t.runId));
3574
+ let t = yield* po(e, o, l, b);
3575
+ t.kind === "resume" ? (_ = t.runId, v = t.ops, y = "resume") : (yield* D.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(D.annotateLogs({ scope: "voltro:migrate" })), yield* so(e, t.runId));
3560
3576
  }
3561
- y === "fresh" && v.length > 0 && (yield* no(e, _, l.toFingerprint, v)), h.length > 0 && (yield* vi(e, D.gen(function* () {
3577
+ y === "fresh" && v.length > 0 && (yield* io(e, _, l.toFingerprint, v)), h.length > 0 && (yield* bi(e, D.gen(function* () {
3562
3578
  let e = yield* O.SqlClient, t = [], r = () => D.gen(function* () {
3563
3579
  for (let e of t.splice(0)) yield* e.data, yield* e.after;
3564
3580
  });
3565
- for (let i of h) Ga.has(i.op.kind) && t.length > 0 && (yield* r()), a.push(yield* lo(e, i, n, "fresh", (e) => t.push(e)));
3581
+ for (let i of h) qa.has(i.op.kind) && t.length > 0 && (yield* r()), a.push(yield* fo(e, i, n, "fresh", (e) => t.push(e)));
3566
3582
  yield* r();
3567
3583
  })));
3568
3584
  let x = [], S = () => D.gen(function* () {
3569
3585
  let t = x.splice(0);
3570
3586
  if (t.length !== 0) {
3571
- yield* vi(e, D.gen(function* () {
3587
+ yield* bi(e, D.gen(function* () {
3572
3588
  for (let e of t) yield* e.data;
3573
3589
  }));
3574
3590
  for (let n of t) yield* n.after, a.push({
3575
3591
  op: n.op,
3576
3592
  status: "applied",
3577
3593
  durationMs: Number(process.hrtime.bigint() - n.startedAt) / 1e6
3578
- }), yield* ro(e, _, n.index, "applied", Number(process.hrtime.bigint() - n.startedAt) / 1e6);
3594
+ }), yield* ao(e, _, n.index, "applied", Number(process.hrtime.bigint() - n.startedAt) / 1e6);
3579
3595
  }
3580
3596
  });
3581
3597
  for (let { index: t, planned: r } of v) {
3582
- Ga.has(r.op.kind) && x.length > 0 && (yield* S()), yield* ro(e, _, t, "started");
3583
- let i = a.length, o = process.hrtime.bigint(), s = yield* lo(e, r, n, y, (e) => x.push({
3598
+ qa.has(r.op.kind) && x.length > 0 && (yield* S()), yield* ao(e, _, t, "started");
3599
+ let i = a.length, o = process.hrtime.bigint(), s = yield* fo(e, r, n, y, (e) => x.push({
3584
3600
  ...e,
3585
3601
  index: t,
3586
3602
  startedAt: o
3587
3603
  })).pipe(D.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${v.length + h.length} operation(s) applied before this one${h.length > 0 ? ` (${h.length} of them in a transaction)` : ""}.\n` + (m ? " 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 ledger records how far it got (operation ${t} was in flight).\n`) })));
3588
3604
  if (s.deferred === !0) {
3589
- yield* ro(e, _, t, "added");
3605
+ yield* ao(e, _, t, "added");
3590
3606
  continue;
3591
3607
  }
3592
- a.push(s), yield* ro(e, _, t, "applied", s.durationMs);
3608
+ a.push(s), yield* ao(e, _, t, "applied", s.durationMs);
3593
3609
  }
3594
3610
  yield* S();
3595
3611
  let C = yield* n.replan(e);
3596
3612
  if (C.operations.length > 0) {
3597
- let e = C.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");
3598
- return yield* D.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 ${C.operations.length}:\n${e}${C.operations.length > 10 ? `\n … and ${C.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.`));
3613
+ let e = (e) => "column" in e ? typeof e.column == "string" ? `.${e.column}` : `.${String(e.column.name ?? "")}` : "", t = C.operations.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n"), n = a.filter((e) => e.status === "applied"), r = n.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n") + (n.length > 10 ? `\n … and ${n.length - 10} more` : "");
3614
+ return yield* D.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 ${C.operations.length}:\n${t}${C.operations.length > 10 ? `\n … and ${C.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.\n` + (m ? " This dialect applies a plan atomically, so the run is rolled back and the schema IS unchanged.\n" : ` This dialect does NOT apply a plan atomically. The ${n.length} operation(s) below are COMMITTED\n and there is no rollback — the schema is PART-APPLIED, not unchanged:\n${r}\n Re-running plans from where the database now is, which is a different plan from the one that failed.\n`) + "Two 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."));
3599
3615
  }
3600
- let ee = a.filter((e) => e.status === "applied").length, w = Date.now() - i, T = _, te = (/* @__PURE__ */ new Date()).toISOString(), ne = yield* W(e, te), E = [...h, ...v.map((e) => e.planned)];
3616
+ let ee = a.filter((e) => e.status === "applied").length, w = Date.now() - i, te = _, T = (/* @__PURE__ */ new Date()).toISOString(), ne = yield* W(e, T), E = [...h, ...v.map((e) => e.planned)];
3601
3617
  yield* e`
3602
3618
  INSERT INTO ${e("_voltro_migration_plans")}
3603
3619
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
3604
3620
  ${e("appliedBy")}, ${e("environment")}, ${e("source")},
3605
3621
  ${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
3606
3622
  VALUES
3607
- (${T}, ${l.toFingerprint}, ${C.fromFingerprint}, ${JSON.stringify(E)},
3623
+ (${te}, ${l.toFingerprint}, ${C.fromFingerprint}, ${JSON.stringify(E)},
3608
3624
  ${n.appliedBy}, ${n.environment}, ${n.source},
3609
3625
  ${w}, ${ne}, ${n.notes ?? null})
3610
- `, yield* ao(e, _);
3626
+ `, yield* so(e, _);
3611
3627
  let re = [...new Set(E.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
3612
- return yield* D.promise(() => le({ changedTables: re }).catch(() => {})), {
3613
- id: T,
3614
- appliedAt: te,
3628
+ return yield* D.promise(() => ce({ changedTables: re }).catch(() => {})), {
3629
+ id: te,
3630
+ appliedAt: T,
3615
3631
  fingerprint: l.toFingerprint,
3616
3632
  operations: E,
3617
3633
  appliedBy: n.appliedBy,
@@ -3621,7 +3637,7 @@ BEGIN
3621
3637
  source: n.source,
3622
3638
  ...n.notes ? { notes: n.notes } : {}
3623
3639
  };
3624
- }), go = (e, t) => {
3640
+ }), vo = (e, t) => {
3625
3641
  switch (t.kind) {
3626
3642
  case "drop-foreign-key": return {
3627
3643
  ...e,
@@ -3654,36 +3670,36 @@ BEGIN
3654
3670
  };
3655
3671
  }
3656
3672
  }, Q = (e, t, n) => {
3657
- let r = n.tables.find((e) => e.name === t.table), i = () => r === void 0 ? D.void : qa(e, t.table, na(go(r, t)), t.kind);
3673
+ let r = n.tables.find((e) => e.name === t.table), i = () => r === void 0 ? D.void : Ya(e, t.table, ia(vo(r, t)), t.kind);
3658
3674
  switch (t.kind) {
3659
3675
  case "drop-foreign-key": return e.onDialectOrElse({
3660
- mysql: () => Y(e, za(t), t.kind),
3676
+ mysql: () => Y(e, Va(t), t.kind),
3661
3677
  sqlite: i,
3662
- orElse: () => Y(e, Ra(t), t.kind)
3678
+ orElse: () => Y(e, Ba(t), t.kind)
3663
3679
  });
3664
3680
  case "drop-index": return e.onDialectOrElse({
3665
- mysql: () => Y(e, ya(t), t.kind),
3666
- mssql: () => Y(e, ba(t), t.kind),
3667
- orElse: () => Y(e, va(t), t.kind)
3681
+ mysql: () => Y(e, xa(t), t.kind),
3682
+ mssql: () => Y(e, Sa(t), t.kind),
3683
+ orElse: () => Y(e, ba(t), t.kind)
3668
3684
  });
3669
3685
  case "drop-column": return e.onDialectOrElse({
3670
- mysql: () => H(e).pipe(D.flatMap((n) => Y(e, Oi(t, n), t.kind, [hi]))),
3686
+ mysql: () => oi(e).pipe(D.flatMap((n) => Y(e, Ai(t, n), t.kind, [_i]))),
3671
3687
  sqlite: i,
3672
- orElse: () => Y(e, Di(t, G), t.kind)
3688
+ orElse: () => Y(e, ki(t, G), t.kind)
3673
3689
  });
3674
3690
  case "rename-column": return e.onDialectOrElse({
3675
- mysql: () => Y(e, ki(t, K), t.kind),
3676
- mssql: () => Ja(e, t),
3677
- orElse: () => Y(e, ki(t, G), t.kind)
3691
+ mysql: () => Y(e, ji(t, K), t.kind),
3692
+ mssql: () => Xa(e, t),
3693
+ orElse: () => Y(e, ji(t, G), t.kind)
3678
3694
  });
3679
3695
  }
3680
- }, _o = (e, t, n) => lo(e, t, { declared: n }), vo = (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"), yo = (e) => e`
3696
+ }, yo = (e, t, n) => fo(e, t, { declared: n }), bo = (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"), xo = (e) => e`
3681
3697
  SELECT fingerprint
3682
3698
  FROM _voltro_migration_plans
3683
3699
  ORDER BY ${e("appliedAt")} DESC
3684
3700
  LIMIT 1
3685
- `.pipe(D.map((e) => e.length > 0 ? e[0].fingerprint : void 0), D.catchAll(() => D.succeed(void 0))), bo = (e, t, n) => D.gen(function* () {
3686
- if ((yield* yo(e)) === t.toFingerprint) return "already-current";
3701
+ `.pipe(D.map((e) => e.length > 0 ? e[0].fingerprint : void 0), D.catchAll(() => D.succeed(void 0))), So = (e, t, n) => D.gen(function* () {
3702
+ if ((yield* xo(e)) === t.toFingerprint) return "already-current";
3687
3703
  let r = `plan_${Date.now().toString(36)}`, i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
3688
3704
  return yield* e`
3689
3705
  INSERT INTO ${e("_voltro_migration_plans")}
@@ -3695,8 +3711,8 @@ BEGIN
3695
3711
  ${n.appliedBy}, ${n.environment}, ${n.source},
3696
3712
  ${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
3697
3713
  `, "recorded";
3698
- }).pipe(D.catchAll(() => D.succeed("already-current"))), xo = (e, t) => D.gen(function* () {
3699
- let n = I(L(t, j(e))), r = yield* yo(e);
3714
+ }).pipe(D.catchAll(() => D.succeed("already-current"))), Co = (e, t) => D.gen(function* () {
3715
+ let n = R(z(t, A(e))), r = yield* xo(e);
3700
3716
  return r === n ? {
3701
3717
  kind: "up-to-date",
3702
3718
  fingerprint: n
@@ -3705,23 +3721,23 @@ BEGIN
3705
3721
  expected: n,
3706
3722
  ...r === void 0 ? {} : { actual: r }
3707
3723
  };
3708
- }), So = [
3724
+ }), wo = [
3709
3725
  "pgeagertest_",
3710
3726
  "mig_e2e_",
3711
3727
  "mig_test_",
3712
3728
  "mysqleagertest_",
3713
3729
  "mssqleagertest_",
3714
3730
  "sqliteeagertest_"
3715
- ], Co = (e) => So.some((t) => e.startsWith(t)), wo = (e, t) => D.gen(function* () {
3731
+ ], To = (e) => wo.some((t) => e.startsWith(t)), Eo = (e, t) => D.gen(function* () {
3716
3732
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
3717
- let n = t.filter((e) => Co(e.name)).map((e) => e.name);
3733
+ let n = t.filter((e) => To(e.name)).map((e) => e.name);
3718
3734
  if (n.length === 0) return [];
3719
3735
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(D.catchAll(() => D.void));
3720
3736
  return n;
3721
- }), To = () => {
3737
+ }), Do = () => {
3722
3738
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
3723
3739
  return e.length > 0 ? { ignoreTables: e } : {};
3724
- }, Eo = (e) => {
3740
+ }, Oo = (e) => {
3725
3741
  if (e === void 0) return;
3726
3742
  let t = e.trim();
3727
3743
  if (t === "") return;
@@ -3731,55 +3747,55 @@ BEGIN
3731
3747
  kind: "tables",
3732
3748
  tables: new Set(n)
3733
3749
  } : void 0;
3734
- }, Do = (e) => typeof e.table == "string" ? e.table : void 0, Oo = (e, t = { kind: "all" }) => ({
3750
+ }, ko = (e) => typeof e.table == "string" ? e.table : void 0, Ao = (e, t = { kind: "all" }) => ({
3735
3751
  ...e,
3736
3752
  operations: e.operations.map((e) => {
3737
3753
  if (!e.blocked || e.classification !== "lossy") return e;
3738
3754
  if (t?.kind === "tables") {
3739
- let n = Do(e.op);
3755
+ let n = ko(e.op);
3740
3756
  if (n === void 0 || !t.tables.has(n)) return e;
3741
3757
  }
3742
3758
  let { blocked: n, ...r } = e;
3743
3759
  return r;
3744
3760
  })
3745
- }), ko = (e, t, n) => t === "postgres" ? Qn(e, n).pipe(D.flatMap((e) => {
3761
+ }), jo = (e, t, n) => t === "postgres" ? Qn(e, n).pipe(D.flatMap((e) => {
3746
3762
  let t = $n(e);
3747
3763
  return t === void 0 ? D.void : D.logWarning(`auto-migrate: ${t}`).pipe(D.annotateLogs({ scope: "voltro:migrate" }));
3748
- }), D.catchAll(() => D.void)) : D.void, Ao = (e, t, n) => D.gen(function* () {
3749
- let r = j(e), i = t;
3764
+ }), D.catchAll(() => D.void)) : D.void, Mo = (e, t, n) => D.gen(function* () {
3765
+ let r = A(e), i = t;
3750
3766
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
3751
- let t = I(L(i, r));
3752
- if ((yield* yo(e)) === t) return yield* ko(e, r, i), {
3767
+ let t = R(z(i, r));
3768
+ if ((yield* xo(e)) === t) return yield* jo(e, r, i), {
3753
3769
  kind: "up-to-date",
3754
3770
  fingerprint: t
3755
3771
  };
3756
3772
  }
3757
- let a = yield* ni(e), o = yield* wo(e, a.tables);
3773
+ let a = yield* ri(e), o = yield* Eo(e, a.tables);
3758
3774
  o.length > 0 && (yield* D.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(D.annotateLogs({
3759
3775
  scope: "voltro:migrate",
3760
3776
  count: o.length
3761
- })), a = yield* ni(e));
3777
+ })), a = yield* ri(e));
3762
3778
  {
3763
- let e = n.softDropRetentionDays ?? 7, t = ee(a, { retentionDays: e });
3764
- t.length > 0 && (yield* D.logWarning(`auto-migrate: ${_(t, e)}`).pipe(D.annotateLogs({
3779
+ let e = n.softDropRetentionDays ?? 7, t = C(a, { retentionDays: e });
3780
+ t.length > 0 && (yield* D.logWarning(`auto-migrate: ${g(t, e)}`).pipe(D.annotateLogs({
3765
3781
  scope: "voltro:migrate",
3766
3782
  snapshots: t.map((e) => e.name)
3767
3783
  })));
3768
3784
  }
3769
- let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !ne(e.name) || s.has(e.name)), l = jr({
3785
+ let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !T(e.name) || s.has(e.name)), l = jr({
3770
3786
  declared: i,
3771
3787
  live: { tables: c(a.tables) },
3772
3788
  dialect: r,
3773
- ...To()
3789
+ ...Do()
3774
3790
  });
3775
3791
  if (l.summary.blocked > 0) {
3776
- let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Eo(process.env.VOLTRO_DESTRUCTIVE_OK);
3777
- if (t === void 0 || !e || (l = Oo(l, t), l.operations.some((e) => e.blocked))) return {
3792
+ let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Oo(process.env.VOLTRO_DESTRUCTIVE_OK);
3793
+ if (t === void 0 || !e || (l = Ao(l, t), l.operations.some((e) => e.blocked))) return {
3778
3794
  kind: "refused-blocked",
3779
3795
  plan: l
3780
3796
  };
3781
3797
  }
3782
- return l.operations.length === 0 ? (yield* bo(e, l, {
3798
+ return l.operations.length === 0 ? (yield* So(e, l, {
3783
3799
  appliedBy: n.appliedBy,
3784
3800
  environment: n.environment === "prod" ? "dev" : n.environment,
3785
3801
  source: "auto-diff"
@@ -3788,27 +3804,27 @@ BEGIN
3788
3804
  fingerprint: l.toFingerprint
3789
3805
  }) : {
3790
3806
  kind: "applied",
3791
- applied: yield* mo(e, l, {
3807
+ applied: yield* go(e, l, {
3792
3808
  declared: t,
3793
3809
  appliedBy: n.appliedBy,
3794
3810
  environment: n.environment === "prod" ? "dev" : n.environment,
3795
3811
  source: "auto-diff",
3796
3812
  replan: (e) => D.gen(function* () {
3797
- let t = yield* ni(e);
3813
+ let t = yield* ri(e);
3798
3814
  return jr({
3799
3815
  declared: i,
3800
3816
  live: { tables: c(t.tables) },
3801
3817
  dialect: r,
3802
- ...To()
3818
+ ...Do()
3803
3819
  });
3804
3820
  })
3805
3821
  }),
3806
3822
  plan: l
3807
3823
  };
3808
- }), jo = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? D.succeed({
3824
+ }), No = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? D.succeed({
3809
3825
  kind: "skipped",
3810
3826
  reason: "VOLTRO_AUTO_MIGRATE=0"
3811
- }) : n.environment === "prod" ? xo(e, t) : Ao(e, t, n), Mo = (e, t) => {
3827
+ }) : n.environment === "prod" ? Co(e, t) : Mo(e, t, n), Po = (e, t) => {
3812
3828
  switch (e.kind) {
3813
3829
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
3814
3830
  case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${Kn(e.fingerprint)})`;
@@ -3818,7 +3834,7 @@ BEGIN
3818
3834
  }
3819
3835
  case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${Kn(e.expected)}` + (e.actual ? ` live=${Kn(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
3820
3836
  case "refused-blocked": {
3821
- 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` + vo(e.plan), c = [""];
3837
+ 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` + bo(e.plan), c = [""];
3822
3838
  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) {
3823
3839
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
3824
3840
  for (let r of e.plan.operations) {
@@ -3835,7 +3851,7 @@ BEGIN
3835
3851
  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");
3836
3852
  }
3837
3853
  }
3838
- }, No = (e) => typeof e.__definition == "function" ? s({ c: e }).c : e, $ = (e, t = /* @__PURE__ */ new Map()) => {
3854
+ }, Fo = (e) => typeof e.__definition == "function" ? o({ c: e }).c : e, $ = (e, t = /* @__PURE__ */ new Map()) => {
3839
3855
  let n = {};
3840
3856
  for (let r of e.columns) {
3841
3857
  let e = r.references, i = e === void 0 ? void 0 : t.get(e.table);
@@ -3886,66 +3902,66 @@ BEGIN
3886
3902
  })),
3887
3903
  ...e.primaryKey === void 0 ? {} : { appliedPrimaryKey: e.primaryKey }
3888
3904
  };
3889
- }, Po = (e) => {
3905
+ }, Io = (e) => {
3890
3906
  let t = new Map(e.tables.map((e) => [e.name, e]));
3891
3907
  return e.tables.map((e) => $(e, t));
3892
- }, Fo = (e, t = "safe") => ({
3908
+ }, Lo = (e, t = "safe") => ({
3893
3909
  op: e,
3894
3910
  classification: t,
3895
3911
  reason: "file migration schema operation"
3896
- }), Io = (e) => D.isEffect(e) ? e : D.tryPromise({
3912
+ }), Ro = (e) => D.isEffect(e) ? e : D.tryPromise({
3897
3913
  try: () => e,
3898
3914
  catch: (e) => e
3899
- }), Lo = (e, t) => e.run === void 0 ? Promise.reject(/* @__PURE__ */ Error("this data store cannot execute raw SQL inside its transaction — use the store for data, or a non-transactional scope for sql")) : e.run(t), Ro = (t, n, r) => {
3900
- let i = () => ni(t), a = (e, t) => e.tables.find((e) => e.name === t), o = (e, t, n) => a(e, t)?.columns.find((e) => e.name === n), s = (e) => D.succeed(e), c = (e) => new Map(e.tables.map((e) => [e.name, e])), l = (e, t) => {
3901
- let n = a(e, t);
3915
+ }), zo = (e, t) => e.run === void 0 ? Promise.reject(/* @__PURE__ */ Error("this data store cannot execute raw SQL inside its transaction — use the store for data, or a non-transactional scope for sql")) : e.run(t), Bo = (e, t, n) => {
3916
+ let r = () => ri(e), i = (e, t) => e.tables.find((e) => e.name === t), a = (e, t, n) => i(e, t)?.columns.find((e) => e.name === n), o = (e) => D.succeed(e), s = (e) => new Map(e.tables.map((e) => [e.name, e])), c = (e, t) => {
3917
+ let n = i(e, t);
3902
3918
  if (n === void 0) throw Error(`schema: table ${t} does not exist`);
3903
3919
  return n;
3904
- }, u = (e) => D.gen(function* () {
3905
- let r = () => i().pipe(D.map((t) => ({ tables: t.tables.filter((t) => t.name === e.tableName) }))), a = Oo(jr({
3906
- declared: [e],
3907
- live: yield* r(),
3908
- dialect: n
3920
+ }, l = (n) => D.gen(function* () {
3921
+ let i = () => r().pipe(D.map((e) => ({ tables: e.tables.filter((e) => e.name === n.tableName) }))), a = Ao(jr({
3922
+ declared: [n],
3923
+ live: yield* i(),
3924
+ dialect: t
3909
3925
  })), o = a.operations.filter((e) => e.blocked !== void 0);
3910
- if (o.length > 0) return yield* D.fail(/* @__PURE__ */ Error(`evolve(${e.tableName}): ${o.length} operation(s) cannot be planned:\n` + o.map((e) => ` - ${e.op.kind}: ${e.blocked?.fix ?? e.reason}`).join("\n")));
3911
- for (let n of a.operations) yield* _o(t, n, [e]);
3926
+ if (o.length > 0) return yield* D.fail(/* @__PURE__ */ Error(`evolve(${n.tableName}): ${o.length} operation(s) cannot be planned:\n` + o.map((e) => ` - ${e.op.kind}: ${e.blocked?.fix ?? e.reason}`).join("\n")));
3927
+ for (let t of a.operations) yield* yo(e, t, [n]);
3912
3928
  let s = jr({
3913
- declared: [e],
3914
- live: yield* r(),
3915
- dialect: n
3929
+ declared: [n],
3930
+ live: yield* i(),
3931
+ dialect: t
3916
3932
  });
3917
- return s.operations.length > 0 ? yield* D.fail(/* @__PURE__ */ Error(`evolve(${e.tableName}): applied ${a.operations.length} operation(s) and the re-plan still finds ${s.operations.length}: ${s.operations.map((e) => e.op.kind).join(", ")} — the migration did not converge`)) : { applied: a.operations.length };
3933
+ return s.operations.length > 0 ? yield* D.fail(/* @__PURE__ */ Error(`evolve(${n.tableName}): applied ${a.operations.length} operation(s) and the re-plan still finds ${s.operations.length}: ${s.operations.map((e) => e.op.kind).join(", ")} — the migration did not converge`)) : { applied: a.operations.length };
3918
3934
  });
3919
3935
  return {
3920
- snapshot: i,
3921
- evolve: u,
3936
+ snapshot: r,
3937
+ evolve: l,
3922
3938
  createTable: (e) => D.gen(function* () {
3923
- return (yield* i()).tables.some((t) => t.name === e.tableName) ? yield* s("already-present") : (yield* u(e), "applied");
3939
+ return (yield* r()).tables.some((t) => t.name === e.tableName) ? yield* o("already-present") : (yield* l(e), "applied");
3924
3940
  }),
3925
- dropTable: (e) => D.gen(function* () {
3926
- return (yield* i()).tables.some((t) => t.name === e) ? (yield* _o(t, Fo({
3941
+ dropTable: (t) => D.gen(function* () {
3942
+ return (yield* r()).tables.some((e) => e.name === t) ? (yield* yo(e, Lo({
3927
3943
  kind: "drop-table",
3928
- table: e
3929
- }, "lossy"), []), "applied") : yield* s("already-absent");
3944
+ table: t
3945
+ }, "lossy"), []), "applied") : yield* o("already-absent");
3930
3946
  }),
3931
- renameTable: (e, n) => D.gen(function* () {
3932
- let r = yield* i(), o = a(r, e) !== void 0, c = a(r, n) !== void 0;
3933
- return !o && c ? yield* s("already-present") : o ? c ? yield* D.fail(/* @__PURE__ */ Error(`renameTable: ${n} already exists beside ${e}`)) : (yield* _o(t, Fo({
3947
+ renameTable: (t, n) => D.gen(function* () {
3948
+ let a = yield* r(), s = i(a, t) !== void 0, l = i(a, n) !== void 0;
3949
+ return !s && l ? yield* o("already-present") : s ? l ? yield* D.fail(/* @__PURE__ */ Error(`renameTable: ${n} already exists beside ${t}`)) : (yield* yo(e, Lo({
3934
3950
  kind: "rename-table",
3935
- from: e,
3951
+ from: t,
3936
3952
  to: n
3937
- }), [$(l(r, e))]), "applied") : yield* D.fail(/* @__PURE__ */ Error(`renameTable: ${e} does not exist`));
3953
+ }), [$(c(a, t))]), "applied") : yield* D.fail(/* @__PURE__ */ Error(`renameTable: ${t} does not exist`));
3938
3954
  }),
3939
- addColumn: (e, n, r) => D.gen(function* () {
3940
- let a = yield* i(), o = l(a, e);
3941
- if (o.columns.some((e) => e.name === n)) return yield* s("already-present");
3942
- let d = No(r);
3955
+ addColumn: (t, n, i) => D.gen(function* () {
3956
+ let a = yield* r(), u = c(a, t);
3957
+ if (u.columns.some((e) => e.name === n)) return yield* o("already-present");
3958
+ let d = Fo(i);
3943
3959
  if (!d.nullable && !d.hasDefault && d.backfill === void 0) {
3944
- let r = yield* t`SELECT COUNT(*) AS n FROM ${t(e)}`;
3945
- if (Number(r[0]?.n ?? 0) > 0) return yield* D.fail(/* @__PURE__ */ Error(`addColumn(${e}.${n}): a NOT NULL column without a default cannot be added to a table with rows on any dialect. Add it nullable or with a default, fill it (rewrite), then alterColumn(${JSON.stringify(e)}, ${JSON.stringify(n)}, { nullable: false }).`));
3960
+ let r = yield* e`SELECT COUNT(*) AS n FROM ${e(t)}`;
3961
+ if (Number(r[0]?.n ?? 0) > 0) return yield* D.fail(/* @__PURE__ */ Error(`addColumn(${t}.${n}): a NOT NULL column without a default cannot be added to a table with rows on any dialect. Add it nullable or with a default, fill it (rewrite), then alterColumn(${JSON.stringify(t)}, ${JSON.stringify(n)}, { nullable: false }).`));
3946
3962
  }
3947
- let f = $(o, c(a));
3948
- return yield* u({
3963
+ let f = $(u, s(a));
3964
+ return yield* l({
3949
3965
  ...f,
3950
3966
  fields: {
3951
3967
  ...f.fields,
@@ -3954,12 +3970,12 @@ BEGIN
3954
3970
  }), "applied";
3955
3971
  }),
3956
3972
  alterColumn: (e, t, n) => D.gen(function* () {
3957
- let r = yield* i(), a = l(r, e), o = a.columns.find((e) => e.name === t);
3958
- if (o === void 0) return yield* D.fail(/* @__PURE__ */ Error(`alterColumn: ${e}.${t} does not exist`));
3959
- let d = n.default === void 0 || (n.default === null ? !o.hasDefault : o.hasDefault && String(o.defaultValue) === String(n.default));
3960
- if ((n.nullable === void 0 || n.nullable === o.nullable) && d) return yield* s("already-present");
3973
+ let i = yield* r(), a = c(i, e), u = a.columns.find((e) => e.name === t);
3974
+ if (u === void 0) return yield* D.fail(/* @__PURE__ */ Error(`alterColumn: ${e}.${t} does not exist`));
3975
+ let d = n.default === void 0 || (n.default === null ? !u.hasDefault : u.hasDefault && String(u.defaultValue) === String(n.default));
3976
+ if ((n.nullable === void 0 || n.nullable === u.nullable) && d) return yield* o("already-present");
3961
3977
  let f = {
3962
- ...o,
3978
+ ...u,
3963
3979
  ...n.nullable === void 0 ? {} : { nullable: n.nullable },
3964
3980
  ...n.default === void 0 ? {} : n.default === null ? {
3965
3981
  hasDefault: !1,
@@ -3969,127 +3985,124 @@ BEGIN
3969
3985
  defaultValue: n.default
3970
3986
  }
3971
3987
  };
3972
- return yield* u($({
3988
+ return yield* l($({
3973
3989
  ...a,
3974
3990
  columns: a.columns.map((e) => e.name === t ? f : e)
3975
- }, c(r))), "applied";
3991
+ }, s(i))), "applied";
3976
3992
  }),
3977
3993
  addIndex: (e, t, n = {}) => D.gen(function* () {
3978
- let r = yield* i(), a = l(r, e), o = n.unique === !0;
3979
- if (o && t.length === 1) {
3994
+ let i = yield* r(), a = c(i, e), u = n.unique === !0;
3995
+ if (u && t.length === 1) {
3980
3996
  let n = a.columns.find((e) => e.name === t[0]);
3981
- return n === void 0 ? yield* D.fail(/* @__PURE__ */ Error(`addIndex: ${e}.${t[0]} does not exist`)) : n.unique ? yield* s("already-present") : (yield* u($({
3997
+ return n === void 0 ? yield* D.fail(/* @__PURE__ */ Error(`addIndex: ${e}.${t[0]} does not exist`)) : n.unique ? yield* o("already-present") : (yield* l($({
3982
3998
  ...a,
3983
3999
  columns: a.columns.map((e) => e.name === n.name ? {
3984
4000
  ...e,
3985
4001
  unique: !0
3986
4002
  } : e)
3987
- }, c(r))), "applied");
4003
+ }, s(i))), "applied");
3988
4004
  }
3989
4005
  let d = n.name ?? `${e}_${t.join("_")}_idx`;
3990
- if (a.indexes.some((e) => e.name === d)) return yield* s("already-present");
4006
+ if (a.indexes.some((e) => e.name === d)) return yield* o("already-present");
3991
4007
  let f = {
3992
4008
  name: d,
3993
4009
  table: e,
3994
4010
  columns: t,
3995
- unique: o
4011
+ unique: u
3996
4012
  };
3997
- return yield* u($({
4013
+ return yield* l($({
3998
4014
  ...a,
3999
4015
  indexes: [...a.indexes, f]
4000
- }, c(r))), "applied";
4016
+ }, s(i))), "applied";
4001
4017
  }),
4002
- addForeignKey: (e, t, r, o = {}) => D.gen(function* () {
4003
- let d = yield* i(), f = l(d, e), p = f.columns.find((e) => e.name === t);
4004
- if (p === void 0) return yield* D.fail(/* @__PURE__ */ Error(`addForeignKey: ${e}.${t} does not exist`));
4005
- if (p.references !== void 0) return yield* s("already-present");
4006
- if (a(d, r.table) === void 0) return yield* D.fail(/* @__PURE__ */ Error(`addForeignKey: target table ${r.table} does not exist`));
4007
- let m = r.column ?? "id";
4008
- if ((n === "mysql" || n === "mariadb" || n === "mssql") && p.type === "text" && p.maxLength === void 0) return yield* D.fail(/* @__PURE__ */ Error(`addForeignKey(${e}.${t}): an unbounded text column cannot carry a FOREIGN KEY on ${n} — the referencing column must match the key's width. Add the column as \`reference(() => target)\` (addColumn), or give it \`text().maxLength(n)\` matching the key first.`));
4018
+ addForeignKey: (e, n, a, u = {}) => D.gen(function* () {
4019
+ let d = yield* r(), f = c(d, e), p = f.columns.find((e) => e.name === n);
4020
+ if (p === void 0) return yield* D.fail(/* @__PURE__ */ Error(`addForeignKey: ${e}.${n} does not exist`));
4021
+ if (p.references !== void 0) return yield* o("already-present");
4022
+ if (i(d, a.table) === void 0) return yield* D.fail(/* @__PURE__ */ Error(`addForeignKey: target table ${a.table} does not exist`));
4023
+ let m = a.column ?? "id";
4024
+ if ((t === "mysql" || t === "mariadb" || t === "mssql") && p.type === "text" && p.maxLength === void 0) return yield* D.fail(/* @__PURE__ */ Error(`addForeignKey(${e}.${n}): an unbounded text column cannot carry a FOREIGN KEY on ${t} — the referencing column must match the key's width. Add the column as \`reference(() => target)\` (addColumn), or give it \`text().maxLength(n)\` matching the key first.`));
4009
4025
  let h = {
4010
4026
  ...p,
4011
4027
  type: "reference",
4012
4028
  references: {
4013
- table: r.table,
4029
+ table: a.table,
4014
4030
  column: m,
4015
- onDelete: o.onDelete ?? "noAction",
4016
- onUpdate: o.onUpdate ?? "noAction"
4031
+ onDelete: u.onDelete ?? "noAction",
4032
+ onUpdate: u.onUpdate ?? "noAction"
4017
4033
  }
4018
4034
  };
4019
- return yield* u($({
4035
+ return yield* l($({
4020
4036
  ...f,
4021
- columns: f.columns.map((e) => e.name === t ? h : e)
4022
- }, c(d))), "applied";
4037
+ columns: f.columns.map((e) => e.name === n ? h : e)
4038
+ }, s(d))), "applied";
4023
4039
  }),
4024
4040
  truncate: (t) => D.gen(function* () {
4025
- yield* D.tryPromise({
4026
- try: () => r.deleteMany(t, { where: e("id") }),
4027
- catch: (e) => e
4028
- });
4041
+ return (yield* r()).tables.some((e) => e.name === t) ? (yield* e`DELETE FROM ${e(t)}`, "applied") : yield* o("already-absent");
4029
4042
  }),
4030
- tableExists: (e) => i().pipe(D.map((t) => a(t, e) !== void 0)),
4031
- columnExists: (e, t) => i().pipe(D.map((n) => o(n, e, t) !== void 0)),
4032
- indexExists: (e, t) => i().pipe(D.map((n) => a(n, e)?.indexes.some((e) => e.name === t) ?? !1)),
4033
- foreignKeyExists: (e, t) => i().pipe(D.map((n) => o(n, e, t)?.references !== void 0)),
4034
- dropForeignKey: (e, n) => D.gen(function* () {
4035
- let r = yield* i(), a = o(r, e, n);
4036
- return a?.references === void 0 ? yield* s("already-absent") : (yield* Q(t, {
4043
+ tableExists: (e) => r().pipe(D.map((t) => i(t, e) !== void 0)),
4044
+ columnExists: (e, t) => r().pipe(D.map((n) => a(n, e, t) !== void 0)),
4045
+ indexExists: (e, t) => r().pipe(D.map((n) => i(n, e)?.indexes.some((e) => e.name === t) ?? !1)),
4046
+ foreignKeyExists: (e, t) => r().pipe(D.map((n) => a(n, e, t)?.references !== void 0)),
4047
+ dropForeignKey: (t, n) => D.gen(function* () {
4048
+ let i = yield* r(), s = a(i, t, n);
4049
+ return s?.references === void 0 ? yield* o("already-absent") : (yield* Q(e, {
4037
4050
  kind: "drop-foreign-key",
4038
- table: e,
4051
+ table: t,
4039
4052
  column: n,
4040
- ...a.references.constraintName === void 0 ? {} : { name: a.references.constraintName }
4041
- }, r), "applied");
4053
+ ...s.references.constraintName === void 0 ? {} : { name: s.references.constraintName }
4054
+ }, i), "applied");
4042
4055
  }),
4043
- dropIndex: (e, n) => D.gen(function* () {
4044
- let r = yield* i();
4045
- return a(r, e)?.indexes.some((e) => e.name === n) ?? !1 ? (yield* Q(t, {
4056
+ dropIndex: (t, n) => D.gen(function* () {
4057
+ let a = yield* r();
4058
+ return i(a, t)?.indexes.some((e) => e.name === n) ?? !1 ? (yield* Q(e, {
4046
4059
  kind: "drop-index",
4047
- table: e,
4060
+ table: t,
4048
4061
  index: n
4049
- }, r), "applied") : yield* s("already-absent");
4062
+ }, a), "applied") : yield* o("already-absent");
4050
4063
  }),
4051
- dropColumn: (e, n) => D.gen(function* () {
4052
- let r = yield* i(), c = o(r, e, n);
4053
- if (c === void 0) return yield* s("already-absent");
4054
- c.references !== void 0 && (yield* Q(t, {
4064
+ dropColumn: (t, n) => D.gen(function* () {
4065
+ let s = yield* r(), c = a(s, t, n);
4066
+ if (c === void 0) return yield* o("already-absent");
4067
+ c.references !== void 0 && (yield* Q(e, {
4055
4068
  kind: "drop-foreign-key",
4056
- table: e,
4069
+ table: t,
4057
4070
  column: n,
4058
4071
  ...c.references.constraintName === void 0 ? {} : { name: c.references.constraintName }
4059
- }, r), r = yield* i());
4060
- for (let i of a(r, e)?.indexes ?? []) i.columns.includes(n) && i.name !== `${e}_pkey` && (yield* Q(t, {
4072
+ }, s), s = yield* r());
4073
+ for (let r of i(s, t)?.indexes ?? []) r.columns.includes(n) && r.name !== `${t}_pkey` && (yield* Q(e, {
4061
4074
  kind: "drop-index",
4062
- table: e,
4063
- index: i.name
4064
- }, r));
4065
- return a(r, e)?.indexes.some((t) => t.columns.includes(n) && t.name !== `${e}_pkey`) && (r = yield* i()), yield* Q(t, {
4075
+ table: t,
4076
+ index: r.name
4077
+ }, s));
4078
+ return i(s, t)?.indexes.some((e) => e.columns.includes(n) && e.name !== `${t}_pkey`) && (s = yield* r()), yield* Q(e, {
4066
4079
  kind: "drop-column",
4067
- table: e,
4080
+ table: t,
4068
4081
  column: n
4069
- }, r), "applied";
4082
+ }, s), "applied";
4070
4083
  }),
4071
- renameColumn: (e, n, r) => D.gen(function* () {
4072
- let a = yield* i(), c = o(a, e, n) !== void 0, l = o(a, e, r) !== void 0;
4073
- return !c && l ? yield* s("already-present") : c ? l ? yield* D.fail(/* @__PURE__ */ Error(`renameColumn: ${e}.${r} already exists beside ${n} — a rename cannot merge two columns`)) : (yield* Q(t, {
4084
+ renameColumn: (t, n, i) => D.gen(function* () {
4085
+ let s = yield* r(), c = a(s, t, n) !== void 0, l = a(s, t, i) !== void 0;
4086
+ return !c && l ? yield* o("already-present") : c ? l ? yield* D.fail(/* @__PURE__ */ Error(`renameColumn: ${t}.${i} already exists beside ${n} — a rename cannot merge two columns`)) : (yield* Q(e, {
4074
4087
  kind: "rename-column",
4075
- table: e,
4088
+ table: t,
4076
4089
  from: n,
4077
- to: r
4078
- }, a), "applied") : yield* D.fail(/* @__PURE__ */ Error(`renameColumn: ${e}.${n} does not exist`));
4090
+ to: i
4091
+ }, s), "applied") : yield* D.fail(/* @__PURE__ */ Error(`renameColumn: ${t}.${n} does not exist`));
4079
4092
  })
4080
4093
  };
4081
- }, zo = (e, n, r, a) => {
4094
+ }, Vo = (t, n, i, a) => {
4082
4095
  let o;
4083
4096
  return (async function* () {
4084
4097
  for (;;) {
4085
- let s = [o === void 0 ? void 0 : i("id", o), a].filter((e) => e !== void 0), c = await e.query({
4098
+ let s = [o === void 0 ? void 0 : r("id", o), a].filter((e) => e !== void 0), c = await t.query({
4086
4099
  table: n,
4087
- predicate: s.length === 0 ? void 0 : s.length === 1 ? s[0] : t(...s),
4100
+ predicate: s.length === 0 ? void 0 : s.length === 1 ? s[0] : e(...s),
4088
4101
  order: [{
4089
4102
  column: "id",
4090
4103
  direction: "asc"
4091
4104
  }],
4092
- take: r,
4105
+ take: i,
4093
4106
  skip: void 0,
4094
4107
  projection: void 0
4095
4108
  });
@@ -4097,11 +4110,11 @@ BEGIN
4097
4110
  let l = c[c.length - 1].id;
4098
4111
  if (l == null) throw Error(`each/rewrite: ${n} rows carry no \`id\` — paging needs one`);
4099
4112
  if (o !== void 0 && !(String(l) > String(o))) throw Error(`each/rewrite: paging ${n} did not advance past ${String(o)}`);
4100
- if (o = l, yield c, c.length < r) return;
4113
+ if (o = l, yield c, c.length < i) return;
4101
4114
  }
4102
4115
  })();
4103
- }, Bo = (e) => e > 0 ? D.sleep(`${e} millis`) : D.void, Vo = (e) => (t, n, r = {}) => D.gen(function* () {
4104
- let i = r.batchSize ?? 1e3, a = 0, o = 0, s = zo(e, t, i);
4116
+ }, Ho = (e) => e > 0 ? D.sleep(`${e} millis`) : D.void, Uo = (e) => (t, n, r = {}) => D.gen(function* () {
4117
+ let i = r.batchSize ?? 1e3, a = 0, o = 0, s = Vo(e, t, i);
4105
4118
  for (;;) {
4106
4119
  let e = yield* D.tryPromise({
4107
4120
  try: () => s.next(),
@@ -4109,22 +4122,22 @@ BEGIN
4109
4122
  });
4110
4123
  if (e.done) break;
4111
4124
  o++;
4112
- for (let t of e.value) yield* Io(n(t)), a++;
4113
- yield* Bo(r.sleepMs ?? 0);
4125
+ for (let t of e.value) yield* Ro(n(t)), a++;
4126
+ yield* Ho(r.sleepMs ?? 0);
4114
4127
  }
4115
4128
  return {
4116
4129
  scanned: a,
4117
4130
  pages: o
4118
4131
  };
4119
- }), Ho = (e, t) => t == null ? p(e) : c(e, t), Uo = (e) => typeof e != "object" || !e || e instanceof Date, Wo = (e) => (n, r, i = {}) => D.gen(function* () {
4120
- let a = i.batchSize ?? 1e3, o = i.maxPasses ?? 10, s = i.guard ?? [], l = {
4132
+ }), Wo = (e, t) => t == null ? f(e) : s(e, t), Go = (e) => typeof e != "object" || !e || e instanceof Date, Ko = (t) => (n, r, i = {}) => D.gen(function* () {
4133
+ let a = i.batchSize ?? 1e3, o = i.maxPasses ?? 10, c = i.guard ?? [], l = {
4121
4134
  passes: 0,
4122
4135
  scanned: 0,
4123
4136
  rewritten: 0,
4124
4137
  contended: 0
4125
4138
  }, u = l;
4126
4139
  for (let d = 1; d <= o; d++) {
4127
- let o = 0, f = 0, p = 0, m = zo(e, n, a);
4140
+ let o = 0, f = 0, p = 0, m = Vo(t, n, a);
4128
4141
  for (;;) {
4129
4142
  let a = yield* D.tryPromise({
4130
4143
  try: () => m.next(),
@@ -4140,15 +4153,15 @@ BEGIN
4140
4153
  if (a === void 0) continue;
4141
4154
  let l = Object.entries(a).filter(([e, t]) => !Object.is(i[e], t));
4142
4155
  if (l.length === 0) continue;
4143
- let u = [c("id", i.id)];
4144
- for (let [e] of l) Uo(i[e]) && u.push(Ho(e, i[e]));
4145
- for (let e of s) u.push(Ho(e, i[e]));
4156
+ let u = [s("id", i.id)];
4157
+ for (let [e] of l) Go(i[e]) && u.push(Wo(e, i[e]));
4158
+ for (let e of c) u.push(Wo(e, i[e]));
4146
4159
  (yield* D.tryPromise({
4147
- try: () => e.updateMany(n, Object.fromEntries(l), { where: t(...u) }),
4160
+ try: () => t.updateMany(n, Object.fromEntries(l), { where: e(...u) }),
4148
4161
  catch: (e) => e
4149
4162
  })) === 1 ? f++ : p++;
4150
4163
  }
4151
- yield* Bo(i.sleepMs ?? 0);
4164
+ yield* Ho(i.sleepMs ?? 0);
4152
4165
  }
4153
4166
  if (u = {
4154
4167
  passes: d,
@@ -4162,8 +4175,8 @@ BEGIN
4162
4175
  contended: l.contended + p
4163
4176
  }, f === 0 && p === 0) return l;
4164
4177
  }
4165
- return yield* D.fail(new T(n, u));
4166
- }), Go = (e) => {
4178
+ return yield* D.fail(new w(n, u));
4179
+ }), qo = (e) => {
4167
4180
  let t = `migrations:file:${e.migrationId}`, n = [], r = (t) => {
4168
4181
  if (typeof t != "string" || t.trim().length < 12) throw Error(`raw(reason): say why this migration needs raw SQL — the reason is what a reviewer and \`voltro doctor\` read (got ${JSON.stringify(t)})`);
4169
4182
  return e.sql;
@@ -4185,9 +4198,9 @@ BEGIN
4185
4198
  ...n ?? {}
4186
4199
  }))
4187
4200
  },
4188
- schema: Ro(a, e.dialect, i),
4189
- each: Vo(i),
4190
- rewrite: Wo(i),
4201
+ schema: Bo(a, e.dialect, i),
4202
+ each: Uo(i),
4203
+ rewrite: Ko(i),
4191
4204
  expect: (e, t) => {
4192
4205
  n.push({
4193
4206
  description: e,
@@ -4195,7 +4208,7 @@ BEGIN
4195
4208
  });
4196
4209
  },
4197
4210
  skipUnless: (e, t) => D.gen(function* () {
4198
- if (!(typeof e == "boolean" ? e : yield* Io(e))) return yield* D.fail(new re(t));
4211
+ if (!(typeof e == "boolean" ? e : yield* Ro(e))) return yield* D.fail(new E(t));
4199
4212
  })
4200
4213
  }))(e.store, e.sql),
4201
4214
  transactional: (t) => D.tryPromise({
@@ -4204,18 +4217,18 @@ BEGIN
4204
4217
  store: e,
4205
4218
  raw: r
4206
4219
  });
4207
- return D.isEffect(n) ? Lo(e, n) : n;
4220
+ return D.isEffect(n) ? zo(e, n) : n;
4208
4221
  }),
4209
4222
  catch: (e) => e
4210
4223
  })
4211
4224
  },
4212
4225
  expectations: n
4213
4226
  };
4214
- }, Ko = (e) => D.gen(function* () {
4227
+ }, Jo = (e) => D.gen(function* () {
4215
4228
  let t = [];
4216
- for (let { description: n, check: r } of e) (yield* Io(r())) || t.push(n);
4229
+ for (let { description: n, check: r } of e) (yield* Ro(r())) || t.push(n);
4217
4230
  return t;
4218
- }), qo = _e({ scope: "voltro:migrate" }), Jo = /* @__PURE__ */ new Set([
4231
+ }), Yo = ge({ scope: "voltro:migrate" }), Xo = (e) => he("sha256").update(e).digest("hex").slice(0, 16), Zo = /* @__PURE__ */ new Set([
4219
4232
  "node_modules",
4220
4233
  "dist",
4221
4234
  "build",
@@ -4224,38 +4237,46 @@ BEGIN
4224
4237
  ".next",
4225
4238
  ".git",
4226
4239
  ".framework"
4227
- ]), Yo = async (e) => {
4240
+ ]), Qo = async (e) => {
4228
4241
  let t = [], n = async (e) => {
4229
- let r = await ve.readdir(e, { withFileTypes: !0 }).catch(() => []);
4242
+ let r = await _e.readdir(e, { withFileTypes: !0 }).catch(() => []);
4230
4243
  for (let i of r) {
4231
- if (Jo.has(i.name)) continue;
4232
- let r = ye(e, i.name);
4233
- i.isDirectory() ? await n(r) : i.isFile() && se.test(i.name) && t.push(r);
4244
+ if (Zo.has(i.name)) continue;
4245
+ let r = ve(e, i.name);
4246
+ i.isDirectory() ? await n(r) : i.isFile() && oe.test(i.name) && t.push(r);
4234
4247
  }
4235
4248
  };
4236
4249
  return await n(e), t.sort((e, t) => {
4237
4250
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
4238
4251
  return n.localeCompare(r);
4239
4252
  });
4240
- }, Xo = async (e) => {
4253
+ }, $o = async (e) => {
4241
4254
  let t = [];
4242
4255
  for (let n of e) {
4243
- let e = (await import(be(n).href)).default;
4244
- if (!ce(e)) {
4245
- qo.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
4256
+ let e = (await import(ye(n).href)).default;
4257
+ if (!se(e)) {
4258
+ Yo.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
4246
4259
  continue;
4247
4260
  }
4261
+ let r = await _e.readFile(n, "utf8").catch(() => "");
4248
4262
  t.push({
4249
4263
  file: n,
4250
- migration: e
4264
+ migration: e,
4265
+ hash: Xo(r)
4251
4266
  });
4252
4267
  }
4253
4268
  return t;
4254
- }, Zo = (e) => e`
4255
- SELECT ${e("id")}
4269
+ }, es = (e) => ts(e).pipe(D.map((e) => e.map((e) => e.id))), ts = (e) => e`
4270
+ SELECT ${e("id")}, ${e("fingerprint")}
4256
4271
  FROM ${e("_voltro_migration_plans")}
4257
4272
  WHERE ${e("source")} = 'file'
4258
- `.pipe(D.map((e) => e.map((e) => e.id)), D.catchAll(() => D.succeed([]))), Qo = class extends Error {
4273
+ `.pipe(D.map((e) => e.map((e) => ({
4274
+ id: e.id,
4275
+ hash: e.fingerprint ?? ""
4276
+ }))), D.catchAll(() => D.succeed([]))), ns = (e, t) => t.filter((t) => {
4277
+ let n = e.get(t.migration.id);
4278
+ return n !== void 0 && n !== "" && n !== t.hash;
4279
+ }).map((e) => e.migration.id), rs = class extends Error {
4259
4280
  migrationId;
4260
4281
  file;
4261
4282
  cause;
@@ -4263,7 +4284,7 @@ BEGIN
4263
4284
  constructor(e, t, n) {
4264
4285
  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";
4265
4286
  }
4266
- }, $o = (e, t, n) => D.gen(function* () {
4287
+ }, is = (e, t, n) => D.gen(function* () {
4267
4288
  let r = yield* W(e, n.appliedAtIso);
4268
4289
  yield* e`
4269
4290
  INSERT INTO ${e("_voltro_migration_plans")}
@@ -4271,53 +4292,53 @@ BEGIN
4271
4292
  ${e("appliedBy")}, ${e("environment")}, ${e("source")},
4272
4293
  ${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
4273
4294
  VALUES
4274
- (${t.migration.id}, ${""}, ${JSON.stringify([{
4295
+ (${t.migration.id}, ${t.hash}, ${JSON.stringify([{
4275
4296
  kind: "file",
4276
4297
  file: t.file
4277
4298
  }])},
4278
4299
  ${n.appliedBy}, ${n.env}, ${"file"},
4279
4300
  ${n.durationMs}, ${r}, ${n.notes})
4280
- `.pipe(D.mapError((e) => new Qo(t.migration.id, t.file, e)));
4281
- }), es = (e, t, n) => D.gen(function* () {
4301
+ `.pipe(D.mapError((e) => new rs(t.migration.id, t.file, e)));
4302
+ }), as = (e, t, n) => D.gen(function* () {
4282
4303
  let r = e.migration.up(t), i = !D.isEffect(r), a = yield* (D.isEffect(r) ? r : D.tryPromise({
4283
4304
  try: () => r,
4284
4305
  catch: (e) => e
4285
- })).pipe(D.as(void 0), D.catchIf((e) => e instanceof re, (e) => D.succeed(e.reason)));
4306
+ })).pipe(D.as(void 0), D.catchIf((e) => e instanceof E, (e) => D.succeed(e.reason)));
4286
4307
  if (a === void 0) {
4287
- let t = yield* Ko(n);
4288
- if (t.length > 0) return yield* D.fail(new x(e.migration.id, t));
4308
+ let t = yield* Jo(n);
4309
+ if (t.length > 0) return yield* D.fail(new b(e.migration.id, t));
4289
4310
  }
4290
4311
  return {
4291
4312
  skipped: a,
4292
4313
  promiseForm: i
4293
4314
  };
4294
- }), ts = (e, t, n, r, i, a) => D.gen(function* () {
4295
- let o = Date.now(), s = (/* @__PURE__ */ new Date()).toISOString(), c = j(e), l = `migrations:file:${n.migration.id}`, u = (e) => ({
4315
+ }), os = (e, t, n, r, i, a) => D.gen(function* () {
4316
+ let o = Date.now(), s = (/* @__PURE__ */ new Date()).toISOString(), c = A(e), l = `migrations:file:${n.migration.id}`, u = (e) => ({
4296
4317
  durationMs: Date.now() - o,
4297
4318
  notes: e.skipped === void 0 ? n.migration.description : `skipped: ${e.skipped}`
4298
4319
  });
4299
4320
  if (n.migration.transactional !== !1 && !a) {
4300
4321
  if (t.run === void 0) return yield* D.fail(/* @__PURE__ */ Error(`migration ${n.migration.id}: transactional: true needs a SQL-backed store`));
4301
4322
  let a = c === "mysql" || c === "mariadb", o = `probe_${n.migration.id}_${Date.now().toString(36)}`;
4302
- a && (yield* Qa(e, c));
4303
- let d = () => e`SELECT COUNT(*) AS n FROM ${e(M)} WHERE ${e("runId")} = ${o}`.pipe(D.map((e) => Number(e[0]?.n ?? 0) > 0)), f = yield* D.tryPromise({
4323
+ a && (yield* eo(e, c));
4324
+ let d = () => e`SELECT COUNT(*) AS n FROM ${e(j)} WHERE ${e("runId")} = ${o}`.pipe(D.map((e) => Number(e[0]?.n ?? 0) > 0)), f = yield* D.tryPromise({
4304
4325
  try: () => t.transactional(async (t) => {
4305
- a && await t.run(e`INSERT INTO ${e(M)} (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")}, ${e("status")}, ${e("opKind")}, ${e("opTarget")}, ${e("payload")})
4326
+ a && await t.run(e`INSERT INTO ${e(j)} (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")}, ${e("status")}, ${e("opKind")}, ${e("opTarget")}, ${e("payload")})
4306
4327
  VALUES (${`mop_${o}`}, ${o}, ${""}, ${0}, ${"pending"}, ${"probe"}, ${""}, ${"{}"})`);
4307
- let { ctx: l, expectations: f } = Go({
4328
+ let { ctx: l, expectations: f } = qo({
4308
4329
  sql: e,
4309
4330
  store: t,
4310
4331
  dialect: c,
4311
4332
  migrationId: n.migration.id,
4312
4333
  appliedAt: s
4313
- }), p = await t.run(es(n, l, f)), m = a && await D.runPromise(d().pipe(D.provideService(O.SqlClient, e))), { durationMs: h, notes: g } = u(p);
4314
- return await t.run($o(e, n, {
4334
+ }), p = await t.run(as(n, l, f)), m = a && await D.runPromise(d().pipe(D.provideService(O.SqlClient, e))), { durationMs: h, notes: g } = u(p);
4335
+ return await t.run(is(e, n, {
4315
4336
  env: r,
4316
4337
  appliedBy: i,
4317
4338
  durationMs: h,
4318
4339
  appliedAtIso: s,
4319
4340
  notes: m ? `${g} — transactional guarantee broken by the body (DDL on ${c})` : g
4320
- })), a && await t.run(e`DELETE FROM ${e(M)} WHERE ${e("runId")} = ${o}`), {
4341
+ })), a && await t.run(e`DELETE FROM ${e(j)} WHERE ${e("runId")} = ${o}`), {
4321
4342
  ...p,
4322
4343
  durationMs: h,
4323
4344
  broken: m
@@ -4325,49 +4346,67 @@ BEGIN
4325
4346
  }),
4326
4347
  catch: (e) => e
4327
4348
  });
4328
- return f.broken ? yield* D.fail(new C(n.migration.id, c)) : (f.skipped !== void 0 && (yield* D.logInfo(`migration ${n.migration.id} skipped: ${f.skipped}`).pipe(D.annotateLogs({ scope: l }))), { durationMs: f.durationMs });
4349
+ return f.broken ? yield* D.fail(new S(n.migration.id, c)) : (f.skipped !== void 0 && (yield* D.logInfo(`migration ${n.migration.id} skipped: ${f.skipped}`).pipe(D.annotateLogs({ scope: l }))), { durationMs: f.durationMs });
4329
4350
  }
4330
- let { ctx: d, expectations: f } = Go({
4351
+ let { ctx: d, expectations: f } = qo({
4331
4352
  sql: e,
4332
4353
  store: t,
4333
4354
  dialect: c,
4334
4355
  migrationId: n.migration.id,
4335
4356
  appliedAt: s
4336
- }), p = yield* es(n, d, f), { durationMs: m, notes: h } = u(p);
4337
- return p.promiseForm && p.skipped === void 0 && m < 2 && (yield* D.logWarning(`migration ${n.migration.id}: up() resolved in ${m}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(D.annotateLogs({ scope: l }))), p.skipped !== void 0 && (yield* D.logInfo(`migration ${n.migration.id} skipped: ${p.skipped}`).pipe(D.annotateLogs({ scope: l }))), yield* $o(e, n, {
4357
+ }), p = yield* as(n, d, f), { durationMs: m, notes: h } = u(p);
4358
+ return p.promiseForm && p.skipped === void 0 && m < 2 && (yield* D.logWarning(`migration ${n.migration.id}: up() resolved in ${m}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(D.annotateLogs({ scope: l }))), p.skipped !== void 0 && (yield* D.logInfo(`migration ${n.migration.id} skipped: ${p.skipped}`).pipe(D.annotateLogs({ scope: l }))), yield* is(e, n, {
4338
4359
  env: r,
4339
4360
  appliedBy: i,
4340
4361
  durationMs: m,
4341
4362
  appliedAtIso: s,
4342
4363
  notes: h
4343
4364
  }), { durationMs: m };
4344
- }), ns = (e, t) => D.gen(function* () {
4365
+ }), ss = (e, t) => D.gen(function* () {
4345
4366
  let n = yield* D.tryPromise({
4346
- try: () => Yo(ye(t, "migrations")),
4367
+ try: () => Qo(ve(t, "migrations")),
4347
4368
  catch: (e) => e
4348
4369
  });
4349
4370
  if (n.length === 0) return {
4350
4371
  pending: [],
4351
- skipped: []
4372
+ skipped: [],
4373
+ drifted: []
4352
4374
  };
4353
4375
  let r = yield* D.tryPromise({
4354
- try: () => Xo(n),
4376
+ try: () => $o(n),
4355
4377
  catch: (e) => e
4356
4378
  });
4357
4379
  if (r.length === 0) return {
4358
4380
  pending: [],
4359
- skipped: []
4381
+ skipped: [],
4382
+ drifted: []
4360
4383
  };
4361
- let i = new Set(yield* Zo(e));
4384
+ let i = new Map((yield* ts(e)).map((e) => [e.id, e.hash])), a = ns(i, r);
4385
+ for (let e of a) Yo.warn("file migration: the body on disk is not the one that was applied — the file no longer describes this database", {
4386
+ id: e,
4387
+ file: r.find((t) => t.migration.id === e)?.file
4388
+ });
4362
4389
  return {
4363
4390
  pending: r.filter((e) => !i.has(e.migration.id)),
4364
- skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
4391
+ skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id),
4392
+ drifted: a
4365
4393
  };
4366
- }), rs = (e, t) => ns(e, t).pipe(D.map((e) => e.pending.map((e) => e.migration.id))), is = (e, t) => ns(e, t).pipe(D.map((e) => e.pending.map((e) => ({
4394
+ }), cs = (e, t) => ss(e, t).pipe(D.map((e) => e.pending.map((e) => e.migration.id))), ls = (e, t) => ss(e, t).pipe(D.map((e) => e.pending.map((e) => ({
4367
4395
  id: e.migration.id,
4368
- irreversible: g(e.migration.down)
4369
- })))), as = (e, t) => D.gen(function* () {
4370
- let { pending: n, skipped: r } = yield* ns(e, t.projectRoot);
4396
+ irreversible: h(e.migration.down)
4397
+ })))), us = (e, t) => ss(e, t).pipe(D.map((e) => {
4398
+ let t = new Set(e.drifted);
4399
+ return [...e.skipped.map((e) => ({
4400
+ id: e,
4401
+ applied: !0,
4402
+ bodyChanged: t.has(e)
4403
+ })), ...e.pending.map((e) => ({
4404
+ id: e.migration.id,
4405
+ applied: !1,
4406
+ bodyChanged: !1
4407
+ }))].sort((e, t) => e.id < t.id ? -1 : 1);
4408
+ })), ds = (e, t) => D.gen(function* () {
4409
+ let { pending: n, skipped: r } = yield* ss(e, t.projectRoot);
4371
4410
  return n.length === 0 ? {
4372
4411
  applied: [],
4373
4412
  skipped: r
@@ -4380,7 +4419,7 @@ BEGIN
4380
4419
  id: i.migration.id,
4381
4420
  file: i.file
4382
4421
  }));
4383
- let { durationMs: n } = yield* ts(e, t.store, i, t.env, t.appliedBy, t.enclosed === !0);
4422
+ let { durationMs: n } = yield* os(e, t.store, i, t.env, t.appliedBy, t.enclosed === !0);
4384
4423
  r.push({
4385
4424
  id: i.migration.id,
4386
4425
  durationMs: n
@@ -4394,26 +4433,26 @@ BEGIN
4394
4433
  }), (e) => e.release.pipe(D.orDie)),
4395
4434
  skipped: r
4396
4435
  };
4397
- }), os = (e, t) => e`
4436
+ }), fs = (e, t) => e`
4398
4437
  SELECT ${e("id")}
4399
4438
  FROM ${e("_voltro_migration_plans")}
4400
4439
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
4401
- `, ss = (e, t) => D.gen(function* () {
4402
- if (!(yield* os(e, t.id))[0]) return yield* D.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
4440
+ `, ps = (e, t) => D.gen(function* () {
4441
+ if (!(yield* fs(e, t.id))[0]) return yield* D.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
4403
4442
  let n = yield* D.tryPromise({
4404
- try: () => Yo(ye(t.projectRoot, "migrations")),
4443
+ try: () => Qo(ve(t.projectRoot, "migrations")),
4405
4444
  catch: (e) => e
4406
4445
  }), r = (yield* D.tryPromise({
4407
- try: () => Xo(n),
4446
+ try: () => $o(n),
4408
4447
  catch: (e) => e
4409
4448
  })).find((e) => e.migration.id === t.id);
4410
4449
  if (!r) return yield* D.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
4411
- let i = g(r.migration.down);
4450
+ let i = h(r.migration.down);
4412
4451
  return i === void 0 ? yield* D.acquireUseRelease($e(e, { schema: t.lockSchema }), () => D.gen(function* () {
4413
- let n = Date.now(), { ctx: i } = Go({
4452
+ let n = Date.now(), { ctx: i } = qo({
4414
4453
  sql: e,
4415
4454
  store: t.store,
4416
- dialect: j(e),
4455
+ dialect: A(e),
4417
4456
  migrationId: t.id,
4418
4457
  appliedAt: (/* @__PURE__ */ new Date()).toISOString()
4419
4458
  }), a = r.migration.down(i);
@@ -4426,8 +4465,8 @@ BEGIN
4426
4465
  id: t.id,
4427
4466
  durationMs: o
4428
4467
  };
4429
- }), (e) => e.release.pipe(D.orDie)) : yield* D.fail(new b(t.id, i));
4430
- }), cs = (e) => D.gen(function* () {
4468
+ }), (e) => e.release.pipe(D.orDie)) : yield* D.fail(new y(t.id, i));
4469
+ }), ms = (e) => D.gen(function* () {
4431
4470
  let t = yield* O.SqlClient, n = yield* t`
4432
4471
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
4433
4472
  WHERE source = 'auto-diff'
@@ -4472,7 +4511,7 @@ BEGIN
4472
4511
  snapshotFingerprint: e.fingerprint,
4473
4512
  snapshotId: i
4474
4513
  };
4475
- }), ls = { safe: !0 }, us = (e) => {
4514
+ }), hs = { safe: !0 }, gs = (e) => {
4476
4515
  switch (e.kind) {
4477
4516
  case "add-enum-value": return { safe: !0 };
4478
4517
  case "drop-column": return {
@@ -4500,7 +4539,7 @@ BEGIN
4500
4539
  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`,
4501
4540
  remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
4502
4541
  };
4503
- case "alter-column-nullability": return e.toNullable ? ls : {
4542
+ case "alter-column-nullability": return e.toNullable ? hs : {
4504
4543
  safe: !1,
4505
4544
  reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
4506
4545
  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)`
@@ -4511,12 +4550,12 @@ BEGIN
4511
4550
  reason: `old instances still write "${e.table}" without honouring the new uniqueness; a colliding insert now fails mid-rollout`,
4512
4551
  remedy: "make code enforce uniqueness first and deploy that; add the constraint in a LATER deploy once no old writer remains"
4513
4552
  };
4514
- case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ? ls : {
4553
+ case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ? hs : {
4515
4554
  safe: !1,
4516
4555
  reason: `writes to "${e.table}"."${e.column}" must satisfy the new JSON validation`,
4517
4556
  remedy: "ensure all writers supply valid JSON in the required domain before enabling this check"
4518
4557
  };
4519
- case "add-check": return e.table.startsWith("_voltro_") ? ls : {
4558
+ case "add-check": return e.table.startsWith("_voltro_") ? hs : {
4520
4559
  safe: !1,
4521
4560
  reason: `old instances may write values to "${e.table}" the new CHECK rejects`,
4522
4561
  remedy: "make code satisfy the constraint first and deploy that; add the CHECK in a LATER deploy"
@@ -4535,12 +4574,12 @@ BEGIN
4535
4574
  case "drop-unique":
4536
4575
  case "drop-unique-composite":
4537
4576
  case "drop-foreign-key":
4538
- case "drop-check": return ls;
4577
+ case "drop-check": return hs;
4539
4578
  }
4540
- }, ds = (e) => {
4579
+ }, _s = (e) => {
4541
4580
  let t = [];
4542
4581
  for (let n of e) {
4543
- let e = us(n.op);
4582
+ let e = gs(n.op);
4544
4583
  e.safe || t.push({
4545
4584
  op: n,
4546
4585
  reason: e.reason,
@@ -4548,7 +4587,7 @@ BEGIN
4548
4587
  });
4549
4588
  }
4550
4589
  return t;
4551
- }, fs = (e) => {
4590
+ }, vs = (e) => {
4552
4591
  if (!e.enabled || e.unsafeCount === 0) return {
4553
4592
  refuse: !1,
4554
4593
  warnForced: !1,
@@ -4564,18 +4603,18 @@ BEGIN
4564
4603
  warnForced: !1,
4565
4604
  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.`
4566
4605
  };
4567
- }, ps = (e) => {
4606
+ }, ys = (e) => {
4568
4607
  let t = e.table;
4569
4608
  if (typeof t == "string") return t;
4570
4609
  let n = e.from;
4571
4610
  return typeof n == "string" ? n : void 0;
4572
- }, ms = (e) => ({
4611
+ }, bs = (e) => ({
4573
4612
  kind: e.op.kind,
4574
- table: ps(e.op),
4613
+ table: ys(e.op),
4575
4614
  classification: e.classification,
4576
4615
  reason: e.reason,
4577
4616
  blockedFix: e.blocked?.fix
4578
- }), hs = (e) => e.operations.map(ms), gs = async (e) => {
4617
+ }), xs = (e) => e.operations.map(bs), Ss = async (e) => {
4579
4618
  let t = e.log ?? (() => {}), n = {
4580
4619
  branchId: e.branchId,
4581
4620
  mechanism: e.mechanism,
@@ -4594,10 +4633,10 @@ BEGIN
4594
4633
  applied: !1,
4595
4634
  converged: !1,
4596
4635
  residual: r,
4597
- infidelity: hs(o)
4636
+ infidelity: xs(o)
4598
4637
  };
4599
4638
  else {
4600
- let i = await e.plan(), o = hs(i), s = o.filter((e) => e.classification === "lossy"), c = Oo(i), l = c.operations.filter((e) => e.blocked !== void 0).map(ms);
4639
+ let i = await e.plan(), o = xs(i), s = o.filter((e) => e.classification === "lossy"), c = Ao(i), l = c.operations.filter((e) => e.blocked !== void 0).map(bs);
4601
4640
  if (l.length > 0) a = {
4602
4641
  ...n,
4603
4642
  outcome: "blocked",
@@ -4622,7 +4661,7 @@ BEGIN
4622
4661
  };
4623
4662
  else {
4624
4663
  await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
4625
- let i = hs(await e.replan());
4664
+ let i = xs(await e.replan());
4626
4665
  a = {
4627
4666
  ...n,
4628
4667
  outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
@@ -4660,7 +4699,7 @@ BEGIN
4660
4699
  ...a,
4661
4700
  tornDown: o
4662
4701
  };
4663
- }, _s = (e) => {
4702
+ }, Cs = (e) => {
4664
4703
  switch (e.outcome) {
4665
4704
  case "clean": return 0;
4666
4705
  case "lossy": return 2;
@@ -4669,22 +4708,22 @@ BEGIN
4669
4708
  case "infidelity": return 1;
4670
4709
  case "failed": return 1;
4671
4710
  }
4672
- }, vs = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ys = (e) => {
4711
+ }, ws = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Ts = (e) => {
4673
4712
  let t = [];
4674
4713
  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"}`);
4675
4714
  else if (e.outcome === "infidelity") {
4676
4715
  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:");
4677
- for (let n of e.infidelity) t.push(vs(n));
4716
+ for (let n of e.infidelity) t.push(ws(n));
4678
4717
  } else {
4679
4718
  t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
4680
- for (let n of e.operations) t.push(vs(n));
4681
- 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(vs(n));
4719
+ for (let n of e.operations) t.push(ws(n));
4720
+ 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(ws(n));
4682
4721
  }
4683
4722
  return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
4684
- }, bs = (e, ...t) => ({
4723
+ }, Es = (e, ...t) => ({
4685
4724
  _tag: "RawSqlFragment",
4686
4725
  strings: [...e],
4687
4726
  values: [...t]
4688
- }), xs = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
4727
+ }), Ds = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
4689
4728
  //#endregion
4690
- export { bt as DEFAULT_CDC_CHANNEL, U as DEPLOY_LEDGER_TABLE, se as FILE_MIGRATION_PATTERN, Qo as FileMigrationLedgerError, b as IrreversibleMigrationError, rt as MIGRATION_ATOMICITY, et as MIGRATION_NEEDS_TWO_CONNECTIONS, x as MigrationExpectationFailed, re as MigrationSkipped, xt as REACTIVE_TRIGGER_PREFIX, T as RewriteUnstableError, C as TransactionBrokenByBodyError, Ne as VOLTRO_MIGRATION_LOCK_KEY, oi as _voltroDeploysTable, $e as acquireMigrationLock, W as appliedAtValue, Zo as appliedFileMigrationIds, oo as appliedLedgerOperations, gn as applyNamespacedSchema, mo as applyPlan, on as applySchema, fs as assessRollingDeployGate, _s as branchRehearsalExitCode, Hr as chunkTables, us as classifyRollingDeploySafety, so as clearResumeLedger, ci as closeDeploy, L as declaredSnapshot, Ot as defaultArrayClause, Dt as defaultClause, kt as defaultJsonClause, Mo as describeOutcome, Eo as destructiveScope, Qn as detectReactiveTriggerDrift, ga as emitAddIndexMysql, sa as emitCreateTableMssql, Ji as emitCreateTableMysql, Ui as emitCreateTablePg, ea as emitCreateTableSqlite, Di as emitDropColumnDdl, Oi as emitDropColumnDdlMysql, an as emitFrameworkBootstrapSql, nn as emitNamespaceProvisionDdl, rn as emitNamespacedSchemaSql, tn as emitSchemaSql, ri as engineFromVersion, $a as ensureDeployLedgerTable, Qa as ensureLedgerTable, $t as enumRenameBlocks, Qt as enumTypeBlocks, Kt as extensionBlocks, li as failDeploy, Ko as failedExpectations, I as fingerprintSchema, ze as fnv1a64, ys as formatBranchRehearsal, $n as formatReactiveTriggerDrift, To as ignoreTablesFromEnv, ni as introspectSchema, S as irreversible, g as irreversibleReason, pi as isAlreadySatisfied, ce as isFileMigration, xs as isRawSqlFragment, cn as isReRunSafeDdl, Go as makeFileMigrationContext, Pr as mapPgType, Po as materialiseSnapshot, ue as migration, it as migrationAtomicityFor, Be as migrationLockKeyForSchema, Ve as migrationLockNameForSchema, da as mysqlIndexPrefixFor, Ct as notifyFunctionName, At as numericIdSql, si as openDeploy, Nr as parseEnumCheck, rs as pendingFileMigrationIds, is as pendingFileMigrationSummary, jr as planMigrations, _n as provisionTenantNamespace, St as reactiveTriggerName, Gt as reactiveTriggerRepairSql, bo as recordUpToDate, gs as rehearseMigrationOnBranch, ms as rehearsedOperation, Ki as renderColumnMysql, Bi as renderColumnPg, Fe as resolveMigrationLockSchema, H as resolveMysqlEngine, ss as rollbackFileBasedMigration, ds as rollingDeployUnsafeOps, as as runFileBasedMigrations, vn as runFrameworkBootstrap, hn as runMigrate, _o as runMigrationOp, jo as runPlannedMigrations, Q as runSchemaOp, Kn as shortFingerprint, qn as snapshotColumn, bs as sql, P as sqlType, cs as squashMigrationPlans, Oo as unblockLossy, ui as unfinishedDeploys, nt as withMigrationLock };
4729
+ export { bt as DEFAULT_CDC_CHANNEL, U as DEPLOY_LEDGER_TABLE, oe as FILE_MIGRATION_PATTERN, rs as FileMigrationLedgerError, y as IrreversibleMigrationError, rt as MIGRATION_ATOMICITY, et as MIGRATION_NEEDS_TWO_CONNECTIONS, b as MigrationExpectationFailed, E as MigrationSkipped, xt as REACTIVE_TRIGGER_PREFIX, w as RewriteUnstableError, S as TransactionBrokenByBodyError, Ne as VOLTRO_MIGRATION_LOCK_KEY, ci as _voltroDeploysTable, $e as acquireMigrationLock, Ka as addColumnDdl, W as appliedAtValue, es as appliedFileMigrationIds, ts as appliedFileMigrations, co as appliedLedgerOperations, gn as applyNamespacedSchema, go as applyPlan, on as applySchema, vs as assessRollingDeployGate, Cs as branchRehearsalExitCode, Hr as chunkTables, gs as classifyRollingDeploySafety, lo as clearResumeLedger, ui as closeDeploy, z as declaredSnapshot, jt as defaultArrayClause, At as defaultClause, P as defaultJsonClause, Po as describeOutcome, Oo as destructiveScope, Qn as detectReactiveTriggerDrift, va as emitAddIndexMysql, la as emitCreateTableMssql, Xi as emitCreateTableMysql, Gi as emitCreateTablePg, na as emitCreateTableSqlite, ki as emitDropColumnDdl, Ai as emitDropColumnDdlMysql, an as emitFrameworkBootstrapSql, nn as emitNamespaceProvisionDdl, rn as emitNamespacedSchemaSql, tn as emitSchemaSql, ii as engineFromVersion, to as ensureDeployLedgerTable, eo as ensureLedgerTable, $t as enumRenameBlocks, Qt as enumTypeBlocks, Kt as extensionBlocks, di as failDeploy, Jo as failedExpectations, us as fileMigrationStatus, R as fingerprintSchema, ze as fnv1a64, Ts as formatBranchRehearsal, $n as formatReactiveTriggerDrift, Do as ignoreTablesFromEnv, ri as introspectSchema, x as irreversible, h as irreversibleReason, hi as isAlreadySatisfied, se as isFileMigration, Ds as isRawSqlFragment, cn as isReRunSafeDdl, qo as makeFileMigrationContext, Pr as mapPgType, Io as materialiseSnapshot, le as migration, it as migrationAtomicityFor, Xo as migrationBodyHash, Be as migrationLockKeyForSchema, Ve as migrationLockNameForSchema, pa as mysqlIndexPrefixFor, Et as notifyFunctionName, F as numericIdSql, li as openDeploy, Nr as parseEnumCheck, cs as pendingFileMigrationIds, ls as pendingFileMigrationSummary, jr as planMigrations, _n as provisionTenantNamespace, St as reactiveTriggerName, Gt as reactiveTriggerRepairSql, So as recordUpToDate, Ss as rehearseMigrationOnBranch, bs as rehearsedOperation, Ji as renderColumnMysql, Hi as renderColumnPg, Fe as resolveMigrationLockSchema, oi as resolveMysqlEngine, ps as rollbackFileBasedMigration, _s as rollingDeployUnsafeOps, ds as runFileBasedMigrations, vn as runFrameworkBootstrap, hn as runMigrate, yo as runMigrationOp, No as runPlannedMigrations, Q as runSchemaOp, Kn as shortFingerprint, qn as snapshotColumn, Es as sql, N as sqlType, ms as squashMigrationPlans, Ao as unblockLossy, fi as unfinishedDeploys, nt as withMigrationLock };