@voltro/database 0.13.0 → 0.15.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, "`"), b = (e) => typeof e == "string" ? e : e.name ?? String(e), te = (e, t) => `_ua_${t}_${e}`.slice(0, 64), x = (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) {
@@ -51,7 +51,7 @@ var _ = (e, t, n, r = 400) => {
51
51
  for (let r of t.fields) {
52
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 = te(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
- }, S = (e, t) => `${e}::${t}`, ne = (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(S(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
- }, re = 6322741009312437n, ie = 250, ae = () => {
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
- }, oe = (e) => d.gen(function* () {
90
- let t = ae(), 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(`${ie} 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
- }), se = (e) => d.gen(function* () {
97
- yield* e`SELECT pg_advisory_unlock(${re.toString()}::bigint)`;
98
- }), ce = `voltro_migration_${re.toString(36)}`, le = 30, ue = (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(${ce}, ${le}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ce}' within ${le}s (another migration is in progress, or a prior one left it held).`)));
101
- }), de = (e) => d.gen(function* () {
102
- yield* e`SELECT RELEASE_LOCK(${ce})`;
103
- }), fe = `voltro_migration_${re.toString(36)}`, pe = 3e4, me = (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 = ${fe}, @LockMode = 'Exclusive',
107
- @LockOwner = 'Session', @LockTimeout = ${pe};
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 '${fe}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
- }), he = (e) => d.gen(function* () {
111
- yield* e`EXEC sp_releaseapplock @Resource = ${fe}, @LockOwner = 'Session'`;
112
- }), ge = d.void, C = (e) => e.onDialectOrElse({
113
- mysql: () => ue(e),
114
- mssql: () => me(e),
115
- sqlite: () => ge,
116
- orElse: () => oe(e)
117
- }), w = (e) => e.onDialectOrElse({
118
- mysql: () => de(e),
119
- mssql: () => he(e),
120
- sqlite: () => ge,
121
- orElse: () => se(e)
122
- }), _e = (e, t) => d.acquireUseRelease(C(e), () => t, () => w(e).pipe(d.orDie)), ve = f({ scope: "voltro:migrate" }), T = (e) => {
123
- ve.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
124
- }, E = (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 `${E({
136
- ...t,
137
- type: t.arrayElement,
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({
118
+ mysql: () => le(e),
119
+ mssql: () => pe(e),
120
+ sqlite: () => me,
121
+ orElse: () => ae(e)
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,26 +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
- }, ye = (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, "''")}'` : Array.isArray(r) ? be(r, t, n) : typeof r == "object" && r ? D(r, n) : null;
239
- }, be = (e, t, n) => {
240
- if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return D(e, n);
241
- let r = E({
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
242
  ...t,
243
243
  type: t.arrayElement,
244
244
  arrayElement: void 0
245
245
  }, n);
246
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
- }, D = (e, t) => {
247
+ }, k = (e, t) => {
248
248
  let n = JSON.stringify(e).replace(/'/g, "''");
249
249
  return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
250
- }, O = (e, t) => {
250
+ }, A = (e, t) => {
251
251
  switch (t) {
252
252
  case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
253
253
  case "mysql":
@@ -256,7 +256,7 @@ var _ = (e, t, n, r = 400) => {
256
256
  case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
257
257
  case "turso": return `"${e}" INTEGER PRIMARY KEY`;
258
258
  }
259
- }, k = (e, t) => {
259
+ }, j = (e, t) => {
260
260
  if (e === "restrict" && t === "mssql") return "NO ACTION";
261
261
  switch (e) {
262
262
  case "cascade": return "CASCADE";
@@ -264,107 +264,107 @@ var _ = (e, t, n, r = 400) => {
264
264
  case "setNull": return "SET NULL";
265
265
  case "noAction": return "NO ACTION";
266
266
  }
267
- }, xe = (e, t, n) => n === null ? u(e, t) : `${u(n, t)}.${u(e, t)}`, Se = 191, Ce = (e, t, n) => {
268
- let r = u(e, n);
269
- if (n !== "mysql" && n !== "mariadb") return r;
270
- let i = t[e];
271
- if (!i) return r;
272
- let a = E(i, n).toUpperCase();
273
- return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${Se})` : r;
274
- }, we = (e, t) => {
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;
274
+ }, Se = (e, t) => {
275
275
  if (!e.generatedAs) return null;
276
276
  let { expr: n, stored: r } = e.generatedAs;
277
- if (t === "postgres") return r || T("[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`;
278
278
  if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
279
279
  if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
280
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.");
281
281
  return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
282
- }, Te = (t, n, r, i, a = !1, o = !1) => {
283
- if (n.type === "id" && n.idScheme?.kind === "numeric") return O(t, r);
284
- let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" : E(n, r), c = [u(t, r), s];
282
+ }, Ce = (t, n, r, i, a = !1, o = !1) => {
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];
285
285
  n.type === "id" && !o && c.push("PRIMARY KEY");
286
- let l = we(n, r);
286
+ let l = Se(n, r);
287
287
  if (l) c.push(l);
288
288
  else {
289
289
  n.nullable || c.push("NOT NULL"), n.unique && n.type !== "id" && c.push("UNIQUE");
290
- let e = ye(n, r);
290
+ let e = _e(n, r);
291
291
  e && c.push(e);
292
292
  }
293
293
  if (n.type === "reference" && n.references && !a) {
294
- let e = n.references();
295
- c.push(`REFERENCES ${u(e.tableName, r)} (${u("id", r)})`);
296
- let t = k(n.onDelete ?? "restrict", r);
297
- c.push(`ON DELETE ${t}`);
298
- let i = k(n.refOnUpdate ?? "noAction", r);
299
- 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}`);
300
300
  }
301
301
  if (n.oneOf && n.oneOf.length > 0) {
302
- let e = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
303
- 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}))`);
304
304
  }
305
305
  if (n.checks && n.checks.length > 0) for (let e of n.checks) c.push(`CHECK (${e})`);
306
- if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" || e(r))) {
307
- let e = n.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
308
- 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}))`);
309
309
  }
310
310
  if (n.type === "json" || n.type === "array") {
311
- let n = u(t, r);
312
- 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)`);
313
313
  }
314
314
  return c.join(" ");
315
- }, Ee = (e, t, n = null, r) => {
316
- let i = /* @__PURE__ */ new Set();
317
- for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
318
- for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
319
- let a = e.appliedPrimaryKey ?? [], o = a.length > 0, s = Object.entries(e.fields).map(([e, n]) => ` ${Te(e, n, t, i, r?.has(e) ?? !1, o)}`).join(",\n"), c = (e.appliedUniques ?? []).map((n) => {
320
- let r = n.fields.map((n) => Ce(n, e.fields, t)).join(", ");
321
- return ` CONSTRAINT ${u(n.name, t)} UNIQUE (${r})`;
322
- }), l = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${u(e.name, t)} CHECK (${e.expr})`), d = [
323
- ...o ? [` PRIMARY KEY (${a.map((n) => Ce(n, e.fields, t)).join(", ")})`] : [],
324
- ...c,
325
- ...l
326
- ], f = d.length > 0 ? `${s},\n${d.join(",\n")}` : s, p = xe(e.tableName, t, n);
327
- if (t === "mssql") {
328
- let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${p} (\n${f}\n)`;
329
- 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, "''")}');`;
330
330
  }
331
331
  return [
332
332
  `CREATE TABLE IF NOT EXISTS ${p} (`,
333
333
  f,
334
334
  ");"
335
335
  ].join("\n");
336
- }, De = (e, t, n) => {
337
- 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 = [];
338
- 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;
339
- }, Oe = (e, n, r = null) => {
340
- 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) => {
341
341
  let o = {
342
342
  using: "",
343
343
  withSuffix: "",
344
344
  skip: !1
345
345
  };
346
346
  if (i === void 0 || i === "btree") return o;
347
- if (i === "gist") return n === "postgres" ? {
347
+ if (i === "gist") return r === "postgres" ? {
348
348
  using: " USING GIST",
349
349
  withSuffix: "",
350
350
  skip: !1
351
- } : (T(`[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);
352
- 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" ? {
353
353
  using: " USING GIN",
354
354
  withSuffix: "",
355
355
  skip: !1
356
- } : n === "mysql" || n === "mariadb" ? (T(`[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(...).`), {
357
357
  using: "",
358
358
  withSuffix: "",
359
359
  skip: !0
360
- }) : (T(`[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);
361
- 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" ? {
362
362
  using: " USING BRIN",
363
363
  withSuffix: "",
364
364
  skip: !1
365
- } : (T(`[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);
366
366
  if (i === "hnsw") {
367
- if (n === "postgres") {
367
+ if (r === "postgres") {
368
368
  let e = a?.hnsw?.m ?? 16, n = a?.hnsw?.efConstruction ?? 64, r = a?.hnsw?.opclass ?? t(a?.hnsw?.distance);
369
369
  return {
370
370
  using: " USING hnsw",
@@ -373,65 +373,65 @@ var _ = (e, t, n, r = 400) => {
373
373
  skip: !1
374
374
  };
375
375
  }
376
- return T(`[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.`), {
377
377
  using: "",
378
378
  withSuffix: "",
379
379
  skip: !0
380
380
  };
381
381
  }
382
382
  return o;
383
- }, l = (t, r) => {
384
- let i = t.map((t) => {
385
- if (typeof t == "string") return Ce(t, e.fields, n);
386
- if ("jsonPath" in t) {
387
- let { column: e, path: r, numeric: i } = t.jsonPath;
388
- 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 })})`;
389
389
  }
390
- return `(${t.expr})`;
390
+ return `(${e.expr})`;
391
391
  });
392
- return r !== void 0 && i.length === 1 ? `${i[0]} ${r}` : i.join(", ");
393
- }, d = (e, t, i, a, o, s = "", d = !1) => {
394
- 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);
395
395
  if (f.skip) return "";
396
- let p = l(i, f.opclass), m = `${f.withSuffix}${s}`, h = xe(t, n, r), g = d ? "UNIQUE " : "";
397
- 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};`;
398
398
  };
399
- for (let t of e.appliedFullText ?? []) if (n === "postgres") {
400
- let r = t.config ?? "english", a = `${t.name}_tsv`, o = t.columns.map((e) => {
401
- let i = t.weights?.[e] ?? "A";
402
- 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}')`;
403
403
  }).join(" || ");
404
- 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)});`);
405
- } else if (n === "mysql" || n === "mariadb") {
406
- let r = t.columns.map((e) => u(e, n)).join(", ");
407
- i.push(`CREATE FULLTEXT INDEX ${u(t.name, n)} ON ${u(e.tableName, n)} (${r});`);
408
- } 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.`);
409
- else n === "sqlite" ? i.push(...De(e.tableName, t, n)) : T(`[voltro:migrate] full-text index '${t.name}' on '${e.tableName}': ${n} uses a ranked LIKE search at query time (no native FTS catalog required).`);
410
- for (let t of e.appliedIndexes) {
411
- if ((n === "mariadb" || n === "mssql") && t.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
412
- T(`[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(...).`);
413
413
  continue;
414
414
  }
415
- 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.`);
416
- let r = "";
417
- t.where !== void 0 && t.where.length > 0 && (n === "mysql" || n === "mariadb" ? T(`[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}`);
418
- let a = d(t.name, e.tableName, t.fields, t.kind, t.kindOptions, r, t.unique === !0);
419
- a !== "" && i.push(a), t.fields.every((e) => typeof e == "string") && o.add(s(t.fields));
420
- }
421
- for (let [t, n] of Object.entries(e.fields)) {
422
- if (n.type !== "reference" || n.fkAutoIndex === !1 || o.has(s([t]))) continue;
423
- let r = `${e.tableName}_${t}_idx`;
424
- i.push(d(r, e.tableName, [t])), o.add(s([t]));
425
- }
426
- return i.join("\n");
427
- }, ke = "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;", Ae = (e) => `
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");
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) => `
428
428
  ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
429
429
  DROP TRIGGER IF EXISTS framework_changes_${e.tableName} ON "${e.tableName}";
430
430
  CREATE TRIGGER framework_changes_${e.tableName}
431
431
  AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
432
432
  FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
433
- `.trim(), je = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Me = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Ne = (e) => {
434
- let t = new Map(e.map((e) => [e.tableName, e])), n = ne(e.map((e) => e.tableName), (e) => {
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) => {
434
+ let t = new Map(e.map((e) => [e.tableName, e])), n = w(e.map((e) => e.tableName), (e) => {
435
435
  let n = t.get(e);
436
436
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
437
437
  if (n.type !== "reference" || !n.references) return [];
@@ -442,7 +442,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
442
442
  }] : [];
443
443
  }) : [];
444
444
  }), r = [];
