@voltro/database 0.12.0 → 0.14.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,4 +1,4 @@
1
- import { R as e, U as t, a as n, c as r, ct as i, i as a, n as o, nt as s, r as c, t as l, z as u } from "./fileBased-DEW2BvnP.js";
1
+ import { B as e, W as t, a as n, c as r, i, lt as a, n as o, r as s, rt as c, t as l, z as u } from "./fileBased-Dfuv6JWP.js";
2
2
  import { Effect as d } from "effect";
3
3
  import { createLogger as f } from "@voltro/logger";
4
4
  import { SqlClient as p } from "@effect/sql";
@@ -39,7 +39,7 @@ var _ = (e, t, n, r = 400) => {
39
39
  t !== void 0 && s.push(`db.${e}: ${t}`);
40
40
  }
41
41
  return s.push(""), s.join("\n");
42
- }, v = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, y = (e) => e.replace(/"/g, "`"), te = (e) => typeof e == "string" ? e : e.name ?? String(e), ne = (e, t) => `_ua_${t}_${e}`.slice(0, 64), b = (e, t) => {
42
+ }, v = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, y = (e) => e.replace(/"/g, "`"), b = (e) => typeof e == "string" ? e : e.name ?? String(e), x = (e, t) => `_ua_${t}_${e}`.slice(0, 64), S = (e, t) => {
43
43
  if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(v)) return e;
44
44
  let n = { ...e.fields }, r = [], i = [];
