@voltro/database 0.51.0 → 0.53.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/CHANGELOG.md +356 -0
- package/dist/{frameworkLiveTables-DNu6F6P8.js → frameworkLiveTables-ChVR-C5F.js} +139 -128
- package/dist/index.d.ts +61 -8
- package/dist/index.js +786 -779
- package/dist/sql.js +136 -136
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as e,
|
|
1
|
+
import { $ as e, Bt as t, Q as n, Qt as r, St as i, Vt as a, Z as o, Zt as s, _ as c, a as l, c as u, gt as d, i as f, l as p, m, n as h, nt as g, o as _, p as v, r as y, rt as b } from "./frameworkLiveTables-ChVR-C5F.js";
|
|
2
2
|
import { Effect as x, Schedule as S } from "effect";
|
|
3
3
|
import { createHash as ee } from "node:crypto";
|
|
4
4
|
import { createLogger as te } from "@voltro/logger";
|
|
@@ -154,19 +154,19 @@ var ae = (e, t, n, r = 400) => {
|
|
|
154
154
|
mariadb: "per-operation",
|
|
155
155
|
sqlite: "per-operation",
|
|
156
156
|
turso: "per-operation"
|
|
157
|
-
}, Ie = (e) => Fe[e], D = "_voltro_migration_ops", Le =
|
|
158
|
-
id:
|
|
159
|
-
runId:
|
|
160
|
-
planFingerprint:
|
|
161
|
-
opIndex:
|
|
162
|
-
opKind:
|
|
163
|
-
opTarget:
|
|
164
|
-
status:
|
|
165
|
-
payload:
|
|
166
|
-
startedAt:
|
|
167
|
-
appliedAt:
|
|
168
|
-
durationMs:
|
|
169
|
-
createdAt:
|
|
157
|
+
}, Ie = (e) => Fe[e], D = "_voltro_migration_ops", Le = g(D, {
|
|
158
|
+
id: t({ prefix: "mop" }),
|
|
159
|
+
runId: s(),
|
|
160
|
+
planFingerprint: s(),
|
|
161
|
+
opIndex: a(),
|
|
162
|
+
opKind: s(),
|
|
163
|
+
opTarget: s(),
|
|
164
|
+
status: s(),
|
|
165
|
+
payload: s(),
|
|
166
|
+
startedAt: r().nullable(),
|
|
167
|
+
appliedAt: r().nullable(),
|
|
168
|
+
durationMs: a().nullable(),
|
|
169
|
+
createdAt: r().default("now")
|
|
170
170
|
}), Re = (e) => {
|
|
171
171
|
switch (e.kind) {
|
|
172
172
|
case "create-table": return /* @__PURE__ */ new Set([
|
|
@@ -219,54 +219,54 @@ Object.keys(Fe);
|
|
|
219
219
|
//#region src/migrations/reactiveTriggerName.ts
|
|
220
220
|
var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "framework_changes" ? `${Je}${e}` : `${Je}${t}_${e}`, Xe = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Ze = "voltro:notify:v2", Qe = te({ scope: "voltro:migrate" }), k = (e) => {
|
|
221
221
|
Qe.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
222
|
-
}, A = (e,
|
|
222
|
+
}, A = (e, t) => {
|
|
223
223
|
let r = e.type;
|
|
224
224
|
if (e.spatial) {
|
|
225
|
-
if (
|
|
226
|
-
throw Error(`@voltro/plugin-postgis: ${e.spatial.kind}('${e.spatial.geomKind}', ${e.spatial.srid}) is postgres-only — the active dialect is '${
|
|
225
|
+
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
226
|
+
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.`);
|
|
227
227
|
}
|
|
228
228
|
if (r === "raw") {
|
|
229
229
|
if (e.rawDdl === void 0) throw Error("raw() column is missing its DDL fragment — this is a framework bug.");
|
|
230
230
|
return e.rawDdl;
|
|
231
231
|
}
|
|
232
232
|
if (r === "array" && e.arrayElement) {
|
|
233
|
-
if (
|
|
233
|
+
if (t === "postgres") return `${A({
|
|
234
234
|
...e,
|
|
235
235
|
type: e.arrayElement,
|
|
236
236
|
arrayElement: void 0
|
|
237
|
-
},
|
|
238
|
-
if (
|
|
239
|
-
if (
|
|
240
|
-
if (t
|
|
237
|
+
}, t)}[]`;
|
|
238
|
+
if (t === "mysql" || t === "mariadb") return "JSON";
|
|
239
|
+
if (t === "mssql") return "NVARCHAR(MAX)";
|
|
240
|
+
if (n(t)) return "TEXT";
|
|
241
241
|
}
|
|
242
242
|
if (r === "vector") {
|
|
243
243
|
let r = e.vectorDim;
|
|
244
244
|
if (r === void 0) throw Error("vector column is missing its dimension — this is a framework bug.");
|
|
245
245
|
let i = e.vectorPrecision === "half";
|
|
246
|
-
if (
|
|
247
|
-
if (
|
|
248
|
-
if (
|
|
249
|
-
if (t
|
|
246
|
+
if (t === "postgres") return i ? `HALFVEC(${r})` : `VECTOR(${r})`;
|
|
247
|
+
if (t === "mysql" || t === "mariadb") return `VECTOR(${r})`;
|
|
248
|
+
if (t === "mssql") return "VARBINARY(MAX)";
|
|
249
|
+
if (n(t)) return "BLOB";
|
|
250
250
|
}
|
|
251
251
|
if (r === "interval") {
|
|
252
|
-
if (
|
|
253
|
-
if (
|
|
254
|
-
if (t
|
|
252
|
+
if (t === "postgres") return "INTERVAL";
|
|
253
|
+
if (t === "mysql" || t === "mariadb" || t === "mssql") return "BIGINT";
|
|
254
|
+
if (n(t)) return "INTEGER";
|
|
255
255
|
}
|
|
256
256
|
if (r === "decimal") {
|
|
257
257
|
let r = e.precision, i = e.scale ?? 0;
|
|
258
258
|
if (r === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
|
|
259
|
-
return t
|
|
259
|
+
return n(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${r}, ${i})` : `DECIMAL(${r}, ${i})`;
|
|
260
260
|
}
|
|
261
|
-
if (r === "bigint") return t
|
|
261
|
+
if (r === "bigint") return n(t) ? "INTEGER" : "BIGINT";
|
|
262
262
|
if (r === "enum") {
|
|
263
|
-
if (
|
|
264
|
-
if (
|
|
265
|
-
if (
|
|
266
|
-
if (t
|
|
263
|
+
if (t === "postgres") return e.enumName ?? "TEXT";
|
|
264
|
+
if (t === "mysql" || t === "mariadb") return `ENUM(${(e.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
|
|
265
|
+
if (t === "mssql") return "NVARCHAR(255)";
|
|
266
|
+
if (n(t)) return "TEXT";
|
|
267
267
|
}
|
|
268
|
-
if (r === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return
|
|
269
|
-
if (t
|
|
268
|
+
if (r === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : n(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
|
|
269
|
+
if (n(t)) switch (r) {
|
|
270
270
|
case "id": return "TEXT";
|
|
271
271
|
case "text": return "TEXT";
|
|
272
272
|
case "integer": return "INTEGER";
|
|
@@ -282,7 +282,7 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
282
282
|
case "array": return "TEXT";
|
|
283
283
|
case "interval": return "INTEGER";
|
|
284
284
|
}
|
|
285
|
-
if (
|
|
285
|
+
if (t === "mysql" || t === "mariadb") switch (r) {
|
|
286
286
|
case "id": return "VARCHAR(64)";
|
|
287
287
|
case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : e.generatedAs ? "TEXT" : "LONGTEXT";
|
|
288
288
|
case "integer": return "INT";
|
|
@@ -298,7 +298,7 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
298
298
|
case "array": return "JSON";
|
|
299
299
|
case "interval": return "BIGINT";
|
|
300
300
|
}
|
|
301
|
-
if (
|
|
301
|
+
if (t === "mssql") switch (r) {
|
|
302
302
|
case "id": return "NVARCHAR(64)";
|
|
303
303
|
case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "NVARCHAR(450)" : "NVARCHAR(MAX)";
|
|
304
304
|
case "integer": return "INT";
|
|
@@ -330,10 +330,10 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
330
330
|
case "array": return "TEXT[]";
|
|
331
331
|
case "interval": return "INTERVAL";
|
|
332
332
|
}
|
|
333
|
-
}, $e = (e,
|
|
333
|
+
}, $e = (e, t) => {
|
|
334
334
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
335
335
|
let r = e.defaultValue;
|
|
336
|
-
return r === "now" ? t
|
|
336
|
+
return r === "now" ? n(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof r == "boolean" ? t === "postgres" ? `DEFAULT ${r}` : `DEFAULT ${+!!r}` : typeof r == "number" ? `DEFAULT ${r}` : typeof r == "string" ? `DEFAULT '${r.replace(/'/g, "''")}'` : Array.isArray(r) ? et(r, e, t) : typeof r == "object" && r ? j(r, t) : null;
|
|
337
337
|
}, et = (e, t, n) => {
|
|
338
338
|
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return j(e, n);
|
|
339
339
|
let r = A({
|
|
@@ -381,9 +381,9 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
381
381
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
382
382
|
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.");
|
|
383
383
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
384
|
-
}, ot = (
|
|
385
|
-
if (r.type === "id" && r.idScheme?.kind === "numeric") return M(
|
|
386
|
-
let l = i === "mssql" && r.type === "text" && !r.generatedAs && r.maxLength === void 0 && a?.has(
|
|
384
|
+
}, ot = (t, r, i, a, s = !1, c = !1) => {
|
|
385
|
+
if (r.type === "id" && r.idScheme?.kind === "numeric") return M(t, i);
|
|
386
|
+
let l = i === "mssql" && r.type === "text" && !r.generatedAs && r.maxLength === void 0 && a?.has(t) ? "NVARCHAR(450)" : A(r, i), u = [e(t, i), l];
|
|
387
387
|
r.type === "id" && !c && u.push("PRIMARY KEY");
|
|
388
388
|
let d = at(r, i);
|
|
389
389
|
if (d) u.push(d);
|
|
@@ -401,17 +401,17 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
401
401
|
a !== "NO ACTION" && u.push(`ON UPDATE ${a}`);
|
|
402
402
|
}
|
|
403
403
|
if (r.oneOf && r.oneOf.length > 0) {
|
|
404
|
-
let
|
|
405
|
-
u.push(`CHECK (${e(
|
|
404
|
+
let n = r.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
405
|
+
u.push(`CHECK (${e(t, i)} IN (${n}))`);
|
|
406
406
|
}
|
|
407
407
|
if (r.checks && r.checks.length > 0) for (let e of r.checks) u.push(`CHECK (${e})`);
|
|
408
|
-
if (r.type === "enum" && r.enumValues && r.enumValues.length > 0 && (i === "mssql" ||
|
|
409
|
-
let
|
|
410
|
-
u.push(`CHECK (${e(
|
|
408
|
+
if (r.type === "enum" && r.enumValues && r.enumValues.length > 0 && (i === "mssql" || n(i))) {
|
|
409
|
+
let n = r.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
410
|
+
u.push(`CHECK (${e(t, i)} IN (${n}))`);
|
|
411
411
|
}
|
|
412
412
|
if (r.type === "json" || r.type === "array") {
|
|
413
|
-
let r = e(
|
|
414
|
-
|
|
413
|
+
let r = e(t, i);
|
|
414
|
+
n(i) ? u.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : i === "mssql" && u.push(`CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
|
|
415
415
|
}
|
|
416
416
|
return u.join(" ");
|
|
417
417
|
}, st = (t, n, r = null, i) => {
|
|
@@ -472,7 +472,7 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
472
472
|
} : (k(`[voltro:migrate] brin index '${e}' on '${t}': ${n} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
|
|
473
473
|
if (r === "hnsw") {
|
|
474
474
|
if (n === "postgres") {
|
|
475
|
-
let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ??
|
|
475
|
+
let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? b(i?.hnsw?.distance);
|
|
476
476
|
return {
|
|
477
477
|
using: " USING hnsw",
|
|
478
478
|
withSuffix: ` WITH (m = ${e}, ef_construction = ${t})`,
|
|
@@ -492,7 +492,7 @@ var O = "framework_changes", Je = "framework_changes_", Ye = (e, t) => t === "fr
|
|
|
492
492
|
if (typeof e == "string") return it(e, t.fields, n);
|
|
493
493
|
if ("jsonPath" in e) {
|
|
494
494
|
let { column: t, path: r, numeric: i } = e.jsonPath;
|
|
495
|
-
return `(${
|
|
495
|
+
return `(${v(t, r, n, { numeric: i })})`;
|
|
496
496
|
}
|
|
497
497
|
return `(${e.expr})`;
|
|
498
498
|
});
|
|
@@ -666,9 +666,9 @@ $$ LANGUAGE plpgsql;
|
|
|
666
666
|
case "mariadb": return `ALTER TABLE ${i(t.table)} ${l(!0)};`;
|
|
667
667
|
default: return `ALTER TABLE ${i(t.table)} ${l(!1)};`;
|
|
668
668
|
}
|
|
669
|
-
}, yt = (e,
|
|
669
|
+
}, yt = (e, t) => {
|
|
670
670
|
let r = /* @__PURE__ */ new Map();
|
|
671
|
-
if (t
|
|
671
|
+
if (n(t)) return r;
|
|
672
672
|
for (let t of e) {
|
|
673
673
|
let e = r.get(t.table) ?? /* @__PURE__ */ new Set();
|
|
674
674
|
e.add(t.column), r.set(t.table, e);
|
|
@@ -694,38 +694,38 @@ $$ LANGUAGE plpgsql;
|
|
|
694
694
|
if (t !== "postgres") return "";
|
|
695
695
|
let n = /* @__PURE__ */ new Set();
|
|
696
696
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
697
|
-
let
|
|
698
|
-
for (let e of n) for (let { from: t, to: n } of
|
|
699
|
-
let
|
|
700
|
-
|
|
697
|
+
let r = [];
|
|
698
|
+
for (let e of n) for (let { from: t, to: n } of i(e)) {
|
|
699
|
+
let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
|
|
700
|
+
r.push(`DO \$\$
|
|
701
701
|
DECLARE
|
|
702
702
|
type_oid oid;
|
|
703
703
|
BEGIN
|
|
704
|
-
SELECT oid INTO type_oid FROM pg_type WHERE typname = '${
|
|
704
|
+
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 $$;`);
|
|
705
705
|
}
|
|
706
|
-
return
|
|
706
|
+
return r.join("\n\n");
|
|
707
707
|
}, St = (e) => {
|
|
708
708
|
let t = [], n = [];
|
|
709
|
-
for (let r of e)
|
|
709
|
+
for (let r of e) m(r) ? n.push(r) : t.push(r);
|
|
710
710
|
return {
|
|
711
711
|
tables: t,
|
|
712
712
|
views: n
|
|
713
713
|
};
|
|
714
|
-
}, Ct = (e,
|
|
715
|
-
let { tables: i, views: a } = St(e), { sorted: o, cyclic:
|
|
716
|
-
|
|
717
|
-
let d = xt(o,
|
|
714
|
+
}, Ct = (e, t, r = O) => {
|
|
715
|
+
let { tables: i, views: a } = St(e), { sorted: o, cyclic: s } = _t(i.map((e) => de(e, t))), l = yt(s, t), u = [];
|
|
716
|
+
t === "postgres" && ht(o) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && gt(o) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
717
|
+
let d = xt(o, t);
|
|
718
718
|
d && u.push(d);
|
|
719
|
-
let f = bt(o,
|
|
719
|
+
let f = bt(o, t);
|
|
720
720
|
f && u.push(f);
|
|
721
|
-
for (let e of o) u.push(st(e,
|
|
722
|
-
if (!t
|
|
721
|
+
for (let e of o) u.push(st(e, t, null, l.get(e.tableName)));
|
|
722
|
+
if (!n(t)) for (let e of s) u.push(vt(e, t));
|
|
723
723
|
for (let e of o) {
|
|
724
|
-
let
|
|
725
|
-
|
|
724
|
+
let n = lt(e, t);
|
|
725
|
+
n && u.push(n);
|
|
726
726
|
}
|
|
727
|
-
u.push(...ut(o,
|
|
728
|
-
for (let e of a) u.push(
|
|
727
|
+
u.push(...ut(o, t, r));
|
|
728
|
+
for (let e of a) u.push(c(e, t));
|
|
729
729
|
return u.join("\n\n") + "\n";
|
|
730
730
|
}, wt = (t, n, r) => {
|
|
731
731
|
let i = e(t, n);
|
|
@@ -737,13 +737,13 @@ BEGIN
|
|
|
737
737
|
case "turso":
|
|
738
738
|
case "sqlite": return `ATTACH DATABASE '${(r ?? `${t}.db`).replace(/'/g, "''")}' AS ${i};`;
|
|
739
739
|
}
|
|
740
|
-
}, Tt = (
|
|
740
|
+
}, Tt = (t, r, i, a) => {
|
|
741
741
|
let o = wt(i, r, a), s = e(i, r);
|
|
742
|
-
if (r === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${Ct(
|
|
743
|
-
if (r === "mysql" || r === "mariadb") return `${o}\n\nUSE ${s};\n\n${Ct(
|
|
744
|
-
let { sorted: c, cyclic: l } = _t(
|
|
742
|
+
if (r === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${Ct(t, r)}`;
|
|
743
|
+
if (r === "mysql" || r === "mariadb") return `${o}\n\nUSE ${s};\n\n${Ct(t, r)}`;
|
|
744
|
+
let { sorted: c, cyclic: l } = _t(t), u = yt(l, r), d = [o];
|
|
745
745
|
for (let e of c) d.push(st(e, r, i, u.get(e.tableName)));
|
|
746
|
-
if (!
|
|
746
|
+
if (!n(r)) for (let e of l) d.push(vt(e, r, i));
|
|
747
747
|
for (let e of c) {
|
|
748
748
|
let t = lt(e, r, i);
|
|
749
749
|
t && d.push(t);
|
|
@@ -813,7 +813,7 @@ BEGIN
|
|
|
813
813
|
let i = Tt(e, n, t), a = yield* C.SqlClient;
|
|
814
814
|
yield* Ne(a, Pt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(x.orDie);
|
|
815
815
|
}), Rt = async (e, t, n, r = "postgres", i = {}) => {
|
|
816
|
-
await x.runPromise(Lt(e, t, r, i).pipe(x.provide(n))), await
|
|
816
|
+
await x.runPromise(Lt(e, t, r, i).pipe(x.provide(n))), await p({
|
|
817
817
|
namespace: t,
|
|
818
818
|
dialect: r
|
|
819
819
|
});
|
|
@@ -922,7 +922,7 @@ BEGIN
|
|
|
922
922
|
let i = n;
|
|
923
923
|
if (i.dropped || !i.references || i.fkAutoIndex === !1 || s.has(t)) continue;
|
|
924
924
|
let a = `${e.tableName}_${t}_idx`;
|
|
925
|
-
|
|
925
|
+
d(e.tableName, a, !0, [t]), r({
|
|
926
926
|
name: a,
|
|
927
927
|
table: e.tableName,
|
|
928
928
|
columns: [t],
|
|
@@ -1084,7 +1084,7 @@ BEGIN
|
|
|
1084
1084
|
} catch {
|
|
1085
1085
|
return;
|
|
1086
1086
|
}
|
|
1087
|
-
}, sn = (e,
|
|
1087
|
+
}, sn = (e, t, r) => r === void 0 || n(r) ? !0 : e.type !== "text" || t.type !== "text" || on(e, r) === t.maxLength, cn = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && nn(e, t) && sn(e, t, n) && JSON.stringify(rn(e.references)) === JSON.stringify(rn(t.references)) && an(e.oneOf, t.oneOf), ln = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
|
|
1088
1088
|
kind: "add-check",
|
|
1089
1089
|
table: e,
|
|
1090
1090
|
column: t.name,
|
|
@@ -1183,88 +1183,88 @@ BEGIN
|
|
|
1183
1183
|
}, xn = (e, t, n) => {
|
|
1184
1184
|
let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
|
|
1185
1185
|
return n === "postgres" ? `${r} — add \`{ using: '${t.name}::${t.type}' }\` when the cast is not implicit, or use a file-based migration` : `${r} — ${n === void 0 ? "this dialect" : n} converts in place (\`using\` is postgres-only and is ignored here), so verify the conversion is value-preserving for your data, or use a file-based migration`;
|
|
1186
|
-
}, Sn = (e,
|
|
1186
|
+
}, Sn = (e, t, r, i, a, o) => {
|
|
1187
1187
|
let s = [];
|
|
1188
|
-
if (
|
|
1189
|
-
let
|
|
1188
|
+
if (t.nullable !== r.nullable) {
|
|
1189
|
+
let n = {
|
|
1190
1190
|
kind: "alter-column-nullability",
|
|
1191
1191
|
table: e,
|
|
1192
|
-
column:
|
|
1193
|
-
toNullable:
|
|
1192
|
+
column: t.name,
|
|
1193
|
+
toNullable: t.nullable
|
|
1194
1194
|
};
|
|
1195
|
-
s.push(
|
|
1195
|
+
s.push(t.nullable ? R(n, "safe", `loosen ${e}.${t.name} to nullable`) : R(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
1196
1196
|
}
|
|
1197
|
-
if (
|
|
1198
|
-
if (
|
|
1199
|
-
let
|
|
1197
|
+
if (t.unique !== r.unique) {
|
|
1198
|
+
if (t.unique) {
|
|
1199
|
+
let n = {
|
|
1200
1200
|
kind: "add-unique",
|
|
1201
1201
|
table: e,
|
|
1202
|
-
column:
|
|
1202
|
+
column: t.name
|
|
1203
1203
|
}, r = (a ?? 0) >= o;
|
|
1204
|
-
s.push(r ? R(
|
|
1204
|
+
s.push(r ? R(n, "online-required", `online unique build on ${a} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
1205
1205
|
} else s.push(R({
|
|
1206
1206
|
kind: "drop-unique",
|
|
1207
1207
|
table: e,
|
|
1208
|
-
column:
|
|
1209
|
-
}, "safe", `drop unique constraint on ${e}.${
|
|
1208
|
+
column: t.name
|
|
1209
|
+
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1210
1210
|
}
|
|
1211
|
-
if (bn(
|
|
1212
|
-
let
|
|
1213
|
-
if (
|
|
1211
|
+
if (bn(t.type, i) !== bn(r.type, i)) {
|
|
1212
|
+
let n = t.narrowedFrom;
|
|
1213
|
+
if (n && n.from === r.type) {
|
|
1214
1214
|
let i = {
|
|
1215
1215
|
kind: "alter-column-type",
|
|
1216
1216
|
table: e,
|
|
1217
|
-
column:
|
|
1217
|
+
column: t.name,
|
|
1218
1218
|
from: r.type,
|
|
1219
|
-
to:
|
|
1220
|
-
...
|
|
1219
|
+
to: t.type,
|
|
1220
|
+
...n.using === void 0 ? {} : { using: n.using }
|
|
1221
1221
|
};
|
|
1222
|
-
s.push(R(i, "needs-backfill", `type change ${r.type} → ${
|
|
1222
|
+
s.push(R(i, "needs-backfill", `type change ${r.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${n.from}') declared` + (n.using ? ` with USING ${n.using}` : " (implicit cast)")));
|
|
1223
1223
|
} else {
|
|
1224
|
-
let
|
|
1224
|
+
let n = {
|
|
1225
1225
|
kind: "alter-column-type",
|
|
1226
1226
|
table: e,
|
|
1227
|
-
column:
|
|
1227
|
+
column: t.name,
|
|
1228
1228
|
from: r.type,
|
|
1229
|
-
to:
|
|
1229
|
+
to: t.type
|
|
1230
1230
|
};
|
|
1231
|
-
s.push(R(
|
|
1231
|
+
s.push(R(n, "lossy", `type change ${r.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: xn(r.type, t, i) }));
|
|
1232
1232
|
}
|
|
1233
1233
|
}
|
|
1234
|
-
if (
|
|
1235
|
-
let
|
|
1234
|
+
if (t.type === "text" && r.type === "text" && !n(i ?? "postgres") && t.maxLength !== r.maxLength) {
|
|
1235
|
+
let n = t.maxLength === void 0 || r.maxLength !== void 0 && t.maxLength > r.maxLength, i = r.maxLength === void 0 ? "unbounded" : `varchar(${r.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
|
|
1236
1236
|
s.push(R({
|
|
1237
1237
|
kind: "alter-column-type",
|
|
1238
1238
|
table: e,
|
|
1239
|
-
column:
|
|
1239
|
+
column: t.name,
|
|
1240
1240
|
from: "text",
|
|
1241
1241
|
to: "text"
|
|
1242
|
-
},
|
|
1242
|
+
}, n ? "safe" : "needs-backfill", n ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
|
|
1243
1243
|
}
|
|
1244
|
-
if (!nn(
|
|
1245
|
-
let
|
|
1244
|
+
if (!nn(t, r)) {
|
|
1245
|
+
let n = {
|
|
1246
1246
|
kind: "alter-column-default",
|
|
1247
1247
|
table: e,
|
|
1248
|
-
column:
|
|
1249
|
-
hasDefault:
|
|
1250
|
-
...
|
|
1248
|
+
column: t.name,
|
|
1249
|
+
hasDefault: t.hasDefault,
|
|
1250
|
+
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1251
1251
|
};
|
|
1252
|
-
s.push(R(
|
|
1252
|
+
s.push(R(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1253
1253
|
}
|
|
1254
|
-
if (!an(
|
|
1254
|
+
if (!an(t.oneOf, r.oneOf)) {
|
|
1255
1255
|
r.oneOf && r.oneOf.length > 0 && s.push(R({
|
|
1256
1256
|
kind: "drop-check",
|
|
1257
1257
|
table: e,
|
|
1258
|
-
column:
|
|
1259
|
-
}, "safe", `drop stale enum CHECK on ${e}.${
|
|
1260
|
-
let
|
|
1261
|
-
|
|
1258
|
+
column: t.name
|
|
1259
|
+
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1260
|
+
let n = ln(e, t);
|
|
1261
|
+
n && s.push(n);
|
|
1262
1262
|
}
|
|
1263
|
-
return JSON.stringify(rn(
|
|
1263
|
+
return JSON.stringify(rn(t.references)) !== JSON.stringify(rn(r.references)) && (r.references && s.push(R({
|
|
1264
1264
|
kind: "drop-foreign-key",
|
|
1265
1265
|
table: e,
|
|
1266
|
-
column:
|
|
1267
|
-
}, "safe", `drop FK on ${e}.${
|
|
1266
|
+
column: t.name
|
|
1267
|
+
}, "safe", `drop FK on ${e}.${t.name} (→ ${r.references.table})`)), s.push(...Cn(e, t))), s;
|
|
1268
1268
|
}, Cn = (e, t) => {
|
|
1269
1269
|
let n = [];
|
|
1270
1270
|
if (!t.references) return n;
|
|
@@ -1443,7 +1443,7 @@ BEGIN
|
|
|
1443
1443
|
}
|
|
1444
1444
|
}
|
|
1445
1445
|
let s = new Set(e.ignoreTables ?? []);
|
|
1446
|
-
for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) ||
|
|
1446
|
+
for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || h(t.name) || y(t.name) || s.has(t.name) || a.push(gn(t.name));
|
|
1447
1447
|
for (let s of t.tables) {
|
|
1448
1448
|
let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
|
|
1449
1449
|
if (!c) continue;
|
|
@@ -1452,7 +1452,7 @@ BEGIN
|
|
|
1452
1452
|
let u = l.live, d = n.get(s.name), f = dn(s, u, e.dialect), p = fn(s, u), m = wn(d.table, d.columnDefs, f);
|
|
1453
1453
|
a.push(...m.ops);
|
|
1454
1454
|
for (let e of f.removed) {
|
|
1455
|
-
if (m.consumedRemovedNames.has(e.name) ||
|
|
1455
|
+
if (m.consumedRemovedNames.has(e.name) || y(e.name)) continue;
|
|
1456
1456
|
let t = d.columnDefs[e.name];
|
|
1457
1457
|
a.push(mn(s.name, e, t));
|
|
1458
1458
|
}
|
|
@@ -1503,8 +1503,8 @@ BEGIN
|
|
|
1503
1503
|
}
|
|
1504
1504
|
a.push(...f);
|
|
1505
1505
|
}
|
|
1506
|
-
let p = new Map(t.tables.map((e) => [e.name, e])),
|
|
1507
|
-
let n =
|
|
1506
|
+
let p = new Map(t.tables.map((e) => [e.name, e])), m = /* @__PURE__ */ new Map(), g = (e, t = /* @__PURE__ */ new Set()) => {
|
|
1507
|
+
let n = m.get(e);
|
|
1508
1508
|
if (n !== void 0) return n;
|
|
1509
1509
|
if (t.has(e)) return 0;
|
|
1510
1510
|
let r = p.get(e);
|
|
@@ -1514,8 +1514,8 @@ BEGIN
|
|
|
1514
1514
|
let n = t.references?.table;
|
|
1515
1515
|
n && n !== e && !d.has(w(e, t.name)) && (a = Math.max(a, g(n, i) + 1));
|
|
1516
1516
|
}
|
|
1517
|
-
return
|
|
1518
|
-
}, _ = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1,
|
|
1517
|
+
return m.set(e, a), a;
|
|
1518
|
+
}, _ = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, v = (e) => {
|
|
1519
1519
|
let t = "table" in e ? e.table : "";
|
|
1520
1520
|
return e.kind === "create-table" ? g(t) : e.kind === "drop-table" ? -g(t) : 0;
|
|
1521
1521
|
}, b = {
|
|
@@ -1539,7 +1539,7 @@ BEGIN
|
|
|
1539
1539
|
}, x = (e) => b[e] ?? 9, S = [...a].sort((e, t) => {
|
|
1540
1540
|
let n = _(e.op.kind), r = _(t.op.kind);
|
|
1541
1541
|
if (n !== r) return n - r;
|
|
1542
|
-
let i =
|
|
1542
|
+
let i = v(e.op), a = v(t.op);
|
|
1543
1543
|
if (i !== a) return i - a;
|
|
1544
1544
|
let o = "table" in e.op ? e.op.table : "", s = "table" in t.op ? t.op.table : "";
|
|
1545
1545
|
if (o !== s) return o.localeCompare(s);
|
|
@@ -2901,7 +2901,7 @@ BEGIN
|
|
|
2901
2901
|
let r = t.operations.filter((e) => e.blocked);
|
|
2902
2902
|
if (r.length > 0) return yield* x.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
2903
2903
|
yield* E(e, { schema: n.lockSchema });
|
|
2904
|
-
let i = Date.now(), a = [], o = Pe(e), s = Ie(o) === "plan-transactional", c = s ? t.operations.filter((e) => e.classification !== "online-required") : [],
|
|
2904
|
+
let i = Date.now(), a = [], o = Pe(e), s = Ie(o) === "plan-transactional", c = s ? t.operations.filter((e) => e.classification !== "online-required") : [], l = s ? t.operations.filter((e) => e.classification === "online-required") : t.operations, d = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, f = l.map((e, t) => ({
|
|
2905
2905
|
index: t,
|
|
2906
2906
|
planned: e
|
|
2907
2907
|
})), p = "fresh";
|
|
@@ -2941,7 +2941,7 @@ BEGIN
|
|
|
2941
2941
|
${g}, ${y}, ${n.notes ?? null})
|
|
2942
2942
|
`, yield* Mi(e, d);
|
|
2943
2943
|
let S = [...new Set(b.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
2944
|
-
return yield* x.promise(() =>
|
|
2944
|
+
return yield* x.promise(() => u({ changedTables: S }).catch(() => {})), {
|
|
2945
2945
|
id: _,
|
|
2946
2946
|
appliedAt: v,
|
|
2947
2947
|
fingerprint: t.toFingerprint,
|
|
@@ -3035,7 +3035,7 @@ BEGIN
|
|
|
3035
3035
|
scope: "voltro:migrate",
|
|
3036
3036
|
count: o.length
|
|
3037
3037
|
})), a = yield* Qn(e));
|
|
3038
|
-
let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !
|
|
3038
|
+
let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !h(e.name) || s.has(e.name)), l = Mn({
|
|
3039
3039
|
declared: i,
|
|
3040
3040
|
live: { tables: c(a.tables) },
|
|
3041
3041
|
dialect: r,
|
|
@@ -3119,7 +3119,7 @@ BEGIN
|
|
|
3119
3119
|
for (let i of r) {
|
|
3120
3120
|
if (Qi.has(i.name)) continue;
|
|
3121
3121
|
let r = re(e, i.name);
|
|
3122
|
-
i.isDirectory() ? await n(r) : i.isFile() &&
|
|
3122
|
+
i.isDirectory() ? await n(r) : i.isFile() && f.test(i.name) && t.push(r);
|
|
3123
3123
|
}
|
|
3124
3124
|
};
|
|
3125
3125
|
return await n(e), t.sort((e, t) => {
|
|
@@ -3130,7 +3130,7 @@ BEGIN
|
|
|
3130
3130
|
let t = [];
|
|
3131
3131
|
for (let n of e) {
|
|
3132
3132
|
let e = (await import(ie(n).href)).default;
|
|
3133
|
-
if (!
|
|
3133
|
+
if (!l(e)) {
|
|
3134
3134
|
process.stderr.write(`[voltro:migrate] ${n} has no default-exported \`migration(...)\` — skipped\n`);
|
|
3135
3135
|
continue;
|
|
3136
3136
|
}
|
|
@@ -3539,4 +3539,4 @@ BEGIN
|
|
|
3539
3539
|
values: [...t]
|
|
3540
3540
|
}), Sa = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3541
3541
|
//#endregion
|
|
3542
|
-
export { O as DEFAULT_CDC_CHANNEL,
|
|
3542
|
+
export { O as DEFAULT_CDC_CHANNEL, f as FILE_MIGRATION_PATTERN, na as FileMigrationLedgerError, Je as REACTIVE_TRIGGER_PREFIX, pe as VOLTRO_MIGRATION_LOCK_KEY, E as acquireMigrationLock, W as appliedAtValue, Lt as applyNamespacedSchema, Ii as applyPlan, Dt as applySchema, pa as assessRollingDeployGate, va as branchRehearsalExitCode, Bn as chunkTables, da as classifyRollingDeploySafety, I as declaredSnapshot, et as defaultArrayClause, $e as defaultClause, j as defaultJsonClause, Zi as describeOutcome, Gi as destructiveScope, Yt as detectReactiveTriggerDrift, $r as emitAddIndexMysql, Pr as emitCreateTableMysql, hr as emitDropColumnDdl, gr as emitDropColumnDdlMysql, Et as emitFrameworkBootstrapSql, wt as emitNamespaceProvisionDdl, Tt as emitNamespacedSchemaSql, Ct as emitSchemaSql, $n as engineFromVersion, P as fingerprintSchema, ye as fnv1a64, ba as formatBranchRehearsal, Xt as formatReactiveTriggerDrift, Wi as ignoreTablesFromEnv, Qn as introspectSchema, ir as isAlreadySatisfied, l as isFileMigration, Sa as isRawSqlFragment, kt as isReRunSafeDdl, Pn as mapPgType, _ as migration, be as migrationLockKeyForSchema, T as migrationLockNameForSchema, Yr as mysqlIndexPrefixFor, Xe as notifyFunctionName, M as numericIdSql, Nn as parseEnumCheck, aa as pendingFileMigrationIds, Mn as planMigrations, Rt as provisionTenantNamespace, Ye as reactiveTriggerName, mt as reactiveTriggerRepairSql, zi as recordUpToDate, _a as rehearseMigrationOnBranch, ha as rehearsedOperation, Me as releaseMigrationLock, Mr as renderColumnMysql, Dr as renderColumnPg, he as resolveMigrationLockSchema, U as resolveMysqlEngine, ca as rollbackFileBasedMigration, fa as rollingDeployUnsafeOps, oa as runFileBasedMigrations, zt as runFrameworkBootstrap, It as runMigrate, Xi as runPlannedMigrations, F as shortFingerprint, Gt as snapshotColumn, xa as sql, A as sqlType, la as squashMigrationPlans, qi as unblockLossy, Ne as withMigrationLock };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/database",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "Browser-safe schema DSL, query builder, and cross-dialect migration planner for Voltro — one schema, every SQL backend.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@effect/sql": "^0.52.0",
|
|
47
|
-
"@voltro/logger": "0.
|
|
47
|
+
"@voltro/logger": "0.53.0",
|
|
48
48
|
"typeid-js": "^1.2.0",
|
|
49
49
|
"ulidx": "^2.4.1"
|
|
50
50
|
},
|