445
- for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(S(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({
446
446
  table: t.tableName,
447
447
  column: e,
448
448
  targetTable: i.references().tableName,
@@ -453,7 +453,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
453
453
  if (!(i.has(e.tableName) || a.has(e.tableName))) {
454
454
  a.add(e.tableName);
455
455
  for (let [r, i] of Object.entries(e.fields)) {
456
- if (i.type !== "reference" || !i.references || n.has(S(e.tableName, r))) continue;
456
+ if (i.type !== "reference" || !i.references || n.has(C(e.tableName, r))) continue;
457
457
  let a = i.references();
458
458
  if (a.tableName === e.tableName) continue;
459
459
  let o = t.get(a.tableName);
@@ -467,30 +467,30 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
467
467
  sorted: o,
468
468
  cyclic: r
469
469
  };
470
- }, Pe = (e, t, n = null) => {
471
- let r = (e) => n ? `${u(n, t)}.${u(e, t)}` : u(e, t), i = `${e.table}_${e.column}_fkey`, a = k(e.onDelete, t), o = k(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}`;
472
- 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) {
473
473
  case "postgres": return [
474
474
  "DO $$ BEGIN",
475
475
  " IF NOT EXISTS (SELECT 1 FROM pg_constraint",
476
- ` WHERE conname = '${i}' AND conrelid = '${n ? `${n}.` : ""}${e.table}'::regclass) THEN`,
477
- ` 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)};`,
478
478
  " END IF;",
479
479
  "END $$;"
480
480
  ].join("\n");
481
- case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${i}') ALTER TABLE ${r(e.table)} ${c(!1)};`;
482
- case "mariadb": return `ALTER TABLE ${r(e.table)} ${c(!0)};`;
483
- 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)};`;
484
484
  }
485
- }, Fe = (t, n) => {
486
- let r = /* @__PURE__ */ new Map();
487
- if (e(n)) return r;
488
- for (let e of t) {
489
- let t = r.get(e.table) ?? /* @__PURE__ */ new Set();
490
- 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);
491
491
  }
492
- return r;
493
- }, Ie = (e, t) => {
492
+ return n;
493
+ }, Pe = (e, t) => {
494
494
  if (t !== "postgres") return "";
495
495
  let n = /* @__PURE__ */ new Map();
496
496
  for (let t of e) for (let e of Object.values(t.fields)) {
@@ -506,12 +506,12 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
506
506
  r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
507
507
  }
508
508
  return r.join("\n\n");
509
- }, Le = (e, t) => {
509
+ }, Fe = (e, t) => {
510
510
  if (t !== "postgres") return "";
511
511
  let n = /* @__PURE__ */ new Set();
512
512
  for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
513
513
  let r = [];
514
- 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)) {
515
515
  let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
516
516
  r.push(`DO \$\$
517
517
  DECLARE
@@ -520,94 +520,94 @@ BEGIN
520
520
  SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
521
521
  }
522
522
  return r.join("\n\n");
523
- }, Re = (e) => {
523
+ }, Ie = (e) => {
524
524
  let t = [], r = [];
525
525
  for (let i of e) n(i) ? r.push(i) : t.push(i);
526
526
  return {
527
527
  tables: t,
528
528
  views: r
529
529
  };
530
- }, A = (t, n) => {
531
- let { tables: i, views: a } = Re(t), { sorted: o, cyclic: s } = Ne(i.map((e) => x(e, n))), c = Fe(s, n), l = [];
532
- n === "postgres" && je(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && Me(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
533
- let u = Le(o, n);
534
- u && l.push(u);
535
- let d = Ie(o, n);
536
- d && l.push(d);
537
- for (let e of o) l.push(Ee(e, n, null, c.get(e.tableName)));
538
- if (!e(n)) for (let e of s) l.push(Pe(e, n));
539
- for (let e of o) {
540
- let t = Oe(e, n);
541
- t && l.push(t);
542
- }
543
- let f = o.filter((e) => e.isReactive);
544
- if (f.length > 0 && n === "postgres") {
545
- l.push(ke);
546
- for (let e of f) l.push(Ae(e));
547
- }
548
- for (let e of a) l.push(r(e, n));
549
- return l.join("\n\n") + "\n";
550
- }, ze = (e, t, n) => {
551
- let r = u(e, t);
552
- switch (t) {
553
- 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};`;
554
554
  case "mysql":
555
- case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${r};`;
556
- 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, "''")}');`;
557
557
  case "turso":
558
- case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
559
- }
560
- }, Be = (t, n, r, i) => {
561
- let a = ze(r, n, i), o = u(r, n);
562
- if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${A(t, n)}`;
563
- if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${A(t, n)}`;
564
- let { sorted: s, cyclic: c } = Ne(t), l = Fe(c, n), d = [a];
565
- for (let e of s) d.push(Ee(e, n, r, l.get(e.tableName)));
566
- if (!e(n)) for (let e of c) d.push(Pe(e, n, r));
558
+ case "sqlite": return `ATTACH DATABASE '${(r ?? `${t}.db`).replace(/'/g, "''")}' AS ${i};`;
559
+ }
560
+ }, Re = (t, n, r, i) => {
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)}`;
564
+ let { sorted: s, cyclic: c } = je(t), l = Ne(c, n), d = [a];
565
+ for (let e of s) d.push(we(e, n, r, l.get(e.tableName)));
566
+ if (!u(n)) for (let e of c) d.push(Me(e, n, r));
567
567
  for (let e of s) {
568
- let t = Oe(e, n, r);
568
+ let t = Ee(e, n, r);
569
569
  t && d.push(t);
570
570
  }
571
571
  return d.join("\n\n") + "\n";
572
- }, Ve = (e, t) => {
573
- if (t !== "postgres") return A(e, t);
574
- let { sorted: n, cyclic: r } = Ne(e), i = Fe(r, t), a = [], o = Le(n, t);
575
- o && a.push(o);
576
- let s = Ie(n, t);
577
- s && a.push(s);
578
- for (let e of n) a.push(Ee(e, t, null, i.get(e.tableName)));
579
- for (let e of r) a.push(Pe(e, t));
580
- for (let e of n) {
581
- let n = Object.entries(e.fields);
582
- if (n.length === 0) continue;
583
- let r = n.map(([n, r]) => {
584
- let a = Te(n, r, t, void 0, i.get(e.tableName)?.has(n) ?? !1);
585
- 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};`;
586
586
  });
587
- a.push(r.join("\n"));
587
+ o.push(i.join("\n"));
588
588
  }
589
- for (let e of n) {
590
- let n = Oe(e, t);
591
- n && a.push(n);
589
+ for (let e of r) {
590
+ let t = Ee(e, n);
591
+ t && o.push(t);
592
592
  }
593
- let c = n.filter((e) => e.isReactive);
594
- if (c.length > 0) {
595
- a.push(ke);
596
- for (let e of c) a.push(Ae(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));
597
597
  }
598
- return a.join("\n\n") + "\n";
599
- }, He = (e, t = "postgres") => d.gen(function* () {
598
+ return o.join("\n\n") + "\n";
599
+ }, Be = (e, t = "postgres") => d.gen(function* () {
600
600
  let n = yield* p.SqlClient;
601
- yield* _e(n, Ge(n, A(e, t), t)).pipe(d.orDie);
602
- }), Ue = (e, t) => {
601
+ yield* he(n, Ue(n, M(e, t), t)).pipe(d.orDie);
602
+ }), Ve = (e, t) => {
603
603
  let n = t.cause ?? {};
604
604
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
605
- }, We = (e) => d.gen(function* () {
605
+ }, He = (e) => d.gen(function* () {
606
606
  let t = yield* p.SqlClient;
607
- for (let n of Ke(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ve.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(d.catchIf((e) => Ue(n, e), () => d.void), d.tapError((e) => d.sync(() => {
608
- ve.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));
609
609
  })), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
610
- }), Ge = (e, t, n) => (n === "turso" ? We(t) : e.withTransaction(We(t))).pipe(d.orDie), Ke = (e) => {
610
+ }), Ue = (e, t, n) => (n === "turso" ? He(t) : e.withTransaction(He(t))).pipe(d.orDie), We = (e) => {
611
611
  let t = [], n = "", r = !1;
612
612
  for (let i = 0; i < e.length; i++) {
613
613
  if (e.slice(i, i + 2) === "$$") {
@@ -622,40 +622,40 @@ BEGIN
622
622
  }
623
623
  let i = n.trim();
624
624
  return i.length > 0 && t.push(i), t;
625
- }, qe = async (e, t, n = "postgres") => {
626
- await d.runPromise(He(e, n).pipe(d.provide(t)));
627
- }, Je = (e, t, n = "postgres") => d.gen(function* () {
628
- let r = Be(e, n, t), i = yield* p.SqlClient;
629
- yield* _e(i, Ge(i, r, n)).pipe(d.orDie);
630
- }), Ye = async (e, t, n, r = "postgres") => {
631
- await d.runPromise(Je(e, t, r).pipe(d.provide(n)));
632
- }, Xe = async (e, t, n = "postgres") => {
625
+ }, Ge = async (e, t, n = "postgres") => {
626
+ await d.runPromise(Be(e, n).pipe(d.provide(t)));
627
+ }, Ke = (e, t, n = "postgres") => d.gen(function* () {
628
+ let r = Re(e, n, t), i = yield* p.SqlClient;
629
+ yield* he(i, Ue(i, r, n)).pipe(d.orDie);
630
+ }), qe = async (e, t, n, r = "postgres") => {
631
+ await d.runPromise(Ke(e, t, r).pipe(d.provide(n)));
632
+ }, Je = async (e, t, n = "postgres") => {
633
633
  await d.runPromise(d.gen(function* () {
634
- let t = Ve(e, n), r = yield* p.SqlClient;
635
- yield* _e(r, Ge(r, t, n)).pipe(d.orDie);
634
+ let t = ze(e, n), r = yield* p.SqlClient;
635
+ yield* he(r, Ue(r, t, n)).pipe(d.orDie);
636
636
  }).pipe(d.provide(t)));
637
- }, Ze = (e) => {
637
+ }, Ye = (e) => {
638
638
  if (e == null) return e;
639
- if (Array.isArray(e)) return e.map(Ze);
639
+ if (Array.isArray(e)) return e.map(Ye);
640
640
  if (typeof e != "object") return e;
641
641
  let t = {};
642
642
  for (let n of Object.keys(e).sort()) {
643
643
  let r = e[n];
644
- r !== void 0 && (t[n] = Ze(r));
644
+ r !== void 0 && (t[n] = Ye(r));
645
645
  }
646
646
  return t;
647
- }, Qe = (e) => {
647
+ }, Xe = (e) => {
648
648
  if (!e.idScheme && !e.sensitive && !e.safe) return e;
649
649
  let { idScheme: t, sensitive: n, safe: r, ...i } = e;
650
650
  return i;
651
- }, $e = (e) => [...e].map(Qe).sort((e, t) => e.name.localeCompare(t.name)), et = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), tt = (e) => [...e].map((e) => ({
651
+ }, Ze = (e) => [...e].map(Xe).sort((e, t) => e.name.localeCompare(t.name)), Qe = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), $e = (e) => [...e].map((e) => ({
652
652
  name: e.name,
653
- columns: $e(e.columns),
654
- indexes: et(e.indexes)
655
- })).sort((e, t) => e.name.localeCompare(t.name)), j = (e) => {
656
- let t = { tables: tt(e.tables) }, n = JSON.stringify(Ze(t));
653
+ columns: Ze(e.columns),
654
+ indexes: Qe(e.indexes)
655
+ })).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
656
+ let t = { tables: $e(e.tables) }, n = JSON.stringify(Ye(t));
657
657
  return m("sha256").update(n).digest("hex");
658
- }, M = (e) => e.slice(0, 16), nt = (e, t) => {
658
+ }, P = (e) => e.slice(0, 16), et = (e, t) => {
659
659
  let n = t.references ? {
660
660
  table: t.references().tableName,
661
661
  column: "id",
@@ -693,7 +693,7 @@ BEGIN
693
693
  ...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
694
694
  ...t.spatial === void 0 ? {} : { spatial: t.spatial }
695
695
  };
696
- }, rt = (e) => {
696
+ }, tt = (e) => {
697
697
  let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
698
698
  n.has(e.name) || (n.add(e.name), t.push(e));
699
699
  }, i = e.appliedPrimaryKey ?? [];
@@ -727,13 +727,13 @@ BEGIN
727
727
  columns: t.fields,