45
45
  for (let t of e.appliedIndexes) {
@@ -49,9 +49,9 @@ var _ = (e, t, n, r = 400) => {
49
49
  }
50
50
  let a = y(t.where), o = [];
51
51
  for (let r of t.fields) {
52
- let i = te(r);
52
+ let i = b(r);
53
53
  if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
54
- let s = ne(t.name, i);
54
+ let s = x(t.name, i);
55
55
  o.push(s), n[s] = {
56
56
  type: "text",
57
57
  nullable: !0,
@@ -74,101 +74,101 @@ var _ = (e, t, n, r = 400) => {
74
74
  appliedIndexes: r,
75
75
  appliedUniques: [...e.appliedUniques ?? [], ...i]
76
76
  };
77
- }, x = (e, t) => `${e}::${t}`, S = (e, t) => {
77
+ }, C = (e, t) => `${e}::${t}`, w = (e, t) => {
78
78
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
79
79
  n.add(e);
80
80
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
81
- for (let t of o) n.has(t.target) ? i.add(x(e, t.column)) : r.has(t.target) || a(t.target);
81
+ for (let t of o) n.has(t.target) ? i.add(C(e, t.column)) : r.has(t.target) || a(t.target);
82
82
  n.delete(e), r.add(e);
83
83
  };
84
84
  for (let t of [...e].sort()) r.has(t) || a(t);
85
85
  return i;
86
- }, C = 6322741009312437n, re = 250, ie = () => {
86
+ }, te = 6322741009312437n, ne = 250, re = () => {
87
87
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
88
88
  return Number.isFinite(e) && e > 0 ? e : 3e4;
89
- }, ae = (e) => d.gen(function* () {
90
- let t = ie(), n = Date.now();
89
+ }, ie = (e) => d.gen(function* () {
90
+ let t = re(), n = Date.now();
91
91
  for (;;) {
92
92
  if ((yield* e`
93
93
  SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
94
- Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* d.sleep(`${re} millis`);
94
+ Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* d.sleep(`${ne} millis`);
95
95
  }
96
- }), oe = (e) => d.gen(function* () {
97
- yield* e`SELECT pg_advisory_unlock(${C.toString()}::bigint)`;
98
- }), se = `voltro_migration_${C.toString(36)}`, ce = 30, le = (e) => d.gen(function* () {
96
+ }), ae = (e) => d.gen(function* () {
97
+ yield* e`SELECT pg_advisory_unlock(${te.toString()}::bigint)`;
98
+ }), oe = `voltro_migration_${te.toString(36)}`, se = 30, ce = (e) => d.gen(function* () {
99
99
  (yield* e`
100
- SELECT GET_LOCK(${se}, ${ce}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${se}' within ${ce}s (another migration is in progress, or a prior one left it held).`)));
101
- }), ue = (e) => d.gen(function* () {
102
- yield* e`SELECT RELEASE_LOCK(${se})`;
103
- }), de = `voltro_migration_${C.toString(36)}`, fe = 3e4, pe = (e) => d.gen(function* () {
100
+ SELECT GET_LOCK(${oe}, ${se}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${oe}' within ${se}s (another migration is in progress, or a prior one left it held).`)));
101
+ }), le = (e) => d.gen(function* () {
102
+ yield* e`SELECT RELEASE_LOCK(${oe})`;
103
+ }), ue = `voltro_migration_${te.toString(36)}`, de = 3e4, fe = (e) => d.gen(function* () {
104
104
  let t = yield* e`
105
105
  DECLARE @res int;
106
- EXEC @res = sp_getapplock @Resource = ${de}, @LockMode = 'Exclusive',
107
- @LockOwner = 'Session', @LockTimeout = ${fe};
106
+ EXEC @res = sp_getapplock @Resource = ${ue}, @LockMode = 'Exclusive',
107
+ @LockOwner = 'Session', @LockTimeout = ${de};
108
108
  SELECT @res AS res`;
109
- (t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${de}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
- }), me = (e) => d.gen(function* () {
111
- yield* e`EXEC sp_releaseapplock @Resource = ${de}, @LockOwner = 'Session'`;
112
- }), he = d.void, w = (e) => e.onDialectOrElse({
109
+ (t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ue}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
+ }), pe = (e) => d.gen(function* () {
111
+ yield* e`EXEC sp_releaseapplock @Resource = ${ue}, @LockOwner = 'Session'`;
112
+ }), me = d.void, T = (e) => e.onDialectOrElse({
113
+ mysql: () => ce(e),
114
+ mssql: () => fe(e),
115
+ sqlite: () => me,
116
+ orElse: () => ie(e)
117
+ }), E = (e) => e.onDialectOrElse({
113
118
  mysql: () => le(e),
114
119
  mssql: () => pe(e),
115
- sqlite: () => he,
120
+ sqlite: () => me,
116
121
  orElse: () => ae(e)
117
- }), T = (e) => e.onDialectOrElse({
118
- mysql: () => ue(e),
119
- mssql: () => me(e),
120
- sqlite: () => he,
121
- orElse: () => oe(e)
122
- }), ge = (e, t) => d.acquireUseRelease(w(e), () => t, () => T(e).pipe(d.orDie)), _e = f({ scope: "voltro:migrate" }), E = (e) => {
123
- _e.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
124
- }, D = (t, n) => {
125
- let r = t.type;
126
- if (t.spatial) {
127
- if (n === "postgres") return `${t.spatial.kind}(${t.spatial.geomKind},${t.spatial.srid})`;
128
- throw Error(`@voltro/plugin-postgis: ${t.spatial.kind}('${t.spatial.geomKind}', ${t.spatial.srid}) is postgres-only — the active dialect is '${n}'. PostGIS has no portable equivalent; use store: 'postgres' (or DB_DIALECT=postgres) for spatial columns, or model the value as plain text/json.`);
129
- }
130
- if (r === "raw") {
131
- if (t.rawDdl === void 0) throw Error("raw() column is missing its DDL fragment — this is a framework bug.");
132
- return t.rawDdl;
133
- }
134
- if (r === "array" && t.arrayElement) {
135
- if (n === "postgres") return `${D({
136
- ...t,
137
- type: t.arrayElement,
122
+ }), he = (e, t) => d.acquireUseRelease(T(e), () => t, () => E(e).pipe(d.orDie)), ge = f({ scope: "voltro:migrate" }), D = (e) => {
123
+ ge.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
124
+ }, O = (e, t) => {
125
+ let n = e.type;
126
+ if (e.spatial) {
127
+ if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
128
+ throw Error(`@voltro/plugin-postgis: ${e.spatial.kind}('${e.spatial.geomKind}', ${e.spatial.srid}) is postgres-only — the active dialect is '${t}'. PostGIS has no portable equivalent; use store: 'postgres' (or DB_DIALECT=postgres) for spatial columns, or model the value as plain text/json.`);
129
+ }
130
+ if (n === "raw") {
131
+ if (e.rawDdl === void 0) throw Error("raw() column is missing its DDL fragment — this is a framework bug.");
132
+ return e.rawDdl;
133
+ }
134
+ if (n === "array" && e.arrayElement) {
135
+ if (t === "postgres") return `${O({
136
+ ...e,
137
+ type: e.arrayElement,
138
138
  arrayElement: void 0
139
- }, n)}[]`;
140
- if (n === "mysql" || n === "mariadb") return "JSON";
141
- if (n === "mssql") return "NVARCHAR(MAX)";
142
- if (e(n)) return "TEXT";
143
- }
144
- if (r === "vector") {
145
- let r = t.vectorDim;
146
- if (r === void 0) throw Error("vector column is missing its dimension — this is a framework bug.");
147
- let i = t.vectorPrecision === "half";
148
- if (n === "postgres") return i ? `HALFVEC(${r})` : `VECTOR(${r})`;
149
- if (n === "mysql" || n === "mariadb") return `VECTOR(${r})`;
150
- if (n === "mssql") return "VARBINARY(MAX)";
151
- if (e(n)) return "BLOB";
152
- }
153
- if (r === "interval") {
154
- if (n === "postgres") return "INTERVAL";
155
- if (n === "mysql" || n === "mariadb" || n === "mssql") return "BIGINT";
156
- if (e(n)) return "INTEGER";
157
- }
158
- if (r === "decimal") {
159
- let r = t.precision, i = t.scale ?? 0;
160
- if (r === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
161
- return e(n) ? "NUMERIC" : n === "postgres" ? `NUMERIC(${r}, ${i})` : `DECIMAL(${r}, ${i})`;
162
- }
163
- if (r === "bigint") return e(n) ? "INTEGER" : "BIGINT";
164
- if (r === "enum") {
165
- if (n === "postgres") return t.enumName ?? "TEXT";
166
- if (n === "mysql" || n === "mariadb") return `ENUM(${(t.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
167
- if (n === "mssql") return "NVARCHAR(255)";
168
- if (e(n)) return "TEXT";
169
- }
170
- if (r === "text" && t.maxLength !== void 0 && t.generatedAs === void 0) return n === "mssql" ? `NVARCHAR(${t.maxLength})` : e(n) ? "TEXT" : `VARCHAR(${t.maxLength})`;
171
- if (e(n)) switch (r) {
139
+ }, t)}[]`;
140
+ if (t === "mysql" || t === "mariadb") return "JSON";
141
+ if (t === "mssql") return "NVARCHAR(MAX)";
142
+ if (u(t)) return "TEXT";
143
+ }
144
+ if (n === "vector") {
145
+ let n = e.vectorDim;
146
+ if (n === void 0) throw Error("vector column is missing its dimension — this is a framework bug.");
147
+ let r = e.vectorPrecision === "half";
148
+ if (t === "postgres") return r ? `HALFVEC(${n})` : `VECTOR(${n})`;
149
+ if (t === "mysql" || t === "mariadb") return `VECTOR(${n})`;
150
+ if (t === "mssql") return "VARBINARY(MAX)";
151
+ if (u(t)) return "BLOB";
152
+ }
153
+ if (n === "interval") {
154
+ if (t === "postgres") return "INTERVAL";
155
+ if (t === "mysql" || t === "mariadb" || t === "mssql") return "BIGINT";
156
+ if (u(t)) return "INTEGER";
157
+ }
158
+ if (n === "decimal") {
159
+ let n = e.precision, r = e.scale ?? 0;
160
+ if (n === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
161
+ return u(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
162
+ }
163
+ if (n === "bigint") return u(t) ? "INTEGER" : "BIGINT";
164
+ if (n === "enum") {
165
+ if (t === "postgres") return e.enumName ?? "TEXT";
166
+ if (t === "mysql" || t === "mariadb") return `ENUM(${(e.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
167
+ if (t === "mssql") return "NVARCHAR(255)";
168
+ if (u(t)) return "TEXT";
169
+ }
170
+ if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : u(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
171
+ if (u(t)) switch (n) {
172
172
  case "id": return "TEXT";
173
173
  case "text": return "TEXT";
174
174
  case "integer": return "INTEGER";
@@ -184,9 +184,9 @@ var _ = (e, t, n, r = 400) => {
184
184
  case "array": return "TEXT";
185
185
  case "interval": return "INTEGER";
186
186
  }
187
- if (n === "mysql" || n === "mariadb") switch (r) {
187
+ if (t === "mysql" || t === "mariadb") switch (n) {
188
188
  case "id": return "VARCHAR(64)";
189
- case "text": return t.hasDefault && t.defaultFactory === void 0 || t.oneOf && t.oneOf.length > 0 ? "VARCHAR(255)" : t.generatedAs ? "TEXT" : "LONGTEXT";
189
+ case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : e.generatedAs ? "TEXT" : "LONGTEXT";
190
190
  case "integer": return "INT";
191
191
  case "real": return "DOUBLE";
192
192
  case "boolean": return "TINYINT(1)";
@@ -200,9 +200,9 @@ var _ = (e, t, n, r = 400) => {
200
200
  case "array": return "JSON";
201
201
  case "interval": return "BIGINT";
202
202
  }
203
- if (n === "mssql") switch (r) {
203
+ if (t === "mssql") switch (n) {
204
204
  case "id": return "NVARCHAR(64)";
205
- case "text": return t.hasDefault && t.defaultFactory === void 0 || t.oneOf && t.oneOf.length > 0 ? "NVARCHAR(450)" : "NVARCHAR(MAX)";
205
+ case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "NVARCHAR(450)" : "NVARCHAR(MAX)";
206
206
  case "integer": return "INT";
207
207
  case "real": return "FLOAT";
208
208
  case "boolean": return "BIT";
@@ -216,7 +216,7 @@ var _ = (e, t, n, r = 400) => {
216
216
  case "array": return "NVARCHAR(MAX)";
217
217
  case "interval": return "BIGINT";
218
218
  }
219
- switch (r) {
219
+ switch (n) {
220
220
  case "id": return "TEXT";
221
221
  case "text": return "TEXT";
222
222
  case "integer": return "INTEGER";
@@ -228,18 +228,26 @@ var _ = (e, t, n, r = 400) => {
228
228
  case "bytes": return "BYTEA";
229
229
  case "reference": return "TEXT";
230
230
  case "vector": return "VECTOR";
231
- case "enum": return t.enumName ?? "TEXT";
231
+ case "enum": return e.enumName ?? "TEXT";
232
232
  case "array": return "TEXT[]";
233
233
  case "interval": return "INTERVAL";
234
234
  }
235
- }, ve = (t, n) => {
236
- if (!t.hasDefault || t.defaultFactory !== void 0) return null;
237
- let r = t.defaultValue;
238
- return r === "now" ? e(n) ? "DEFAULT CURRENT_TIMESTAMP" : n === "mssql" ? "DEFAULT SYSUTCDATETIME()" : n === "mysql" || n === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof r == "boolean" ? n === "postgres" ? `DEFAULT ${r}` : `DEFAULT ${+!!r}` : typeof r == "number" ? `DEFAULT ${r}` : typeof r == "string" ? `DEFAULT '${r.replace(/'/g, "''")}'` : typeof r == "object" && r && !Array.isArray(r) ? O(r, n) : null;
239
- }, O = (e, t) => {
235
+ }, _e = (e, t) => {
236
+ if (!e.hasDefault || e.defaultFactory !== void 0) return null;
237
+ let n = e.defaultValue;
238
+ return n === "now" ? u(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) ? ve(n, e, t) : typeof n == "object" && n ? k(n, t) : null;
239
+ }, ve = (e, t, n) => {
240
+ if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return k(e, n);
241
+ let r = O({
242
+ ...t,
243
+ type: t.arrayElement,
244
+ arrayElement: void 0
245
+ }, n);
246
+ return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
247
+ }, k = (e, t) => {
240
248
  let n = JSON.stringify(e).replace(/'/g, "''");
241
249
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
242
- }, k = (e, t) => {
250
+ }, A = (e, t) => {
243
251
  switch (t) {
244
252
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
245
253
  case "mysql":
@@ -248,7 +256,7 @@ var _ = (e, t, n, r = 400) => {
248
256
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
249
257
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
250
258
  }
251
- }, A = (e, t) => {
259
+ }, j = (e, t) => {
252
260
  if (e === "restrict" && t === "mssql") return "NO ACTION";
253
261
  switch (e) {
254
262
  case "cascade": return "CASCADE";
@@ -256,107 +264,107 @@ var _ = (e, t, n, r = 400) => {
256
264
  case "setNull": return "SET NULL";
257
265
  case "noAction": return "NO ACTION";
258
266
  }
259
- }, ye = (e, t, n) => n === null ? u(e, t) : `${u(n, t)}.${u(e, t)}`, be = 191, xe = (e, t, n) => {
260
- let r = u(e, n);
261
- if (n !== "mysql" && n !== "mariadb") return r;
262
- let i = t[e];
263
- if (!i) return r;
264
- let a = D(i, n).toUpperCase();
265
- return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${be})` : r;
267
+ }, ye = (t, n, r) => r === null ? e(t, n) : `${e(r, n)}.${e(t, n)}`, be = 191, xe = (t, n, r) => {
268
+ let i = e(t, r);
269
+ if (r !== "mysql" && r !== "mariadb") return i;
270
+ let a = n[t];
271
+ if (!a) return i;
272
+ let o = O(a, r).toUpperCase();
273
+ return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${be})` : i;
266
274
  }, Se = (e, t) => {
267
275
  if (!e.generatedAs) return null;
268
276
  let { expr: n, stored: r } = e.generatedAs;
269
- if (t === "postgres") return r || E("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
277
+ if (t === "postgres") return r || D("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
270
278
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
271
279
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
272
280
  if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
273
281
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
274
282
  }, Ce = (t, n, r, i, a = !1, o = !1) => {
275
- if (n.type === "id" && n.idScheme?.kind === "numeric") return k(t, r);
276
- let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" : D(n, r), c = [u(t, r), s];
283
+ if (n.type === "id" && n.idScheme?.kind === "numeric") return A(t, r);
284
+ let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" : O(n, r), c = [e(t, r), s];
277
285
  n.type === "id" && !o && c.push("PRIMARY KEY");
278
286
  let l = Se(n, r);
279
287
  if (l) c.push(l);
280
288
  else {
281
289
  n.nullable || c.push("NOT NULL"), n.unique && n.type !== "id" && c.push("UNIQUE");
282
- let e = ve(n, r);
290
+ let e = _e(n, r);
283
291
  e && c.push(e);
284
292
  }
285
293
  if (n.type === "reference" && n.references && !a) {
286
- let e = n.references();
287
- c.push(`REFERENCES ${u(e.tableName, r)} (${u("id", r)})`);
288
- let t = A(n.onDelete ?? "restrict", r);
289
- c.push(`ON DELETE ${t}`);
290
- let i = A(n.refOnUpdate ?? "noAction", r);
291
- i !== "NO ACTION" && c.push(`ON UPDATE ${i}`);
294
+ let t = n.references();
295
+ c.push(`REFERENCES ${e(t.tableName, r)} (${e("id", r)})`);
296
+ let i = j(n.onDelete ?? "restrict", r);
297
+ c.push(`ON DELETE ${i}`);
298
+ let a = j(n.refOnUpdate ?? "noAction", r);
299
+ a !== "NO ACTION" && c.push(`ON UPDATE ${a}`);
292
300
  }
293
301
  if (n.oneOf && n.oneOf.length > 0) {
294
- let e = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
295
- c.push(`CHECK (${u(t, r)} IN (${e}))`);
302
+ let i = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
303
+ c.push(`CHECK (${e(t, r)} IN (${i}))`);
296
304
  }
297
305
  if (n.checks && n.checks.length > 0) for (let e of n.checks) c.push(`CHECK (${e})`);
298
- if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" || e(r))) {
299
- let e = n.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
300
- c.push(`CHECK (${u(t, r)} IN (${e}))`);
306
+ if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" || u(r))) {
307
+ let i = n.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
308
+ c.push(`CHECK (${e(t, r)} IN (${i}))`);
301
309
  }
302
310
  if (n.type === "json" || n.type === "array") {
303
- let n = u(t, r);
304
- e(r) ? c.push(`CHECK (${n} IS NULL OR json_valid(${n}))`) : r === "mssql" && c.push(`CHECK (${n} IS NULL OR ISJSON(${n}) = 1)`);
311
+ let n = e(t, r);
312
+ u(r) ? c.push(`CHECK (${n} IS NULL OR json_valid(${n}))`) : r === "mssql" && c.push(`CHECK (${n} IS NULL OR ISJSON(${n}) = 1)`);
305
313
  }
306
314
  return c.join(" ");
307
- }, we = (e, t, n = null, r) => {
308
- let i = /* @__PURE__ */ new Set();
309
- for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
310
- for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
311
- let a = e.appliedPrimaryKey ?? [], o = a.length > 0, s = Object.entries(e.fields).map(([e, n]) => ` ${Ce(e, n, t, i, r?.has(e) ?? !1, o)}`).join(",\n"), c = (e.appliedUniques ?? []).map((n) => {
312
- let r = n.fields.map((n) => xe(n, e.fields, t)).join(", ");
313
- return ` CONSTRAINT ${u(n.name, t)} UNIQUE (${r})`;
314
- }), l = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${u(e.name, t)} CHECK (${e.expr})`), d = [
315
- ...o ? [` PRIMARY KEY (${a.map((n) => xe(n, e.fields, t)).join(", ")})`] : [],
316
- ...c,
317
- ...l
318
- ], f = d.length > 0 ? `${s},\n${d.join(",\n")}` : s, p = ye(e.tableName, t, n);
319
- if (t === "mssql") {
320
- let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${p} (\n${f}\n)`;
321
- return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
315
+ }, we = (t, n, r = null, i) => {
316
+ let a = /* @__PURE__ */ new Set();
317
+ for (let e of t.appliedIndexes ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
318
+ for (let e of t.appliedUniques ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
319
+ let o = t.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(t.fields).map(([e, t]) => ` ${Ce(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (t.appliedUniques ?? []).map((r) => {
320
+ let i = r.fields.map((e) => xe(e, t.fields, n)).join(", ");
321
+ return ` CONSTRAINT ${e(r.name, n)} UNIQUE (${i})`;
322
+ }), u = (t.appliedChecks ?? []).map((t) => ` CONSTRAINT ${e(t.name, n)} CHECK (${t.expr})`), d = [
323
+ ...s ? [` PRIMARY KEY (${o.map((e) => xe(e, t.fields, n)).join(", ")})`] : [],
324
+ ...l,
325
+ ...u
326
+ ], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = ye(t.tableName, n, r);
327
+ if (n === "mssql") {
328
+ let e = r === null ? t.tableName : `${r}.${t.tableName}`, n = `CREATE TABLE ${p} (\n${f}\n)`;
329
+ return `IF OBJECT_ID('${e.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
322
330
  }
323
331
  return [
324
332
  `CREATE TABLE IF NOT EXISTS ${p} (`,
325
333
  f,
326
334
  ");"
327
335
  ].join("\n");
328
- }, Te = (e, t, n) => {
329
- let r = `${e}_${t.name}_fts`, i = (e) => u(e, n), a = t.columns.map(i).join(", "), o = t.columns.map((e) => `new.${i(e)}`).join(", "), s = [];
330
- return s.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${i(r)} USING fts5(${a}, row_id UNINDEXED, tokenize='porter');`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ai`)} AFTER INSERT ON ${i(e)} BEGIN\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${o}, new.${i("id")});\nEND;`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ad`)} AFTER DELETE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\nEND;`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_au`)} AFTER UPDATE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${o}, new.${i("id")});\nEND;`), s;
331
- }, Ee = (e, n, r = null) => {
332
- let i = [], o = /* @__PURE__ */ new Set(), s = (e) => e.join("\0"), c = (e, r, i, a) => {
336
+ }, Te = (t, n, r) => {
337
+ let i = `${t}_${n.name}_fts`, a = (t) => e(t, r), o = n.columns.map(a).join(", "), s = n.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
338
+ return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(i)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ai`)} AFTER INSERT ON ${a(t)} 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(t)} 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(t)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
339
+ }, Ee = (n, r, a = null) => {
340
+ let o = [], s = /* @__PURE__ */ new Set(), c = (e) => e.join("\0"), l = (e, n, i, a) => {
333
341
  let o = {
334
342
  using: "",
335
343
  withSuffix: "",
336
344
  skip: !1
337
345
  };
338
346
  if (i === void 0 || i === "btree") return o;
339
- if (i === "gist") return n === "postgres" ? {
347
+ if (i === "gist") return r === "postgres" ? {
340
348
  using: " USING GIST",
341
349
  withSuffix: "",
342
350
  skip: !1
343
- } : (E(`[voltro:migrate] index '${e}' on '${r}': ${n} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), o);
344
- if (i === "gin") return n === "postgres" ? {
351
+ } : (D(`[voltro:migrate] index '${e}' on '${n}': ${r} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), o);
352
+ if (i === "gin") return r === "postgres" ? {
345
353
  using: " USING GIN",
346
354
  withSuffix: "",
347
355
  skip: !1
348
- } : n === "mysql" || n === "mariadb" ? (E(`[voltro:migrate] gin index '${e}' on '${r}': ${n} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
356
+ } : r === "mysql" || r === "mariadb" ? (D(`[voltro:migrate] gin index '${e}' on '${n}': ${r} 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(...).`), {
349
357
  using: "",
350
358
  withSuffix: "",
351
359
  skip: !0
352
- }) : (E(`[voltro:migrate] gin index '${e}' on '${r}': ${n} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), o);
353
- if (i === "brin") return n === "postgres" ? {
360
+ }) : (D(`[voltro:migrate] gin index '${e}' on '${n}': ${r} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), o);
361
+ if (i === "brin") return r === "postgres" ? {
354
362
  using: " USING BRIN",
355
363
  withSuffix: "",
356
364
  skip: !1
357
- } : (E(`[voltro:migrate] brin index '${e}' on '${r}': ${n} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), o);
365
+ } : (D(`[voltro:migrate] brin index '${e}' on '${n}': ${r} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), o);
358
366
  if (i === "hnsw") {
359
- if (n === "postgres") {
367
+ if (r === "postgres") {
360
368
  let e = a?.hnsw?.m ?? 16, n = a?.hnsw?.efConstruction ?? 64, r = a?.hnsw?.opclass ?? t(a?.hnsw?.distance);
361
369
  return {
362
370
  using: " USING hnsw",
@@ -365,57 +373,57 @@ var _ = (e, t, n, r = 400) => {
365
373
  skip: !1
366
374
  };
367
375
  }
368
- return E(`[voltro:migrate] hnsw index '${e}' on '${r}': ${n} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
376
+ return D(`[voltro:migrate] hnsw index '${e}' on '${n}': ${r} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
369
377
  using: "",
370
378
  withSuffix: "",
371
379
  skip: !0
372
380
  };
373
381
  }
374
382
  return o;
375
- }, l = (t, r) => {
376
- let i = t.map((t) => {
377
- if (typeof t == "string") return xe(t, e.fields, n);
378
- if ("jsonPath" in t) {
379
- let { column: e, path: r, numeric: i } = t.jsonPath;
380
- return `(${a(e, r, n, { numeric: i })})`;
383
+ }, u = (e, t) => {
384
+ let a = e.map((e) => {
385
+ if (typeof e == "string") return xe(e, n.fields, r);
386
+ if ("jsonPath" in e) {
387
+ let { column: t, path: n, numeric: a } = e.jsonPath;
388
+ return `(${i(t, n, r, { numeric: a })})`;
381
389
  }
382
- return `(${t.expr})`;
390
+ return `(${e.expr})`;
383
391
  });
384
- return r !== void 0 && i.length === 1 ? `${i[0]} ${r}` : i.join(", ");
385
- }, d = (e, t, i, a, o, s = "", d = !1) => {
386
- let f = c(e, t, a, o);
392
+ return t !== void 0 && a.length === 1 ? `${a[0]} ${t}` : a.join(", ");
393
+ }, d = (t, n, i, o, s, c = "", d = !1) => {
394
+ let f = l(t, n, o, s);
387
395
  if (f.skip) return "";
388
- let p = l(i, f.opclass), m = `${f.withSuffix}${s}`, h = ye(t, n, r), g = d ? "UNIQUE " : "";
389
- return n === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${u(e, n)} ON ${h}${f.using} (${p})${m};` : n === "mysql" ? `CREATE ${g}INDEX ${u(e, n)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${u(e, n)} ON ${h}${f.using} (${p})${m};`;
396
+ let p = u(i, f.opclass), m = `${f.withSuffix}${c}`, h = ye(n, r, a), g = d ? "UNIQUE " : "";
397
+ return r === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${t}') CREATE ${g}INDEX ${e(t, r)} ON ${h}${f.using} (${p})${m};` : r === "mysql" ? `CREATE ${g}INDEX ${e(t, r)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${e(t, r)} ON ${h}${f.using} (${p})${m};`;
390
398
  };
391
- for (let t of e.appliedFullText ?? []) if (n === "postgres") {
392
- let r = t.config ?? "english", a = `${t.name}_tsv`, o = t.columns.map((e) => {
393
- let i = t.weights?.[e] ?? "A";
394
- return `setweight(to_tsvector('${r}', coalesce(${u(e, n)}, '')), '${i}')`;
399
+ for (let t of n.appliedFullText ?? []) if (r === "postgres") {
400
+ let i = t.config ?? "english", a = `${t.name}_tsv`, s = t.columns.map((n) => {
401
+ let a = t.weights?.[n] ?? "A";
402
+ return `setweight(to_tsvector('${i}', coalesce(${e(n, r)}, '')), '${a}')`;
395
403
  }).join(" || ");
396
- i.push(`ALTER TABLE ${u(e.tableName, n)} ADD COLUMN IF NOT EXISTS ${u(a, n)} tsvector GENERATED ALWAYS AS (${o}) STORED;`), i.push(`CREATE INDEX IF NOT EXISTS ${u(t.name, n)} ON ${u(e.tableName, n)} USING GIN (${u(a, n)});`);
397
- } else if (n === "mysql" || n === "mariadb") {
398
- let r = t.columns.map((e) => u(e, n)).join(", ");
399
- i.push(`CREATE FULLTEXT INDEX ${u(t.name, n)} ON ${u(e.tableName, n)} (${r});`);
400
- } else if (n === "turso") throw Error(`@voltro/sql-turso: full-text index '${t.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.`);
401
- else n === "sqlite" ? i.push(...Te(e.tableName, t, n)) : E(`[voltro:migrate] full-text index '${t.name}' on '${e.tableName}': ${n} uses a ranked LIKE search at query time (no native FTS catalog required).`);
402
- for (let t of e.appliedIndexes) {
403
- if ((n === "mariadb" || n === "mssql") && t.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
404
- E(`[voltro:migrate] json-path index '${t.name}' on '${e.tableName}': ${n} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${n}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
404
+ o.push(`ALTER TABLE ${e(n.tableName, r)} ADD COLUMN IF NOT EXISTS ${e(a, r)} tsvector GENERATED ALWAYS AS (${s}) STORED;`), o.push(`CREATE INDEX IF NOT EXISTS ${e(t.name, r)} ON ${e(n.tableName, r)} USING GIN (${e(a, r)});`);
405
+ } else if (r === "mysql" || r === "mariadb") {
406
+ let i = t.columns.map((t) => e(t, r)).join(", ");
407
+ o.push(`CREATE FULLTEXT INDEX ${e(t.name, r)} ON ${e(n.tableName, r)} (${i});`);
408
+ } else if (r === "turso") throw Error(`@voltro/sql-turso: full-text index '${t.name}' on '${n.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
409
+ else r === "sqlite" ? o.push(...Te(n.tableName, t, r)) : D(`[voltro:migrate] full-text index '${t.name}' on '${n.tableName}': ${r} uses a ranked LIKE search at query time (no native FTS catalog required).`);
410
+ for (let e of n.appliedIndexes) {
411
+ if ((r === "mariadb" || r === "mssql") && e.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
412
+ D(`[voltro:migrate] json-path index '${e.name}' on '${n.tableName}': ${r} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${r}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
405
413
  continue;
406
414
  }
407
- if (t.unique && t.where !== void 0 && t.where.length > 0 && (n === "mysql" || n === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${t.name}' on '${e.tableName}' cannot be expressed on ${n} — it has no partial (WHERE) index support, and a full UNIQUE index would forbid re-creating a soft-deleted row. Use a generated STORED column (text().generatedAs("CASE WHEN \`deletedAt\` IS NULL THEN <key> ELSE NULL END", { stored: true })) + .unique([...]) on ${n}, or move this table to postgres/sqlite/mssql.`);
408
- let r = "";
409
- t.where !== void 0 && t.where.length > 0 && (n === "mysql" || n === "mariadb" ? E(`[voltro:migrate] partial index '${t.name}' on '${e.tableName}': ${n} does not support WHERE clauses on indexes — emitting a full index`) : r = ` WHERE ${t.where}`);
410
- let a = d(t.name, e.tableName, t.fields, t.kind, t.kindOptions, r, t.unique === !0);
411
- a !== "" && i.push(a), t.fields.every((e) => typeof e == "string") && o.add(s(t.fields));
412
- }
413
- for (let [t, n] of Object.entries(e.fields)) {
414
- if (n.type !== "reference" || n.fkAutoIndex === !1 || o.has(s([t]))) continue;
415
- let r = `${e.tableName}_${t}_idx`;
416
- i.push(d(r, e.tableName, [t])), o.add(s([t]));
417
- }
418
- return i.join("\n");
415
+ if (e.unique && e.where !== void 0 && e.where.length > 0 && (r === "mysql" || r === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${e.name}' on '${n.tableName}' cannot be expressed on ${r} — 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 ${r}, or move this table to postgres/sqlite/mssql.`);
416
+ let t = "";
417
+ e.where !== void 0 && e.where.length > 0 && (r === "mysql" || r === "mariadb" ? D(`[voltro:migrate] partial index '${e.name}' on '${n.tableName}': ${r} does not support WHERE clauses on indexes — emitting a full index`) : t = ` WHERE ${e.where}`);
418
+ let i = d(e.name, n.tableName, e.fields, e.kind, e.kindOptions, t, e.unique === !0);
419
+ i !== "" && o.push(i), e.fields.every((e) => typeof e == "string") && s.add(c(e.fields));
420
+ }
421
+ for (let [e, t] of Object.entries(n.fields)) {
422
+ if (t.type !== "reference" || t.fkAutoIndex === !1 || s.has(c([e]))) continue;
423
+ let r = `${n.tableName}_${e}_idx`;
424
+ o.push(d(r, n.tableName, [e])), s.add(c([e]));
425
+ }
426
+ return o.join("\n");
419
427
  }, De = "CREATE OR REPLACE FUNCTION framework_notify_change() RETURNS trigger AS $$\nDECLARE\n payload TEXT;\nBEGIN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n -- The schema the write landed in. Under namespace isolation this is\n -- the tenant schema (tenant_<id>); the CDC consumer uses it so a\n -- write in tenant A namespace does not spuriously wake tenant B\n -- subscriptions on the same-named table. public/absent = shared.\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', CASE WHEN TG_OP = 'INSERT' THEN NULL ELSE row_to_json(OLD) END,\n 'new', CASE WHEN TG_OP = 'DELETE' THEN NULL ELSE row_to_json(NEW) END\n )::text;\n -- pg_notify hard-caps the payload at 8000 bytes; a wide reactive row\n -- (big text / json column) would otherwise abort the write itself.\n -- Fall back to a body-less notice — the CDC consumer treats absent\n -- old/new as \"all columns changed\" and re-queries, so correctness is\n -- preserved; only the delta-diff fast path is skipped for that write.\n IF octet_length(payload) >= 7999 THEN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', NULL,\n 'new', NULL,\n 'oversized', true\n )::text;\n END IF;\n PERFORM pg_notify('framework_changes', payload);\n RETURN COALESCE(NEW, OLD);\nEND;\n$$ LANGUAGE plpgsql;", Oe = (e) => `
420
428
  ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
421
429
  DROP TRIGGER IF EXISTS framework_changes_${e.tableName} ON "${e.tableName}";
@@ -423,7 +431,7 @@ CREATE TRIGGER framework_changes_${e.tableName}
423
431
  AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
424
432
  FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
425
433
  `.trim(), ke = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Ae = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), je = (e) => {
426
- let t = new Map(e.map((e) => [e.tableName, e])), n = S(e.map((e) => e.tableName), (e) => {
434
+ let t = new Map(e.map((e) => [e.tableName, e])), n = w(e.map((e) => e.tableName), (e) => {
427
435
  let n = t.get(e);
428
436
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
429
437
  if (n.type !== "reference" || !n.references) return [];
@@ -434,7 +442,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
434
442
  }] : [];
435
443
  }) : [];
436
444
  }), r = [];
437
- for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(x(t.tableName, e)) && r.push({
445
+ for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(C(t.tableName, e)) && r.push({
438
446
  table: t.tableName,
439
447
  column: e,
440
448
  targetTable: i.references().tableName,
@@ -445,7 +453,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
445
453
  if (!(i.has(e.tableName) || a.has(e.tableName))) {
446
454
  a.add(e.tableName);
447
455
  for (let [r, i] of Object.entries(e.fields)) {
448
- if (i.type !== "reference" || !i.references || n.has(x(e.tableName, r))) continue;
456
+ if (i.type !== "reference" || !i.references || n.has(C(e.tableName, r))) continue;
449
457
  let a = i.references();
450
458
  if (a.tableName === e.tableName) continue;
451
459
  let o = t.get(a.tableName);
@@ -459,29 +467,29 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
459
467
  sorted: o,
460
468
  cyclic: r
461
469
  };
462
- }, Me = (e, t, n = null) => {
463
- let r = (e) => n ? `${u(n, t)}.${u(e, t)}` : u(e, t), i = `${e.table}_${e.column}_fkey`, a = A(e.onDelete, t), o = A(e.onUpdate, t), s = ` ON DELETE ${a}${o === "NO ACTION" ? "" : ` ON UPDATE ${o}`}`, c = (n) => `ADD CONSTRAINT ${u(i, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${u(e.column, t)}) REFERENCES ${r(e.targetTable)} (${u("id", t)})${s}`;
464
- switch (t) {
470
+ }, Me = (t, n, r = null) => {
471
+ let i = (t) => r ? `${e(r, n)}.${e(t, n)}` : e(t, n), a = `${t.table}_${t.column}_fkey`, o = j(t.onDelete, n), s = j(t.onUpdate, n), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${e(a, n)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${e(t.column, n)}) REFERENCES ${i(t.targetTable)} (${e("id", n)})${c}`;
472
+ switch (n) {
465
473
  case "postgres": return [
466
474
  "DO $$ BEGIN",
467
475
  " IF NOT EXISTS (SELECT 1 FROM pg_constraint",
468
- ` WHERE conname = '${i}' AND conrelid = '${n ? `${n}.` : ""}${e.table}'::regclass) THEN`,
469
- ` ALTER TABLE ${r(e.table)} ${c(!1)};`,
476
+ ` WHERE conname = '${a}' AND conrelid = '${r ? `${r}.` : ""}${t.table}'::regclass) THEN`,
477
+ ` ALTER TABLE ${i(t.table)} ${l(!1)};`,
470
478
  " END IF;",
471
479
  "END $$;"
472
480
  ].join("\n");
473
- case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${i}') ALTER TABLE ${r(e.table)} ${c(!1)};`;
474
- case "mariadb": return `ALTER TABLE ${r(e.table)} ${c(!0)};`;
475
- default: return `ALTER TABLE ${r(e.table)} ${c(!1)};`;
481
+ case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${a}') ALTER TABLE ${i(t.table)} ${l(!1)};`;
482
+ case "mariadb": return `ALTER TABLE ${i(t.table)} ${l(!0)};`;
483
+ default: return `ALTER TABLE ${i(t.table)} ${l(!1)};`;
476
484
  }
477
- }, Ne = (t, n) => {
478
- let r = /* @__PURE__ */ new Map();
479
- if (e(n)) return r;
480
- for (let e of t) {
481
- let t = r.get(e.table) ?? /* @__PURE__ */ new Set();
482
- t.add(e.column), r.set(e.table, t);
485
+ }, Ne = (e, t) => {
486
+ let n = /* @__PURE__ */ new Map();
487
+ if (u(t)) return n;
488
+ for (let t of e) {
489
+ let e = n.get(t.table) ?? /* @__PURE__ */ new Set();
490
+ e.add(t.column), n.set(t.table, e);
483
491
  }
484
- return r;
492
+ return n;
485
493
  }, Pe = (e, t) => {
486
494
  if (t !== "postgres") return "";
487
495
  let n = /* @__PURE__ */ new Map();
@@ -503,7 +511,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
503
511
  let n = /* @__PURE__ */ new Set();
504
512
  for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
505
513
  let r = [];
506
- for (let e of n) for (let { from: t, to: n } of i(e)) {
514
+ for (let e of n) for (let { from: t, to: n } of a(e)) {
507
515
  let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
508
516
  r.push(`DO \$\$
509
517
  DECLARE
@@ -519,85 +527,85 @@ BEGIN
519
527
  tables: t,
520
528
  views: r
521
529
  };
522
- }, j = (t, n) => {
523
- let { tables: i, views: a } = Ie(t), { sorted: o, cyclic: s } = je(i.map((e) => b(e, n))), c = Ne(s, n), l = [];
524
- n === "postgres" && ke(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && Ae(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
525
- let u = Fe(o, n);
526
- u && l.push(u);
527
- let d = Pe(o, n);
528
- d && l.push(d);
529
- for (let e of o) l.push(we(e, n, null, c.get(e.tableName)));
530
- if (!e(n)) for (let e of s) l.push(Me(e, n));
531
- for (let e of o) {
532
- let t = Ee(e, n);
533
- t && l.push(t);
534
- }
535
- let f = o.filter((e) => e.isReactive);
536
- if (f.length > 0 && n === "postgres") {
537
- l.push(De);
538
- for (let e of f) l.push(Oe(e));
539
- }
540
- for (let e of a) l.push(r(e, n));
541
- return l.join("\n\n") + "\n";
542
- }, Le = (e, t, n) => {
543
- let r = u(e, t);
544
- switch (t) {
545
- case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
530
+ }, M = (e, t) => {
531
+ let { tables: n, views: i } = Ie(e), { sorted: a, cyclic: o } = je(n.map((e) => S(e, t))), s = Ne(o, t), c = [];
532
+ t === "postgres" && ke(a) && c.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && Ae(a) && c.push("CREATE EXTENSION IF NOT EXISTS postgis;");
533
+ let l = Fe(a, t);
534
+ l && c.push(l);
535
+ let d = Pe(a, t);
536
+ d && c.push(d);
537
+ for (let e of a) c.push(we(e, t, null, s.get(e.tableName)));
538
+ if (!u(t)) for (let e of o) c.push(Me(e, t));
539
+ for (let e of a) {
540
+ let n = Ee(e, t);
541
+ n && c.push(n);
542
+ }
543
+ let f = a.filter((e) => e.isReactive !== !1);
544
+ if (f.length > 0 && t === "postgres") {
545
+ c.push(De);
546
+ for (let e of f) c.push(Oe(e));
547
+ }
548
+ for (let e of i) c.push(r(e, t));
549
+ return c.join("\n\n") + "\n";
550
+ }, Le = (t, n, r) => {
551
+ let i = e(t, n);
552
+ switch (n) {
553
+ case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
546
554
  case "mysql":
547
- case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${r};`;
548
- case "mssql": return `IF SCHEMA_ID('${e.replace(/'/g, "''")}') IS NULL EXEC(N'CREATE SCHEMA ${r.replace(/'/g, "''")}');`;
555
+ case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${i};`;
556
+ case "mssql": return `IF SCHEMA_ID('${t.replace(/'/g, "''")}') IS NULL EXEC(N'CREATE SCHEMA ${i.replace(/'/g, "''")}');`;
549
557
  case "turso":
550
- case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
558
+ case "sqlite": return `ATTACH DATABASE '${(r ?? `${t}.db`).replace(/'/g, "''")}' AS ${i};`;
551
559
  }
552
560
  }, Re = (t, n, r, i) => {
553
- let a = Le(r, n, i), o = u(r, n);
554
- if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${j(t, n)}`;
555
- if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${j(t, n)}`;
561
+ let a = Le(r, n, i), o = e(r, n);
562
+ if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${M(t, n)}`;
563
+ if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${M(t, n)}`;
556
564
  let { sorted: s, cyclic: c } = je(t), l = Ne(c, n), d = [a];
557
565
  for (let e of s) d.push(we(e, n, r, l.get(e.tableName)));
558
- if (!e(n)) for (let e of c) d.push(Me(e, n, r));
566
+ if (!u(n)) for (let e of c) d.push(Me(e, n, r));
559
567
  for (let e of s) {
560
568
  let t = Ee(e, n, r);
561
569
  t && d.push(t);
562
570
  }
563
571
  return d.join("\n\n") + "\n";
564
- }, ze = (e, t) => {
565
- if (t !== "postgres") return j(e, t);
566
- let { sorted: n, cyclic: r } = je(e), i = Ne(r, t), a = [], o = Fe(n, t);
567
- o && a.push(o);
568
- let s = Pe(n, t);
569
- s && a.push(s);
570
- for (let e of n) a.push(we(e, t, null, i.get(e.tableName)));
571
- for (let e of r) a.push(Me(e, t));
572
- for (let e of n) {
573
- let n = Object.entries(e.fields);
574
- if (n.length === 0) continue;
575
- let r = n.map(([n, r]) => {
576
- let a = Ce(n, r, t, void 0, i.get(e.tableName)?.has(n) ?? !1);
577
- return `ALTER TABLE ${u(e.tableName, t)} ADD COLUMN IF NOT EXISTS ${a};`;
572
+ }, ze = (t, n) => {
573
+ if (n !== "postgres") return M(t, n);
574
+ let { sorted: r, cyclic: i } = je(t), a = Ne(i, n), o = [], s = Fe(r, n);
575
+ s && o.push(s);
576
+ let c = Pe(r, n);
577
+ c && o.push(c);
578
+ for (let e of r) o.push(we(e, n, null, a.get(e.tableName)));
579
+ for (let e of i) o.push(Me(e, n));
580
+ for (let t of r) {
581
+ let r = Object.entries(t.fields);
582
+ if (r.length === 0) continue;
583
+ let i = r.map(([r, i]) => {
584
+ let o = Ce(r, i, n, void 0, a.get(t.tableName)?.has(r) ?? !1);
585
+ return `ALTER TABLE ${e(t.tableName, n)} ADD COLUMN IF NOT EXISTS ${o};`;
578
586
  });
579
- a.push(r.join("\n"));
587
+ o.push(i.join("\n"));
580
588
  }
581
- for (let e of n) {
582
- let n = Ee(e, t);
583
- n && a.push(n);
589
+ for (let e of r) {
590
+ let t = Ee(e, n);
591
+ t && o.push(t);
584
592
  }
585
- let c = n.filter((e) => e.isReactive);
586
- if (c.length > 0) {
587
- a.push(De);
588
- for (let e of c) a.push(Oe(e));
593
+ let l = r.filter((e) => e.isReactive);
594
+ if (l.length > 0) {
595
+ o.push(De);
596
+ for (let e of l) o.push(Oe(e));
589
597
  }
590
- return a.join("\n\n") + "\n";
598
+ return o.join("\n\n") + "\n";
591
599
  }, Be = (e, t = "postgres") => d.gen(function* () {
592
600
  let n = yield* p.SqlClient;
593
- yield* ge(n, Ue(n, j(e, t), t)).pipe(d.orDie);
601
+ yield* he(n, Ue(n, M(e, t), t)).pipe(d.orDie);
594
602
  }), Ve = (e, t) => {
595
603
  let n = t.cause ?? {};
596
604
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
597
605
  }, He = (e) => d.gen(function* () {
598
606
  let t = yield* p.SqlClient;
599
- for (let n of We(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && _e.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(d.catchIf((e) => Ve(n, e), () => d.void), d.tapError((e) => d.sync(() => {
600
- _e.error(_("migrate: statement failed", n, e, 200));
607
+ for (let n of We(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ge.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(d.catchIf((e) => Ve(n, e), () => d.void), d.tapError((e) => d.sync(() => {
608
+ ge.error(_("migrate: statement failed", n, e, 200));
601
609
  })), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
602
610
  }), Ue = (e, t, n) => (n === "turso" ? He(t) : e.withTransaction(He(t))).pipe(d.orDie), We = (e) => {
603
611
  let t = [], n = "", r = !1;
@@ -618,13 +626,13 @@ BEGIN
618
626
  await d.runPromise(Be(e, n).pipe(d.provide(t)));
619
627
  }, Ke = (e, t, n = "postgres") => d.gen(function* () {
620
628
  let r = Re(e, n, t), i = yield* p.SqlClient;
621
- yield* ge(i, Ue(i, r, n)).pipe(d.orDie);
629
+ yield* he(i, Ue(i, r, n)).pipe(d.orDie);
622
630
  }), qe = async (e, t, n, r = "postgres") => {
623
631
  await d.runPromise(Ke(e, t, r).pipe(d.provide(n)));
624
632
  }, Je = async (e, t, n = "postgres") => {
625
633
  await d.runPromise(d.gen(function* () {
626
634
  let t = ze(e, n), r = yield* p.SqlClient;
627
- yield* ge(r, Ue(r, t, n)).pipe(d.orDie);
635
+ yield* he(r, Ue(r, t, n)).pipe(d.orDie);
628
636
  }).pipe(d.provide(t)));
629
637
  }, Ye = (e) => {
630
638
  if (e == null) return e;
@@ -644,10 +652,10 @@ BEGIN
644
652
  name: e.name,
645
653
  columns: Ze(e.columns),
646
654
  indexes: Qe(e.indexes)
647
- })).sort((e, t) => e.name.localeCompare(t.name)), M = (e) => {
655
+ })).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
648
656
  let t = { tables: $e(e.tables) }, n = JSON.stringify(Ye(t));
649
657
  return m("sha256").update(n).digest("hex");
650
- }, N = (e) => e.slice(0, 16), et = (e, t) => {
658
+ }, P = (e) => e.slice(0, 16), et = (e, t) => {
651
659
  let n = t.references ? {
652
660
  table: t.references().tableName,
653
661
  column: "id",
@@ -677,7 +685,13 @@ BEGIN
677
685
  ...t.narrowedFrom.using === void 0 ? {} : { using: t.narrowedFrom.using }
678
686
  } } : {},
679
687
  ...t.sensitive ? { sensitive: t.sensitive } : t.encrypted && !t.safe ? { sensitive: { class: "secret" } } : {},
680
- ...t.safe ? { safe: !0 } : {}
688
+ ...t.safe ? { safe: !0 } : {},
689
+ ...t.vectorDim === void 0 ? {} : { vectorDim: t.vectorDim },
690
+ ...t.vectorPrecision === void 0 ? {} : { vectorPrecision: t.vectorPrecision },
691
+ ...t.arrayElement === void 0 ? {} : { arrayElement: t.arrayElement },
692
+ ...t.enumName === void 0 ? {} : { enumName: t.enumName },
693
+ ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
694
+ ...t.spatial === void 0 ? {} : { spatial: t.spatial }
681
695
  };
682
696
  }, tt = (e) => {
683
697
  let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
@@ -713,13 +727,13 @@ BEGIN
713
727
  columns: t.fields,
714
728
  unique: !0
715
729
  });
716
- let c = /* @__PURE__ */ new Set();
717
- for (let e of a) e.fields.every((e) => typeof e == "string") && c.add(e.fields.join("\0"));
730
+ let s = /* @__PURE__ */ new Set();
731
+ for (let e of a) e.fields.every((e) => typeof e == "string") && s.add(e.fields.join("\0"));
718
732
  for (let [t, n] of Object.entries(e.fields)) {
719
733
  let i = n;
720
- if (i.dropped || !i.references || i.fkAutoIndex === !1 || c.has(t)) continue;
734
+ if (i.dropped || !i.references || i.fkAutoIndex === !1 || s.has(t)) continue;
721
735
  let a = `${e.tableName}_${t}_idx`;
722
- s(e.tableName, a, !0, [t]), r({
736
+ c(e.tableName, a, !0, [t]), r({
723
737
  name: a,
724
738
  table: e.tableName,
725
739
  columns: [t],
@@ -751,22 +765,56 @@ BEGIN
751
765
  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}').`);
752
766
  t.set(e.name, n.name);
753
767
  }
754
- }, P = (e, t) => {
755
- let n = e.map((e) => nt(b(e, t)));
768
+ }, F = (e, t) => {
769
+ let n = e.map((e) => nt(S(e, t)));
756
770
  return rt(n), { tables: n };
757
- }, it = /* @__PURE__ */ new Set(["voltro_isr_cache"]), at = (e) => it.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), ot = {
771
+ }, it = "framework_changes_", at = (e, t) => d.gen(function* () {
772
+ let n = t.filter((e) => !e.tableName.startsWith("_voltro_"));
773
+ if (n.length === 0) return {
774
+ missing: [],
775
+ stale: []
776
+ };
777
+ let r = yield* e`
778
+ SELECT t.tgname
779
+ FROM pg_trigger t
780
+ JOIN pg_class c ON c.oid = t.tgrelid
781
+ JOIN pg_namespace n ON n.oid = c.relnamespace
782
+ WHERE NOT t.tgisinternal
783
+ AND n.nspname = current_schema()
784
+ AND t.tgname LIKE ${`${it}%`}
785
+ `, i = new Set(r.map((e) => e.tgname)), a = [], o = [];
786
+ for (let e of n) {
787
+ let t = i.has(`${it}${e.tableName}`), n = e.isReactive !== !1;
788
+ n && !t && a.push(e.tableName), !n && t && o.push(e.tableName);
789
+ }
790
+ return {
791
+ missing: a.sort(),
792
+ stale: o.sort()
793
+ };
794
+ }), ot = (e) => {
795
+ let t = [];
796
+ if (e.missing.length > 0) {
797
+ let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
798
+ t.push(`${e.missing.length} reactive table(s) have NO change trigger in the database — ${n}${r}. Writes to them will not reach another instance's subscribers; a single instance is unaffected, which is why this stays invisible until you scale out. Run \`voltro db apply\` to install them.`);
799
+ }
800
+ if (e.stale.length > 0) {
801
+ let n = e.stale.slice(0, 8).join(", ");
802
+ t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
803
+ }
804
+ return t.length > 0 ? t.join("\n") : void 0;
805
+ }, st = /* @__PURE__ */ new Set(["voltro_isr_cache"]), I = (e) => st.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), ct = {
758
806
  postgres: !0,
759
807
  mysql: !0,
760
808
  mariadb: !0,
761
809
  mssql: !0,
762
810
  sqlite: !0
763
- }, st = {
811
+ }, lt = {
764
812
  postgres: !0,
765
813
  mysql: !1,
766
814
  mariadb: !1,
767
815
  mssql: !0,
768
816
  sqlite: !0
769
- }, ct = (e) => {
817
+ }, ut = (e) => {
770
818
  switch (e) {
771
819
  case "add-column":
772
820
  case "drop-column":
@@ -776,43 +824,43 @@ BEGIN
776
824
  case "add-foreign-key":
777
825
  case "add-unique":
778
826
  case "add-unique-composite":
779
- case "add-check": return st;
780
- default: return ot;
827
+ case "add-check": return lt;
828
+ default: return ct;
781
829
  }
782
- }, lt = (e, t) => {
830
+ }, dt = (e, t) => {
783
831
  let n = new Map(t.tables.map((e) => [e.name, e]));
784
832
  return new Map(e.map((e) => [e.tableName, {
785
833
  table: e,
786
834
  snapshot: n.get(e.tableName),
787
835
  columnDefs: e.fields
788
836
  }]));
789
- }, ut = (e) => (t, n) => t.name === e ? -1 : n.name === e ? 1 : t.name.localeCompare(n.name), F = (e) => {
837
+ }, ft = (e) => (t, n) => t.name === e ? -1 : n.name === e ? 1 : t.name.localeCompare(n.name), L = (e) => {
790
838
  if (typeof e != "object" || !e) return JSON.stringify(e);
791
- if (Array.isArray(e)) return `[${e.map(F).join(",")}]`;
839
+ if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
792
840
  let t = e;
793
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${F(t[e])}`).join(",")}}`;
794
- }, dt = (e) => {
841
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
842
+ }, pt = (e) => {
795
843
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
796
844
  let t = e.defaultValue;
797
845
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
798
846
  if (typeof t == "number") return String(t);
799
- if (typeof t != "string") return F(t);
847
+ if (typeof t != "string") return L(t);
800
848
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
801
849
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
802
850
  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);
803
851
  if (o) try {
804
- return F(JSON.parse(o[1]));
852
+ return L(JSON.parse(o[1]));
805
853
  } catch {}
806
854
  if (a.startsWith("{") || a.startsWith("[")) try {
807
- return F(JSON.parse(a));
855
+ return L(JSON.parse(a));
808
856
  } catch {}
809
857
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
810
- }, ft = (e, t) => {
811
- let n = dt(e), r = dt(t);
858
+ }, mt = (e, t) => {
859
+ let n = pt(e), r = pt(t);
812
860
  if (n === r) return !0;
813
861
  let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
814
862
  return i(n) === i(r);
815
- }, I = (e) => {
863
+ }, R = (e) => {
816
864
  if (!e) return null;
817
865
  let t = (e) => e === "restrict" ? "noAction" : e;
818
866
  return {
@@ -821,18 +869,18 @@ BEGIN
821
869
  onDelete: t(e.onDelete),
822
870
  onUpdate: t(e.onUpdate)
823
871
  };
824
- }, pt = (e, t) => {
872
+ }, ht = (e, t) => {
825
873
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
826
874
  if (!n && !r) return !0;
827
875
  if (!n || !r || n.length !== r.length) return !1;
828
876
  let i = [...n].sort(), a = [...r].sort();
829
877
  return i.every((e, t) => e === a[t]);
830
- }, mt = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && ft(e, t) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && pt(e.oneOf, t.oneOf), ht = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
878
+ }, gt = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && mt(e, t) && JSON.stringify(R(e.references)) === JSON.stringify(R(t.references)) && ht(e.oneOf, t.oneOf), _t = (e, t) => t.oneOf && t.oneOf.length > 0 ? z({
831
879
  kind: "add-check",
832
880
  table: e,
833
881
  column: t.name,
834
882
  values: t.oneOf
835
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, gt = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), _t = (e, t) => {
883
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, vt = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), yt = (e, t) => {
836
884
  let n = new Map(t.columns.map((e) => [e.name, e])), r = new Map(e.columns.map((e) => [e.name, e])), i = [], a = [], o = [];
837
885
  for (let t of e.columns) {
838
886
  let e = n.get(t.name);
@@ -840,7 +888,7 @@ BEGIN
840
888
  i.push(t);
841
889
  continue;
842
890
  }
843
- mt(t, e) || o.push({
891
+ gt(t, e) || o.push({
844
892
  declared: t,
845
893
  live: e
846
894
  });
@@ -851,47 +899,47 @@ BEGIN
851
899
  removed: a,
852
900
  changed: o
853
901
  };
854
- }, vt = (e, t) => {
902
+ }, bt = (e, t) => {
855
903
  let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
856
904
  for (let t of e.indexes) {
857
905
  let e = n.get(t.name);
858
- (!e || !gt(t, e)) && i.push(t);
906
+ (!e || !vt(t, e)) && i.push(t);
859
907
  }
860
908
  for (let e of t.indexes) r.has(e.name) || a.push(e);
861
909
  return {
862
910
  added: i,
863
911
  removed: a
864
912
  };
865
- }, L = (e, t, n, r) => ({
913
+ }, z = (e, t, n, r) => ({
866
914
  op: e,
867
915
  classification: t,
868
- atomicByDialect: ct(e.kind),
916
+ atomicByDialect: ut(e.kind),
869
917
  ...n ? { reason: n } : {},
870
918
  ...r ? { blocked: r } : {}
871
- }), yt = (e, t, n) => {
919
+ }), xt = (e, t, n) => {
872
920
  let r = {
873
921
  kind: "add-column",
874
922
  table: e,
875
923
  column: t
876
924
  };
877
- return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
878
- }, bt = (e, t, n) => {
925
+ return t.nullable ? z(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? z(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? z(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : z(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
926
+ }, St = (e, t, n) => {
879
927
  let r = {
880
928
  kind: "drop-column",
881
929
  table: e,
882
930
  column: t.name
883
931
  };
884
- return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
885
- }, xt = (e, t, n, r) => L({
932
+ return n?.dropped ? z(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : z(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
933
+ }, Ct = (e, t, n, r) => z({
886
934
  kind: "create-table",
887
935
  table: e,
888
936
  columns: t,
889
937
  indexes: n,
890
938
  ...r && r.length > 0 ? { primaryKey: r } : {}
891
- }, "safe", "new table — no data to preserve"), St = (e) => L({
939
+ }, "safe", "new table — no data to preserve"), wt = (e) => z({
892
940
  kind: "drop-table",
893
941
  table: e
894
- }, "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" }), Ct = 5e4, wt = (e, t, n, r) => {
942
+ }, "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" }), Tt = 5e4, Et = (e, t, n, r) => {
895
943
  let i = (n ?? 0) >= r, a;
896
944
  return a = t.unique ? t.columns.length === 1 ? {
897
945
  kind: "add-unique",
@@ -906,16 +954,16 @@ BEGIN
906
954
  kind: "add-index",
907
955
  table: e,
908
956
  index: t
909
- }, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
910
- }, Tt = (e, t) => t.unique && t.columns.length > 1 ? L({
957
+ }, i ? z(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
958
+ }, Dt = (e, t) => t.unique && t.columns.length > 1 ? z({
911
959
  kind: "drop-unique-composite",
912
960
  table: e,
913
961
  name: t.name
914
- }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
962
+ }, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : z({
915
963
  kind: "drop-index",
916
964
  table: e,
917
965
  index: t.name
918
- }, "safe", "drop index (no data loss — index is derived data)"), Et = (e, t) => {
966
+ }, "safe", "drop index (no data loss — index is derived data)"), Ot = (e, t) => {
919
967
  if (e === "reference") return "text";
920
968
  switch (t) {
921
969
  case "sqlite":
@@ -923,7 +971,7 @@ BEGIN
923
971
  case "mssql": return e === "json" ? "text" : e;
924
972
  default: return e;
925
973
  }
926
- }, Dt = (e, t, n, r, i, a) => {
974
+ }, kt = (e, t, n, r, i, a) => {
927
975
  let o = [];
928
976
  if (t.nullable !== n.nullable) {
929
977
  let n = {
@@ -932,7 +980,7 @@ BEGIN
932
980
  column: t.name,
933
981
  toNullable: t.nullable
934
982
  };
935
- o.push(t.nullable ? L(n, "safe", `loosen ${e}.${t.name} to nullable`) : L(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
983
+ o.push(t.nullable ? z(n, "safe", `loosen ${e}.${t.name} to nullable`) : z(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
936
984
  }
937
985
  if (t.unique !== n.unique) if (t.unique) {
938
986
  let n = {
@@ -940,13 +988,13 @@ BEGIN
940
988
  table: e,
941
989
  column: t.name
942
990
  }, r = (i ?? 0) >= a;
943
- o.push(r ? L(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
944
- } else o.push(L({
991
+ o.push(r ? z(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
992
+ } else o.push(z({
945
993
  kind: "drop-unique",
946
994
  table: e,
947
995
  column: t.name
948
996
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
949
- if (Et(t.type, r) !== Et(n.type, r)) {
997
+ if (Ot(t.type, r) !== Ot(n.type, r)) {
950
998
  let r = t.narrowedFrom;
951
999
  if (r && r.from === n.type) {
952
1000
  let i = {
@@ -957,7 +1005,7 @@ BEGIN
957
1005
  to: t.type,
958
1006
  ...r.using === void 0 ? {} : { using: r.using }
959
1007
  };
960
- o.push(L(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
1008
+ o.push(z(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
961
1009
  } else {
962
1010
  let r = {
963
1011
  kind: "alter-column-type",
@@ -966,10 +1014,10 @@ BEGIN
966
1014
  from: n.type,
967
1015
  to: t.type
968
1016
  };
969
- o.push(L(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
1017
+ o.push(z(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
970
1018
  }
971
1019
  }
972
- if (!ft(t, n)) {
1020
+ if (!mt(t, n)) {
973
1021
  let n = {
974
1022
  kind: "alter-column-default",
975
1023
  table: e,
@@ -977,18 +1025,18 @@ BEGIN
977
1025
  hasDefault: t.hasDefault,
978
1026
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
979
1027
  };
980
- o.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
1028
+ o.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
981
1029
  }
982
- if (!pt(t.oneOf, n.oneOf)) {
983
- n.oneOf && n.oneOf.length > 0 && o.push(L({
1030
+ if (!ht(t.oneOf, n.oneOf)) {
1031
+ n.oneOf && n.oneOf.length > 0 && o.push(z({
984
1032
  kind: "drop-check",
985
1033
  table: e,
986
1034
  column: t.name
987
1035
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
988
- let r = ht(e, t);
1036
+ let r = _t(e, t);
989
1037
  r && o.push(r);
990
1038
  }
991
- if (JSON.stringify(I(t.references)) !== JSON.stringify(I(n.references)) && (n.references && o.push(L({
1039
+ if (JSON.stringify(R(t.references)) !== JSON.stringify(R(n.references)) && (n.references && o.push(z({
992
1040
  kind: "drop-foreign-key",
993
1041
  table: e,
994
1042
  column: t.name
@@ -1002,17 +1050,17 @@ BEGIN
1002
1050
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1003
1051
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1004
1052
  };
1005
- r === "null" && !t.nullable ? o.push(L(i, "lossy", `add FK ${e}.${t.name} → ${n}: 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` })) : r === "null" || r === "delete" ? o.push(L({
1053
+ r === "null" && !t.nullable ? o.push(z(i, "lossy", `add FK ${e}.${t.name} → ${n}: 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` })) : r === "null" || r === "delete" ? o.push(z({
1006
1054
  ...i,
1007
1055
  orphanPolicy: r
1008
- }, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(L(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
1056
+ }, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(z(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
1009
1057
  }
1010
1058
  return o;
1011
- }, Ot = (e, t, n) => {
1059
+ }, At = (e, t, n) => {
1012
1060
  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));
1013
1061
  for (let [n, c] of Object.entries(t)) {
1014
1062
  let t = c.renamedFrom;
1015
- t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
1063
+ t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(z({
1016
1064
  kind: "rename-column",
1017
1065
  table: e.tableName,
1018
1066
  from: t,
@@ -1024,7 +1072,7 @@ BEGIN
1024
1072
  consumedAddedNames: i,
1025
1073
  consumedRemovedNames: a
1026
1074
  };
1027
- }, kt = (e) => {
1075
+ }, jt = (e) => {
1028
1076
  let t = {
1029
1077
  safe: 0,
1030
1078
  needsDefault: 0,
@@ -1059,37 +1107,37 @@ BEGIN
1059
1107
  break;
1060
1108
  }
1061
1109
  return t;
1062
- }, At = (e) => {
1063
- let t = P(e.declared, e.dialect), n = lt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Ct, a = [];
1110
+ }, Mt = (e) => {
1111
+ let t = F(e.declared, e.dialect), n = dt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Tt, a = [];
1064
1112
  for (let e of t.tables) if (!r.has(e.name)) {
1065
- a.push(xt(e.name, e.columns, e.indexes, e.primaryKey));
1113
+ a.push(Ct(e.name, e.columns, e.indexes, e.primaryKey));
1066
1114
  for (let t of e.columns) {
1067
- let n = ht(e.name, t);
1115
+ let n = _t(e.name, t);
1068
1116
  n && a.push(n);
1069
1117
  }
1070
1118
  }
1071
1119
  let o = new Set(e.ignoreTables ?? []);
1072
- for (let t of e.live.tables) n.has(t.name) || at(t.name) || o.has(t.name) || a.push(St(t.name));
1120
+ for (let t of e.live.tables) n.has(t.name) || I(t.name) || o.has(t.name) || a.push(wt(t.name));
1073
1121
  for (let o of t.tables) {
1074
1122
  let t = r.get(o.name);
1075
1123
  if (!t) continue;
1076
- let s = n.get(o.name), c = _t(o, t), l = vt(o, t), u = Ot(s.table, s.columnDefs, c);
1124
+ let s = n.get(o.name), c = yt(o, t), l = bt(o, t), u = At(s.table, s.columnDefs, c);
1077
1125
  a.push(...u.ops);
1078
1126
  for (let e of c.removed) {
1079
1127
  if (u.consumedRemovedNames.has(e.name)) continue;
1080
1128
  let t = s.columnDefs[e.name];
1081
- a.push(bt(o.name, e, t));
1129
+ a.push(St(o.name, e, t));
1082
1130
  }
1083
1131
  for (let e of c.added) {
1084
1132
  if (u.consumedAddedNames.has(e.name)) continue;
1085
1133
  let t = s.columnDefs[e.name];
1086
- a.push(yt(o.name, e, t));
1087
- let n = ht(o.name, e);
1134
+ a.push(xt(o.name, e, t));
1135
+ let n = _t(o.name, e);
1088
1136
  n && a.push(n);
1089
1137
  }
1090
- for (let e of l.added) a.push(wt(o.name, e, t.rowCount, i));
1091
- for (let e of l.removed) a.push(Tt(o.name, e));
1092
- for (let { declared: n, live: r } of c.changed) a.push(...Dt(o.name, n, r, e.dialect, t.rowCount, i));
1138
+ for (let e of l.added) a.push(Et(o.name, e, t.rowCount, i));
1139
+ for (let e of l.removed) a.push(Dt(o.name, e));
1140
+ for (let { declared: n, live: r } of c.changed) a.push(...kt(o.name, n, r, e.dialect, t.rowCount, i));
1093
1141
  }
1094
1142
  let s = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), c = new Map(t.tables.map((e) => [e.name, e])), l = (e) => {
1095
1143
  let t = c.get(e);
@@ -1097,8 +1145,8 @@ BEGIN
1097
1145
  column: e.name,
1098
1146
  target: e.references.table
1099
1147
  }] : []) : [];
1100
- }, u = S([...s], l), d = [];
1101
- for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(x(e.name, t.name)) || d.push(L({
1148
+ }, u = w([...s], l), d = [];
1149
+ for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(C(e.name, t.name)) || d.push(z({
1102
1150
  kind: "add-foreign-key",
1103
1151
  table: e.name,
1104
1152
  column: t.name,
@@ -1113,8 +1161,8 @@ BEGIN
1113
1161
  let n = a[t];
1114
1162
  if (n.op.kind !== "create-table") continue;
1115
1163
  let r = n.op;
1116
- if (!r.columns.some((e) => u.has(x(r.table, e.name)))) continue;
1117
- let i = r.columns.map((t) => u.has(x(r.table, t.name)) ? e(t) : t);
1164
+ if (!r.columns.some((e) => u.has(C(r.table, e.name)))) continue;
1165
+ let i = r.columns.map((t) => u.has(C(r.table, t.name)) ? e(t) : t);
1118
1166
  a[t] = {
1119
1167
  ...n,
1120
1168
  op: {
@@ -1134,7 +1182,7 @@ BEGIN
1134
1182
  let i = new Set(t).add(e), a = 0;
1135
1183
  for (let t of r.columns) {
1136
1184
  let n = t.references?.table;
1137
- n && n !== e && !u.has(x(e, t.name)) && (a = Math.max(a, m(n, i) + 1));
1185
+ n && n !== e && !u.has(C(e, t.name)) && (a = Math.max(a, m(n, i) + 1));
1138
1186
  }
1139
1187
  return p.set(e, a), a;
1140
1188
  }, h = (e) => e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, g = (e) => {
@@ -1169,11 +1217,11 @@ BEGIN
1169
1217
  });
1170
1218
  return {
1171
1219
  operations: v,
1172
- fromFingerprint: M(e.live),
1173
- toFingerprint: M(t),
1174
- summary: kt(v)
1220
+ fromFingerprint: N(e.live),
1221
+ toFingerprint: N(t),
1222
+ summary: jt(v)
1175
1223
  };
1176
- }, jt = (e) => {
1224
+ }, Nt = (e) => {
1177
1225
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1178
1226
  if (!t) return null;
1179
1227
  let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
@@ -1181,7 +1229,7 @@ BEGIN
1181
1229
  column: t[1],
1182
1230
  values: n
1183
1231
  };
1184
- }, Mt = (e, t) => {
1232
+ }, Pt = (e, t) => {
1185
1233
  if (t === "vector") return "vector";
1186
1234
  switch (e) {
1187
1235
  case "text":
@@ -1208,7 +1256,7 @@ BEGIN
1208
1256
  case "USER-DEFINED": return "text";
1209
1257
  default: return "text";
1210
1258
  }
1211
- }, R = (e) => {
1259
+ }, B = (e) => {
1212
1260
  switch (e.toUpperCase()) {
1213
1261
  case "CASCADE": return "cascade";
1214
1262
  case "RESTRICT": return "restrict";
@@ -1216,25 +1264,25 @@ BEGIN
1216
1264
  case "SET DEFAULT": return "noAction";
1217
1265
  default: return "noAction";
1218
1266
  }
1219
- }, Nt = (e, t) => {
1267
+ }, Ft = (e, t) => {
1220
1268
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1221
1269
  return Number.isInteger(n) && n > 0 ? n : t;
1222
- }, Pt = () => Nt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Ft = 300, It = () => {
1270
+ }, It = () => Ft(process.env.VOLTRO_INTROSPECT_BATCH, 20), Lt = 300, Rt = () => {
1223
1271
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1224
- return e !== void 0 && e.trim() === "0" ? 0 : Nt(e, 3e4);
1225
- }, Lt = (e, t) => {
1272
+ return e !== void 0 && e.trim() === "0" ? 0 : Ft(e, 3e4);
1273
+ }, zt = (e, t) => {
1226
1274
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1227
1275
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1228
1276
  return r;
1229
- }, Rt = (e) => {
1230
- let t = It(), n = d.gen(function* () {
1277
+ }, Bt = (e) => {
1278
+ let t = Rt(), n = d.gen(function* () {
1231
1279
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1232
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Pt(), a = (e, t) => d.gen(function* () {
1280
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = It(), a = (e, t) => d.gen(function* () {
1233
1281
  let r = [];
1234
- for (let a of Lt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1282
+ for (let a of zt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1235
1283
  return r;
1236
1284
  }), o = [];
1237
- for (let t = 0;; t += Ft) {
1285
+ for (let t = 0;; t += Lt) {
1238
1286
  let n = yield* e`
1239
1287
  SELECT c.relname AS table_name,
1240
1288
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1242,9 +1290,9 @@ BEGIN
1242
1290
  JOIN pg_namespace n ON n.oid = c.relnamespace
1243
1291
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1244
1292
  ORDER BY c.relname
1245
- LIMIT ${r(Ft)} OFFSET ${r(t)}
1293
+ LIMIT ${r(Lt)} OFFSET ${r(t)}
1246
1294
  `;
1247
- if (o.push(...n), n.length < Ft) break;
1295
+ if (o.push(...n), n.length < Lt) break;
1248
1296
  }
1249
1297
  let s = /* @__PURE__ */ new Set(), c = [];
1250
1298
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
@@ -1329,7 +1377,7 @@ BEGIN
1329
1377
  AND c.relname IN ${t}
1330
1378
  )
1331
1379
  SELECT * FROM ix ORDER BY table_name, index_name, position
1332
- `), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map();
1380
+ `), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), S = /* @__PURE__ */ new Map();
1333
1381
  for (let e of u) {
1334
1382
  let t = _.get(e.table_name);
1335
1383
  t || (t = [], _.set(e.table_name, t)), t.push(e);
@@ -1338,25 +1386,25 @@ BEGIN
1338
1386
  let t = v.get(e.table_name);
1339
1387
  t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
1340
1388
  }
1341
- let x = /* @__PURE__ */ new Map();
1389
+ let C = /* @__PURE__ */ new Map();
1342
1390
  for (let e of p) {
1343
- let t = `${e.table_name}${e.constraint_name}`, n = x.get(t);
1391
+ let t = `${e.table_name}${e.constraint_name}`, n = C.get(t);
1344
1392
  n || (n = {
1345
1393
  table: e.table_name,
1346
1394
  columns: []
1347
- }, x.set(t, n)), n.columns.push({
1395
+ }, C.set(t, n)), n.columns.push({
1348
1396
  name: e.column_name,
1349
1397
  position: e.position
1350
1398
  });
1351
1399
  }
1352
- for (let [e, t] of x) {
1400
+ for (let [e, t] of C) {
1353
1401
  let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
1354
1402
  if (n.length === 1) {
1355
1403
  let e = y.get(t.table);
1356
1404
  e || (e = /* @__PURE__ */ new Set(), y.set(t.table, e)), e.add(n[0]);
1357
1405
  } else {
1358
- let r = te.get(t.table);
1359
- r || (r = [], te.set(t.table, r)), r.push({
1406
+ let r = b.get(t.table);
1407
+ r || (r = [], b.set(t.table, r)), r.push({
1360
1408
  name: e.slice(e.indexOf("\0") + 1),
1361
1409
  table: t.table,
1362
1410
  columns: n,
@@ -1365,23 +1413,23 @@ BEGIN
1365
1413
  }
1366
1414
  }
1367
1415
  for (let e of g) {
1368
- let t = ne.get(e.source_table);
1369
- t || (t = [], ne.set(e.source_table, t)), t.push(e);
1416
+ let t = x.get(e.source_table);
1417
+ t || (t = [], x.set(e.source_table, t)), t.push(e);
1370
1418
  }
1371
1419
  for (let e of ee) {
1372
- let t = b.get(e.table_name);
1373
- t || (t = /* @__PURE__ */ new Map(), b.set(e.table_name, t));
1420
+ let t = S.get(e.table_name);
1421
+ t || (t = /* @__PURE__ */ new Map(), S.set(e.table_name, t));
1374
1422
  let n = t.get(e.index_name);
1375
1423
  n || (n = [], t.set(e.index_name, n)), n.push(e);
1376
1424
  }
1377
- let S = [];
1425
+ let w = [];
1378
1426
  for (let e of c) {
1379
- let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = ne.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) => {
1380
- let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : Mt(t.data_type, t.udt_name), c = a ? {
1427
+ let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = x.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
1428
+ let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : Pt(t.data_type, t.udt_name), c = a ? {
1381
1429
  table: a.target_table,
1382
1430
  column: a.target_column,
1383
- onDelete: R(a.delete_rule),
1384
- onUpdate: R(a.update_rule)
1431
+ onDelete: B(a.delete_rule),
1432
+ onUpdate: B(a.update_rule)
1385
1433
  } : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
1386
1434
  return {
1387
1435
  name: t.column_name,
@@ -1393,7 +1441,7 @@ BEGIN
1393
1441
  ...c ? { references: c } : {},
1394
1442
  ...l ? { oneOf: l } : {}
1395
1443
  };
1396
- }), l = [], u = b.get(e.table_name);
1444
+ }), l = [], u = S.get(e.table_name);
1397
1445
  if (u) for (let [t, n] of u) {
1398
1446
  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) => {
1399
1447
  let t = e.position;
@@ -1409,7 +1457,7 @@ BEGIN
1409
1457
  ...a ? { expression: !0 } : {}
1410
1458
  });
1411
1459
  }
1412
- for (let t of te.get(e.table_name) ?? []) l.push(t);
1460
+ for (let t of b.get(e.table_name) ?? []) l.push(t);
1413
1461
  r.size > 0 && l.push({
1414
1462
  name: `${e.table_name}_pkey`,
1415
1463
  table: e.table_name,
@@ -1417,20 +1465,20 @@ BEGIN
1417
1465
  unique: !0
1418
1466
  });
1419
1467
  let d = Number(e.row_count ?? 0);
1420
- S.push({
1468
+ w.push({
1421
1469
  name: e.table_name,
1422
1470
  columns: c,
1423
1471
  indexes: l,
1424
1472
  ...d > 0 ? { rowCount: d } : {}
1425
1473
  });
1426
1474
  }
1427
- return { tables: S };
1475
+ return { tables: w };
1428
1476
  });
1429
1477
  return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
1430
1478
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1431
1479
  return n.includes("statement timeout") || n.includes("57014") ? d.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : d.fail(e);
1432
1480
  }));
1433
- }, zt = (e, t) => {
1481
+ }, Vt = (e, t) => {
1434
1482
  switch (e.toLowerCase()) {
1435
1483
  case "varchar":
1436
1484
  case "char":
@@ -1462,20 +1510,20 @@ BEGIN
1462
1510
  case "json": return "json";
1463
1511
  default: return "text";
1464
1512
  }
1465
- }, z = (e) => e.map((e) => {
1513
+ }, V = (e) => e.map((e) => {
1466
1514
  let t = e, n = {};
1467
1515
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1468
1516
  return n;
1469
- }), Bt = (e) => d.gen(function* () {
1470
- let t = z(yield* e`
1517
+ }), Ht = (e) => d.gen(function* () {
1518
+ let t = V(yield* e`
1471
1519
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1472
1520
  FROM information_schema.tables
1473
1521
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1474
- ORDER BY table_name`), n = z(yield* e`
1522
+ ORDER BY table_name`), n = V(yield* e`
1475
1523
  SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
1476
1524
  FROM information_schema.columns
1477
1525
  WHERE table_schema = DATABASE()
1478
- ORDER BY table_name, ordinal_position`), r = z(yield* e`
1526
+ ORDER BY table_name, ordinal_position`), r = V(yield* e`
1479
1527
  SELECT k.table_name AS source_table,
1480
1528
  k.column_name AS source_column,
1481
1529
  k.referenced_table_name AS target_table,
@@ -1485,11 +1533,11 @@ BEGIN
1485
1533
  JOIN information_schema.referential_constraints r
1486
1534
  ON k.constraint_name = r.constraint_name
1487
1535
  AND k.table_schema = r.constraint_schema
1488
- WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = z(yield* e`
1536
+ WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = V(yield* e`
1489
1537
  SELECT table_name, index_name, non_unique, column_name, seq_in_index
1490
1538
  FROM information_schema.statistics
1491
1539
  WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
1492
- ORDER BY table_name, index_name, seq_in_index`), a = z(yield* e`
1540
+ ORDER BY table_name, index_name, seq_in_index`), a = V(yield* e`
1493
1541
  SELECT table_name, check_clause
1494
1542
  FROM information_schema.check_constraints
1495
1543
  WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
@@ -1499,7 +1547,7 @@ BEGIN
1499
1547
  o.add(`${e.table_name}.${t[1]}`);
1500
1548
  continue;
1501
1549
  }
1502
- let n = jt(e.check_clause);
1550
+ let n = Nt(e.check_clause);
1503
1551
  n && s.set(`${e.table_name}.${n.column}`, n.values);
1504
1552
  }
1505
1553
  let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
@@ -1522,11 +1570,11 @@ BEGIN
1522
1570
  let t = c.get(e.table_name) ?? [], n = l.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), d = u.get(e.table_name);
1523
1571
  if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1524
1572
  let p = t.map((t) => {
1525
- let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : zt(t.data_type, t.column_type), u = c ? {
1573
+ let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : Vt(t.data_type, t.column_type), u = c ? {
1526
1574
  table: c.target_table,
1527
1575
  column: c.target_column,
1528
- onDelete: R(c.delete_rule),
1529
- onUpdate: R(c.update_rule)
1576
+ onDelete: B(c.delete_rule),
1577
+ onUpdate: B(c.update_rule)
1530
1578
  } : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = s.get(`${e.table_name}.${t.column_name}`);
1531
1579
  return {
1532
1580
  name: t.column_name,
@@ -1563,10 +1611,10 @@ BEGIN
1563
1611
  });
1564
1612
  }
1565
1613
  return { tables: f };
1566
- }), Vt = (e) => {
1614
+ }), Ut = (e) => {
1567
1615
  let t = e.toUpperCase();
1568
1616
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1569
- }, Ht = (e) => d.gen(function* () {
1617
+ }, Wt = (e) => d.gen(function* () {
1570
1618
  let t = yield* e`
1571
1619
  SELECT name, sql FROM sqlite_master
1572
1620
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1583,11 +1631,11 @@ BEGIN
1583
1631
  d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1584
1632
  }
1585
1633
  let p = o.map((e) => {
1586
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Vt(e.type), a = r ? {
1634
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Ut(e.type), a = r ? {
1587
1635
  table: r.table,
1588
1636
  column: r.to,
1589
- onDelete: R(r.on_delete),
1590
- onUpdate: R(r.on_update)
1637
+ onDelete: B(r.on_delete),
1638
+ onUpdate: B(r.on_update)
1591
1639
  } : void 0, o = t.get(e.name);
1592
1640
  return {
1593
1641
  name: e.name,
@@ -1622,7 +1670,7 @@ BEGIN
1622
1670
  });
1623
1671
  }
1624
1672
  return { tables: r };
1625
- }), Ut = (e) => {
1673
+ }), Gt = (e) => {
1626
1674
  switch (e.toLowerCase()) {
1627
1675
  case "int":
1628
1676
  case "smallint":
@@ -1644,7 +1692,7 @@ BEGIN
1644
1692
  case "image": return "bytes";
1645
1693
  default: return "text";
1646
1694
  }
1647
- }, B = (e) => e === !0 || e === 1, Wt = (e) => d.gen(function* () {
1695
+ }, H = (e) => e === !0 || e === 1, Kt = (e) => d.gen(function* () {
1648
1696
  let t = yield* e`
1649
1697
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
1650
1698
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
@@ -1700,16 +1748,16 @@ BEGIN
1700
1748
  let t = s.get(e) ?? [], n = c.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = new Set(n.map((e) => e.source_column)), a = l.get(e), d = [], f = /* @__PURE__ */ new Set();
1701
1749
  if (a) for (let [, e] of a) {
1702
1750
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
1703
- if (B(t[0].is_primary)) for (let e of t) d.push(e.column_name);
1704
- else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
1751
+ if (H(t[0].is_primary)) for (let e of t) d.push(e.column_name);
1752
+ else H(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
1705
1753
  }
1706
1754
  let p = t.map((t) => {
1707
- let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Ut(t.data_type), s = i ? {
1755
+ let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Gt(t.data_type), s = i ? {
1708
1756
  table: i.target_table,
1709
1757
  column: i.target_column,
1710
- onDelete: Gt(i.delete_rule),
1711
- onUpdate: Gt(i.update_rule)
1712
- } : void 0, c = t.column_default === null ? null : Kt(t.column_default), l = o.get(`${e}.${t.column_name}`);
1758
+ onDelete: qt(i.delete_rule),
1759
+ onUpdate: qt(i.update_rule)
1760
+ } : void 0, c = t.column_default === null ? null : Jt(t.column_default), l = o.get(`${e}.${t.column_name}`);
1713
1761
  return {
1714
1762
  name: t.column_name,
1715
1763
  type: a,
@@ -1723,11 +1771,11 @@ BEGIN
1723
1771
  }), m = [];
1724
1772
  if (a) for (let [t, n] of a) {
1725
1773
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
1726
- B(r[0].is_primary) || r.length === 1 && B(r[0].is_unique) || r.length === 1 && !B(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
1774
+ H(r[0].is_primary) || r.length === 1 && H(r[0].is_unique) || r.length === 1 && !H(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
1727
1775
  name: t,
1728
1776
  table: e,
1729
1777
  columns: r.map((e) => e.column_name),
1730
- unique: B(r[0].is_unique)
1778
+ unique: H(r[0].is_unique)
1731
1779
  });
1732
1780
  }
1733
1781
  d.length > 0 && m.push({
@@ -1742,29 +1790,37 @@ BEGIN
1742
1790
  });
1743
1791
  }
1744
1792
  return { tables: u };
1745
- }), Gt = (e) => {
1793
+ }), qt = (e) => {
1746
1794
  switch (e.toUpperCase().replace(/_/g, " ")) {
1747
1795
  case "CASCADE": return "cascade";
1748
1796
  case "SET NULL": return "setNull";
1749
1797
  case "SET DEFAULT": return "noAction";
1750
1798
  default: return "noAction";
1751
1799
  }
1752
- }, Kt = (e) => {
1800
+ }, Jt = (e) => {
1753
1801
  let t = e.trim();
1754
1802
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
1755
1803
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
1756
- }, qt = (e) => e.onDialectOrElse({
1757
- mysql: () => Bt(e),
1758
- mssql: () => Wt(e),
1759
- sqlite: () => Ht(e),
1760
- orElse: () => Rt(e)
1761
- }), Jt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, V = (e) => {
1804
+ }, Yt = (e) => e.onDialectOrElse({
1805
+ mysql: () => Ht(e),
1806
+ mssql: () => Kt(e),
1807
+ sqlite: () => Wt(e),
1808
+ orElse: () => Bt(e)
1809
+ }), Xt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Zt = (e, t) => {
1810
+ if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
1811
+ 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;
1812
+ 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.`);
1813
+ return O(e, t);
1814
+ }, Qt = (e) => {
1815
+ let t = Zt(e, "postgres");
1816
+ return t === void 0 ? $t(e) : t;
1817
+ }, $t = (e) => {
1762
1818
  switch (e.type) {
1763
1819
  case "id": return "text";
1764
1820
  case "text": return "text";
1765
1821
  case "integer": return "integer";
1766
1822
  case "real": return "double precision";
1767
- case "decimal": return Jt(e, "NUMERIC");
1823
+ case "decimal": return Xt(e, "NUMERIC");
1768
1824
  case "bigint": return "bigint";
1769
1825
  case "boolean": return "boolean";
1770
1826
  case "timestamp": return "timestamptz";
@@ -1772,19 +1828,21 @@ BEGIN
1772
1828
  case "json": return "jsonb";
1773
1829
  case "bytes": return "bytea";
1774
1830
  case "reference": return "text";
1775
- case "vector": return "text";
1776
- case "enum": return "text";
1777
- case "array": return "text";
1831
+ case "vector":
1832
+ case "enum":
1833
+ case "array": throw Error(`snapshotPgType: '${e.type}' must go through parameterisedSqlType`);
1778
1834
  case "interval": return "interval";
1779
1835
  case "raw": return e.rawDdl ?? "text";
1780
1836
  }
1781
- }, H = (e) => {
1837
+ }, en = (e) => {
1838
+ let t = Zt(e, "mariadb");
1839
+ if (t !== void 0) return t;
1782
1840
  switch (e.type) {
1783
1841
  case "id": return "VARCHAR(64)";
1784
1842
  case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
1785
1843
  case "integer": return "INT";
1786
1844
  case "real": return "DOUBLE";
1787
- case "decimal": return Jt(e, "DECIMAL");
1845
+ case "decimal": return Xt(e, "DECIMAL");
1788
1846
  case "bigint": return "BIGINT";
1789
1847
  case "boolean": return "TINYINT(1)";
1790
1848
  case "timestamp": return "DATETIME(6)";
@@ -1792,31 +1850,38 @@ BEGIN
1792
1850
  case "json": return "JSON";
1793
1851
  case "bytes": return "LONGBLOB";
1794
1852
  case "reference": return "VARCHAR(64)";
1795
- case "vector": return "BLOB";
1796
- case "enum": return "TEXT";
1797
- case "array": return "JSON";
1853
+ case "vector":
1854
+ case "enum":
1855
+ case "array": throw Error(`snapshotMysqlType: '${e.type}' must go through parameterisedSqlType`);
1798
1856
  case "interval": return "BIGINT";
1799
1857
  case "raw": return e.rawDdl ?? "LONGTEXT";
1800
1858
  }
1801
- }, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``, Yt = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, Xt = (e) => `ALTER TABLE ${W(e.table)} DROP COLUMN IF EXISTS ${W(e.column)}, ALGORITHM=COPY;`, Zt = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Qt = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${yn(t)}`)};`, $t = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${n(e.defaultValue) ?? "DEFAULT NULL"};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], en = (e, t, n) => {
1802
- let r = n ?? e.nullable, i = ve(e, "mariadb");
1859
+ }, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``, tn = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, nn = (e) => `ALTER TABLE ${W(e.table)} DROP COLUMN IF EXISTS ${W(e.column)}, ALGORITHM=COPY;`, rn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, an = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${On(t)}`)};`, on = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${sn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, sn = (e, t) => {
1860
+ let n = t(e.defaultValue);
1861
+ 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.`);
1862
+ return n;
1863
+ }, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], cn = (e, t, n) => {
1864
+ let r = G(e, t, n);
1865
+ return r ? et(n, r) : void 0;
1866
+ }, ln = (e, t, n) => {
1867
+ let r = n ?? e.nullable, i = _e(e, "mariadb");
1803
1868
  return [
1804
1869
  W(t),
1805
- D(e, "mariadb"),
1870
+ O(e, "mariadb"),
1806
1871
  r ? null : "NOT NULL",
1807
1872
  i
1808
1873
  ].filter(Boolean).join(" ");
1809
- }, tn = (e) => e == null ? null : 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" && !Array.isArray(e) ? O(e, "mysql") : null, nn = (e) => e == null ? null : 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" && !Array.isArray(e) ? O(e, "postgres") : null, K = (e, t) => {
1874
+ }, un = (e, t) => e == null ? null : Array.isArray(e) ? dn(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" ? k(e, "mysql") : null, dn = (e, t, n) => ve(e, t ?? { type: "json" }, n), fn = (e, t) => e == null ? null : Array.isArray(e) ? dn(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" ? k(e, "postgres") : null, K = (e, t) => {
1810
1875
  if (!e.generatedAs) return null;
1811
1876
  let { expr: n, stored: r } = e.generatedAs;
1812
1877
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
1813
- }, rn = (e) => {
1814
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "postgres");
1878
+ }, pn = (e) => {
1879
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "postgres");
1815
1880
  let t = K(e, "postgres");
1816
- if (t) return `${U(e.name)} ${V(e)} ${t}`;
1817
- let n = [U(e.name), V(e)];
1881
+ if (t) return `${U(e.name)} ${Qt(e)} ${t}`;
1882
+ let n = [U(e.name), Qt(e)];
1818
1883
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
1819
- let t = nn(e.defaultValue);
1884
+ let t = fn(e.defaultValue, e);
1820
1885
  t && n.push(t);
1821
1886
  }
1822
1887
  return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
@@ -1825,20 +1890,20 @@ BEGIN
1825
1890
  setNull: "SET NULL",
1826
1891
  noAction: "NO ACTION"
1827
1892
  }[e.references.onDelete]}`)), n.join(" ");
1828
- }, q = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", an = (e) => {
1829
- let t = e.columns.map((e) => ` ${rn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
1830
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(wn).join(", ")})`);
1893
+ }, q = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", mn = (e) => {
1894
+ let t = e.columns.map((e) => ` ${pn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
1895
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(Nn).join(", ")})`);
1831
1896
  return n;
1832
- }, on = 191, J = (e) => {
1833
- let t = H(e).toUpperCase();
1897
+ }, hn = 191, J = (e) => {
1898
+ let t = en(e).toUpperCase();
1834
1899
  return t.endsWith("TEXT") || t.endsWith("BLOB");
1835
- }, sn = (e) => {
1836
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mariadb");
1900
+ }, gn = (e) => {
1901
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "mariadb");
1837
1902
  let t = K(e, "mariadb");
1838
- if (t) return `${W(e.name)} ${H(e)} ${t}`;
1839
- let n = [W(e.name), H(e)];
1903
+ if (t) return `${W(e.name)} ${en(e)} ${t}`;
1904
+ let n = [W(e.name), en(e)];
1840
1905
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !J(e) && n.push("UNIQUE"), e.hasDefault) {
1841
- let t = tn(e.defaultValue);
1906
+ let t = un(e.defaultValue, e);
1842
1907
  t && n.push(t);
1843
1908
  }
1844
1909
  return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
@@ -1847,25 +1912,27 @@ BEGIN
1847
1912
  setNull: "SET NULL",
1848
1913
  noAction: "NO ACTION"
1849
1914
  }[e.references.onDelete]}`)), n.join(" ");
1850
- }, cn = (e) => {
1915
+ }, _n = (e) => {
1851
1916
  let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
1852
1917
  let n = t.get(e);
1853
- return n && J(n) ? `${W(e)}(${on})` : W(e);
1854
- }, r = e.columns.map((e) => ` ${sn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${r}${q(e, n)}\n)`];
1918
+ return n && J(n) ? `${W(e)}(${hn})` : W(e);
1919
+ }, r = e.columns.map((e) => ` ${gn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${r}${q(e, n)}\n)`];
1855
1920
  for (let t of e.columns) t.unique && t.type !== "id" && J(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${W(`${e.table}_${t.name}_key`)} ON ${W(e.table)} (${n(t.name)})`);
1856
1921
  for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(n).join(", ")})`);
1857
1922
  return i;
1858
- }, ln = {
1923
+ }, vn = {
1859
1924
  cascade: "CASCADE",
1860
1925
  restrict: "RESTRICT",
1861
1926
  setNull: "SET NULL",
1862
1927
  noAction: "NO ACTION"
1863
- }, un = {
1928
+ }, yn = {
1864
1929
  cascade: "CASCADE",
1865
1930
  restrict: "NO ACTION",
1866
1931
  setNull: "SET NULL",
1867
1932
  noAction: "NO ACTION"
1868
- }, dn = (e) => {
1933
+ }, bn = (e) => {
1934
+ let t = Zt(e, "sqlite");
1935
+ if (t !== void 0) return t;
1869
1936
  switch (e.type) {
1870
1937
  case "integer":
1871
1938
  case "boolean": return "INTEGER";
@@ -1875,29 +1942,29 @@ BEGIN
1875
1942
  case "bytes": return "BLOB";
1876
1943
  default: return "TEXT";
1877
1944
  }
1878
- }, Y = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" && !Array.isArray(e) ? O(e, "sqlite") : null, fn = (e) => {
1879
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "sqlite");
1945
+ }, Y = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? k(e, "sqlite") : null, xn = (e) => {
1946
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "sqlite");
1880
1947
  let t = K(e, "sqlite");
1881
- if (t) return `${U(e.name)} ${dn(e)} ${t}`;
1882
- let n = [U(e.name), dn(e)];
1948
+ if (t) return `${U(e.name)} ${bn(e)} ${t}`;
1949
+ let n = [U(e.name), bn(e)];
1883
1950
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
1884
1951
  let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
1885
1952
  t && n.push(t);
1886
1953
  }
1887
- if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${ln[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
1954
+ if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${vn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
1888
1955
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
1889
1956
  n.push(`CHECK (${U(e.name)} IN (${t}))`);
1890
1957
  }
1891
1958
  return n.join(" ");
1892
- }, pn = (e) => {
1893
- let t = e.columns.map((e) => ` ${fn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
1959
+ }, Sn = (e) => {
1960
+ let t = e.columns.map((e) => ` ${xn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
1894
1961
  for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(U).join(", ")})`);
1895
1962
  return n;
1896
1963
  }, X = (e, t) => {
1897
1964
  let n = t.find((t) => t.tableName === e);
1898
1965
  if (!n) return [];
1899
- let r = P([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
1900
- ...pn({
1966
+ let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
1967
+ ...Sn({
1901
1968
  kind: "create-table",
1902
1969
  table: i,
1903
1970
  columns: r.columns,
@@ -1910,23 +1977,25 @@ BEGIN
1910
1977
  ];
1911
1978
  for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e)} (${t.columns.map(U).join(", ")})`);
1912
1979
  return o;
1913
- }, mn = (e, t, n, r) => {
1980
+ }, Cn = (e, t, n, r) => {
1914
1981
  let i = r ?? e.nullable;
1915
- return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${D(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
1916
- }, hn = (e) => {
1982
+ return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${O(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
1983
+ }, wn = (e) => {
1917
1984
  let t = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Z(e.table)} DROP CONSTRAINT [' + @dc + ']');`;
1918
1985
  if (!e.hasDefault) return t;
1919
1986
  let n = Y(e.defaultValue, "SYSUTCDATETIME()");
1920
1987
  if (!n) return t;
1921
1988
  let r = n.replace(/^DEFAULT\s+/i, "");
1922
1989
  return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
1923
- }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, gn = (e) => {
1990
+ }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Tn = (e) => {
1991
+ let t = Zt(e, "mssql");
1992
+ if (t !== void 0) return t;
1924
1993
  switch (e.type) {
1925
1994
  case "id":
1926
1995
  case "reference": return "NVARCHAR(64)";
1927
1996
  case "integer": return "INT";
1928
1997
  case "real": return "FLOAT";
1929
- case "decimal": return Jt(e, "DECIMAL");
1998
+ case "decimal": return Xt(e, "DECIMAL");
1930
1999
  case "bigint": return "BIGINT";
1931
2000
  case "boolean": return "BIT";
1932
2001
  case "timestamp": return "DATETIME2(6)";
@@ -1934,34 +2003,34 @@ BEGIN
1934
2003
  case "bytes": return "VARBINARY(MAX)";
1935
2004
  default: return "NVARCHAR(MAX)";
1936
2005
  }
1937
- }, _n = (e, t) => {
1938
- if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mssql");
1939
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : gn(e), r = K(e, "mssql");
2006
+ }, En = (e, t) => {
2007
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "mssql");
2008
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Tn(e), r = K(e, "mssql");
1940
2009
  if (r) return `${Z(e.name)} ${r}`;
1941
2010
  let i = [Z(e.name), n];
1942
2011
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
1943
2012
  let t = Y(e.defaultValue, "SYSUTCDATETIME()");
1944
2013
  t && i.push(t);
1945
2014
  }
1946
- return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${un[e.references.onDelete]}`)), i.join(" ");
1947
- }, vn = (e) => {
1948
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${_n(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${q(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2015
+ return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${yn[e.references.onDelete]}`)), i.join(" ");
2016
+ }, Dn = (e) => {
2017
+ let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${En(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${q(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
1949
2018
  for (let n of e.indexes) {
1950
2019
  if (n.name === `${e.table}_pkey`) continue;
1951
2020
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
1952
2021
  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)}')`);
1953
2022
  }
1954
2023
  return a;
1955
- }, yn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, bn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, xn = (e, t, n) => {
1956
- let r = `${e.table}${yn(t)}`;
2024
+ }, On = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, kn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, An = (e, t, n) => {
2025
+ let r = `${e.table}${On(t)}`;
1957
2026
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
1958
- }, Sn = (e, t, n) => {
2027
+ }, jn = (e, t, n) => {
1959
2028
  let r = G(e, t, n);
1960
2029
  return r ? J({ type: r.type }) : !1;
1961
- }, Cn = (e, t, n) => Sn(e, t, n) ? `${W(n)}(${on})` : W(n), wn = (e) => e.startsWith("(") ? e : U(e), Tn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${U(e.index.name)} ON ${U(e.table)} (${e.index.columns.map(wn).join(", ")});`, En = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map((n) => Cn(t, e.table, n)).join(", ")});`, Dn = (e) => `DROP INDEX IF EXISTS ${U(e.index)};`, On = (e) => `DROP INDEX ${W(e.index)} ON ${W(e.table)};`, kn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, An = (e) => {
2030
+ }, Mn = (e, t, n) => jn(e, t, n) ? `${W(n)}(${hn})` : W(n), Nn = (e) => e.startsWith("(") ? e : U(e), Pn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${U(e.index.name)} ON ${U(e.table)} (${e.index.columns.map(Nn).join(", ")});`, Fn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map((n) => Mn(t, e.table, n)).join(", ")});`, In = (e) => `DROP INDEX IF EXISTS ${U(e.index)};`, Ln = (e) => `DROP INDEX ${W(e.index)} ON ${W(e.table)};`, Rn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, zn = (e) => {
1962
2031
  let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Z(e.index.name)} ON ${Z(e.table)} (${e.index.columns.map(Z).join(", ")})`;
1963
2032
  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)}');`;
1964
- }, jn = (e, t, n) => {
2033
+ }, Bn = (e, t, n) => {
1965
2034
  let r = n.find((t) => t.tableName === e);
1966
2035
  if (!r) return [];
1967
2036
  let i = [];
@@ -1970,13 +2039,13 @@ BEGIN
1970
2039
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
1971
2040
  }
1972
2041
  return i;
1973
- }, Mn = (e) => `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(`${e.table}_${e.column}_key`)} UNIQUE (${U(e.column)});`, Nn = (e, t) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${Cn(t, e.table, e.column)});`, Pn = (e) => {
2042
+ }, Vn = (e) => `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(`${e.table}_${e.column}_key`)} UNIQUE (${U(e.column)});`, Hn = (e, t) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${Mn(t, e.table, e.column)});`, Un = (e) => {
1974
2043
  let t = e.fields.map((e) => U(e)).join(", ");
1975
2044
  return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
1976
- }, Fn = (e, t) => {
1977
- let n = e.fields.map((n) => Cn(t, e.table, n)).join(", ");
2045
+ }, Wn = (e, t) => {
2046
+ let n = e.fields.map((n) => Mn(t, e.table, n)).join(", ");
1978
2047
  return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
1979
- }, In = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(e.name)};`, Ln = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(e.name)};`, Rn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_key`)};`, zn = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(`${e.table}_${e.column}_key`)};`, Bn = (e, t) => {
2048
+ }, Gn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(e.name)};`, Kn = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(e.name)};`, qn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_key`)};`, Jn = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(`${e.table}_${e.column}_key`)};`, Yn = (e, t) => {
1980
2049
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
1981
2050
  if (e.orphanPolicy) {
1982
2051
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -1994,11 +2063,11 @@ BEGIN
1994
2063
  setNull: "SET NULL",
1995
2064
  noAction: "NO ACTION"
1996
2065
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
1997
- }, Vn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_fkey`)};`, Hn = (e) => `ALTER TABLE ${W(e.table)} DROP FOREIGN KEY ${W(`${e.table}_${e.column}_fkey`)};`, Un = (e, t) => {
2066
+ }, Xn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_fkey`)};`, Zn = (e) => `ALTER TABLE ${W(e.table)} DROP FOREIGN KEY ${W(`${e.table}_${e.column}_fkey`)};`, Qn = (e, t) => {
1998
2067
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
1999
2068
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2000
- }, Wn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_check`)};`, Gn = (e) => `ALTER TABLE ${W(e.table)} DROP CHECK ${W(`${e.table}_${e.column}_check`)};`, Kn = (e, t, n, r) => {
2001
- let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Z : U, s = a ? H(i) : r === "mssql" ? gn(i) : r === "sqlite" ? dn(i) : V(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? tn(e) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : nn(e), u = K(i, r);
2069
+ }, $n = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_check`)};`, er = (e) => `ALTER TABLE ${W(e.table)} DROP CHECK ${W(`${e.table}_${e.column}_check`)};`, tr = (e, t, n, r) => {
2070
+ let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Z : U, s = a ? en(i) : r === "mssql" ? Tn(i) : r === "sqlite" ? bn(i) : Qt(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? un(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : fn(e, i), u = K(i, r);
2002
2071
  if (u) {
2003
2072
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2004
2073
  return {
@@ -2014,7 +2083,8 @@ BEGIN
2014
2083
  };
2015
2084
  }
2016
2085
  if (t.classification === "needs-default") {
2017
- let t = l(i.defaultValue) ?? "DEFAULT NULL";
2086
+ let t = l(i.defaultValue);
2087
+ 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.`);
2018
2088
  return {
2019
2089
  pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t};`],
2020
2090
  post: []
@@ -2025,7 +2095,7 @@ BEGIN
2025
2095
  post: f ? [f] : []
2026
2096
  };
2027
2097
  return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
2028
- }, qn = (e) => {
2098
+ }, nr = (e) => {
2029
2099
  let t = new Map(e.map((e) => [e.tableName, e]));
2030
2100
  return (e, n) => {
2031
2101
  let r = t.get(e);
@@ -2047,21 +2117,21 @@ BEGIN
2047
2117
  };
2048
2118
  }, Q = (e, t, n) => e.unsafe(t).pipe(d.tapError((e) => d.sync(() => {
2049
2119
  process.stderr.write(_(`applier: statement failed (op=${n})`, t, e, 400));
2050
- })), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), Jn = (e, t, n) => d.gen(function* () {
2051
- let r = process.hrtime.bigint(), i = qn(n.declared), a = t.op;
2120
+ })), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), rr = (e, t, n) => d.gen(function* () {
2121
+ let r = process.hrtime.bigint(), i = nr(n.declared), a = t.op;
2052
2122
  switch (a.kind) {
2053
2123
  case "create-table": {
2054
2124
  let t = yield* e.onDialectOrElse({
2055
- mysql: () => d.succeed(cn(a)),
2056
- mssql: () => d.succeed(vn(a)),
2057
- sqlite: () => d.succeed(pn(a)),
2058
- orElse: () => d.succeed(an(a))
2125
+ mysql: () => d.succeed(_n(a)),
2126
+ mssql: () => d.succeed(Dn(a)),
2127
+ sqlite: () => d.succeed(Sn(a)),
2128
+ orElse: () => d.succeed(mn(a))
2059
2129
  });
2060
2130
  for (let n of t) yield* Q(e, n, a.kind);
2061
2131
  break;
2062
2132
  }
2063
2133
  case "drop-table": {
2064
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? xn(a, n, e) : bn(a, e);
2134
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? An(a, n, e) : kn(a, e);
2065
2135
  yield* e.onDialectOrElse({
2066
2136
  mysql: () => Q(e, r(W), a.kind),
2067
2137
  orElse: () => Q(e, r(U), a.kind)
@@ -2071,71 +2141,71 @@ BEGIN
2071
2141
  case "drop-column": {
2072
2142
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2073
2143
  yield* e.onDialectOrElse({
2074
- mysql: () => Q(e, t ? Qt(a, n, W) : Xt(a), a.kind),
2075
- orElse: () => Q(e, t ? Qt(a, n, U) : Yt(a, U), a.kind)
2144
+ mysql: () => Q(e, t ? an(a, n, W) : nn(a), a.kind),
2145
+ orElse: () => Q(e, t ? an(a, n, U) : tn(a, U), a.kind)
2076
2146
  });
2077
2147
  break;
2078
2148
  }
2079
2149
  case "rename-column":
2080
2150
  yield* e.onDialectOrElse({
2081
- mysql: () => Q(e, Zt(a, W), a.kind),
2151
+ mysql: () => Q(e, rn(a, W), a.kind),
2082
2152
  mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
2083
- orElse: () => Q(e, Zt(a, U), a.kind)
2153
+ orElse: () => Q(e, rn(a, U), a.kind)
2084
2154
  });
2085
2155
  break;
2086
2156
  case "add-index":
2087
2157
  yield* e.onDialectOrElse({
2088
- mysql: () => Q(e, En(a, n.declared), a.kind),
2089
- mssql: () => $(e, [...jn(a.table, a.index.columns, n.declared), An(a)], a.kind),
2090
- orElse: () => Q(e, Tn(a, t.classification === "online-required"), a.kind)
2158
+ mysql: () => Q(e, Fn(a, n.declared), a.kind),
2159
+ mssql: () => $(e, [...Bn(a.table, a.index.columns, n.declared), zn(a)], a.kind),
2160
+ orElse: () => Q(e, Pn(a, t.classification === "online-required"), a.kind)
2091
2161
  });
2092
2162
  break;
2093
2163
  case "drop-index":
2094
2164
  yield* e.onDialectOrElse({
2095
- mysql: () => Q(e, On(a), a.kind),
2096
- mssql: () => Q(e, kn(a), a.kind),
2097
- orElse: () => Q(e, Dn(a), a.kind)
2165
+ mysql: () => Q(e, Ln(a), a.kind),
2166
+ mssql: () => Q(e, Rn(a), a.kind),
2167
+ orElse: () => Q(e, In(a), a.kind)
2098
2168
  });
2099
2169
  break;
2100
2170
  case "add-unique":
2101
2171
  yield* e.onDialectOrElse({
2102
- mysql: () => Q(e, Nn(a, n.declared), a.kind),
2172
+ mysql: () => Q(e, Hn(a, n.declared), a.kind),
2103
2173
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2104
- mssql: () => $(e, [...jn(a.table, [a.column], n.declared), Mn(a)], a.kind),
2105
- orElse: () => Q(e, Mn(a), a.kind)
2174
+ mssql: () => $(e, [...Bn(a.table, [a.column], n.declared), Vn(a)], a.kind),
2175
+ orElse: () => Q(e, Vn(a), a.kind)
2106
2176
  });
2107
2177
  break;
2108
2178
  case "drop-unique":
2109
2179
  yield* e.onDialectOrElse({
2110
- mysql: () => Q(e, zn(a), a.kind),
2180
+ mysql: () => Q(e, Jn(a), a.kind),
2111
2181
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2112
- orElse: () => Q(e, Rn(a), a.kind)
2182
+ orElse: () => Q(e, qn(a), a.kind)
2113
2183
  });
2114
2184
  break;
2115
2185
  case "add-unique-composite":
2116
2186
  yield* e.onDialectOrElse({
2117
- mysql: () => Q(e, Fn(a, n.declared), a.kind),
2187
+ mysql: () => Q(e, Wn(a, n.declared), a.kind),
2118
2188
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2119
- mssql: () => $(e, [...jn(a.table, a.fields, n.declared), Pn(a)], a.kind),
2120
- orElse: () => Q(e, Pn(a), a.kind)
2189
+ mssql: () => $(e, [...Bn(a.table, a.fields, n.declared), Un(a)], a.kind),
2190
+ orElse: () => Q(e, Un(a), a.kind)
2121
2191
  });
2122
2192
  break;
2123
2193
  case "drop-unique-composite":
2124
2194
  yield* e.onDialectOrElse({
2125
- mysql: () => Q(e, Ln(a), a.kind),
2195
+ mysql: () => Q(e, Kn(a), a.kind),
2126
2196
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2127
- orElse: () => Q(e, In(a), a.kind)
2197
+ orElse: () => Q(e, Gn(a), a.kind)
2128
2198
  });
2129
2199
  break;
2130
2200
  case "add-foreign-key":
2131
2201
  yield* e.onDialectOrElse({
2132
- mysql: () => $(e, Bn(a, W), a.kind),
2202
+ mysql: () => $(e, Yn(a, W), a.kind),
2133
2203
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2134
- orElse: () => $(e, Bn(a, U), a.kind)
2204
+ orElse: () => $(e, Yn(a, U), a.kind)
2135
2205
  });
2136
2206
  break;
2137
2207
  case "add-column": {
2138
- let n = Kn(a, t, i, yield* e.onDialectOrElse({
2208
+ let n = tr(a, t, i, yield* e.onDialectOrElse({
2139
2209
  mysql: () => d.succeed("mariadb"),
2140
2210
  mssql: () => d.succeed("mssql"),
2141
2211
  sqlite: () => d.succeed("sqlite"),
@@ -2181,35 +2251,37 @@ BEGIN
2181
2251
  yield* e.onDialectOrElse({
2182
2252
  mysql: () => {
2183
2253
  let t = G(n.declared, a.table, a.column);
2184
- return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${en(t, a.column, a.toNullable)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2254
+ return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${ln(t, a.column, a.toNullable)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2185
2255
  },
2186
2256
  mssql: () => {
2187
2257
  let t = G(n.declared, a.table, a.column);
2188
- return t ? Q(e, mn(t, a.column, a.table, a.toNullable), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
2258
+ return t ? Q(e, Cn(t, a.column, a.table, a.toNullable), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
2189
2259
  },
2190
2260
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2191
2261
  orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
2192
2262
  });
2193
2263
  break;
2194
- case "alter-column-default":
2264
+ case "alter-column-default": {
2265
+ let t = cn(n.declared, a.table, a.column);
2195
2266
  yield* e.onDialectOrElse({
2196
- mysql: () => Q(e, $t(a, W, tn), a.kind),
2197
- mssql: () => Q(e, hn(a), a.kind),
2267
+ mysql: () => Q(e, on(a, W, (e) => un(e, t)), a.kind),
2268
+ mssql: () => Q(e, wn(a), a.kind),
2198
2269
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2199
- orElse: () => Q(e, $t(a, U, nn), a.kind)
2270
+ orElse: () => Q(e, on(a, U, (e) => fn(e, t)), a.kind)
2200
2271
  });
2201
2272
  break;
2273
+ }
2202
2274
  case "alter-column-type": {
2203
- let r = V({ type: a.to }), i = a.using ? ` USING ${a.using}` : "";
2275
+ let r = Qt(cn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
2204
2276
  if (t.classification !== "online-required") {
2205
2277
  yield* e.onDialectOrElse({
2206
2278
  mysql: () => {
2207
2279
  let t = G(n.declared, a.table, a.column);
2208
- return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${en(t, a.column)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2280
+ return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${ln(t, a.column)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2209
2281
  },
2210
2282
  mssql: () => {
2211
2283
  let t = G(n.declared, a.table, a.column);
2212
- return t ? Q(e, mn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2284
+ return t ? Q(e, Cn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2213
2285
  },
2214
2286
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2215
2287
  orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} TYPE ${r}${i};`, a.kind)
@@ -2233,23 +2305,23 @@ BEGIN
2233
2305
  }
2234
2306
  case "drop-foreign-key":
2235
2307
  yield* e.onDialectOrElse({
2236
- mysql: () => Q(e, Hn(a), a.kind),
2308
+ mysql: () => Q(e, Zn(a), a.kind),
2237
2309
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2238
- orElse: () => Q(e, Vn(a), a.kind)
2310
+ orElse: () => Q(e, Xn(a), a.kind)
2239
2311
  });
2240
2312
  break;
2241
2313
  case "add-check":
2242
2314
  yield* e.onDialectOrElse({
2243
- mysql: () => Q(e, Un(a, W), a.kind),
2315
+ mysql: () => Q(e, Qn(a, W), a.kind),
2244
2316
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2245
- orElse: () => Q(e, Un(a, U), a.kind)
2317
+ orElse: () => Q(e, Qn(a, U), a.kind)
2246
2318
  });
2247
2319
  break;
2248
2320
  case "drop-check":
2249
2321
  yield* e.onDialectOrElse({
2250
- mysql: () => Q(e, Gn(a), a.kind),
2322
+ mysql: () => Q(e, er(a), a.kind),
2251
2323
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2252
- orElse: () => Q(e, Wn(a), a.kind)
2324
+ orElse: () => Q(e, $n(a), a.kind)
2253
2325
  });
2254
2326
  break;
2255
2327
  }
@@ -2258,10 +2330,10 @@ BEGIN
2258
2330
  status: "applied",
2259
2331
  durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
2260
2332
  };
2261
- }), Yn = (e, t, n) => d.gen(function* () {
2333
+ }), ir = (e, t, n) => d.gen(function* () {
2262
2334
  let r = t.operations.filter((e) => e.blocked);
2263
2335
  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.`));
2264
- yield* w(e);
2336
+ yield* T(e);
2265
2337
  let i = Date.now(), a = [];
2266
2338
  try {
2267
2339
  let r = yield* e.onDialectOrElse({
@@ -2271,15 +2343,20 @@ BEGIN
2271
2343
  }), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
2272
2344
  i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
2273
2345
  let e = yield* p.SqlClient;
2274
- for (let t of i) a.push(yield* Jn(e, t, n));
2346
+ for (let t of i) a.push(yield* rr(e, t, n));
2275
2347
  })));
2276
- for (let t of o) a.push(yield* Jn(e, t, n));
2348
+ for (let t of o) a.push(yield* rr(e, t, n));
2277
2349
  } finally {
2278
- yield* T(e).pipe(d.orDie);
2350
+ yield* E(e).pipe(d.orDie);
2351
+ }
2352
+ let o = yield* n.replan(e);
2353
+ if (o.operations.length > 0) {
2354
+ let e = o.operations.slice(0, 10).map((e) => ` - ${e.op.kind} ${"table" in e.op ? e.op.table : ""}${"column" in e.op ? `.${String(e.op.column)}` : ""}`).join("\n");
2355
+ return yield* d.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${t.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${o.operations.length}:\n${e}${o.operations.length > 10 ? `\n … and ${o.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug: the DDL for these operations is a no-op. Report the operation kinds above with the column types involved.`));
2279
2356
  }
2280
- let o = Date.now() - i, s = `plan_${Date.now().toString(36)}`, c = (/* @__PURE__ */ new Date()).toISOString(), l = yield* e.onDialectOrElse({
2281
- mysql: () => d.succeed(c.replace("T", " ").replace("Z", "")),
2282
- orElse: () => d.succeed(c)
2357
+ let s = a.filter((e) => e.status === "applied").length, c = Date.now() - i, l = `plan_${Date.now().toString(36)}`, u = (/* @__PURE__ */ new Date()).toISOString(), f = yield* e.onDialectOrElse({
2358
+ mysql: () => d.succeed(u.replace("T", " ").replace("Z", "")),
2359
+ orElse: () => d.succeed(u)
2283
2360
  });
2284
2361
  return yield* e`
2285
2362
  INSERT INTO ${e("_voltro_migration_plans")}
@@ -2287,33 +2364,34 @@ BEGIN
2287
2364
  ${e("appliedBy")}, ${e("environment")}, ${e("source")},
2288
2365
  ${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
2289
2366
  VALUES
2290
- (${s}, ${t.toFingerprint}, ${JSON.stringify(t.operations)},
2367
+ (${l}, ${t.toFingerprint}, ${JSON.stringify(t.operations)},
2291
2368
  ${n.appliedBy}, ${n.environment}, ${n.source},
2292
- ${o}, ${l}, ${n.notes ?? null})
2369
+ ${c}, ${f}, ${n.notes ?? null})
2293
2370
  `, {
2294
- id: s,
2295
- appliedAt: c,
2371
+ id: l,
2372
+ appliedAt: u,
2296
2373
  fingerprint: t.toFingerprint,
2297
2374
  operations: t.operations,
2298
2375
  appliedBy: n.appliedBy,
2299
2376
  environment: n.environment,
2300
- durationMs: o,
2377
+ durationMs: c,
2378
+ appliedOps: s,
2301
2379
  source: n.source,
2302
2380
  ...n.notes ? { notes: n.notes } : {}
2303
2381
  };
2304
- }), Xn = (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"), Zn = (e) => e`
2382
+ }), ar = (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"), or = (e) => e`
2305
2383
  SELECT fingerprint
2306
2384
  FROM _voltro_migration_plans
2307
2385
  ORDER BY ${e("appliedAt")} DESC
2308
2386
  LIMIT 1
2309
- `.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), Qn = (e) => e.onDialectOrElse({
2387
+ `.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), sr = (e) => e.onDialectOrElse({
2310
2388
  pg: () => "postgres",
2311
2389
  mysql: () => "mysql",
2312
2390
  mssql: () => "mssql",
2313
2391
  sqlite: () => "sqlite",
2314
2392
  orElse: () => "sqlite"
2315
- }), $n = (e, t) => d.gen(function* () {
2316
- let n = M(P(t, Qn(e))), r = yield* Zn(e);
2393
+ }), cr = (e, t) => d.gen(function* () {
2394
+ let n = N(F(t, sr(e))), r = yield* or(e);
2317
2395
  return r === n ? {
2318
2396
  kind: "up-to-date",
2319
2397
  fingerprint: n
@@ -2322,48 +2400,51 @@ BEGIN
2322
2400
  expected: n,
2323
2401
  ...r === void 0 ? {} : { actual: r }
2324
2402
  };
2325
- }), er = [
2403
+ }), lr = [
2326
2404
  "pgeagertest_",
2327
2405
  "mig_e2e_",
2328
2406
  "mig_test_",
2329
2407
  "mysqleagertest_",
2330
2408
  "mssqleagertest_",
2331
2409
  "sqliteeagertest_"
2332
- ], tr = (e) => er.some((t) => e.startsWith(t)), nr = (e, t) => d.gen(function* () {
2410
+ ], ur = (e) => lr.some((t) => e.startsWith(t)), dr = (e, t) => d.gen(function* () {
2333
2411
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2334
- let n = t.filter((e) => tr(e.name)).map((e) => e.name);
2412
+ let n = t.filter((e) => ur(e.name)).map((e) => e.name);
2335
2413
  if (n.length === 0) return [];
2336
2414
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
2337
2415
  return n;
2338
- }), rr = () => {
2416
+ }), fr = () => {
2339
2417
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2340
2418
  return e.length > 0 ? { ignoreTables: e } : {};
2341
- }, ir = (e) => ({
2419
+ }, pr = (e) => ({
2342
2420
  ...e,
2343
2421
  operations: e.operations.map((e) => {
2344
2422
  if (!e.blocked || e.classification !== "lossy") return e;
2345
2423
  let { blocked: t, ...n } = e;
2346
2424
  return n;
2347
2425
  })
2348
- }), ar = (e, t, n) => d.gen(function* () {
2349
- let r = Qn(e), i = t.filter((e) => !at(e.tableName));
2426
+ }), mr = (e, t, n) => t === "postgres" ? at(e, n).pipe(d.flatMap((e) => {
2427
+ let t = ot(e);
2428
+ return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
2429
+ }), d.catchAll(() => d.void)) : d.void, hr = (e, t, n) => d.gen(function* () {
2430
+ let r = sr(e), i = t.filter((e) => !I(e.tableName));
2350
2431
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2351
- let t = M(P(i, r));
2352
- if ((yield* Zn(e)) === t) return {
2432
+ let t = N(F(i, r));
2433
+ if ((yield* or(e)) === t) return yield* mr(e, r, i), {
2353
2434
  kind: "up-to-date",
2354
2435
  fingerprint: t
2355
2436
  };
2356
2437
  }
2357
- let a = yield* qt(e), o = yield* nr(e, a.tables);
2438
+ let a = yield* Yt(e), o = yield* dr(e, a.tables);
2358
2439
  o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
2359
2440
  scope: "voltro:migrate",
2360
2441
  count: o.length
2361
- })), a = yield* qt(e));
2362
- let s = At({
2442
+ })), a = yield* Yt(e));
2443
+ let s = Mt({
2363
2444
  declared: i,
2364
- live: { tables: a.tables.filter((e) => !at(e.name)) },
2445
+ live: { tables: a.tables.filter((e) => !I(e.name)) },
2365
2446
  dialect: r,
2366
- ...rr()
2447
+ ...fr()
2367
2448
  });
2368
2449
  if (s.summary.blocked > 0) {
2369
2450
  let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy");
@@ -2371,39 +2452,48 @@ BEGIN
2371
2452
  kind: "refused-blocked",
2372
2453
  plan: s
2373
2454
  };
2374
- s = ir(s);
2455
+ s = pr(s);
2375
2456
  }
2376
2457
  return s.operations.length === 0 ? {
2377
2458
  kind: "up-to-date",
2378
2459
  fingerprint: s.toFingerprint
2379
2460
  } : {
2380
2461
  kind: "applied",
2381
- applied: yield* Yn(e, s, {
2462
+ applied: yield* ir(e, s, {
2382
2463
  declared: t,
2383
2464
  appliedBy: n.appliedBy,
2384
2465
  environment: n.environment === "prod" ? "dev" : n.environment,
2385
- source: "auto-diff"
2466
+ source: "auto-diff",
2467
+ replan: (e) => d.gen(function* () {
2468
+ let t = yield* Yt(e);
2469
+ return Mt({
2470
+ declared: i,
2471
+ live: { tables: t.tables.filter((e) => !I(e.name)) },
2472
+ dialect: r,
2473
+ ...fr()
2474
+ });
2475
+ })
2386
2476
  }),
2387
2477
  plan: s
2388
2478
  };
2389
- }), or = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
2479
+ }), gr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
2390
2480
  kind: "skipped",
2391
2481
  reason: "VOLTRO_AUTO_MIGRATE=0"
2392
- }) : n.environment === "prod" ? $n(e, t) : ar(e, t, n), sr = (e, t) => {
2482
+ }) : n.environment === "prod" ? cr(e, t) : hr(e, t, n), _r = (e, t) => {
2393
2483
  switch (e.kind) {
2394
2484
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
2395
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${N(e.fingerprint)})`;
2485
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
2396
2486
  case "applied": {
2397
2487
  let t = e.plan.summary;
2398
- return `auto-migrate: applied ${e.plan.operations.length} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${N(e.applied.fingerprint)}`;
2488
+ return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${P(e.applied.fingerprint)}`;
2399
2489
  }
2400
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${N(e.expected)}` + (e.actual ? ` live=${N(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2490
+ case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${P(e.expected)}` + (e.actual ? ` live=${P(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2401
2491
  case "refused-blocked": {
2402
- 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 === "add-column").length, i = t.filter((e) => e.op.kind === "drop-column").length, a = t.filter((e) => e.classification === "needs-rename-annotation").length, o = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + Xn(e.plan), s = [""];
2492
+ 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 === "add-column").length, i = t.filter((e) => e.op.kind === "drop-column").length, a = t.filter((e) => e.classification === "needs-rename-annotation").length, o = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + ar(e.plan), s = [""];
2403
2493
  return n > 0 && s.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=${t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean).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.", " → Add it to your declared set + chain `.dropped()` on it, OR", " write a file-based migration in `migrations/` that DROPs it, OR", " set `VOLTRO_DESTRUCTIVE_OK=1` for ONE `voltro dev` run (acknowledges data loss).", " 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`)."), r > 0 && s.push(`${r} 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."), i > 0 && s.push(`${i} column(s) are missing from your declared schema.`, " → If intentional: chain `.dropped()` on the column slot in the table declaration.", " → If a typo: restore the field. Data survives until you drop it."), a > 0 && s.push(`${a} 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."), s.push("", "See `voltro db plan` for the full machine-readable diff."), o + "\n" + s.join("\n");
2404
2494
  }
2405
2495
  }
2406
- }, cr = /* @__PURE__ */ new Set([
2496
+ }, vr = /* @__PURE__ */ new Set([
2407
2497
  "node_modules",
2408
2498
  "dist",
2409
2499
  "build",
@@ -2412,11 +2502,11 @@ BEGIN
2412
2502
  ".next",
2413
2503
  ".git",
2414
2504
  ".framework"
2415
- ]), lr = async (e) => {
2505
+ ]), yr = async (e) => {
2416
2506
  let t = [], n = async (e) => {
2417
2507
  let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
2418
2508
  for (let i of r) {
2419
- if (cr.has(i.name)) continue;
2509
+ if (vr.has(i.name)) continue;
2420
2510
  let r = g(e, i.name);
2421
2511
  i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
2422
2512
  }
@@ -2425,7 +2515,7 @@ BEGIN
2425
2515
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
2426
2516
  return n.localeCompare(r);
2427
2517
  });
2428
- }, ur = async (e) => {
2518
+ }, br = async (e) => {
2429
2519
  let t = [];
2430
2520
  for (let n of e) {
2431
2521
  let e = (await import(ee(n).href)).default;
@@ -2439,11 +2529,11 @@ BEGIN
2439
2529
  });
2440
2530
  }
2441
2531
  return t;
2442
- }, dr = (e) => e`
2532
+ }, xr = (e) => e`
2443
2533
  SELECT ${e("id")}
2444
2534
  FROM ${e("_voltro_migration_plans")}
2445
2535
  WHERE ${e("source")} = 'file'
2446
- `.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), fr = (e, t, n, r) => d.gen(function* () {
2536
+ `.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), Sr = (e, t, n, r) => d.gen(function* () {
2447
2537
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
2448
2538
  sql: e,
2449
2539
  log: {
@@ -2476,70 +2566,76 @@ BEGIN
2476
2566
  ${r}, ${n}, ${"file"},
2477
2567
  ${c}, ${a}, ${t.migration.description})
2478
2568
  `, { durationMs: c };
2479
- }), pr = (e, t) => d.gen(function* () {
2569
+ }), Cr = (e, t) => d.gen(function* () {
2480
2570
  let n = yield* d.tryPromise({
2481
- try: () => lr(g(t.projectRoot, "migrations")),
2571
+ try: () => yr(g(t, "migrations")),
2482
2572
  catch: (e) => e
2483
2573
  });
2484
2574
  if (n.length === 0) return {
2485
- applied: [],
2575
+ pending: [],
2486
2576
  skipped: []
2487
2577
  };
2488
2578
  let r = yield* d.tryPromise({
2489
- try: () => ur(n),
2579
+ try: () => br(n),
2490
2580
  catch: (e) => e
2491
2581
  });
2492
2582
  if (r.length === 0) return {
2493
- applied: [],
2583
+ pending: [],
2494
2584
  skipped: []
2495
2585
  };
2496
- let i = new Set(yield* dr(e)), a = r.filter((e) => !i.has(e.migration.id)), o = r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id);
2497
- if (a.length === 0) return {
2586
+ let i = new Set(yield* xr(e));
2587
+ return {
2588
+ pending: r.filter((e) => !i.has(e.migration.id)),
2589
+ skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
2590
+ };
2591
+ }), wr = (e, t) => Cr(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Tr = (e, t) => d.gen(function* () {
2592
+ let { pending: n, skipped: r } = yield* Cr(e, t.projectRoot);
2593
+ if (n.length === 0) return {
2498
2594
  applied: [],
2499
- skipped: o
2595
+ skipped: r
2500
2596
  };
2501
- yield* w(e);
2502
- let s = [];
2597
+ yield* T(e);
2598
+ let i = [];
2503
2599
  try {
2504
- for (let n of a) {
2600
+ for (let r of n) {
2505
2601
  yield* d.logInfo("file-based migration applying").pipe(d.annotateLogs({
2506
2602
  scope: "voltro:migrate",
2507
- id: n.migration.id,
2508
- file: n.file
2603
+ id: r.migration.id,
2604
+ file: r.file
2509
2605
  }));
2510
- let { durationMs: r } = yield* fr(e, n, t.env, t.appliedBy);
2511
- s.push({
2512
- id: n.migration.id,
2513
- durationMs: r
2606
+ let { durationMs: n } = yield* Sr(e, r, t.env, t.appliedBy);
2607
+ i.push({
2608
+ id: r.migration.id,
2609
+ durationMs: n
2514
2610
  }), yield* d.logInfo("file-based migration applied").pipe(d.annotateLogs({
2515
2611
  scope: "voltro:migrate",
2516
- id: n.migration.id,
2517
- durationMs: r
2612
+ id: r.migration.id,
2613
+ durationMs: n
2518
2614
  }));
2519
2615
  }
2520
2616
  } finally {
2521
- yield* T(e).pipe(d.orDie);
2617
+ yield* E(e).pipe(d.orDie);
2522
2618
  }
2523
2619
  return {
2524
- applied: s,
2525
- skipped: o
2620
+ applied: i,
2621
+ skipped: r
2526
2622
  };
2527
- }), mr = (e, t) => e`
2623
+ }), Er = (e, t) => e`
2528
2624
  SELECT ${e("id")}
2529
2625
  FROM ${e("_voltro_migration_plans")}
2530
2626
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
2531
2627
  LIMIT 1
2532
- `, hr = (e, t) => d.gen(function* () {
2533
- if (!(yield* mr(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2628
+ `, Dr = (e, t) => d.gen(function* () {
2629
+ if (!(yield* Er(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2534
2630
  let n = yield* d.tryPromise({
2535
- try: () => lr(g(t.projectRoot, "migrations")),
2631
+ try: () => yr(g(t.projectRoot, "migrations")),
2536
2632
  catch: (e) => e
2537
2633
  }), r = (yield* d.tryPromise({
2538
- try: () => ur(n),
2634
+ try: () => br(n),
2539
2635
  catch: (e) => e
2540
2636
  })).find((e) => e.migration.id === t.id);
2541
2637
  if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
2542
- yield* w(e);
2638
+ yield* T(e);
2543
2639
  let i = Date.now();
2544
2640
  try {
2545
2641
  let n = {
@@ -2566,9 +2662,9 @@ BEGIN
2566
2662
  durationMs: o
2567
2663
  };
2568
2664
  } finally {
2569
- yield* T(e).pipe(d.orDie);
2665
+ yield* E(e).pipe(d.orDie);
2570
2666
  }
2571
- }), gr = (e) => d.gen(function* () {
2667
+ }), Or = (e) => d.gen(function* () {
2572
2668
  let t = yield* p.SqlClient, n = yield* t`
2573
2669
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
2574
2670
  WHERE source = 'auto-diff'
@@ -2613,10 +2709,10 @@ BEGIN
2613
2709
  snapshotFingerprint: e.fingerprint,
2614
2710
  snapshotId: i
2615
2711
  };
2616
- }), _r = (e, ...t) => ({
2712
+ }), kr = (e, ...t) => ({
2617
2713
  _tag: "RawSqlFragment",
2618
2714
  strings: [...e],
2619
2715
  values: [...t]
2620
- }), vr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2716
+ }), Ar = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2621
2717
  //#endregion
2622
- export { l as FILE_MIGRATION_PATTERN, C as VOLTRO_MIGRATION_LOCK_KEY, ut as _internalCmp, w as acquireMigrationLock, Ke as applyNamespacedSchema, Yn as applyPlan, Be as applySchema, Lt as chunkTables, P as declaredSnapshot, ve as defaultClause, O as defaultJsonClause, sr as describeOutcome, Yt as emitDropColumnDdl, Xt as emitDropColumnDdlMysql, ze as emitFrameworkBootstrapSql, Le as emitNamespaceProvisionDdl, Re as emitNamespacedSchemaSql, j as emitSchemaSql, M as fingerprintSchema, rr as ignoreTablesFromEnv, qt as introspectSchema, o as isFileMigration, vr as isRawSqlFragment, Mt as mapPgType, c as migration, k as numericIdSql, jt as parseEnumCheck, At as planMigrations, qe as provisionTenantNamespace, T as releaseMigrationLock, sn as renderColumnMysql, rn as renderColumnPg, hr as rollbackFileBasedMigration, pr as runFileBasedMigrations, Je as runFrameworkBootstrap, Ge as runMigrate, or as runPlannedMigrations, N as shortFingerprint, _r as sql, D as sqlType, gr as squashMigrationPlans, ir as unblockLossy, ge as withMigrationLock };
2718
+ export { l as FILE_MIGRATION_PATTERN, it as REACTIVE_TRIGGER_PREFIX, te as VOLTRO_MIGRATION_LOCK_KEY, ft as _internalCmp, T as acquireMigrationLock, Ke as applyNamespacedSchema, ir as applyPlan, Be as applySchema, zt as chunkTables, F as declaredSnapshot, ve as defaultArrayClause, _e as defaultClause, k as defaultJsonClause, _r as describeOutcome, at as detectReactiveTriggerDrift, tn as emitDropColumnDdl, nn as emitDropColumnDdlMysql, ze as emitFrameworkBootstrapSql, Le as emitNamespaceProvisionDdl, Re as emitNamespacedSchemaSql, M as emitSchemaSql, N as fingerprintSchema, ot as formatReactiveTriggerDrift, fr as ignoreTablesFromEnv, Yt as introspectSchema, o as isFileMigration, Ar as isRawSqlFragment, Pt as mapPgType, s as migration, A as numericIdSql, Nt as parseEnumCheck, wr as pendingFileMigrationIds, Mt as planMigrations, qe as provisionTenantNamespace, E as releaseMigrationLock, gn as renderColumnMysql, pn as renderColumnPg, Dr as rollbackFileBasedMigration, Tr as runFileBasedMigrations, Je as runFrameworkBootstrap, Ge as runMigrate, gr as runPlannedMigrations, P as shortFingerprint, et as snapshotColumn, kr as sql, O as sqlType, Or as squashMigrationPlans, pr as unblockLossy, he as withMigrationLock };