@voltro/database 0.55.0 → 0.56.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 +497 -0
- package/dist/index.d.ts +174 -3
- package/dist/index.js +387 -318
- package/dist/sql.d.ts +15 -24
- package/dist/sql.js +200 -180
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { $ as e, $t as t, Ht as n, Ut as r, a as i, at as a, c as o, d as s, en as c, et as l, g as u, h as d, i as f, it as p, o as m, r as h, s as g, tt as _, u as v, vt as y, wt as b, y as x } from "./frameworkLiveTables-CwDemhjW.js";
|
|
2
2
|
import { Effect as S, Schedule as C } from "effect";
|
|
3
|
-
import { createHash as
|
|
4
|
-
import { createLogger as
|
|
5
|
-
import { SqlClient as
|
|
6
|
-
import { promises as
|
|
7
|
-
import { join as
|
|
8
|
-
import { pathToFileURL as
|
|
3
|
+
import { createHash as w } from "node:crypto";
|
|
4
|
+
import { createLogger as T } from "@voltro/logger";
|
|
5
|
+
import { SqlClient as E } from "@effect/sql";
|
|
6
|
+
import { promises as ee } from "node:fs";
|
|
7
|
+
import { join as te } from "node:path";
|
|
8
|
+
import { pathToFileURL as ne } from "node:url";
|
|
9
9
|
//#region src/migrations/ddlError.ts
|
|
10
|
-
var
|
|
10
|
+
var re = (e, t, n, r = 400) => {
|
|
11
11
|
let i = n, a = i.cause ?? {}, o = (e) => {
|
|
12
12
|
let t = a[e];
|
|
13
13
|
return t == null || t === "" ? void 0 : String(t);
|
|
@@ -38,21 +38,21 @@ var ae = (e, t, n, r = 400) => {
|
|
|
38
38
|
let t = o(e);
|
|
39
39
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
40
|
}
|
|
41
|
-
let c =
|
|
41
|
+
let c = ie(o("code"));
|
|
42
42
|
return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
|
|
43
|
-
},
|
|
44
|
-
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(
|
|
43
|
+
}, ie = (e) => e === "3F000" ? "remedy: the connection's search_path names a schema that does not exist. Voltro sets it from DB_SCHEMA — create the schema (`CREATE SCHEMA \"<name>\"`) or unset DB_SCHEMA to use the connection default. Voltro creates TABLES, never the schema itself: that is a namespace decision, and inventing one from a typo is how a migration lands somewhere nobody is looking." : void 0, ae = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, oe = (e) => e.replace(/"/g, "`"), se = (e) => typeof e == "string" ? e : e.name ?? String(e), ce = (e, t) => `_ua_${t}_${e}`.slice(0, 64), le = (e, t) => {
|
|
44
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(ae)) return e;
|
|
45
45
|
let n = { ...e.fields }, r = [], i = [];
|
|
46
46
|
for (let t of e.appliedIndexes) {
|
|
47
|
-
if (!
|
|
47
|
+
if (!ae(t)) {
|
|
48
48
|
r.push(t);
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
|
-
let a =
|
|
51
|
+
let a = oe(t.where), o = [];
|
|
52
52
|
for (let r of t.fields) {
|
|
53
|
-
let i =
|
|
53
|
+
let i = se(r);
|
|
54
54
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
55
|
-
let s =
|
|
55
|
+
let s = ce(t.name, i);
|
|
56
56
|
o.push(s), n[s] = {
|
|
57
57
|
type: "text",
|
|
58
58
|
nullable: !0,
|
|
@@ -75,73 +75,73 @@ var ae = (e, t, n, r = 400) => {
|
|
|
75
75
|
appliedIndexes: r,
|
|
76
76
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
77
77
|
};
|
|
78
|
-
},
|
|
78
|
+
}, D = (e, t) => `${e}::${t}`, ue = (e, t) => {
|
|
79
79
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
80
80
|
n.add(e);
|
|
81
81
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
82
|
-
for (let t of o) n.has(t.target) ? i.add(
|
|
82
|
+
for (let t of o) n.has(t.target) ? i.add(D(e, t.column)) : r.has(t.target) || a(t.target);
|
|
83
83
|
n.delete(e), r.add(e);
|
|
84
84
|
};
|
|
85
85
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
86
86
|
return i;
|
|
87
|
-
},
|
|
87
|
+
}, de = 6322741009312437n, fe = (e) => {
|
|
88
88
|
let t = e?.trim();
|
|
89
89
|
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
90
|
-
},
|
|
91
|
-
let t =
|
|
92
|
-
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t *
|
|
90
|
+
}, pe = (e) => e?.schema === void 0 ? fe(process.env.DB_SCHEMA) : fe(e.schema), me = 14695981039346656037n, he = 1099511628211n, ge = 18446744073709551615n, _e = (e) => {
|
|
91
|
+
let t = me;
|
|
92
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * he & ge;
|
|
93
93
|
return t;
|
|
94
|
-
},
|
|
95
|
-
let t =
|
|
96
|
-
return t === void 0 ?
|
|
97
|
-
},
|
|
98
|
-
let t = `voltro_migration_${
|
|
94
|
+
}, ve = (e) => {
|
|
95
|
+
let t = fe(e);
|
|
96
|
+
return t === void 0 ? de : _e(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
97
|
+
}, ye = (e) => {
|
|
98
|
+
let t = `voltro_migration_${de.toString(36)}`, n = fe(e);
|
|
99
99
|
if (n === void 0) return t;
|
|
100
100
|
let r = `${t}_${n}`;
|
|
101
|
-
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(
|
|
102
|
-
},
|
|
101
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(_e(`voltro_migration_lock:${n}`) & ge).toString(16)}`;
|
|
102
|
+
}, be = 250, xe = () => {
|
|
103
103
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
104
104
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
105
|
-
},
|
|
106
|
-
let n =
|
|
105
|
+
}, Se = (e, t) => S.gen(function* () {
|
|
106
|
+
let n = xe(), r = Date.now();
|
|
107
107
|
for (;;) {
|
|
108
108
|
if ((yield* e`
|
|
109
109
|
SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`)[0]?.got) return;
|
|
110
|
-
Date.now() - r >= n && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* S.sleep(`${
|
|
110
|
+
Date.now() - r >= n && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* S.sleep(`${be} millis`);
|
|
111
111
|
}
|
|
112
|
-
}),
|
|
112
|
+
}), Ce = (e, t) => S.gen(function* () {
|
|
113
113
|
yield* e`SELECT pg_advisory_unlock(${t.toString()}::bigint)`;
|
|
114
|
-
}),
|
|
114
|
+
}), we = 30, Te = (e, t) => S.gen(function* () {
|
|
115
115
|
(yield* e`
|
|
116
|
-
SELECT GET_LOCK(${t}, ${
|
|
117
|
-
}),
|
|
116
|
+
SELECT GET_LOCK(${t}, ${we}) AS got`)[0]?.got !== 1 && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${we}s (another migration is in progress, or a prior one left it held).`)));
|
|
117
|
+
}), Ee = (e, t) => S.gen(function* () {
|
|
118
118
|
yield* e`SELECT RELEASE_LOCK(${t})`;
|
|
119
|
-
}),
|
|
119
|
+
}), De = 3e4, Oe = (e, t) => S.gen(function* () {
|
|
120
120
|
let n = yield* e`
|
|
121
121
|
DECLARE @res int;
|
|
122
122
|
EXEC @res = sp_getapplock @Resource = ${t}, @LockMode = 'Exclusive',
|
|
123
|
-
@LockOwner = 'Session', @LockTimeout = ${
|
|
123
|
+
@LockOwner = 'Session', @LockTimeout = ${De};
|
|
124
124
|
SELECT @res AS res`;
|
|
125
125
|
(n[0]?.res ?? -999) < 0 && (yield* S.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
126
|
-
}),
|
|
126
|
+
}), ke = (e, t) => S.gen(function* () {
|
|
127
127
|
yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
|
|
128
|
-
}),
|
|
129
|
-
let n =
|
|
128
|
+
}), Ae = S.void, je = (e, t) => {
|
|
129
|
+
let n = pe(t);
|
|
130
130
|
return e.onDialectOrElse({
|
|
131
|
-
mysql: () =>
|
|
132
|
-
mssql: () =>
|
|
133
|
-
sqlite: () =>
|
|
134
|
-
orElse: () =>
|
|
131
|
+
mysql: () => Te(e, ye(n)),
|
|
132
|
+
mssql: () => Oe(e, ye(n)),
|
|
133
|
+
sqlite: () => Ae,
|
|
134
|
+
orElse: () => Se(e, ve(n))
|
|
135
135
|
});
|
|
136
136
|
}, O = (e, t) => {
|
|
137
|
-
let n =
|
|
137
|
+
let n = pe(t);
|
|
138
138
|
return e.onDialectOrElse({
|
|
139
|
-
mysql: () =>
|
|
140
|
-
mssql: () =>
|
|
141
|
-
sqlite: () =>
|
|
142
|
-
orElse: () =>
|
|
139
|
+
mysql: () => Ee(e, ye(n)),
|
|
140
|
+
mssql: () => ke(e, ye(n)),
|
|
141
|
+
sqlite: () => Ae,
|
|
142
|
+
orElse: () => Ce(e, ve(n))
|
|
143
143
|
});
|
|
144
|
-
}, Me = (e, t, n) => S.acquireUseRelease(
|
|
144
|
+
}, Me = (e, t, n) => S.acquireUseRelease(je(e, n), () => t, () => O(e, n).pipe(S.orDie)), Ne = (e) => e.onDialectOrElse({
|
|
145
145
|
pg: () => "postgres",
|
|
146
146
|
mysql: () => "mysql",
|
|
147
147
|
mssql: () => "mssql",
|
|
@@ -217,7 +217,7 @@ var ae = (e, t, n, r = 400) => {
|
|
|
217
217
|
Object.keys(Pe);
|
|
218
218
|
//#endregion
|
|
219
219
|
//#region src/migrations/reactiveTriggerName.ts
|
|
220
|
-
var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "framework_changes" ? `${qe}${e}` : `${qe}${t}_${e}`, Ye = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Xe = "voltro:notify:v2", Ze =
|
|
220
|
+
var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "framework_changes" ? `${qe}${e}` : `${qe}${t}_${e}`, Ye = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Xe = "voltro:notify:v2", Ze = T({ scope: "voltro:migrate" }), j = (e) => {
|
|
221
221
|
Ze.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
222
222
|
}, M = (e, t) => {
|
|
223
223
|
let n = e.type;
|
|
@@ -615,7 +615,7 @@ $$ LANGUAGE plpgsql;
|
|
|
615
615
|
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Je(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
|
|
616
616
|
return r;
|
|
617
617
|
}, mt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), ht = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), gt = (e) => {
|
|
618
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
618
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = ue(e.map((e) => e.tableName), (e) => {
|
|
619
619
|
let n = t.get(e);
|
|
620
620
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
621
621
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -626,7 +626,7 @@ $$ LANGUAGE plpgsql;
|
|
|
626
626
|
}] : [];
|
|
627
627
|
}) : [];
|
|
628
628
|
}), r = [];
|
|
629
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(
|
|
629
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(D(t.tableName, e)) && r.push({
|
|
630
630
|
table: t.tableName,
|
|
631
631
|
column: e,
|
|
632
632
|
targetTable: i.references().tableName,
|
|
@@ -637,7 +637,7 @@ $$ LANGUAGE plpgsql;
|
|
|
637
637
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
638
638
|
a.add(e.tableName);
|
|
639
639
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
640
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
640
|
+
if (i.type !== "reference" || !i.references || n.has(D(e.tableName, r))) continue;
|
|
641
641
|
let a = i.references();
|
|
642
642
|
if (a.tableName === e.tableName) continue;
|
|
643
643
|
let o = t.get(a.tableName);
|
|
@@ -712,7 +712,7 @@ BEGIN
|
|
|
712
712
|
views: n
|
|
713
713
|
};
|
|
714
714
|
}, St = (e, t, n = A) => {
|
|
715
|
-
let { tables: r, views: i } = xt(e), { sorted: a, cyclic: o } = gt(r.map((e) =>
|
|
715
|
+
let { tables: r, views: i } = xt(e), { sorted: a, cyclic: o } = gt(r.map((e) => le(e, t))), s = vt(o, t), c = [];
|
|
716
716
|
t === "postgres" && mt(a) && c.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && ht(a) && c.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
717
717
|
let u = bt(a, t);
|
|
718
718
|
u && c.push(u);
|
|
@@ -758,7 +758,7 @@ BEGIN
|
|
|
758
758
|
for (let e of i) o.push(_t(e, t));
|
|
759
759
|
return o.push(...lt(r, t, n)), o.join("\n\n") + "\n";
|
|
760
760
|
}, Et = (e, t = "postgres", n = A, r = {}) => S.gen(function* () {
|
|
761
|
-
let i = yield*
|
|
761
|
+
let i = yield* E.SqlClient;
|
|
762
762
|
yield* Me(i, Nt(i, St(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
|
|
763
763
|
}), Dt = (e, t) => {
|
|
764
764
|
let n = t.cause ?? {};
|
|
@@ -781,17 +781,17 @@ BEGIN
|
|
|
781
781
|
this.statement = e, this.error = t;
|
|
782
782
|
}
|
|
783
783
|
}, Mt = (e, t, n) => S.gen(function* () {
|
|
784
|
-
let r = yield*
|
|
784
|
+
let r = yield* E.SqlClient, i = n !== void 0 && Fe(t) === "per-operation";
|
|
785
785
|
for (let a of Pt(e)) {
|
|
786
786
|
process.env.VOLTRO_MIGRATE_DEBUG === "1" && Ze.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
|
|
787
787
|
let e = r.unsafe(a).pipe(S.catchIf((e) => Dt(a, e), () => S.succeed([])), S.tapError((e) => S.sync(() => {
|
|
788
|
-
Ze.error(
|
|
788
|
+
Ze.error(re("migrate: statement failed", a, e, 200));
|
|
789
789
|
})));
|
|
790
790
|
yield* (i && n !== void 0 && Ot(a, t) ? e.pipe(S.retry(At((e) => n(e) === "retry"))) : e).pipe(S.mapError((e) => new jt(a, e)));
|
|
791
791
|
}
|
|
792
792
|
}), Nt = (e, t, n, r) => {
|
|
793
793
|
let i = n === "turso" ? Mt(t, n, r) : e.withTransaction(Mt(t, n, r)), a = (e) => e instanceof jt ? e.error : e;
|
|
794
|
-
return (r !== void 0 && Fe(n) === "plan-transactional" ? i.pipe(S.retry(At((e) => r(a(e)) === "retry"))) : i).pipe(S.orDieWith((e) => e instanceof jt ? Error(
|
|
794
|
+
return (r !== void 0 && Fe(n) === "plan-transactional" ? i.pipe(S.retry(At((e) => r(a(e)) === "retry"))) : i).pipe(S.orDieWith((e) => e instanceof jt ? Error(re("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
|
|
795
795
|
}, Pt = (e) => {
|
|
796
796
|
let t = [], n = "", r = !1;
|
|
797
797
|
for (let i = 0; i < e.length; i++) {
|
|
@@ -810,7 +810,7 @@ BEGIN
|
|
|
810
810
|
}, Ft = async (e, t, n = "postgres", r = {}) => {
|
|
811
811
|
await S.runPromise(Et(e, n, void 0, r).pipe(S.provide(t)));
|
|
812
812
|
}, It = (e, t, n = "postgres", r = {}) => S.gen(function* () {
|
|
813
|
-
let i = wt(e, n, t), a = yield*
|
|
813
|
+
let i = wt(e, n, t), a = yield* E.SqlClient;
|
|
814
814
|
yield* Me(a, Nt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
|
|
815
815
|
}), Lt = async (e, t, n, r = "postgres", i = {}) => {
|
|
816
816
|
await S.runPromise(It(e, t, r, i).pipe(S.provide(n))), await s({
|
|
@@ -819,7 +819,7 @@ BEGIN
|
|
|
819
819
|
});
|
|
820
820
|
}, Rt = async (e, t, n = "postgres", r = {}) => {
|
|
821
821
|
await S.runPromise(S.gen(function* () {
|
|
822
|
-
let t = Tt(e, n), i = yield*
|
|
822
|
+
let t = Tt(e, n), i = yield* E.SqlClient;
|
|
823
823
|
yield* Me(i, Nt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
|
|
824
824
|
}).pipe(S.provide(t)));
|
|
825
825
|
}, zt = (e) => {
|
|
@@ -842,7 +842,7 @@ BEGIN
|
|
|
842
842
|
indexes: Ht(e.indexes)
|
|
843
843
|
})).sort((e, t) => e.name.localeCompare(t.name)), Wt = (e) => {
|
|
844
844
|
let t = { tables: Ut(e.tables) }, n = JSON.stringify(zt(t));
|
|
845
|
-
return
|
|
845
|
+
return w("sha256").update(n).digest("hex");
|
|
846
846
|
}, Gt = (e) => e.slice(0, 16), Kt = (e, t) => {
|
|
847
847
|
let n = t.references ? {
|
|
848
848
|
table: t.references().tableName,
|
|
@@ -956,7 +956,7 @@ BEGIN
|
|
|
956
956
|
t.set(e.name, n.name);
|
|
957
957
|
}
|
|
958
958
|
}, I = (e, t) => {
|
|
959
|
-
let n = e.filter((e) => !i(e.tableName)).map((e) => Jt(
|
|
959
|
+
let n = e.filter((e) => !i(e.tableName)).map((e) => Jt(le(e, t)));
|
|
960
960
|
return Yt(n), { tables: n };
|
|
961
961
|
}, Xt = (e, t, n = A) => S.gen(function* () {
|
|
962
962
|
let r = (yield* e`
|
|
@@ -1475,8 +1475,8 @@ BEGIN
|
|
|
1475
1475
|
column: e.name,
|
|
1476
1476
|
target: e.references.table
|
|
1477
1477
|
}] : []) : [];
|
|
1478
|
-
}, d =
|
|
1479
|
-
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(
|
|
1478
|
+
}, d = ue([...c], u), p = [];
|
|
1479
|
+
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(D(e.name, t.name)) || p.push(R({
|
|
1480
1480
|
kind: "add-foreign-key",
|
|
1481
1481
|
table: e.name,
|
|
1482
1482
|
column: t.name,
|
|
@@ -1491,8 +1491,8 @@ BEGIN
|
|
|
1491
1491
|
let n = a[t];
|
|
1492
1492
|
if (n.op.kind !== "create-table") continue;
|
|
1493
1493
|
let r = n.op;
|
|
1494
|
-
if (!r.columns.some((e) => d.has(
|
|
1495
|
-
let i = r.columns.map((t) => d.has(
|
|
1494
|
+
if (!r.columns.some((e) => d.has(D(r.table, e.name)))) continue;
|
|
1495
|
+
let i = r.columns.map((t) => d.has(D(r.table, t.name)) ? e(t) : t);
|
|
1496
1496
|
a[t] = {
|
|
1497
1497
|
...n,
|
|
1498
1498
|
op: {
|
|
@@ -1512,7 +1512,7 @@ BEGIN
|
|
|
1512
1512
|
let i = new Set(t).add(e), a = 0;
|
|
1513
1513
|
for (let t of r.columns) {
|
|
1514
1514
|
let n = t.references?.table;
|
|
1515
|
-
n && n !== e && !d.has(
|
|
1515
|
+
n && n !== e && !d.has(D(e, t.name)) && (a = Math.max(a, _(n, i) + 1));
|
|
1516
1516
|
}
|
|
1517
1517
|
return g.set(e, a), a;
|
|
1518
1518
|
}, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
|
|
@@ -1721,18 +1721,18 @@ BEGIN
|
|
|
1721
1721
|
let t = v.get(e.table_name);
|
|
1722
1722
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1723
1723
|
}
|
|
1724
|
-
let
|
|
1724
|
+
let w = /* @__PURE__ */ new Map();
|
|
1725
1725
|
for (let e of f) {
|
|
1726
|
-
let t = `${e.table_name}\u0000${e.constraint_name}`, n =
|
|
1726
|
+
let t = `${e.table_name}\u0000${e.constraint_name}`, n = w.get(t);
|
|
1727
1727
|
n || (n = {
|
|
1728
1728
|
table: e.table_name,
|
|
1729
1729
|
columns: []
|
|
1730
|
-
},
|
|
1730
|
+
}, w.set(t, n)), n.columns.push({
|
|
1731
1731
|
name: e.column_name,
|
|
1732
1732
|
position: e.position
|
|
1733
1733
|
});
|
|
1734
1734
|
}
|
|
1735
|
-
for (let [e, t] of
|
|
1735
|
+
for (let [e, t] of w) {
|
|
1736
1736
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1737
1737
|
if (n.length === 1) {
|
|
1738
1738
|
let e = y.get(t.table);
|
|
@@ -1757,7 +1757,7 @@ BEGIN
|
|
|
1757
1757
|
let n = t.get(e.index_name);
|
|
1758
1758
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1759
1759
|
}
|
|
1760
|
-
let
|
|
1760
|
+
let T = [];
|
|
1761
1761
|
for (let e of c) {
|
|
1762
1762
|
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = x.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
|
|
1763
1763
|
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" : Fn(t.data_type, t.udt_name), c = a ? {
|
|
@@ -1802,14 +1802,14 @@ BEGIN
|
|
|
1802
1802
|
unique: !0
|
|
1803
1803
|
});
|
|
1804
1804
|
let d = Number(e.row_count ?? 0);
|
|
1805
|
-
|
|
1805
|
+
T.push({
|
|
1806
1806
|
name: e.table_name,
|
|
1807
1807
|
columns: c,
|
|
1808
1808
|
indexes: l,
|
|
1809
1809
|
...d > 0 ? { rowCount: d } : {}
|
|
1810
1810
|
});
|
|
1811
1811
|
}
|
|
1812
|
-
return { tables:
|
|
1812
|
+
return { tables: T };
|
|
1813
1813
|
});
|
|
1814
1814
|
return (t > 0 ? e.withTransaction(n) : n).pipe(S.catchAll((e) => {
|
|
1815
1815
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
@@ -2567,9 +2567,9 @@ BEGIN
|
|
|
2567
2567
|
};
|
|
2568
2568
|
};
|
|
2569
2569
|
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(S.catchIf((e) => ar(e, r), () => S.void), S.tapError((e) => S.sync(() => {
|
|
2570
|
-
process.stderr.write(
|
|
2570
|
+
process.stderr.write(re(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2571
2571
|
})), S.mapError((e) => {
|
|
2572
|
-
let r =
|
|
2572
|
+
let r = re(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2573
2573
|
return Object.assign(e, { message: r });
|
|
2574
2574
|
}), S.map(() => void 0)), Z = (e, t, n) => S.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : _(r, t)} FROM ${_(n, t)} WHERE 1=0`).pipe(S.as(!0), S.catchAll(() => S.succeed(!1))), Ai = (e, t) => S.gen(function* () {
|
|
2575
2575
|
let n = I([Ie], t).tables[0];
|
|
@@ -2909,69 +2909,89 @@ BEGIN
|
|
|
2909
2909
|
planned: e.planned
|
|
2910
2910
|
}))
|
|
2911
2911
|
});
|
|
2912
|
-
}), zi = (e
|
|
2912
|
+
}), zi = (e) => {
|
|
2913
|
+
let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
|
|
2914
|
+
return [
|
|
2915
|
+
t.kind,
|
|
2916
|
+
n("table"),
|
|
2917
|
+
n("column"),
|
|
2918
|
+
n("name"),
|
|
2919
|
+
n("to")
|
|
2920
|
+
].join("\0");
|
|
2921
|
+
}, Bi = (e, t, n) => S.gen(function* () {
|
|
2913
2922
|
let r = t.operations.filter((e) => e.blocked);
|
|
2914
2923
|
if (r.length > 0) return yield* S.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
2915
|
-
yield*
|
|
2916
|
-
let i = Date.now(), a = [], o = Ne(e), s =
|
|
2924
|
+
yield* je(e, { schema: n.lockSchema });
|
|
2925
|
+
let i = Date.now(), a = [], o = Ne(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => zi(e))), l = {
|
|
2926
|
+
...s,
|
|
2927
|
+
operations: s.operations.map((e) => {
|
|
2928
|
+
if (!e.blocked || !c.has(zi(e))) return e;
|
|
2929
|
+
let { blocked: t, ...n } = e;
|
|
2930
|
+
return n;
|
|
2931
|
+
})
|
|
2932
|
+
};
|
|
2933
|
+
(l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* S.logInfo(`migration: re-planned under the lock — ${t.operations.length} operation(s) became ${l.operations.length}. Another writer changed the schema while this plan waited.`).pipe(S.annotateLogs({ scope: "voltro:migrate" })));
|
|
2934
|
+
let u = l.operations.filter((e) => e.blocked);
|
|
2935
|
+
if (u.length > 0) return yield* O(e, { schema: n.lockSchema }).pipe(S.orDie), yield* S.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — re-planning under the migration lock found ${u.length} blocked operation(s). Run \`voltro db plan\` to see the fixes.`));
|
|
2936
|
+
let d = Fe(o) === "plan-transactional", f = d ? l.operations.filter((e) => e.classification !== "online-required") : [], p = d ? l.operations.filter((e) => e.classification === "online-required") : l.operations, m = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, h = p.map((e, t) => ({
|
|
2917
2937
|
index: t,
|
|
2918
2938
|
planned: e
|
|
2919
|
-
})),
|
|
2939
|
+
})), g = "fresh";
|
|
2920
2940
|
try {
|
|
2921
2941
|
yield* Ai(e, o);
|
|
2922
|
-
let
|
|
2923
|
-
if (
|
|
2924
|
-
let n = yield* Ri(e, o,
|
|
2925
|
-
n.kind === "resume" ? (
|
|
2942
|
+
let t = yield* ji(e);
|
|
2943
|
+
if (t.length > 0) {
|
|
2944
|
+
let n = yield* Ri(e, o, l, t);
|
|
2945
|
+
n.kind === "resume" ? (m = n.runId, h = n.ops, g = "resume") : (yield* S.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield* Fi(e, n.runId));
|
|
2926
2946
|
}
|
|
2927
|
-
|
|
2928
|
-
let e = yield*
|
|
2929
|
-
for (let t of
|
|
2947
|
+
g === "fresh" && h.length > 0 && (yield* Mi(e, m, l.toFingerprint, h)), f.length > 0 && (yield* e.withTransaction(S.gen(function* () {
|
|
2948
|
+
let e = yield* E.SqlClient;
|
|
2949
|
+
for (let t of f) a.push(yield* Li(e, t, n));
|
|
2930
2950
|
})));
|
|
2931
|
-
for (let { index: t, planned: r } of
|
|
2932
|
-
yield* Ni(e,
|
|
2933
|
-
let i = a.length, o = yield* Li(e, r, n,
|
|
2934
|
-
a.push(o), yield* Ni(e,
|
|
2951
|
+
for (let { index: t, planned: r } of h) {
|
|
2952
|
+
yield* Ni(e, m, t, "started");
|
|
2953
|
+
let i = a.length, o = yield* Li(e, r, n, g).pipe(S.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${h.length + f.length} operation(s) applied before this one${f.length > 0 ? ` (${f.length} of them in a transaction)` : ""}.\n` + (d ? " This dialect applies a plan atomically, so the run is rolled back.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The next \`voltro db apply\` resumes from operation ${t} — the ledger records the sequence.\n`) })));
|
|
2954
|
+
a.push(o), yield* Ni(e, m, t, "applied", o.durationMs);
|
|
2935
2955
|
}
|
|
2936
2956
|
} finally {
|
|
2937
2957
|
yield* O(e, { schema: n.lockSchema }).pipe(S.orDie);
|
|
2938
2958
|
}
|
|
2939
|
-
let
|
|
2940
|
-
if (
|
|
2941
|
-
let e =
|
|
2942
|
-
return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${
|
|
2959
|
+
let _ = yield* n.replan(e);
|
|
2960
|
+
if (_.operations.length > 0) {
|
|
2961
|
+
let e = _.operations.slice(0, 10).map((e) => ` - ${e.op.kind} ${"table" in e.op ? e.op.table : ""}${"column" in e.op ? `.${String(e.op.column)}` : ""}`).join("\n");
|
|
2962
|
+
return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${l.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${_.operations.length}:\n${e}${_.operations.length > 10 ? `\n … and ${_.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug; the schema is unchanged and safe.\nTwo causes look identical from here, so read the list before assuming either:\n - the DDL for those operations is a no-op (it succeeded and changed nothing), or\n - the planner cannot see what the DDL did, so it proposes the same work again — which is what an\n operation naming an object a PREVIOUS operation created or renamed usually means.\nReport the operation kinds above with the column types involved.`));
|
|
2943
2963
|
}
|
|
2944
|
-
let
|
|
2964
|
+
let y = a.filter((e) => e.status === "applied").length, b = Date.now() - i, x = m, C = (/* @__PURE__ */ new Date()).toISOString(), w = yield* W(e, C), T = [...f, ...h.map((e) => e.planned)];
|
|
2945
2965
|
yield* e`
|
|
2946
2966
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
2947
2967
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
2948
2968
|
${e("appliedBy")}, ${e("environment")}, ${e("source")},
|
|
2949
2969
|
${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
|
|
2950
2970
|
VALUES
|
|
2951
|
-
(${
|
|
2971
|
+
(${x}, ${l.toFingerprint}, ${_.fromFingerprint}, ${JSON.stringify(T)},
|
|
2952
2972
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
2953
|
-
${
|
|
2954
|
-
`, yield* Fi(e,
|
|
2955
|
-
let
|
|
2956
|
-
return yield* S.promise(() => v({ changedTables:
|
|
2957
|
-
id:
|
|
2958
|
-
appliedAt:
|
|
2959
|
-
fingerprint:
|
|
2960
|
-
operations:
|
|
2973
|
+
${b}, ${w}, ${n.notes ?? null})
|
|
2974
|
+
`, yield* Fi(e, m);
|
|
2975
|
+
let ee = [...new Set(T.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
2976
|
+
return yield* S.promise(() => v({ changedTables: ee }).catch(() => {})), {
|
|
2977
|
+
id: x,
|
|
2978
|
+
appliedAt: C,
|
|
2979
|
+
fingerprint: l.toFingerprint,
|
|
2980
|
+
operations: T,
|
|
2961
2981
|
appliedBy: n.appliedBy,
|
|
2962
2982
|
environment: n.environment,
|
|
2963
|
-
durationMs:
|
|
2964
|
-
appliedOps:
|
|
2983
|
+
durationMs: b,
|
|
2984
|
+
appliedOps: y,
|
|
2965
2985
|
source: n.source,
|
|
2966
2986
|
...n.notes ? { notes: n.notes } : {}
|
|
2967
2987
|
};
|
|
2968
|
-
}),
|
|
2988
|
+
}), Vi = (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"), Hi = (e) => e`
|
|
2969
2989
|
SELECT fingerprint
|
|
2970
2990
|
FROM _voltro_migration_plans
|
|
2971
2991
|
ORDER BY ${e("appliedAt")} DESC
|
|
2972
2992
|
LIMIT 1
|
|
2973
|
-
`.pipe(S.map((e) => e.length > 0 ? e[0].fingerprint : void 0), S.catchAll(() => S.succeed(void 0))),
|
|
2974
|
-
if ((yield*
|
|
2993
|
+
`.pipe(S.map((e) => e.length > 0 ? e[0].fingerprint : void 0), S.catchAll(() => S.succeed(void 0))), Ui = (e, t, n) => S.gen(function* () {
|
|
2994
|
+
if ((yield* Hi(e)) === t.toFingerprint) return "already-current";
|
|
2975
2995
|
let r = `plan_${Date.now().toString(36)}`, i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2976
2996
|
return yield* e`
|
|
2977
2997
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
@@ -2983,8 +3003,8 @@ BEGIN
|
|
|
2983
3003
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
2984
3004
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
2985
3005
|
`, "recorded";
|
|
2986
|
-
}).pipe(S.catchAll(() => S.succeed("already-current"))),
|
|
2987
|
-
let n = Wt(I(t, Ne(e))), r = yield*
|
|
3006
|
+
}).pipe(S.catchAll(() => S.succeed("already-current"))), Wi = (e, t) => S.gen(function* () {
|
|
3007
|
+
let n = Wt(I(t, Ne(e))), r = yield* Hi(e);
|
|
2988
3008
|
return r === n ? {
|
|
2989
3009
|
kind: "up-to-date",
|
|
2990
3010
|
fingerprint: n
|
|
@@ -2993,23 +3013,23 @@ BEGIN
|
|
|
2993
3013
|
expected: n,
|
|
2994
3014
|
...r === void 0 ? {} : { actual: r }
|
|
2995
3015
|
};
|
|
2996
|
-
}),
|
|
3016
|
+
}), Gi = [
|
|
2997
3017
|
"pgeagertest_",
|
|
2998
3018
|
"mig_e2e_",
|
|
2999
3019
|
"mig_test_",
|
|
3000
3020
|
"mysqleagertest_",
|
|
3001
3021
|
"mssqleagertest_",
|
|
3002
3022
|
"sqliteeagertest_"
|
|
3003
|
-
],
|
|
3023
|
+
], Ki = (e) => Gi.some((t) => e.startsWith(t)), qi = (e, t) => S.gen(function* () {
|
|
3004
3024
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
3005
|
-
let n = t.filter((e) =>
|
|
3025
|
+
let n = t.filter((e) => Ki(e.name)).map((e) => e.name);
|
|
3006
3026
|
if (n.length === 0) return [];
|
|
3007
3027
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(S.catchAll(() => S.void));
|
|
3008
3028
|
return n;
|
|
3009
|
-
}),
|
|
3029
|
+
}), Ji = () => {
|
|
3010
3030
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
3011
3031
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
3012
|
-
},
|
|
3032
|
+
}, Yi = (e) => {
|
|
3013
3033
|
if (e === void 0) return;
|
|
3014
3034
|
let t = e.trim();
|
|
3015
3035
|
if (t === "") return;
|
|
@@ -3019,30 +3039,30 @@ BEGIN
|
|
|
3019
3039
|
kind: "tables",
|
|
3020
3040
|
tables: new Set(n)
|
|
3021
3041
|
} : void 0;
|
|
3022
|
-
},
|
|
3042
|
+
}, Xi = (e) => typeof e.table == "string" ? e.table : void 0, Zi = (e, t = { kind: "all" }) => ({
|
|
3023
3043
|
...e,
|
|
3024
3044
|
operations: e.operations.map((e) => {
|
|
3025
3045
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
3026
3046
|
if (t?.kind === "tables") {
|
|
3027
|
-
let n =
|
|
3047
|
+
let n = Xi(e.op);
|
|
3028
3048
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
3029
3049
|
}
|
|
3030
3050
|
let { blocked: n, ...r } = e;
|
|
3031
3051
|
return r;
|
|
3032
3052
|
})
|
|
3033
|
-
}),
|
|
3053
|
+
}), Qi = (e, t, n) => t === "postgres" ? Xt(e, n).pipe(S.flatMap((e) => {
|
|
3034
3054
|
let t = Zt(e);
|
|
3035
3055
|
return t === void 0 ? S.void : S.logWarning(`auto-migrate: ${t}`).pipe(S.annotateLogs({ scope: "voltro:migrate" }));
|
|
3036
|
-
}), S.catchAll(() => S.void)) : S.void,
|
|
3056
|
+
}), S.catchAll(() => S.void)) : S.void, $i = (e, t, n) => S.gen(function* () {
|
|
3037
3057
|
let r = Ne(e), i = t;
|
|
3038
3058
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
3039
3059
|
let t = Wt(I(i, r));
|
|
3040
|
-
if ((yield*
|
|
3060
|
+
if ((yield* Hi(e)) === t) return yield* Qi(e, r, i), {
|
|
3041
3061
|
kind: "up-to-date",
|
|
3042
3062
|
fingerprint: t
|
|
3043
3063
|
};
|
|
3044
3064
|
}
|
|
3045
|
-
let a = yield* $n(e), o = yield*
|
|
3065
|
+
let a = yield* $n(e), o = yield* qi(e, a.tables);
|
|
3046
3066
|
o.length > 0 && (yield* S.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(S.annotateLogs({
|
|
3047
3067
|
scope: "voltro:migrate",
|
|
3048
3068
|
count: o.length
|
|
@@ -3051,16 +3071,16 @@ BEGIN
|
|
|
3051
3071
|
declared: i,
|
|
3052
3072
|
live: { tables: c(a.tables) },
|
|
3053
3073
|
dialect: r,
|
|
3054
|
-
...
|
|
3074
|
+
...Ji()
|
|
3055
3075
|
});
|
|
3056
3076
|
if (l.summary.blocked > 0) {
|
|
3057
|
-
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
3058
|
-
if (t === void 0 || !e || (l =
|
|
3077
|
+
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Yi(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
3078
|
+
if (t === void 0 || !e || (l = Zi(l, t), l.operations.some((e) => e.blocked))) return {
|
|
3059
3079
|
kind: "refused-blocked",
|
|
3060
3080
|
plan: l
|
|
3061
3081
|
};
|
|
3062
3082
|
}
|
|
3063
|
-
return l.operations.length === 0 ? (yield*
|
|
3083
|
+
return l.operations.length === 0 ? (yield* Ui(e, l, {
|
|
3064
3084
|
appliedBy: n.appliedBy,
|
|
3065
3085
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3066
3086
|
source: "auto-diff"
|
|
@@ -3069,7 +3089,7 @@ BEGIN
|
|
|
3069
3089
|
fingerprint: l.toFingerprint
|
|
3070
3090
|
}) : {
|
|
3071
3091
|
kind: "applied",
|
|
3072
|
-
applied: yield*
|
|
3092
|
+
applied: yield* Bi(e, l, {
|
|
3073
3093
|
declared: t,
|
|
3074
3094
|
appliedBy: n.appliedBy,
|
|
3075
3095
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
@@ -3080,16 +3100,16 @@ BEGIN
|
|
|
3080
3100
|
declared: i,
|
|
3081
3101
|
live: { tables: c(t.tables) },
|
|
3082
3102
|
dialect: r,
|
|
3083
|
-
...
|
|
3103
|
+
...Ji()
|
|
3084
3104
|
});
|
|
3085
3105
|
})
|
|
3086
3106
|
}),
|
|
3087
3107
|
plan: l
|
|
3088
3108
|
};
|
|
3089
|
-
}),
|
|
3109
|
+
}), ea = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? S.succeed({
|
|
3090
3110
|
kind: "skipped",
|
|
3091
3111
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
3092
|
-
}) : n.environment === "prod" ?
|
|
3112
|
+
}) : n.environment === "prod" ? Wi(e, t) : $i(e, t, n), ta = (e, t) => {
|
|
3093
3113
|
switch (e.kind) {
|
|
3094
3114
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
3095
3115
|
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${Gt(e.fingerprint)})`;
|
|
@@ -3099,7 +3119,7 @@ BEGIN
|
|
|
3099
3119
|
}
|
|
3100
3120
|
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${Gt(e.expected)}` + (e.actual ? ` live=${Gt(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
3101
3121
|
case "refused-blocked": {
|
|
3102
|
-
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` +
|
|
3122
|
+
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` + Vi(e.plan), c = [""];
|
|
3103
3123
|
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) {
|
|
3104
3124
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
3105
3125
|
for (let r of e.plan.operations) {
|
|
@@ -3116,7 +3136,7 @@ BEGIN
|
|
|
3116
3136
|
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");
|
|
3117
3137
|
}
|
|
3118
3138
|
}
|
|
3119
|
-
},
|
|
3139
|
+
}, na = /* @__PURE__ */ new Set([
|
|
3120
3140
|
"node_modules",
|
|
3121
3141
|
"dist",
|
|
3122
3142
|
"build",
|
|
@@ -3125,12 +3145,12 @@ BEGIN
|
|
|
3125
3145
|
".next",
|
|
3126
3146
|
".git",
|
|
3127
3147
|
".framework"
|
|
3128
|
-
]),
|
|
3148
|
+
]), ra = async (e) => {
|
|
3129
3149
|
let t = [], n = async (e) => {
|
|
3130
|
-
let r = await
|
|
3150
|
+
let r = await ee.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
3131
3151
|
for (let i of r) {
|
|
3132
|
-
if (
|
|
3133
|
-
let r =
|
|
3152
|
+
if (na.has(i.name)) continue;
|
|
3153
|
+
let r = te(e, i.name);
|
|
3134
3154
|
i.isDirectory() ? await n(r) : i.isFile() && m.test(i.name) && t.push(r);
|
|
3135
3155
|
}
|
|
3136
3156
|
};
|
|
@@ -3138,10 +3158,10 @@ BEGIN
|
|
|
3138
3158
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
3139
3159
|
return n.localeCompare(r);
|
|
3140
3160
|
});
|
|
3141
|
-
},
|
|
3161
|
+
}, ia = async (e) => {
|
|
3142
3162
|
let t = [];
|
|
3143
3163
|
for (let n of e) {
|
|
3144
|
-
let e = (await import(
|
|
3164
|
+
let e = (await import(ne(n).href)).default;
|
|
3145
3165
|
if (!g(e)) {
|
|
3146
3166
|
process.stderr.write(`[voltro:migrate] ${n} has no default-exported \`migration(...)\` — skipped\n`);
|
|
3147
3167
|
continue;
|
|
@@ -3152,11 +3172,11 @@ BEGIN
|
|
|
3152
3172
|
});
|
|
3153
3173
|
}
|
|
3154
3174
|
return t;
|
|
3155
|
-
},
|
|
3175
|
+
}, aa = (e) => e`
|
|
3156
3176
|
SELECT ${e("id")}
|
|
3157
3177
|
FROM ${e("_voltro_migration_plans")}
|
|
3158
3178
|
WHERE ${e("source")} = 'file'
|
|
3159
|
-
`.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))),
|
|
3179
|
+
`.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))), oa = class extends Error {
|
|
3160
3180
|
migrationId;
|
|
3161
3181
|
file;
|
|
3162
3182
|
cause;
|
|
@@ -3164,7 +3184,7 @@ BEGIN
|
|
|
3164
3184
|
constructor(e, t, n) {
|
|
3165
3185
|
super(`migration ${e}: up() SUCCEEDED but the ledger row could not be written.\n The change IS in the database. It is NOT recorded, so the next run would apply it AGAIN.\n Do not re-run ${t} until this is resolved.\n Cause: ${n instanceof Error ? n.message : String(n)}`), this.migrationId = e, this.file = t, this.cause = n, this.name = "FileMigrationLedgerError";
|
|
3166
3186
|
}
|
|
3167
|
-
},
|
|
3187
|
+
}, sa = (e, t, n, r) => S.gen(function* () {
|
|
3168
3188
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
3169
3189
|
sql: e,
|
|
3170
3190
|
log: {
|
|
@@ -3198,10 +3218,10 @@ BEGIN
|
|
|
3198
3218
|
}])},
|
|
3199
3219
|
${r}, ${n}, ${"file"},
|
|
3200
3220
|
${c}, ${l}, ${t.migration.description})
|
|
3201
|
-
`.pipe(S.mapError((e) => new
|
|
3202
|
-
}),
|
|
3221
|
+
`.pipe(S.mapError((e) => new oa(t.migration.id, t.file, e))), { durationMs: c };
|
|
3222
|
+
}), ca = (e, t) => S.gen(function* () {
|
|
3203
3223
|
let n = yield* S.tryPromise({
|
|
3204
|
-
try: () =>
|
|
3224
|
+
try: () => ra(te(t, "migrations")),
|
|
3205
3225
|
catch: (e) => e
|
|
3206
3226
|
});
|
|
3207
3227
|
if (n.length === 0) return {
|
|
@@ -3209,25 +3229,25 @@ BEGIN
|
|
|
3209
3229
|
skipped: []
|
|
3210
3230
|
};
|
|
3211
3231
|
let r = yield* S.tryPromise({
|
|
3212
|
-
try: () =>
|
|
3232
|
+
try: () => ia(n),
|
|
3213
3233
|
catch: (e) => e
|
|
3214
3234
|
});
|
|
3215
3235
|
if (r.length === 0) return {
|
|
3216
3236
|
pending: [],
|
|
3217
3237
|
skipped: []
|
|
3218
3238
|
};
|
|
3219
|
-
let i = new Set(yield*
|
|
3239
|
+
let i = new Set(yield* aa(e));
|
|
3220
3240
|
return {
|
|
3221
3241
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
3222
3242
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
3223
3243
|
};
|
|
3224
|
-
}),
|
|
3225
|
-
let { pending: n, skipped: r } = yield*
|
|
3244
|
+
}), la = (e, t) => ca(e, t).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), ua = (e, t) => S.gen(function* () {
|
|
3245
|
+
let { pending: n, skipped: r } = yield* ca(e, t.projectRoot);
|
|
3226
3246
|
if (n.length === 0) return {
|
|
3227
3247
|
applied: [],
|
|
3228
3248
|
skipped: r
|
|
3229
3249
|
};
|
|
3230
|
-
yield*
|
|
3250
|
+
yield* je(e, { schema: t.lockSchema });
|
|
3231
3251
|
let i = [];
|
|
3232
3252
|
try {
|
|
3233
3253
|
for (let r of n) {
|
|
@@ -3236,7 +3256,7 @@ BEGIN
|
|
|
3236
3256
|
id: r.migration.id,
|
|
3237
3257
|
file: r.file
|
|
3238
3258
|
}));
|
|
3239
|
-
let { durationMs: n } = yield*
|
|
3259
|
+
let { durationMs: n } = yield* sa(e, r, t.env, t.appliedBy);
|
|
3240
3260
|
i.push({
|
|
3241
3261
|
id: r.migration.id,
|
|
3242
3262
|
durationMs: n
|
|
@@ -3253,22 +3273,22 @@ BEGIN
|
|
|
3253
3273
|
applied: i,
|
|
3254
3274
|
skipped: r
|
|
3255
3275
|
};
|
|
3256
|
-
}),
|
|
3276
|
+
}), da = (e, t) => e`
|
|
3257
3277
|
SELECT ${e("id")}
|
|
3258
3278
|
FROM ${e("_voltro_migration_plans")}
|
|
3259
3279
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
3260
3280
|
LIMIT 1
|
|
3261
|
-
`,
|
|
3262
|
-
if (!(yield*
|
|
3281
|
+
`, fa = (e, t) => S.gen(function* () {
|
|
3282
|
+
if (!(yield* da(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
3263
3283
|
let n = yield* S.tryPromise({
|
|
3264
|
-
try: () =>
|
|
3284
|
+
try: () => ra(te(t.projectRoot, "migrations")),
|
|
3265
3285
|
catch: (e) => e
|
|
3266
3286
|
}), r = (yield* S.tryPromise({
|
|
3267
|
-
try: () =>
|
|
3287
|
+
try: () => ia(n),
|
|
3268
3288
|
catch: (e) => e
|
|
3269
3289
|
})).find((e) => e.migration.id === t.id);
|
|
3270
3290
|
if (!r) return yield* S.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
3271
|
-
yield*
|
|
3291
|
+
yield* je(e, { schema: t.lockSchema });
|
|
3272
3292
|
let i = Date.now();
|
|
3273
3293
|
try {
|
|
3274
3294
|
let n = {
|
|
@@ -3297,8 +3317,8 @@ BEGIN
|
|
|
3297
3317
|
} finally {
|
|
3298
3318
|
yield* O(e, { schema: t.lockSchema }).pipe(S.orDie);
|
|
3299
3319
|
}
|
|
3300
|
-
}),
|
|
3301
|
-
let t = yield*
|
|
3320
|
+
}), pa = (e) => S.gen(function* () {
|
|
3321
|
+
let t = yield* E.SqlClient, n = yield* t`
|
|
3302
3322
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
3303
3323
|
WHERE source = 'auto-diff'
|
|
3304
3324
|
AND squashedAt IS NULL
|
|
@@ -3342,7 +3362,7 @@ BEGIN
|
|
|
3342
3362
|
snapshotFingerprint: e.fingerprint,
|
|
3343
3363
|
snapshotId: i
|
|
3344
3364
|
};
|
|
3345
|
-
}),
|
|
3365
|
+
}), ma = { safe: !0 }, ha = (e) => {
|
|
3346
3366
|
switch (e.kind) {
|
|
3347
3367
|
case "drop-column": return {
|
|
3348
3368
|
safe: !1,
|
|
@@ -3369,7 +3389,7 @@ BEGIN
|
|
|
3369
3389
|
reason: `old instances read/write "${e.table}"."${e.column}" as ${e.from}; the new ${e.to} type can reject their writes or fail to decode their reads`,
|
|
3370
3390
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
3371
3391
|
};
|
|
3372
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
3392
|
+
case "alter-column-nullability": return e.toNullable ? ma : {
|
|
3373
3393
|
safe: !1,
|
|
3374
3394
|
reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
3375
3395
|
remedy: `make code always write "${e.column}" and deploy that first; add NOT NULL in a LATER deploy (with a default to cover the gap)`
|
|
@@ -3399,12 +3419,12 @@ BEGIN
|
|
|
3399
3419
|
case "drop-unique":
|
|
3400
3420
|
case "drop-unique-composite":
|
|
3401
3421
|
case "drop-foreign-key":
|
|
3402
|
-
case "drop-check": return
|
|
3422
|
+
case "drop-check": return ma;
|
|
3403
3423
|
}
|
|
3404
|
-
},
|
|
3424
|
+
}, ga = (e) => {
|
|
3405
3425
|
let t = [];
|
|
3406
3426
|
for (let n of e) {
|
|
3407
|
-
let e =
|
|
3427
|
+
let e = ha(n.op);
|
|
3408
3428
|
e.safe || t.push({
|
|
3409
3429
|
op: n,
|
|
3410
3430
|
reason: e.reason,
|
|
@@ -3412,7 +3432,7 @@ BEGIN
|
|
|
3412
3432
|
});
|
|
3413
3433
|
}
|
|
3414
3434
|
return t;
|
|
3415
|
-
},
|
|
3435
|
+
}, _a = (e) => {
|
|
3416
3436
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
3417
3437
|
refuse: !1,
|
|
3418
3438
|
warnForced: !1,
|
|
@@ -3428,18 +3448,18 @@ BEGIN
|
|
|
3428
3448
|
warnForced: !1,
|
|
3429
3449
|
message: `${t}. Old instances would break against the new schema mid-rollout. Split into expand → deploy → contract (see the ⚠ list above), deploy with no overlap (maintenance window / scale-to-zero), or pass --force to override.`
|
|
3430
3450
|
};
|
|
3431
|
-
},
|
|
3451
|
+
}, va = (e) => {
|
|
3432
3452
|
let t = e.table;
|
|
3433
3453
|
if (typeof t == "string") return t;
|
|
3434
3454
|
let n = e.from;
|
|
3435
3455
|
return typeof n == "string" ? n : void 0;
|
|
3436
|
-
},
|
|
3456
|
+
}, ya = (e) => ({
|
|
3437
3457
|
kind: e.op.kind,
|
|
3438
|
-
table:
|
|
3458
|
+
table: va(e.op),
|
|
3439
3459
|
classification: e.classification,
|
|
3440
3460
|
reason: e.reason,
|
|
3441
3461
|
blockedFix: e.blocked?.fix
|
|
3442
|
-
}),
|
|
3462
|
+
}), ba = (e) => e.operations.map(ya), xa = async (e) => {
|
|
3443
3463
|
let t = e.log ?? (() => {}), n = {
|
|
3444
3464
|
branchId: e.branchId,
|
|
3445
3465
|
mechanism: e.mechanism,
|
|
@@ -3458,10 +3478,10 @@ BEGIN
|
|
|
3458
3478
|
applied: !1,
|
|
3459
3479
|
converged: !1,
|
|
3460
3480
|
residual: r,
|
|
3461
|
-
infidelity:
|
|
3481
|
+
infidelity: ba(o)
|
|
3462
3482
|
};
|
|
3463
3483
|
else {
|
|
3464
|
-
let i = await e.plan(), o =
|
|
3484
|
+
let i = await e.plan(), o = ba(i), s = o.filter((e) => e.classification === "lossy"), c = Zi(i), l = c.operations.filter((e) => e.blocked !== void 0).map(ya);
|
|
3465
3485
|
if (l.length > 0) a = {
|
|
3466
3486
|
...n,
|
|
3467
3487
|
outcome: "blocked",
|
|
@@ -3486,7 +3506,7 @@ BEGIN
|
|
|
3486
3506
|
};
|
|
3487
3507
|
else {
|
|
3488
3508
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
3489
|
-
let i =
|
|
3509
|
+
let i = ba(await e.replan());
|
|
3490
3510
|
a = {
|
|
3491
3511
|
...n,
|
|
3492
3512
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -3524,7 +3544,7 @@ BEGIN
|
|
|
3524
3544
|
...a,
|
|
3525
3545
|
tornDown: o
|
|
3526
3546
|
};
|
|
3527
|
-
},
|
|
3547
|
+
}, Sa = (e) => {
|
|
3528
3548
|
switch (e.outcome) {
|
|
3529
3549
|
case "clean": return 0;
|
|
3530
3550
|
case "lossy": return 2;
|
|
@@ -3533,22 +3553,22 @@ BEGIN
|
|
|
3533
3553
|
case "infidelity": return 1;
|
|
3534
3554
|
case "failed": return 1;
|
|
3535
3555
|
}
|
|
3536
|
-
},
|
|
3556
|
+
}, Ca = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, wa = (e) => {
|
|
3537
3557
|
let t = [];
|
|
3538
3558
|
if (t.push(`branch rehearsal · ${e.branchId} · mechanism ${e.mechanism}`), t.push(` branched ${e.branchedTables} table(s), replayed ${e.replayedForeignKeys} foreign key(s)`), e.outcome === "failed") t.push(` FAILED: ${e.error ?? "unknown error"}`);
|
|
3539
3559
|
else if (e.outcome === "infidelity") {
|
|
3540
3560
|
t.push(" BRANCH IS NOT A FAITHFUL COPY of the parent — the rehearsal proves nothing about your migration."), t.push(" The parent's own schema still differs from the branch by:");
|
|
3541
|
-
for (let n of e.infidelity) t.push(
|
|
3561
|
+
for (let n of e.infidelity) t.push(Ca(n));
|
|
3542
3562
|
} else {
|
|
3543
3563
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
3544
|
-
for (let n of e.operations) t.push(
|
|
3545
|
-
if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(
|
|
3564
|
+
for (let n of e.operations) t.push(Ca(n));
|
|
3565
|
+
if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(Ca(n));
|
|
3546
3566
|
}
|
|
3547
3567
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
3548
|
-
},
|
|
3568
|
+
}, Ta = (e, ...t) => ({
|
|
3549
3569
|
_tag: "RawSqlFragment",
|
|
3550
3570
|
strings: [...e],
|
|
3551
3571
|
values: [...t]
|
|
3552
|
-
}),
|
|
3572
|
+
}), Ea = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3553
3573
|
//#endregion
|
|
3554
|
-
export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN,
|
|
3574
|
+
export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN, oa as FileMigrationLedgerError, qe as REACTIVE_TRIGGER_PREFIX, de as VOLTRO_MIGRATION_LOCK_KEY, je as acquireMigrationLock, W as appliedAtValue, It as applyNamespacedSchema, Bi as applyPlan, Et as applySchema, _a as assessRollingDeployGate, Sa as branchRehearsalExitCode, Vn as chunkTables, ha as classifyRollingDeploySafety, I as declaredSnapshot, $e as defaultArrayClause, Qe as defaultClause, N as defaultJsonClause, ta as describeOutcome, Yi as destructiveScope, Xt as detectReactiveTriggerDrift, ni as emitAddIndexMysql, Lr as emitCreateTableMysql, _r as emitDropColumnDdl, vr as emitDropColumnDdlMysql, Tt as emitFrameworkBootstrapSql, Ct as emitNamespaceProvisionDdl, wt as emitNamespacedSchemaSql, St as emitSchemaSql, er as engineFromVersion, Wt as fingerprintSchema, _e as fnv1a64, wa as formatBranchRehearsal, Zt as formatReactiveTriggerDrift, Ji as ignoreTablesFromEnv, $n as introspectSchema, ar as isAlreadySatisfied, g as isFileMigration, Ea as isRawSqlFragment, Ot as isReRunSafeDdl, Fn as mapPgType, o as migration, ve as migrationLockKeyForSchema, ye as migrationLockNameForSchema, Qr as mysqlIndexPrefixFor, Ye as notifyFunctionName, P as numericIdSql, Pn as parseEnumCheck, la as pendingFileMigrationIds, Nn as planMigrations, Lt as provisionTenantNamespace, Je as reactiveTriggerName, pt as reactiveTriggerRepairSql, Ui as recordUpToDate, xa as rehearseMigrationOnBranch, ya as rehearsedOperation, O as releaseMigrationLock, Fr as renderColumnMysql, Ar as renderColumnPg, pe as resolveMigrationLockSchema, U as resolveMysqlEngine, fa as rollbackFileBasedMigration, ga as rollingDeployUnsafeOps, ua as runFileBasedMigrations, Rt as runFrameworkBootstrap, Ft as runMigrate, ea as runPlannedMigrations, Gt as shortFingerprint, Kt as snapshotColumn, Ta as sql, M as sqlType, pa as squashMigrationPlans, Zi as unblockLossy, Me as withMigrationLock };
|