728
728
  unique: !0
729
729
  });
730
- let c = /* @__PURE__ */ new Set();
731
- 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"));
732
732
  for (let [t, n] of Object.entries(e.fields)) {
733
733
  let i = n;
734
- 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;
735
735
  let a = `${e.tableName}_${t}_idx`;
736
- s(e.tableName, a, !0, [t]), r({
736
+ c(e.tableName, a, !0, [t]), r({
737
737
  name: a,
738
738
  table: e.tableName,
739
739
  columns: [t],
@@ -741,11 +741,11 @@ BEGIN
741
741
  });
742
742
  }
743
743
  return t;
744
- }, it = (e) => {
744
+ }, nt = (e) => {
745
745
  let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
746
746
  for (let [r, i] of Object.entries(e.fields)) {
747
747
  if (i.dropped) continue;
748
- let e = nt(r, i);
748
+ let e = et(r, i);
749
749
  n.push(t.has(r) ? {
750
750
  ...e,
751
751
  unique: !0
@@ -755,32 +755,66 @@ BEGIN
755
755
  return {
756
756
  name: e.tableName,
757
757
  columns: n,
758
- indexes: rt(e),
758
+ indexes: tt(e),
759
759
  ...r.length > 0 ? { primaryKey: [...r] } : {}
760
760
  };
761
- }, at = (e) => {
761
+ }, rt = (e) => {
762
762
  let t = /* @__PURE__ */ new Map();
763
763
  for (let n of e) for (let e of n.indexes) {
764
764
  let r = t.get(e.name);
765
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}').`);
766
766
  t.set(e.name, n.name);
767
767
  }
768
- }, N = (e, t) => {
769
- let n = e.map((e) => it(x(e, t)));
770
- return at(n), { tables: n };
771
- }, ot = /* @__PURE__ */ new Set(["voltro_isr_cache"]), P = (e) => ot.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), st = {
768
+ }, F = (e, t) => {
769
+ let n = e.map((e) => nt(S(e, t)));
770
+ return rt(n), { tables: n };
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 = {
772
806
  postgres: !0,
773
807
  mysql: !0,
774
808
  mariadb: !0,
775
809
  mssql: !0,
776
810
  sqlite: !0
777
- }, ct = {
811
+ }, lt = {
778
812
  postgres: !0,
779
813
  mysql: !1,
780
814
  mariadb: !1,
781
815
  mssql: !0,
782
816
  sqlite: !0
783
- }, lt = (e) => {
817
+ }, ut = (e) => {
784
818
  switch (e) {
785
819
  case "add-column":
786
820
  case "drop-column":
@@ -790,43 +824,43 @@ BEGIN
790
824
  case "add-foreign-key":
791
825
  case "add-unique":
792
826
  case "add-unique-composite":
793
- case "add-check": return ct;
794
- default: return st;
827
+ case "add-check": return lt;
828
+ default: return ct;
795
829
  }
796
- }, ut = (e, t) => {
830
+ }, dt = (e, t) => {
797
831
  let n = new Map(t.tables.map((e) => [e.name, e]));
798
832
  return new Map(e.map((e) => [e.tableName, {
799
833
  table: e,
800
834
  snapshot: n.get(e.tableName),
801
835
  columnDefs: e.fields
802
836
  }]));
803
- }, dt = (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) => {
804
838
  if (typeof e != "object" || !e) return JSON.stringify(e);
805
- if (Array.isArray(e)) return `[${e.map(F).join(",")}]`;
839
+ if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
806
840
  let t = e;
807
- return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${F(t[e])}`).join(",")}}`;
808
- }, ft = (e) => {
841
+ return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
842
+ }, pt = (e) => {
809
843
  if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
810
844
  let t = e.defaultValue;
811
845
  if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
812
846
  if (typeof t == "number") return String(t);
813
- if (typeof t != "string") return F(t);
847
+ if (typeof t != "string") return L(t);
814
848
  let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
815
849
  if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
816
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);
817
851
  if (o) try {
818
- return F(JSON.parse(o[1]));
852
+ return L(JSON.parse(o[1]));
819
853
  } catch {}
820
854
  if (a.startsWith("{") || a.startsWith("[")) try {
821
- return F(JSON.parse(a));
855
+ return L(JSON.parse(a));
822
856
  } catch {}
823
857
  return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
824
- }, pt = (e, t) => {
825
- let n = ft(e), r = ft(t);
858
+ }, mt = (e, t) => {
859
+ let n = pt(e), r = pt(t);
826
860
  if (n === r) return !0;
827
861
  let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
828
862
  return i(n) === i(r);
829
- }, I = (e) => {
863
+ }, R = (e) => {
830
864
  if (!e) return null;
831
865
  let t = (e) => e === "restrict" ? "noAction" : e;
832
866
  return {
@@ -835,18 +869,18 @@ BEGIN
835
869
  onDelete: t(e.onDelete),
836
870
  onUpdate: t(e.onUpdate)
837
871
  };
838
- }, mt = (e, t) => {
872
+ }, ht = (e, t) => {
839
873
  let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
840
874
  if (!n && !r) return !0;
841
875
  if (!n || !r || n.length !== r.length) return !1;
842
876
  let i = [...n].sort(), a = [...r].sort();
843
877
  return i.every((e, t) => e === a[t]);
844
- }, ht = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && pt(e, t) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && mt(e.oneOf, t.oneOf), gt = (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({
845
879
  kind: "add-check",
846
880
  table: e,
847
881
  column: t.name,
848
882
  values: t.oneOf
849
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, _t = (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])), vt = (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) => {
850
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 = [];
851
885
  for (let t of e.columns) {
852
886
  let e = n.get(t.name);
@@ -854,7 +888,7 @@ BEGIN
854
888
  i.push(t);
855
889
  continue;
856
890
  }
857
- ht(t, e) || o.push({
891
+ gt(t, e) || o.push({
858
892
  declared: t,
859
893
  live: e
860
894
  });
@@ -865,47 +899,47 @@ BEGIN
865
899
  removed: a,
866
900
  changed: o
867
901
  };
868
- }, yt = (e, t) => {
902
+ }, bt = (e, t) => {
869
903
  let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
870
904
  for (let t of e.indexes) {
871
905
  let e = n.get(t.name);
872
- (!e || !_t(t, e)) && i.push(t);
906
+ (!e || !vt(t, e)) && i.push(t);
873
907
  }
874
908
  for (let e of t.indexes) r.has(e.name) || a.push(e);
875
909
  return {
876
910
  added: i,
877
911
  removed: a
878
912
  };
879
- }, L = (e, t, n, r) => ({
913
+ }, z = (e, t, n, r) => ({
880
914
  op: e,
881
915
  classification: t,
882
- atomicByDialect: lt(e.kind),
916
+ atomicByDialect: ut(e.kind),
883
917
  ...n ? { reason: n } : {},
884
918
  ...r ? { blocked: r } : {}
885
- }), bt = (e, t, n) => {
919
+ }), xt = (e, t, n) => {
886
920
  let r = {
887
921
  kind: "add-column",
888
922
  table: e,
889
923
  column: t
890
924
  };
891
- 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` });
892
- }, xt = (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) => {
893
927
  let r = {
894
928
  kind: "drop-column",
895
929
  table: e,
896
930
  column: t.name
897
931
  };
898
- 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` });
899
- }, St = (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({
900
934
  kind: "create-table",
901
935
  table: e,
902
936
  columns: t,
903
937
  indexes: n,
904
938
  ...r && r.length > 0 ? { primaryKey: r } : {}
905
- }, "safe", "new table — no data to preserve"), Ct = (e) => L({
939
+ }, "safe", "new table — no data to preserve"), wt = (e) => z({
906
940
  kind: "drop-table",
907
941
  table: e
908
- }, "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" }), wt = 5e4, Tt = (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) => {
909
943
  let i = (n ?? 0) >= r, a;
910
944
  return a = t.unique ? t.columns.length === 1 ? {
911
945
  kind: "add-unique",
@@ -920,16 +954,16 @@ BEGIN
920
954
  kind: "add-index",
921
955
  table: e,
922
956
  index: t
923
- }, 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");
924
- }, Et = (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({
925
959
  kind: "drop-unique-composite",
926
960
  table: e,
927
961
  name: t.name
928
- }, "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({
929
963
  kind: "drop-index",
930
964
  table: e,
931
965
  index: t.name
932
- }, "safe", "drop index (no data loss — index is derived data)"), Dt = (e, t) => {
966
+ }, "safe", "drop index (no data loss — index is derived data)"), Ot = (e, t) => {
933
967
  if (e === "reference") return "text";
934
968
  switch (t) {
935
969
  case "sqlite":
@@ -937,7 +971,7 @@ BEGIN
937
971
  case "mssql": return e === "json" ? "text" : e;
938
972
  default: return e;
939
973
  }
940
- }, Ot = (e, t, n, r, i, a) => {
974
+ }, kt = (e, t, n, r, i, a) => {
941
975
  let o = [];
942
976
  if (t.nullable !== n.nullable) {
943
977
  let n = {
@@ -946,7 +980,7 @@ BEGIN
946
980
  column: t.name,
947
981
  toNullable: t.nullable
948
982
  };
949
- 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`));
950
984
  }
951
985
  if (t.unique !== n.unique) if (t.unique) {
952
986
  let n = {
@@ -954,13 +988,13 @@ BEGIN
954
988
  table: e,
955
989
  column: t.name
956
990
  }, r = (i ?? 0) >= a;
957
- 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)`));
958
- } 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({
959
993
  kind: "drop-unique",
960
994
  table: e,
961
995
  column: t.name
962
996
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
963
- if (Dt(t.type, r) !== Dt(n.type, r)) {
997
+ if (Ot(t.type, r) !== Ot(n.type, r)) {
964
998
  let r = t.narrowedFrom;
965
999
  if (r && r.from === n.type) {
966
1000
  let i = {
@@ -971,7 +1005,7 @@ BEGIN
971
1005
  to: t.type,
972
1006
  ...r.using === void 0 ? {} : { using: r.using }
973
1007
  };
974
- 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)")));
975
1009
  } else {
976
1010
  let r = {
977
1011
  kind: "alter-column-type",
@@ -980,10 +1014,10 @@ BEGIN
980
1014
  from: n.type,
981
1015
  to: t.type
982
1016
  };
983
- 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` }));
984
1018
  }
985
1019
  }
986
- if (!pt(t, n)) {
1020
+ if (!mt(t, n)) {
987
1021
  let n = {
988
1022
  kind: "alter-column-default",
989
1023
  table: e,
@@ -991,18 +1025,18 @@ BEGIN
991
1025
  hasDefault: t.hasDefault,
992
1026
  ...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
993
1027
  };
994
- 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`));
995
1029
  }
996
- if (!mt(t.oneOf, n.oneOf)) {
997
- 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({
998
1032
  kind: "drop-check",
999
1033
  table: e,
1000
1034
  column: t.name
1001
1035
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
1002
- let r = gt(e, t);
1036
+ let r = _t(e, t);
1003
1037
  r && o.push(r);
1004
1038
  }
1005
- 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({
1006
1040
  kind: "drop-foreign-key",
1007
1041
  table: e,
1008
1042
  column: t.name
@@ -1016,17 +1050,17 @@ BEGIN
1016
1050
  ...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
1017
1051
  ...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
1018
1052
  };
1019
- 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({
1020
1054
  ...i,
1021
1055
  orphanPolicy: r
1022
- }, "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')`));
1023
1057
  }
1024
1058
  return o;
1025
- }, kt = (e, t, n) => {
1059
+ }, At = (e, t, n) => {
1026
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));
1027
1061
  for (let [n, c] of Object.entries(t)) {
1028
1062
  let t = c.renamedFrom;
1029
- 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({
1030
1064
  kind: "rename-column",
1031
1065
  table: e.tableName,
1032
1066
  from: t,
@@ -1038,7 +1072,7 @@ BEGIN
1038
1072
  consumedAddedNames: i,
1039
1073
  consumedRemovedNames: a
1040
1074
  };
1041
- }, At = (e) => {
1075
+ }, jt = (e) => {
1042
1076
  let t = {
1043
1077
  safe: 0,
1044
1078
  needsDefault: 0,
@@ -1073,37 +1107,37 @@ BEGIN
1073
1107
  break;
1074
1108
  }
1075
1109
  return t;
1076
- }, jt = (e) => {
1077
- let t = N(e.declared, e.dialect), n = ut(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? wt, 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 = [];
1078
1112
  for (let e of t.tables) if (!r.has(e.name)) {
1079
- a.push(St(e.name, e.columns, e.indexes, e.primaryKey));
1113
+ a.push(Ct(e.name, e.columns, e.indexes, e.primaryKey));
1080
1114
  for (let t of e.columns) {
1081
- let n = gt(e.name, t);
1115
+ let n = _t(e.name, t);
1082
1116
  n && a.push(n);
1083
1117
  }
1084
1118
  }
1085
1119
  let o = new Set(e.ignoreTables ?? []);
1086
- for (let t of e.live.tables) n.has(t.name) || P(t.name) || o.has(t.name) || a.push(Ct(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));
1087
1121
  for (let o of t.tables) {
1088
1122
  let t = r.get(o.name);
1089
1123
  if (!t) continue;
1090
- let s = n.get(o.name), c = vt(o, t), l = yt(o, t), u = kt(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);
1091
1125
  a.push(...u.ops);
1092
1126
  for (let e of c.removed) {
1093
1127
  if (u.consumedRemovedNames.has(e.name)) continue;
1094
1128
  let t = s.columnDefs[e.name];
1095
- a.push(xt(o.name, e, t));
1129
+ a.push(St(o.name, e, t));
1096
1130
  }
1097
1131
  for (let e of c.added) {
1098
1132
  if (u.consumedAddedNames.has(e.name)) continue;
1099
1133
  let t = s.columnDefs[e.name];
1100
- a.push(bt(o.name, e, t));
1101
- let n = gt(o.name, e);
1134
+ a.push(xt(o.name, e, t));
1135
+ let n = _t(o.name, e);
1102
1136
  n && a.push(n);
1103
1137
  }
1104
- for (let e of l.added) a.push(Tt(o.name, e, t.rowCount, i));
1105
- for (let e of l.removed) a.push(Et(o.name, e));
1106
- for (let { declared: n, live: r } of c.changed) a.push(...Ot(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));
1107
1141
  }
1108
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) => {
1109
1143
  let t = c.get(e);
@@ -1111,8 +1145,8 @@ BEGIN
1111
1145
  column: e.name,
1112
1146
  target: e.references.table
1113
1147
  }] : []) : [];
1114
- }, u = ne([...s], l), d = [];
1115
- for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(S(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({
1116
1150
  kind: "add-foreign-key",
1117
1151
  table: e.name,
1118
1152
  column: t.name,
@@ -1127,8 +1161,8 @@ BEGIN
1127
1161
  let n = a[t];
1128
1162
  if (n.op.kind !== "create-table") continue;
1129
1163
  let r = n.op;
1130
- if (!r.columns.some((e) => u.has(S(r.table, e.name)))) continue;
1131
- let i = r.columns.map((t) => u.has(S(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);
1132
1166
  a[t] = {
1133
1167
  ...n,
1134
1168
  op: {
@@ -1148,7 +1182,7 @@ BEGIN
1148
1182
  let i = new Set(t).add(e), a = 0;
1149
1183
  for (let t of r.columns) {
1150
1184
  let n = t.references?.table;
1151
- n && n !== e && !u.has(S(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));
1152
1186
  }
1153
1187
  return p.set(e, a), a;
1154
1188
  }, h = (e) => e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, g = (e) => {
@@ -1183,11 +1217,11 @@ BEGIN
1183
1217
  });
1184
1218
  return {
1185
1219
  operations: v,
1186
- fromFingerprint: j(e.live),
1187
- toFingerprint: j(t),
1188
- summary: At(v)
1220
+ fromFingerprint: N(e.live),
1221
+ toFingerprint: N(t),
1222
+ summary: jt(v)
1189
1223
  };
1190
- }, Mt = (e) => {
1224
+ }, Nt = (e) => {
1191
1225
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1192
1226
  if (!t) return null;
1193
1227
  let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
@@ -1195,7 +1229,7 @@ BEGIN
1195
1229
  column: t[1],
1196
1230
  values: n
1197
1231
  };
1198
- }, Nt = (e, t) => {
1232
+ }, Pt = (e, t) => {
1199
1233
  if (t === "vector") return "vector";
1200
1234
  switch (e) {
1201
1235
  case "text":
@@ -1222,7 +1256,7 @@ BEGIN
1222
1256
  case "USER-DEFINED": return "text";
1223
1257
  default: return "text";
1224
1258
  }
1225
- }, R = (e) => {
1259
+ }, B = (e) => {
1226
1260
  switch (e.toUpperCase()) {
1227
1261
  case "CASCADE": return "cascade";
1228
1262
  case "RESTRICT": return "restrict";
@@ -1230,25 +1264,25 @@ BEGIN
1230
1264
  case "SET DEFAULT": return "noAction";
1231
1265
  default: return "noAction";
1232
1266
  }
1233
- }, Pt = (e, t) => {
1267
+ }, Ft = (e, t) => {
1234
1268
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1235
1269
  return Number.isInteger(n) && n > 0 ? n : t;
1236
- }, Ft = () => Pt(process.env.VOLTRO_INTROSPECT_BATCH, 20), It = 300, Lt = () => {
1270
+ }, It = () => Ft(process.env.VOLTRO_INTROSPECT_BATCH, 20), Lt = 300, Rt = () => {
1237
1271
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1238
- return e !== void 0 && e.trim() === "0" ? 0 : Pt(e, 3e4);
1239
- }, Rt = (e, t) => {
1272
+ return e !== void 0 && e.trim() === "0" ? 0 : Ft(e, 3e4);
1273
+ }, zt = (e, t) => {
1240
1274
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1241
1275
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1242
1276
  return r;
1243
- }, zt = (e) => {
1244
- let t = Lt(), n = d.gen(function* () {
1277
+ }, Bt = (e) => {
1278
+ let t = Rt(), n = d.gen(function* () {
1245
1279
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1246
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Ft(), 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* () {
1247
1281
  let r = [];
1248
- for (let a of Rt(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)));
1249
1283
  return r;
1250
1284
  }), o = [];
1251
- for (let t = 0;; t += It) {
1285
+ for (let t = 0;; t += Lt) {
1252
1286
  let n = yield* e`
1253
1287
  SELECT c.relname AS table_name,
1254
1288
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1256,9 +1290,9 @@ BEGIN
1256
1290
  JOIN pg_namespace n ON n.oid = c.relnamespace
1257
1291
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1258
1292
  ORDER BY c.relname
1259
- LIMIT ${r(It)} OFFSET ${r(t)}
1293
+ LIMIT ${r(Lt)} OFFSET ${r(t)}
1260
1294
  `;
1261
- if (o.push(...n), n.length < It) break;
1295
+ if (o.push(...n), n.length < Lt) break;
1262
1296
  }
1263
1297
  let s = /* @__PURE__ */ new Set(), c = [];
1264
1298
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
@@ -1343,7 +1377,7 @@ BEGIN
1343
1377
  AND c.relname IN ${t}
1344
1378
  )
1345
1379
  SELECT * FROM ix ORDER BY table_name, index_name, position
1346
- `), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map(), x = /* @__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();
1347
1381
  for (let e of u) {
1348
1382
  let t = _.get(e.table_name);
1349
1383
  t || (t = [], _.set(e.table_name, t)), t.push(e);
@@ -1352,18 +1386,18 @@ BEGIN
1352
1386
  let t = v.get(e.table_name);
1353
1387
  t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
1354
1388
  }
1355
- let S = /* @__PURE__ */ new Map();
1389
+ let C = /* @__PURE__ */ new Map();
1356
1390
  for (let e of p) {
1357
- let t = `${e.table_name}${e.constraint_name}`, n = S.get(t);
1391
+ let t = `${e.table_name}${e.constraint_name}`, n = C.get(t);
1358
1392
  n || (n = {
1359
1393
  table: e.table_name,
1360
1394
  columns: []
1361
- }, S.set(t, n)), n.columns.push({
1395
+ }, C.set(t, n)), n.columns.push({
1362
1396
  name: e.column_name,
1363
1397
  position: e.position
1364
1398
  });
1365
1399
  }
1366
- for (let [e, t] of S) {
1400
+ for (let [e, t] of C) {
1367
1401
  let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
1368
1402
  if (n.length === 1) {
1369
1403
  let e = y.get(t.table);
@@ -1379,23 +1413,23 @@ BEGIN
1379
1413
  }
1380
1414
  }
1381
1415
  for (let e of g) {
1382
- let t = te.get(e.source_table);
1383
- t || (t = [], te.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);
1384
1418
  }
1385
1419
  for (let e of ee) {
1386
- let t = x.get(e.table_name);
1387
- t || (t = /* @__PURE__ */ new Map(), x.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));
1388
1422
  let n = t.get(e.index_name);
1389
1423
  n || (n = [], t.set(e.index_name, n)), n.push(e);
1390
1424
  }
1391
- let ne = [];
1425
+ let w = [];
1392
1426
  for (let e of c) {
1393
- 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 = te.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
1394
- 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" : Nt(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 ? {
1395
1429
  table: a.target_table,
1396
1430
  column: a.target_column,
1397
- onDelete: R(a.delete_rule),
1398
- onUpdate: R(a.update_rule)
1431
+ onDelete: B(a.delete_rule),
1432
+ onUpdate: B(a.update_rule)
1399
1433
  } : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
1400
1434
  return {
1401
1435
  name: t.column_name,
@@ -1407,7 +1441,7 @@ BEGIN
1407
1441
  ...c ? { references: c } : {},
1408
1442
  ...l ? { oneOf: l } : {}
1409
1443
  };
1410
- }), l = [], u = x.get(e.table_name);
1444
+ }), l = [], u = S.get(e.table_name);
1411
1445
  if (u) for (let [t, n] of u) {
1412
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) => {
1413
1447
  let t = e.position;
@@ -1431,20 +1465,20 @@ BEGIN
1431
1465
  unique: !0
1432
1466
  });
1433
1467
  let d = Number(e.row_count ?? 0);
1434
- ne.push({
1468
+ w.push({
1435
1469
  name: e.table_name,
1436
1470
  columns: c,
1437
1471
  indexes: l,
1438
1472
  ...d > 0 ? { rowCount: d } : {}
1439
1473
  });
1440
1474
  }
1441
- return { tables: ne };
1475
+ return { tables: w };
1442
1476
  });
1443
1477
  return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
1444
1478
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1445
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);
1446
1480
  }));
1447
- }, Bt = (e, t) => {
1481
+ }, Vt = (e, t) => {
1448
1482
  switch (e.toLowerCase()) {
1449
1483
  case "varchar":
1450
1484
  case "char":
@@ -1476,20 +1510,20 @@ BEGIN
1476
1510
  case "json": return "json";
1477
1511
  default: return "text";
1478
1512
  }
1479
- }, z = (e) => e.map((e) => {
1513
+ }, V = (e) => e.map((e) => {
1480
1514
  let t = e, n = {};
1481
1515
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1482
1516
  return n;
1483
- }), Vt = (e) => d.gen(function* () {
1484
- let t = z(yield* e`
1517
+ }), Ht = (e) => d.gen(function* () {
1518
+ let t = V(yield* e`
1485
1519
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1486
1520
  FROM information_schema.tables
1487
1521
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1488
- ORDER BY table_name`), n = z(yield* e`
1522
+ ORDER BY table_name`), n = V(yield* e`
1489
1523
  SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
1490
1524
  FROM information_schema.columns
1491
1525
  WHERE table_schema = DATABASE()
1492
- ORDER BY table_name, ordinal_position`), r = z(yield* e`
1526
+ ORDER BY table_name, ordinal_position`), r = V(yield* e`
1493
1527
  SELECT k.table_name AS source_table,
1494
1528
  k.column_name AS source_column,
1495
1529
  k.referenced_table_name AS target_table,
@@ -1499,11 +1533,11 @@ BEGIN
1499
1533
  JOIN information_schema.referential_constraints r
1500
1534
  ON k.constraint_name = r.constraint_name
1501
1535
  AND k.table_schema = r.constraint_schema
1502
- 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`
1503
1537
  SELECT table_name, index_name, non_unique, column_name, seq_in_index
1504
1538
  FROM information_schema.statistics
1505
1539
  WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
1506
- 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`
1507
1541
  SELECT table_name, check_clause
1508
1542
  FROM information_schema.check_constraints
1509
1543
  WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
@@ -1513,7 +1547,7 @@ BEGIN
1513
1547
  o.add(`${e.table_name}.${t[1]}`);
1514
1548
  continue;
1515
1549
  }
1516
- let n = Mt(e.check_clause);
1550
+ let n = Nt(e.check_clause);
1517
1551
  n && s.set(`${e.table_name}.${n.column}`, n.values);
1518
1552
  }
1519
1553
  let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
@@ -1536,11 +1570,11 @@ BEGIN
1536
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);
1537
1571
  if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1538
1572
  let p = t.map((t) => {
1539
- 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" : Bt(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 ? {
1540
1574
  table: c.target_table,
1541
1575
  column: c.target_column,
1542
- onDelete: R(c.delete_rule),
1543
- onUpdate: R(c.update_rule)
1576
+ onDelete: B(c.delete_rule),
1577
+ onUpdate: B(c.update_rule)
1544
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}`);
1545
1579
  return {
1546
1580
  name: t.column_name,
@@ -1577,10 +1611,10 @@ BEGIN
1577
1611
  });
1578
1612
  }
1579
1613
  return { tables: f };
1580
- }), Ht = (e) => {
1614
+ }), Ut = (e) => {
1581
1615
  let t = e.toUpperCase();
1582
1616
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1583
- }, Ut = (e) => d.gen(function* () {
1617
+ }, Wt = (e) => d.gen(function* () {
1584
1618
  let t = yield* e`
1585
1619
  SELECT name, sql FROM sqlite_master
1586
1620
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1597,11 +1631,11 @@ BEGIN
1597
1631
  d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1598
1632
  }
1599
1633
  let p = o.map((e) => {
1600
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Ht(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 ? {
1601
1635
  table: r.table,
1602
1636
  column: r.to,
1603
- onDelete: R(r.on_delete),
1604
- onUpdate: R(r.on_update)
1637
+ onDelete: B(r.on_delete),
1638
+ onUpdate: B(r.on_update)
1605
1639
  } : void 0, o = t.get(e.name);
1606
1640
  return {
1607
1641
  name: e.name,
@@ -1636,7 +1670,7 @@ BEGIN
1636
1670
  });
1637
1671
  }
1638
1672
  return { tables: r };
1639
- }), Wt = (e) => {
1673
+ }), Gt = (e) => {
1640
1674
  switch (e.toLowerCase()) {
1641
1675
  case "int":
1642
1676
  case "smallint":
@@ -1658,7 +1692,7 @@ BEGIN
1658
1692
  case "image": return "bytes";
1659
1693
  default: return "text";
1660
1694
  }
1661
- }, B = (e) => e === !0 || e === 1, Gt = (e) => d.gen(function* () {
1695
+ }, H = (e) => e === !0 || e === 1, Kt = (e) => d.gen(function* () {
1662
1696
  let t = yield* e`
1663
1697
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
1664
1698
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
@@ -1714,16 +1748,16 @@ BEGIN
1714
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();
1715
1749
  if (a) for (let [, e] of a) {
1716
1750
  let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
1717
- if (B(t[0].is_primary)) for (let e of t) d.push(e.column_name);
1718
- 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);
1719
1753
  }
1720
1754
  let p = t.map((t) => {
1721
- 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" : Wt(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 ? {
1722
1756
  table: i.target_table,
1723
1757
  column: i.target_column,
1724
- onDelete: Kt(i.delete_rule),
1725
- onUpdate: Kt(i.update_rule)
1726
- } : void 0, c = t.column_default === null ? null : qt(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}`);
1727
1761
  return {
1728
1762
  name: t.column_name,
1729
1763
  type: a,
@@ -1737,11 +1771,11 @@ BEGIN
1737
1771
  }), m = [];
1738
1772
  if (a) for (let [t, n] of a) {
1739
1773
  let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
1740
- 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({
1741
1775
  name: t,
1742
1776
  table: e,
1743
1777
  columns: r.map((e) => e.column_name),
1744
- unique: B(r[0].is_unique)
1778
+ unique: H(r[0].is_unique)
1745
1779
  });
1746
1780
  }
1747
1781
  d.length > 0 && m.push({
@@ -1756,37 +1790,37 @@ BEGIN
1756
1790
  });
1757
1791
  }
1758
1792
  return { tables: u };
1759
- }), Kt = (e) => {
1793
+ }), qt = (e) => {
1760
1794
  switch (e.toUpperCase().replace(/_/g, " ")) {
1761
1795
  case "CASCADE": return "cascade";
1762
1796
  case "SET NULL": return "setNull";
1763
1797
  case "SET DEFAULT": return "noAction";
1764
1798
  default: return "noAction";
1765
1799
  }
1766
- }, qt = (e) => {
1800
+ }, Jt = (e) => {
1767
1801
  let t = e.trim();
1768
1802
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
1769
1803
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
1770
- }, V = (e) => e.onDialectOrElse({
1771
- mysql: () => Vt(e),
1772
- mssql: () => Gt(e),
1773
- sqlite: () => Ut(e),
1774
- orElse: () => zt(e)
1775
- }), Jt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, H = (e, t) => {
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) => {
1776
1810
  if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
1777
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;
1778
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.`);
1779
- return E(e, t);
1780
- }, U = (e) => {
1781
- let t = H(e, "postgres");
1782
- return t === void 0 ? Yt(e) : t;
1783
- }, Yt = (e) => {
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) => {
1784
1818
  switch (e.type) {
1785
1819
  case "id": return "text";
1786
1820
  case "text": return "text";
1787
1821
  case "integer": return "integer";
1788
1822
  case "real": return "double precision";
1789
- case "decimal": return Jt(e, "NUMERIC");
1823
+ case "decimal": return Xt(e, "NUMERIC");
1790
1824
  case "bigint": return "bigint";
1791
1825
  case "boolean": return "boolean";
1792
1826
  case "timestamp": return "timestamptz";
@@ -1800,15 +1834,15 @@ BEGIN
1800
1834
  case "interval": return "interval";
1801
1835
  case "raw": return e.rawDdl ?? "text";
1802
1836
  }
1803
- }, W = (e) => {
1804
- let t = H(e, "mariadb");
1837
+ }, en = (e) => {
1838
+ let t = Zt(e, "mariadb");
1805
1839
  if (t !== void 0) return t;
1806
1840
  switch (e.type) {
1807
1841
  case "id": return "VARCHAR(64)";
1808
1842
  case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
1809
1843
  case "integer": return "INT";
1810
1844
  case "real": return "DOUBLE";
1811
- case "decimal": return Jt(e, "DECIMAL");
1845
+ case "decimal": return Xt(e, "DECIMAL");
1812
1846
  case "bigint": return "BIGINT";
1813
1847
  case "boolean": return "TINYINT(1)";
1814
1848
  case "timestamp": return "DATETIME(6)";
@@ -1822,82 +1856,82 @@ BEGIN
1822
1856
  case "interval": return "BIGINT";
1823
1857
  case "raw": return e.rawDdl ?? "LONGTEXT";
1824
1858
  }
1825
- }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, Xt = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, Zt = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, Qt = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, $t = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Tn(t)}`)};`, en = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${tn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, tn = (e, t) => {
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) => {
1826
1860
  let n = t(e.defaultValue);
1827
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.`);
1828
1862
  return n;
1829
- }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], nn = (e, t, n) => {
1830
- let r = q(e, t, n);
1831
- return r ? nt(n, r) : void 0;
1832
- }, rn = (e, t, n) => {
1833
- let r = n ?? e.nullable, i = ye(e, "mariadb");
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");
1834
1868
  return [
1835
- K(t),
1836
- E(e, "mariadb"),
1869
+ W(t),
1870
+ O(e, "mariadb"),
1837
1871
  r ? null : "NOT NULL",
1838
1872
  i
1839
1873
  ].filter(Boolean).join(" ");
1840
- }, an = (e, t) => e == null ? null : Array.isArray(e) ? on(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" ? D(e, "mysql") : null, on = (e, t, n) => be(e, t ?? { type: "json" }, n), sn = (e, t) => e == null ? null : Array.isArray(e) ? on(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" ? D(e, "postgres") : null, J = (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) => {
1841
1875
  if (!e.generatedAs) return null;
1842
1876
  let { expr: n, stored: r } = e.generatedAs;
1843
1877
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
1844
- }, cn = (e) => {
1845
- if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "postgres");
1846
- let t = J(e, "postgres");
1847
- if (t) return `${G(e.name)} ${U(e)} ${t}`;
1848
- let n = [G(e.name), U(e)];
1878
+ }, pn = (e) => {
1879
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "postgres");
1880
+ let t = K(e, "postgres");
1881
+ if (t) return `${U(e.name)} ${Qt(e)} ${t}`;
1882
+ let n = [U(e.name), Qt(e)];
1849
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) {
1850
- let t = sn(e.defaultValue, e);
1884
+ let t = fn(e.defaultValue, e);
1851
1885
  t && n.push(t);
1852
1886
  }
1853
- return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
1887
+ return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
1854
1888
  cascade: "CASCADE",
1855
1889
  restrict: "RESTRICT",
1856
1890
  setNull: "SET NULL",
1857
1891
  noAction: "NO ACTION"
1858
1892
  }[e.references.onDelete]}`)), n.join(" ");
1859
- }, ln = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", un = (e) => {
1860
- let t = e.columns.map((e) => ` ${cn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${ln(e, G)}\n)`];
1861
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(An).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(", ")})`);
1862
1896
  return n;
1863
- }, dn = 191, fn = (e) => {
1864
- let t = W(e).toUpperCase();
1897
+ }, hn = 191, J = (e) => {
1898
+ let t = en(e).toUpperCase();
1865
1899
  return t.endsWith("TEXT") || t.endsWith("BLOB");
1866
- }, pn = (e) => {
1867
- if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "mariadb");
1868
- let t = J(e, "mariadb");
1869
- if (t) return `${K(e.name)} ${W(e)} ${t}`;
1870
- let n = [K(e.name), W(e)];
1871
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !fn(e) && n.push("UNIQUE"), e.hasDefault) {
1872
- let t = an(e.defaultValue, e);
1900
+ }, gn = (e) => {
1901
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "mariadb");
1902
+ let t = K(e, "mariadb");
1903
+ if (t) return `${W(e.name)} ${en(e)} ${t}`;
1904
+ let n = [W(e.name), en(e)];
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) {
1906
+ let t = un(e.defaultValue, e);
1873
1907
  t && n.push(t);
1874
1908
  }
1875
- return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
1909
+ return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
1876
1910
  cascade: "CASCADE",
1877
1911
  restrict: "RESTRICT",
1878
1912
  setNull: "SET NULL",
1879
1913
  noAction: "NO ACTION"
1880
1914
  }[e.references.onDelete]}`)), n.join(" ");
1881
- }, mn = (e) => {
1915
+ }, _n = (e) => {
1882
1916
  let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
1883
1917
  let n = t.get(e);
1884
- return n && fn(n) ? `${K(e)}(${dn})` : K(e);
1885
- }, r = e.columns.map((e) => ` ${pn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${ln(e, n)}\n)`];
1886
- for (let t of e.columns) t.unique && t.type !== "id" && fn(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
1887
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(n).join(", ")})`);
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)`];
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)})`);
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(", ")})`);
1888
1922
  return i;
1889
- }, hn = {
1923
+ }, vn = {
1890
1924
  cascade: "CASCADE",
1891
1925
  restrict: "RESTRICT",
1892
1926
  setNull: "SET NULL",
1893
1927
  noAction: "NO ACTION"
1894
- }, gn = {
1928
+ }, yn = {
1895
1929
  cascade: "CASCADE",
1896
1930
  restrict: "NO ACTION",
1897
1931
  setNull: "SET NULL",
1898
1932
  noAction: "NO ACTION"
1899
- }, _n = (e) => {
1900
- let t = H(e, "sqlite");
1933
+ }, bn = (e) => {
1934
+ let t = Zt(e, "sqlite");
1901
1935
  if (t !== void 0) return t;
1902
1936
  switch (e.type) {
1903
1937
  case "integer":
@@ -1908,60 +1942,60 @@ BEGIN
1908
1942
  case "bytes": return "BLOB";
1909
1943
  default: return "TEXT";
1910
1944
  }
1911
- }, 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" ? D(e, "sqlite") : null, vn = (e) => {
1912
- if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "sqlite");
1913
- let t = J(e, "sqlite");
1914
- if (t) return `${G(e.name)} ${_n(e)} ${t}`;
1915
- let n = [G(e.name), _n(e)];
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");
1947
+ let t = K(e, "sqlite");
1948
+ if (t) return `${U(e.name)} ${bn(e)} ${t}`;
1949
+ let n = [U(e.name), bn(e)];
1916
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) {
1917
1951
  let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
1918
1952
  t && n.push(t);
1919
1953
  }
1920
- if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${hn[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) {
1921
1955
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
1922
- n.push(`CHECK (${G(e.name)} IN (${t}))`);
1956
+ n.push(`CHECK (${U(e.name)} IN (${t}))`);
1923
1957
  }
1924
1958
  return n.join(" ");
1925
- }, yn = (e) => {
1926
- let t = e.columns.map((e) => ` ${vn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${ln(e, G)}\n)`];
1927
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(G).join(", ")})`);
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)`];
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(", ")})`);
1928
1962
  return n;
1929
1963
  }, X = (e, t) => {
1930
1964
  let n = t.find((t) => t.tableName === e);
1931
1965
  if (!n) return [];
1932
- let r = N([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
1933
- ...yn({
1966
+ let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
1967
+ ...Sn({
1934
1968
  kind: "create-table",
1935
1969
  table: i,
1936
1970
  columns: r.columns,
1937
1971
  indexes: [],
1938
1972
  ...r.primaryKey ? { primaryKey: r.primaryKey } : {}
1939
1973
  }),
1940
- `INSERT INTO ${G(i)} (${a}) SELECT ${a} FROM ${G(e)}`,
1941
- `DROP TABLE ${G(e)}`,
1942
- `ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
1974
+ `INSERT INTO ${U(i)} (${a}) SELECT ${a} FROM ${U(e)}`,
1975
+ `DROP TABLE ${U(e)}`,
1976
+ `ALTER TABLE ${U(i)} RENAME TO ${U(e)}`
1943
1977
  ];
1944
- for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e)} (${t.columns.map(G).join(", ")})`);
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(", ")})`);
1945
1979
  return o;
1946
- }, bn = (e, t, n, r) => {
1980
+ }, Cn = (e, t, n, r) => {
1947
1981
  let i = r ?? e.nullable;
1948
- return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${E(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
1949
- }, xn = (e) => {
1982
+ return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${O(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
1983
+ }, wn = (e) => {
1950
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 + ']');`;
1951
1985
  if (!e.hasDefault) return t;
1952
1986
  let n = Y(e.defaultValue, "SYSUTCDATETIME()");
1953
1987
  if (!n) return t;
1954
1988
  let r = n.replace(/^DEFAULT\s+/i, "");
1955
1989
  return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
1956
- }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Sn = (e) => {
1957
- let t = H(e, "mssql");
1990
+ }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Tn = (e) => {
1991
+ let t = Zt(e, "mssql");
1958
1992
  if (t !== void 0) return t;
1959
1993
  switch (e.type) {
1960
1994
  case "id":
1961
1995
  case "reference": return "NVARCHAR(64)";
1962
1996
  case "integer": return "INT";
1963
1997
  case "real": return "FLOAT";
1964
- case "decimal": return Jt(e, "DECIMAL");
1998
+ case "decimal": return Xt(e, "DECIMAL");
1965
1999
  case "bigint": return "BIGINT";
1966
2000
  case "boolean": return "BIT";
1967
2001
  case "timestamp": return "DATETIME2(6)";
@@ -1969,34 +2003,34 @@ BEGIN
1969
2003
  case "bytes": return "VARBINARY(MAX)";
1970
2004
  default: return "NVARCHAR(MAX)";
1971
2005
  }
1972
- }, Cn = (e, t) => {
1973
- if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "mssql");
1974
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Sn(e), r = J(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");
1975
2009
  if (r) return `${Z(e.name)} ${r}`;
1976
2010
  let i = [Z(e.name), n];
1977
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) {
1978
2012
  let t = Y(e.defaultValue, "SYSUTCDATETIME()");
1979
2013
  t && i.push(t);
1980
2014
  }
1981
- return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${gn[e.references.onDelete]}`)), i.join(" ");
1982
- }, wn = (e) => {
1983
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Cn(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${ln(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)}')`];
1984
2018
  for (let n of e.indexes) {
1985
2019
  if (n.name === `${e.table}_pkey`) continue;
1986
2020
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
1987
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)}')`);
1988
2022
  }
1989
2023
  return a;
1990
- }, Tn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, En = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Dn = (e, t, n) => {
1991
- let r = `${e.table}${Tn(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)}`;
1992
2026
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
1993
- }, On = (e, t, n) => {
1994
- let r = q(e, t, n);
1995
- return r ? fn({ type: r.type }) : !1;
1996
- }, kn = (e, t, n) => On(e, t, n) ? `${K(n)}(${dn})` : K(n), An = (e) => e.startsWith("(") ? e : G(e), jn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map(An).join(", ")});`, Mn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => kn(t, e.table, n)).join(", ")});`, Nn = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Pn = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Fn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, In = (e) => {
2027
+ }, jn = (e, t, n) => {
2028
+ let r = G(e, t, n);
2029
+ return r ? J({ type: r.type }) : !1;
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) => {
1997
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(", ")})`;
1998
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)}');`;
1999
- }, Ln = (e, t, n) => {
2033
+ }, Bn = (e, t, n) => {
2000
2034
  let r = n.find((t) => t.tableName === e);
2001
2035
  if (!r) return [];
2002
2036
  let i = [];
@@ -2005,13 +2039,13 @@ BEGIN
2005
2039
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2006
2040
  }
2007
2041
  return i;
2008
- }, Rn = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, zn = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${kn(t, e.table, e.column)});`, Bn = (e) => {
2009
- let t = e.fields.map((e) => G(e)).join(", ");
2010
- return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
2011
- }, Vn = (e, t) => {
2012
- let n = e.fields.map((n) => kn(t, e.table, n)).join(", ");
2013
- return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
2014
- }, Hn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Un = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Wn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Gn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, Kn = (e, t) => {
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) => {
2043
+ let t = e.fields.map((e) => U(e)).join(", ");
2044
+ return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
2045
+ }, Wn = (e, t) => {
2046
+ let n = e.fields.map((n) => Mn(t, e.table, n)).join(", ");
2047
+ return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
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) => {
2015
2049
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2016
2050
  if (e.orphanPolicy) {
2017
2051
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2029,11 +2063,11 @@ BEGIN
2029
2063
  setNull: "SET NULL",
2030
2064
  noAction: "NO ACTION"
2031
2065
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2032
- }, qn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, Jn = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, Yn = (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) => {
2033
2067
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2034
2068
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2035
- }, Xn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, Zn = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, Qn = (e, t, n, r) => {
2036
- let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? W(i) : r === "mssql" ? Sn(i) : r === "sqlite" ? _n(i) : U(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? an(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : sn(e, i), u = J(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);
2037
2071
  if (u) {
2038
2072
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2039
2073
  return {
@@ -2061,7 +2095,7 @@ BEGIN
2061
2095
  post: f ? [f] : []
2062
2096
  };
2063
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;
2064
- }, $n = (e) => {
2098
+ }, nr = (e) => {
2065
2099
  let t = new Map(e.map((e) => [e.tableName, e]));
2066
2100
  return (e, n) => {
2067
2101
  let r = t.get(e);
@@ -2083,95 +2117,95 @@ BEGIN
2083
2117
  };
2084
2118
  }, Q = (e, t, n) => e.unsafe(t).pipe(d.tapError((e) => d.sync(() => {
2085
2119
  process.stderr.write(_(`applier: statement failed (op=${n})`, t, e, 400));
2086
- })), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), er = (e, t, n) => d.gen(function* () {
2087
- let r = process.hrtime.bigint(), i = $n(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;
2088
2122
  switch (a.kind) {
2089
2123
  case "create-table": {
2090
2124
  let t = yield* e.onDialectOrElse({
2091
- mysql: () => d.succeed(mn(a)),
2092
- mssql: () => d.succeed(wn(a)),
2093
- sqlite: () => d.succeed(yn(a)),
2094
- orElse: () => d.succeed(un(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))
2095
2129
  });
2096
2130
  for (let n of t) yield* Q(e, n, a.kind);
2097
2131
  break;
2098
2132
  }
2099
2133
  case "drop-table": {
2100
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Dn(a, n, e) : En(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);
2101
2135
  yield* e.onDialectOrElse({
2102
- mysql: () => Q(e, r(K), a.kind),
2103
- orElse: () => Q(e, r(G), a.kind)
2136
+ mysql: () => Q(e, r(W), a.kind),
2137
+ orElse: () => Q(e, r(U), a.kind)
2104
2138
  });
2105
2139
  break;
2106
2140
  }
2107
2141
  case "drop-column": {
2108
2142
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2109
2143
  yield* e.onDialectOrElse({
2110
- mysql: () => Q(e, t ? $t(a, n, K) : Zt(a), a.kind),
2111
- orElse: () => Q(e, t ? $t(a, n, G) : Xt(a, G), 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)
2112
2146
  });
2113
2147
  break;
2114
2148
  }
2115
2149
  case "rename-column":
2116
2150
  yield* e.onDialectOrElse({
2117
- mysql: () => Q(e, Qt(a, K), a.kind),
2151
+ mysql: () => Q(e, rn(a, W), a.kind),
2118
2152
  mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
2119
- orElse: () => Q(e, Qt(a, G), a.kind)
2153
+ orElse: () => Q(e, rn(a, U), a.kind)
2120
2154
  });
2121
2155
  break;
2122
2156
  case "add-index":
2123
2157
  yield* e.onDialectOrElse({
2124
- mysql: () => Q(e, Mn(a, n.declared), a.kind),
2125
- mssql: () => $(e, [...Ln(a.table, a.index.columns, n.declared), In(a)], a.kind),
2126
- orElse: () => Q(e, jn(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)
2127
2161
  });
2128
2162
  break;
2129
2163
  case "drop-index":
2130
2164
  yield* e.onDialectOrElse({
2131
- mysql: () => Q(e, Pn(a), a.kind),
2132
- mssql: () => Q(e, Fn(a), a.kind),
2133
- orElse: () => Q(e, Nn(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)
2134
2168
  });
2135
2169
  break;
2136
2170
  case "add-unique":
2137
2171
  yield* e.onDialectOrElse({
2138
- mysql: () => Q(e, zn(a, n.declared), a.kind),
2172
+ mysql: () => Q(e, Hn(a, n.declared), a.kind),
2139
2173
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2140
- mssql: () => $(e, [...Ln(a.table, [a.column], n.declared), Rn(a)], a.kind),
2141
- orElse: () => Q(e, Rn(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)
2142
2176
  });
2143
2177
  break;
2144
2178
  case "drop-unique":
2145
2179
  yield* e.onDialectOrElse({
2146
- mysql: () => Q(e, Gn(a), a.kind),
2180
+ mysql: () => Q(e, Jn(a), a.kind),
2147
2181
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2148
- orElse: () => Q(e, Wn(a), a.kind)
2182
+ orElse: () => Q(e, qn(a), a.kind)
2149
2183
  });
2150
2184
  break;
2151
2185
  case "add-unique-composite":
2152
2186
  yield* e.onDialectOrElse({
2153
- mysql: () => Q(e, Vn(a, n.declared), a.kind),
2187
+ mysql: () => Q(e, Wn(a, n.declared), a.kind),
2154
2188
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2155
- mssql: () => $(e, [...Ln(a.table, a.fields, n.declared), Bn(a)], a.kind),
2156
- orElse: () => Q(e, Bn(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)
2157
2191
  });
2158
2192
  break;
2159
2193
  case "drop-unique-composite":
2160
2194
  yield* e.onDialectOrElse({
2161
- mysql: () => Q(e, Un(a), a.kind),
2195
+ mysql: () => Q(e, Kn(a), a.kind),
2162
2196
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2163
- orElse: () => Q(e, Hn(a), a.kind)
2197
+ orElse: () => Q(e, Gn(a), a.kind)
2164
2198
  });
2165
2199
  break;
2166
2200
  case "add-foreign-key":
2167
2201
  yield* e.onDialectOrElse({
2168
- mysql: () => $(e, Kn(a, K), a.kind),
2202
+ mysql: () => $(e, Yn(a, W), a.kind),
2169
2203
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2170
- orElse: () => $(e, Kn(a, G), a.kind)
2204
+ orElse: () => $(e, Yn(a, U), a.kind)
2171
2205
  });
2172
2206
  break;
2173
2207
  case "add-column": {
2174
- let n = Qn(a, t, i, yield* e.onDialectOrElse({
2208
+ let n = tr(a, t, i, yield* e.onDialectOrElse({
2175
2209
  mysql: () => d.succeed("mariadb"),
2176
2210
  mssql: () => d.succeed("mssql"),
2177
2211
  sqlite: () => d.succeed("sqlite"),
@@ -2216,41 +2250,41 @@ BEGIN
2216
2250
  case "alter-column-nullability":
2217
2251
  yield* e.onDialectOrElse({
2218
2252
  mysql: () => {
2219
- let t = q(n.declared, a.table, a.column);
2220
- return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${rn(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.`));
2253
+ let t = G(n.declared, a.table, a.column);
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.`));
2221
2255
  },
2222
2256
  mssql: () => {
2223
- let t = q(n.declared, a.table, a.column);
2224
- return t ? Q(e, bn(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}'.`));
2257
+ let t = G(n.declared, 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}'.`));
2225
2259
  },
2226
2260
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2227
- orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
2261
+ orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
2228
2262
  });
2229
2263
  break;
2230
2264
  case "alter-column-default": {
2231
- let t = nn(n.declared, a.table, a.column);
2265
+ let t = cn(n.declared, a.table, a.column);
2232
2266
  yield* e.onDialectOrElse({
2233
- mysql: () => Q(e, en(a, K, (e) => an(e, t)), a.kind),
2234
- mssql: () => Q(e, xn(a), a.kind),
2267
+ mysql: () => Q(e, on(a, W, (e) => un(e, t)), a.kind),
2268
+ mssql: () => Q(e, wn(a), a.kind),
2235
2269
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2236
- orElse: () => Q(e, en(a, G, (e) => sn(e, t)), a.kind)
2270
+ orElse: () => Q(e, on(a, U, (e) => fn(e, t)), a.kind)
2237
2271
  });
2238
2272
  break;
2239
2273
  }
2240
2274
  case "alter-column-type": {
2241
- let r = U(nn(n.declared, a.table, a.column) ?? { 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}` : "";
2242
2276
  if (t.classification !== "online-required") {
2243
2277
  yield* e.onDialectOrElse({
2244
2278
  mysql: () => {
2245
- let t = q(n.declared, a.table, a.column);
2246
- return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${rn(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.`));
2279
+ let t = G(n.declared, a.table, a.column);
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.`));
2247
2281
  },
2248
2282
  mssql: () => {
2249
- let t = q(n.declared, a.table, a.column);
2250
- return t ? Q(e, bn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2283
+ let t = G(n.declared, 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}'.`));
2251
2285
  },
2252
2286
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2253
- orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} TYPE ${r}${i};`, a.kind)
2287
+ orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} TYPE ${r}${i};`, a.kind)
2254
2288
  });
2255
2289
  break;
2256
2290
  }
@@ -2259,35 +2293,35 @@ BEGIN
2259
2293
  orElse: () => d.void
2260
2294
  });
2261
2295
  let o = `${a.column}__shadow`, s = `${a.column}__old`;
2262
- yield* e.unsafe(`ALTER TABLE ${G(a.table)} ADD COLUMN ${G(o)} ${r}`);
2263
- let c = a.using ?? G(a.column), l;
2296
+ yield* e.unsafe(`ALTER TABLE ${U(a.table)} ADD COLUMN ${U(o)} ${r}`);
2297
+ let c = a.using ?? U(a.column), l;
2264
2298
  for (;;) {
2265
2299
  let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL ORDER BY ${e("id")} LIMIT 5000` : yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} LIMIT 5000`;
2266
2300
  if (t.length === 0) break;
2267
- yield* e.unsafe(`UPDATE ${G(a.table)} SET ${G(o)} = ${c} WHERE ${G(a.column)} IS NOT NULL AND ${G(o)} IS NULL AND ${G("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2301
+ yield* e.unsafe(`UPDATE ${U(a.table)} SET ${U(o)} = ${c} WHERE ${U(a.column)} IS NOT NULL AND ${U(o)} IS NULL AND ${U("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
2268
2302
  }
2269
- yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${G(a.table)} RENAME COLUMN ${G(a.column)} TO ${G(s)}`), yield* e.unsafe(`ALTER TABLE ${G(a.table)} RENAME COLUMN ${G(o)} TO ${G(a.column)}`), yield* e.unsafe(`ALTER TABLE ${G(a.table)} DROP COLUMN ${G(s)}`);
2303
+ yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${U(a.table)} RENAME COLUMN ${U(a.column)} TO ${U(s)}`), yield* e.unsafe(`ALTER TABLE ${U(a.table)} RENAME COLUMN ${U(o)} TO ${U(a.column)}`), yield* e.unsafe(`ALTER TABLE ${U(a.table)} DROP COLUMN ${U(s)}`);
2270
2304
  break;
2271
2305
  }
2272
2306
  case "drop-foreign-key":
2273
2307
  yield* e.onDialectOrElse({
2274
- mysql: () => Q(e, Jn(a), a.kind),
2308
+ mysql: () => Q(e, Zn(a), a.kind),
2275
2309
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2276
- orElse: () => Q(e, qn(a), a.kind)
2310
+ orElse: () => Q(e, Xn(a), a.kind)
2277
2311
  });
2278
2312
  break;
2279
2313
  case "add-check":
2280
2314
  yield* e.onDialectOrElse({
2281
- mysql: () => Q(e, Yn(a, K), a.kind),
2315
+ mysql: () => Q(e, Qn(a, W), a.kind),
2282
2316
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2283
- orElse: () => Q(e, Yn(a, G), a.kind)
2317
+ orElse: () => Q(e, Qn(a, U), a.kind)
2284
2318
  });
2285
2319
  break;
2286
2320
  case "drop-check":
2287
2321
  yield* e.onDialectOrElse({
2288
- mysql: () => Q(e, Zn(a), a.kind),
2322
+ mysql: () => Q(e, er(a), a.kind),
2289
2323
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2290
- orElse: () => Q(e, Xn(a), a.kind)
2324
+ orElse: () => Q(e, $n(a), a.kind)
2291
2325
  });
2292
2326
  break;
2293
2327
  }
@@ -2296,10 +2330,10 @@ BEGIN
2296
2330
  status: "applied",
2297
2331
  durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
2298
2332
  };
2299
- }), tr = (e, t, n) => d.gen(function* () {
2333
+ }), ir = (e, t, n) => d.gen(function* () {
2300
2334
  let r = t.operations.filter((e) => e.blocked);
2301
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.`));
2302
- yield* C(e);
2336
+ yield* T(e);
2303
2337
  let i = Date.now(), a = [];
2304
2338
  try {
2305
2339
  let r = yield* e.onDialectOrElse({
@@ -2309,11 +2343,11 @@ BEGIN
2309
2343
  }), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
2310
2344
  i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
2311
2345
  let e = yield* p.SqlClient;
2312
- for (let t of i) a.push(yield* er(e, t, n));
2346
+ for (let t of i) a.push(yield* rr(e, t, n));
2313
2347
  })));
2314
- for (let t of o) a.push(yield* er(e, t, n));
2348
+ for (let t of o) a.push(yield* rr(e, t, n));
2315
2349
  } finally {
2316
- yield* w(e).pipe(d.orDie);
2350
+ yield* E(e).pipe(d.orDie);
2317
2351
  }
2318
2352
  let o = yield* n.replan(e);
2319
2353
  if (o.operations.length > 0) {
@@ -2345,19 +2379,19 @@ BEGIN
2345
2379
  source: n.source,
2346
2380
  ...n.notes ? { notes: n.notes } : {}
2347
2381
  };
2348
- }), nr = (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"), rr = (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`
2349
2383
  SELECT fingerprint
2350
2384
  FROM _voltro_migration_plans
2351
2385
  ORDER BY ${e("appliedAt")} DESC
2352
2386
  LIMIT 1
2353
- `.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), ir = (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({
2354
2388
  pg: () => "postgres",
2355
2389
  mysql: () => "mysql",
2356
2390
  mssql: () => "mssql",
2357
2391
  sqlite: () => "sqlite",
2358
2392
  orElse: () => "sqlite"
2359
- }), ar = (e, t) => d.gen(function* () {
2360
- let n = j(N(t, ir(e))), r = yield* rr(e);
2393
+ }), cr = (e, t) => d.gen(function* () {
2394
+ let n = N(F(t, sr(e))), r = yield* or(e);
2361
2395
  return r === n ? {
2362
2396
  kind: "up-to-date",
2363
2397
  fingerprint: n
@@ -2366,97 +2400,126 @@ BEGIN
2366
2400
  expected: n,
2367
2401
  ...r === void 0 ? {} : { actual: r }
2368
2402
  };
2369
- }), or = [
2403
+ }), lr = [
2370
2404
  "pgeagertest_",
2371
2405
  "mig_e2e_",
2372
2406
  "mig_test_",
2373
2407
  "mysqleagertest_",
2374
2408
  "mssqleagertest_",
2375
2409
  "sqliteeagertest_"
2376
- ], sr = (e) => or.some((t) => e.startsWith(t)), cr = (e, t) => d.gen(function* () {
2410
+ ], ur = (e) => lr.some((t) => e.startsWith(t)), dr = (e, t) => d.gen(function* () {
2377
2411
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2378
- let n = t.filter((e) => sr(e.name)).map((e) => e.name);
2412
+ let n = t.filter((e) => ur(e.name)).map((e) => e.name);
2379
2413
  if (n.length === 0) return [];
2380
2414
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
2381
2415
  return n;
2382
- }), lr = () => {
2416
+ }), fr = () => {
2383
2417
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2384
2418
  return e.length > 0 ? { ignoreTables: e } : {};
2385
- }, ur = (e) => ({
2419
+ }, pr = (e) => {
2420
+ if (e === void 0) return;
2421
+ let t = e.trim();
2422
+ if (t === "") return;
2423
+ if (t === "1" || t.toLowerCase() === "true") return { kind: "all" };
2424
+ let n = t.split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2425
+ return n.length > 0 ? {
2426
+ kind: "tables",
2427
+ tables: new Set(n)
2428
+ } : void 0;
2429
+ }, mr = (e) => typeof e.table == "string" ? e.table : void 0, hr = (e, t = { kind: "all" }) => ({
2386
2430
  ...e,
2387
2431
  operations: e.operations.map((e) => {
2388
2432
  if (!e.blocked || e.classification !== "lossy") return e;
2389
- let { blocked: t, ...n } = e;
2390
- return n;
2433
+ if (t?.kind === "tables") {
2434
+ let n = mr(e.op);
2435
+ if (n === void 0 || !t.tables.has(n)) return e;
2436
+ }
2437
+ let { blocked: n, ...r } = e;
2438
+ return r;
2391
2439
  })
2392
- }), dr = (e, t, n) => d.gen(function* () {
2393
- let r = ir(e), i = t.filter((e) => !P(e.tableName));
2440
+ }), gr = (e, t, n) => t === "postgres" ? at(e, n).pipe(d.flatMap((e) => {
2441
+ let t = ot(e);
2442
+ return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
2443
+ }), d.catchAll(() => d.void)) : d.void, _r = (e, t, n) => d.gen(function* () {
2444
+ let r = sr(e), i = t.filter((e) => !I(e.tableName));
2394
2445
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2395
- let t = j(N(i, r));
2396
- if ((yield* rr(e)) === t) return {
2446
+ let t = N(F(i, r));
2447
+ if ((yield* or(e)) === t) return yield* gr(e, r, i), {
2397
2448
  kind: "up-to-date",
2398
2449
  fingerprint: t
2399
2450
  };
2400
2451
  }
2401
- let a = yield* V(e), o = yield* cr(e, a.tables);
2452
+ let a = yield* Yt(e), o = yield* dr(e, a.tables);
2402
2453
  o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
2403
2454
  scope: "voltro:migrate",
2404
2455
  count: o.length
2405
- })), a = yield* V(e));
2406
- let s = jt({
2456
+ })), a = yield* Yt(e));
2457
+ let s = Mt({
2407
2458
  declared: i,
2408
- live: { tables: a.tables.filter((e) => !P(e.name)) },
2459
+ live: { tables: a.tables.filter((e) => !I(e.name)) },
2409
2460
  dialect: r,
2410
- ...lr()
2461
+ ...fr()
2411
2462
  });
2412
2463
  if (s.summary.blocked > 0) {
2413
- let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy");
2414
- if (process.env.VOLTRO_DESTRUCTIVE_OK !== "1" || !e) return {
2464
+ let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = pr(process.env.VOLTRO_DESTRUCTIVE_OK);
2465
+ if (t === void 0 || !e || (s = hr(s, t), s.operations.some((e) => e.blocked))) return {
2415
2466
  kind: "refused-blocked",
2416
2467
  plan: s
2417
2468
  };
2418
- s = ur(s);
2419
2469
  }
2420
2470
  return s.operations.length === 0 ? {
2421
2471
  kind: "up-to-date",
2422
2472
  fingerprint: s.toFingerprint
2423
2473
  } : {
2424
2474
  kind: "applied",
2425
- applied: yield* tr(e, s, {
2475
+ applied: yield* ir(e, s, {
2426
2476
  declared: t,
2427
2477
  appliedBy: n.appliedBy,
2428
2478
  environment: n.environment === "prod" ? "dev" : n.environment,
2429
2479
  source: "auto-diff",
2430
2480
  replan: (e) => d.gen(function* () {
2431
- let t = yield* V(e);
2432
- return jt({
2481
+ let t = yield* Yt(e);
2482
+ return Mt({
2433
2483
  declared: i,
2434
- live: { tables: t.tables.filter((e) => !P(e.name)) },
2484
+ live: { tables: t.tables.filter((e) => !I(e.name)) },
2435
2485
  dialect: r,
2436
- ...lr()
2486
+ ...fr()
2437
2487
  });
2438
2488
  })
2439
2489
  }),
2440
2490
  plan: s
2441
2491
  };
2442
- }), fr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
2492
+ }), vr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
2443
2493
  kind: "skipped",
2444
2494
  reason: "VOLTRO_AUTO_MIGRATE=0"
2445
- }) : n.environment === "prod" ? ar(e, t) : dr(e, t, n), pr = (e, t) => {
2495
+ }) : n.environment === "prod" ? cr(e, t) : _r(e, t, n), yr = (e, t) => {
2446
2496
  switch (e.kind) {
2447
2497
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
2448
- case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${M(e.fingerprint)})`;
2498
+ case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
2449
2499
  case "applied": {
2450
2500
  let t = e.plan.summary;
2451
- 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=${M(e.applied.fingerprint)}`;
2501
+ 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)}`;
2452
2502
  }
2453
- case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${M(e.expected)}` + (e.actual ? ` live=${M(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2503
+ 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.";
2454
2504
  case "refused-blocked": {
2455
- 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` + nr(e.plan), s = [""];
2456
- 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");
2505
+ let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + ar(e.plan), c = [""];
2506
+ if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", `Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
2507
+ let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2508
+ for (let r of e.plan.operations) {
2509
+ let e = "table" in r.op ? r.op.table : void 0;
2510
+ if (e === void 0) continue;
2511
+ let i = "column" in r.op ? String(r.op.column) : void 0;
2512
+ if (i === void 0) continue;
2513
+ let a = r.op.kind === "drop-column" ? t : r.op.kind === "add-column" ? n : void 0;
2514
+ a !== void 0 && a.set(e, [...a.get(e) ?? [], i]);
2515
+ }
2516
+ let r = [...t.entries()].filter(([e]) => (n.get(e)?.length ?? 0) > 0).map(([e, t]) => `${e}: ${t.join(", ")} gone, ${n.get(e).join(", ")} new`);
2517
+ c.push(`${a} column(s) are missing from your declared schema.`), r.length > 0 && c.push(" → DID YOU RENAME ONE? This plan drops AND adds columns on the same table:", ...r.map((e) => ` ${e}`), " If so, add `.renamedFrom('<oldName>')` to the NEW column — the planner then emits a", " RENAME and the data moves with it. Dropping and re-adding loses every value."), c.push(" → If intentional: give the field the `dropped()` marker as its VALUE —", " `<column>: dropped()` (import it from `@voltro/database`). It is not a method", " chained onto the column; the slot stays, documenting the hole.", " → If a typo: restore the field. Data survives until you drop it.");
2518
+ }
2519
+ return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
2457
2520
  }
2458
2521
  }
2459
- }, mr = /* @__PURE__ */ new Set([
2522
+ }, br = /* @__PURE__ */ new Set([
2460
2523
  "node_modules",
2461
2524
  "dist",
2462
2525
  "build",
@@ -2465,11 +2528,11 @@ BEGIN
2465
2528
  ".next",
2466
2529
  ".git",
2467
2530
  ".framework"
2468
- ]), hr = async (e) => {
2531
+ ]), xr = async (e) => {
2469
2532
  let t = [], n = async (e) => {
2470
2533
  let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
2471
2534
  for (let i of r) {
2472
- if (mr.has(i.name)) continue;
2535
+ if (br.has(i.name)) continue;
2473
2536
  let r = g(e, i.name);
2474
2537
  i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
2475
2538
  }
@@ -2478,7 +2541,7 @@ BEGIN
2478
2541
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
2479
2542
  return n.localeCompare(r);
2480
2543
  });
2481
- }, gr = async (e) => {
2544
+ }, Sr = async (e) => {
2482
2545
  let t = [];
2483
2546
  for (let n of e) {
2484
2547
  let e = (await import(ee(n).href)).default;
@@ -2492,11 +2555,11 @@ BEGIN
2492
2555
  });
2493
2556
  }
2494
2557
  return t;
2495
- }, _r = (e) => e`
2558
+ }, Cr = (e) => e`
2496
2559
  SELECT ${e("id")}
2497
2560
  FROM ${e("_voltro_migration_plans")}
2498
2561
  WHERE ${e("source")} = 'file'
2499
- `.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), vr = (e, t, n, r) => d.gen(function* () {
2562
+ `.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), wr = (e, t, n, r) => d.gen(function* () {
2500
2563
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
2501
2564
  sql: e,
2502
2565
  log: {
@@ -2529,70 +2592,76 @@ BEGIN
2529
2592
  ${r}, ${n}, ${"file"},
2530
2593
  ${c}, ${a}, ${t.migration.description})
2531
2594
  `, { durationMs: c };
2532
- }), yr = (e, t) => d.gen(function* () {
2595
+ }), Tr = (e, t) => d.gen(function* () {
2533
2596
  let n = yield* d.tryPromise({
2534
- try: () => hr(g(t.projectRoot, "migrations")),
2597
+ try: () => xr(g(t, "migrations")),
2535
2598
  catch: (e) => e
2536
2599
  });
2537
2600
  if (n.length === 0) return {
2538
- applied: [],
2601
+ pending: [],
2539
2602
  skipped: []
2540
2603
  };
2541
2604
  let r = yield* d.tryPromise({
2542
- try: () => gr(n),
2605
+ try: () => Sr(n),
2543
2606
  catch: (e) => e
2544
2607
  });
2545
2608
  if (r.length === 0) return {
2546
- applied: [],
2609
+ pending: [],
2547
2610
  skipped: []
2548
2611
  };
2549
- let i = new Set(yield* _r(e)), a = r.filter((e) => !i.has(e.migration.id)), o = r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id);
2550
- if (a.length === 0) return {
2612
+ let i = new Set(yield* Cr(e));
2613
+ return {
2614
+ pending: r.filter((e) => !i.has(e.migration.id)),
2615
+ skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
2616
+ };
2617
+ }), Er = (e, t) => Tr(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Dr = (e, t) => d.gen(function* () {
2618
+ let { pending: n, skipped: r } = yield* Tr(e, t.projectRoot);
2619
+ if (n.length === 0) return {
2551
2620
  applied: [],
2552
- skipped: o
2621
+ skipped: r
2553
2622
  };
2554
- yield* C(e);
2555
- let s = [];
2623
+ yield* T(e);
2624
+ let i = [];
2556
2625
  try {
2557
- for (let n of a) {
2626
+ for (let r of n) {
2558
2627
  yield* d.logInfo("file-based migration applying").pipe(d.annotateLogs({
2559
2628
  scope: "voltro:migrate",
2560
- id: n.migration.id,
2561
- file: n.file
2629
+ id: r.migration.id,
2630
+ file: r.file
2562
2631
  }));
2563
- let { durationMs: r } = yield* vr(e, n, t.env, t.appliedBy);
2564
- s.push({
2565
- id: n.migration.id,
2566
- durationMs: r
2632
+ let { durationMs: n } = yield* wr(e, r, t.env, t.appliedBy);
2633
+ i.push({
2634
+ id: r.migration.id,
2635
+ durationMs: n
2567
2636
  }), yield* d.logInfo("file-based migration applied").pipe(d.annotateLogs({
2568
2637
  scope: "voltro:migrate",
2569
- id: n.migration.id,
2570
- durationMs: r
2638
+ id: r.migration.id,
2639
+ durationMs: n
2571
2640
  }));
2572
2641
  }
2573
2642
  } finally {
2574
- yield* w(e).pipe(d.orDie);
2643
+ yield* E(e).pipe(d.orDie);
2575
2644
  }
2576
2645
  return {
2577
- applied: s,
2578
- skipped: o
2646
+ applied: i,
2647
+ skipped: r
2579
2648
  };
2580
- }), br = (e, t) => e`
2649
+ }), Or = (e, t) => e`
2581
2650
  SELECT ${e("id")}
2582
2651
  FROM ${e("_voltro_migration_plans")}
2583
2652
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
2584
2653
  LIMIT 1
2585
- `, xr = (e, t) => d.gen(function* () {
2586
- if (!(yield* br(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2654
+ `, kr = (e, t) => d.gen(function* () {
2655
+ if (!(yield* Or(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2587
2656
  let n = yield* d.tryPromise({
2588
- try: () => hr(g(t.projectRoot, "migrations")),
2657
+ try: () => xr(g(t.projectRoot, "migrations")),
2589
2658
  catch: (e) => e
2590
2659
  }), r = (yield* d.tryPromise({
2591
- try: () => gr(n),
2660
+ try: () => Sr(n),
2592
2661
  catch: (e) => e
2593
2662
  })).find((e) => e.migration.id === t.id);
2594
2663
  if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
2595
- yield* C(e);
2664
+ yield* T(e);
2596
2665
  let i = Date.now();
2597
2666
  try {
2598
2667
  let n = {
@@ -2619,9 +2688,9 @@ BEGIN
2619
2688
  durationMs: o
2620
2689
  };
2621
2690
  } finally {
2622
- yield* w(e).pipe(d.orDie);
2691
+ yield* E(e).pipe(d.orDie);
2623
2692
  }
2624
- }), Sr = (e) => d.gen(function* () {
2693
+ }), Ar = (e) => d.gen(function* () {
2625
2694
  let t = yield* p.SqlClient, n = yield* t`
2626
2695
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
2627
2696
  WHERE source = 'auto-diff'
@@ -2666,10 +2735,10 @@ BEGIN
2666
2735
  snapshotFingerprint: e.fingerprint,
2667
2736
  snapshotId: i
2668
2737
  };
2669
- }), Cr = (e, ...t) => ({
2738
+ }), jr = (e, ...t) => ({
2670
2739
  _tag: "RawSqlFragment",
2671
2740
  strings: [...e],
2672
2741
  values: [...t]
2673
- }), wr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2742
+ }), Mr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2674
2743
  //#endregion
2675
- export { l as FILE_MIGRATION_PATTERN, re as VOLTRO_MIGRATION_LOCK_KEY, dt as _internalCmp, C as acquireMigrationLock, Je as applyNamespacedSchema, tr as applyPlan, He as applySchema, Rt as chunkTables, N as declaredSnapshot, be as defaultArrayClause, ye as defaultClause, D as defaultJsonClause, pr as describeOutcome, Xt as emitDropColumnDdl, Zt as emitDropColumnDdlMysql, Ve as emitFrameworkBootstrapSql, ze as emitNamespaceProvisionDdl, Be as emitNamespacedSchemaSql, A as emitSchemaSql, j as fingerprintSchema, lr as ignoreTablesFromEnv, V as introspectSchema, o as isFileMigration, wr as isRawSqlFragment, Nt as mapPgType, c as migration, O as numericIdSql, Mt as parseEnumCheck, jt as planMigrations, Ye as provisionTenantNamespace, w as releaseMigrationLock, pn as renderColumnMysql, cn as renderColumnPg, xr as rollbackFileBasedMigration, yr as runFileBasedMigrations, Xe as runFrameworkBootstrap, qe as runMigrate, fr as runPlannedMigrations, M as shortFingerprint, nt as snapshotColumn, Cr as sql, E as sqlType, Sr as squashMigrationPlans, ur as unblockLossy, _e as withMigrationLock };
2744
+ 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, yr as describeOutcome, pr as destructiveScope, 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, Mr as isRawSqlFragment, Pt as mapPgType, s as migration, A as numericIdSql, Nt as parseEnumCheck, Er as pendingFileMigrationIds, Mt as planMigrations, qe as provisionTenantNamespace, E as releaseMigrationLock, gn as renderColumnMysql, pn as renderColumnPg, kr as rollbackFileBasedMigration, Dr as runFileBasedMigrations, Je as runFrameworkBootstrap, Ge as runMigrate, vr as runPlannedMigrations, P as shortFingerprint, et as snapshotColumn, jr as sql, O as sqlType, Ar as squashMigrationPlans, hr as unblockLossy, he as withMigrationLock };