@voltro/database 0.86.0 → 0.87.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 +5321 -0
- package/THIRD-PARTY-NOTICES.md +1 -225
- package/dist/dataTransfers.js +2 -1
- package/dist/fieldEncryption.js +64 -41
- package/dist/frameworkTables.js +15 -2
- package/dist/idGenerator.js +4 -4
- package/dist/index.d.ts +148 -15
- package/dist/index.js +77 -76
- package/dist/migrate.js +51 -31
- package/dist/migrations/applier.js +399 -384
- package/dist/migrations/ddlStatements.js +9 -0
- package/dist/migrations/fileDiscovery.js +145 -131
- package/dist/migrations/introspect.js +186 -184
- package/dist/migrations/planner.js +24 -14
- package/dist/migrations/postgresEnumCheck.js +4 -1
- package/dist/migrations/sqliteCatalogName.js +13 -0
- package/dist/predicate.js +27 -20
- package/dist/queryBuilder.js +6 -0
- package/dist/rowDecoder.js +61 -11
- package/dist/sql.d.ts +2746 -3748
- package/dist/sql.js +15 -14
- package/dist/sqlCompiler.js +88 -71
- package/dist/sqlMutation.js +55 -0
- package/dist/transactionOutcome.js +4 -1
- package/dist/typeId.js +51 -0
- package/dist/typedStore.js +1 -1
- package/dist/writeRecorder.js +21 -20
- package/package.json +2 -3
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { causeBranches as e, classifyConstraintViolation as t, extractDbCause as n } from "../dbCause.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
2
|
+
import { derivedRowId as r } from "../derivedRowId.js";
|
|
3
|
+
import { FILE_MIGRATION_PATTERN as i, IrreversibleMigrationError as a, MigrationExpectationFailed as o, MigrationSkipped as s, TransactionBrokenByBodyError as c, irreversibleReason as l, isFileMigration as u } from "./fileBased.js";
|
|
4
|
+
import { acquireMigrationLock as d } from "./lock.js";
|
|
5
|
+
import { MIGRATION_OPS_TABLE as f, dialectOf as p } from "./resumeLedger.js";
|
|
6
|
+
import { migrationTableExists as m } from "./migrationTableExists.js";
|
|
7
|
+
import { appliedAtValue as h } from "./appliedAtValue.js";
|
|
8
|
+
import { ensureLedgerTable as g, ensurePlanLedgerTable as _ } from "./applier.js";
|
|
9
|
+
import { isFileMigrationRow as v } from "./ledgerRows.js";
|
|
10
|
+
import { failedExpectations as y, makeFileMigrationContext as b } from "./fileContext.js";
|
|
11
|
+
import { withSchemaProbeRecorder as x } from "./fileSkipProbes.js";
|
|
12
|
+
import { Effect as S } from "effect";
|
|
13
|
+
import { createHash as C } from "node:crypto";
|
|
14
|
+
import { SqlClient as w } from "effect/sql";
|
|
15
|
+
import { createLogger as T } from "@voltro/logger";
|
|
16
|
+
import { promises as E } from "node:fs";
|
|
17
|
+
import { join as D } from "node:path";
|
|
18
|
+
import { pathToFileURL as O } from "node:url";
|
|
18
19
|
//#region src/migrations/fileDiscovery.ts
|
|
19
|
-
var
|
|
20
|
+
var k = T({ scope: "voltro:migrate" }), A = (e) => C("sha256").update(e).digest("hex").slice(0, 16), j = [{
|
|
20
21
|
codemod: "0.78.0/01_file-migration-phase",
|
|
21
22
|
inverse: (e) => {
|
|
22
23
|
let t = /\n {2}phase: 'before-schema',\n {2}/g, n = /\n {2}phase: 'before-schema'(?=\r?\n[ \t]*\})/g, r = e.includes("\r\n") ? "\r\n" : "\n", i = (t) => {
|
|
@@ -25,7 +26,7 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
25
26
|
};
|
|
26
27
|
return [e.replace(t, (e, t) => r + i(t)).replace(n, ""), e.replace(t, " ").replace(n, "")];
|
|
27
28
|
}
|
|
28
|
-
}],
|
|
29
|
+
}], M = (e) => new Set([e, ...j.flatMap((t) => t.inverse(e))].map(A)), N = /* @__PURE__ */ new Set([
|
|
29
30
|
"node_modules",
|
|
30
31
|
"dist",
|
|
31
32
|
"build",
|
|
@@ -34,56 +35,67 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
34
35
|
".next",
|
|
35
36
|
".git",
|
|
36
37
|
".framework"
|
|
37
|
-
]),
|
|
38
|
+
]), P = async (e) => {
|
|
38
39
|
let t = [], n = async (e) => {
|
|
39
|
-
let
|
|
40
|
-
for (let a of
|
|
41
|
-
if (
|
|
42
|
-
let
|
|
43
|
-
a.isDirectory() ? await n(
|
|
40
|
+
let r = await E.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
41
|
+
for (let a of r) {
|
|
42
|
+
if (N.has(a.name)) continue;
|
|
43
|
+
let r = D(e, a.name);
|
|
44
|
+
a.isDirectory() ? await n(r) : a.isFile() && i.test(a.name) && t.push(r);
|
|
44
45
|
}
|
|
45
46
|
};
|
|
46
47
|
return await n(e), t.sort((e, t) => {
|
|
47
48
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
48
49
|
return n.localeCompare(r);
|
|
49
50
|
});
|
|
50
|
-
},
|
|
51
|
+
}, F = async (e) => await import(O(e).href), I = async (e, t = F) => {
|
|
51
52
|
let n = [];
|
|
52
53
|
for (let r of e) {
|
|
53
54
|
let e = (await t(r)).default;
|
|
54
|
-
if (!
|
|
55
|
-
|
|
55
|
+
if (!u(e)) {
|
|
56
|
+
k.warn("migration file has no default-exported `migration(...)` — skipped", { file: r });
|
|
56
57
|
continue;
|
|
57
58
|
}
|
|
58
|
-
let i = await
|
|
59
|
+
let i = await E.readFile(r, "utf8").catch(() => "");
|
|
59
60
|
n.push({
|
|
60
61
|
file: r,
|
|
61
62
|
migration: e,
|
|
62
|
-
hash:
|
|
63
|
-
accepted:
|
|
63
|
+
hash: A(i),
|
|
64
|
+
accepted: M(i)
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
return n;
|
|
67
|
-
},
|
|
68
|
+
}, L = "_voltro_migration_plans", R = (e) => z(e).pipe(S.map((e) => e.map((e) => e.id))), z = (e) => m(e, L).pipe(S.flatMap((t) => t ? e`
|
|
68
69
|
SELECT ${e("id")}, ${e("fingerprint")}
|
|
69
|
-
FROM ${e(
|
|
70
|
-
WHERE ${
|
|
71
|
-
`.pipe(
|
|
70
|
+
FROM ${e(L)}
|
|
71
|
+
WHERE ${v(e)}
|
|
72
|
+
`.pipe(S.map((e) => e.map((e) => ({
|
|
72
73
|
id: e.id,
|
|
73
74
|
hash: e.fingerprint ?? ""
|
|
74
|
-
})))) :
|
|
75
|
+
})))) : S.succeed([]))), B = (e, t) => t.filter((t) => {
|
|
75
76
|
let n = e.get(t.migration.id);
|
|
76
77
|
return n !== void 0 && n !== "" && !t.accepted.has(n);
|
|
77
|
-
}).map((e) => e.migration.id),
|
|
78
|
+
}).map((e) => e.migration.id), V = /* @__PURE__ */ new Set(), H = (e) => t(n(e))?.kind === "unique", U = class extends Error {
|
|
78
79
|
migrationId;
|
|
79
80
|
file;
|
|
80
81
|
cause;
|
|
81
82
|
_tag = "FileMigrationLedgerError";
|
|
82
83
|
constructor(e, t, n) {
|
|
83
|
-
super(
|
|
84
|
+
super(H(n) ? `migration ${e}: up() SUCCEEDED here, and ANOTHER process had already recorded the same migration.\n The body has run TWICE. The ledger row is correct — do not delete it; the next run will not apply ${t} again.\n Two processes applied it without being serialised by the migration lock: check that both reach the same database and lock schema.\n Cause: ${n instanceof Error ? n.message : String(n)}` : `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";
|
|
84
85
|
}
|
|
85
|
-
},
|
|
86
|
-
|
|
86
|
+
}, W = /* @__PURE__ */ new Set([
|
|
87
|
+
"mysql",
|
|
88
|
+
"mariadb",
|
|
89
|
+
"mssql"
|
|
90
|
+
]), G = (e, t) => W.has(e) ? t.filter((e) => e.length > 64) : [], K = class extends Error {
|
|
91
|
+
dialect;
|
|
92
|
+
migrationIds;
|
|
93
|
+
_tag = "MigrationIdTooLongError";
|
|
94
|
+
constructor(e, t) {
|
|
95
|
+
super(`migration id(s) longer than 64 characters cannot be recorded on ${e}: ` + t.map((e) => `${e} (${e.length})`).join(", ") + ". Nothing was applied. Rename the migration file and its `id` to at most 64 characters."), this.dialect = e, this.migrationIds = t, this.name = "MigrationIdTooLongError";
|
|
96
|
+
}
|
|
97
|
+
}, q = (e, t, n) => S.gen(function* () {
|
|
98
|
+
let r = yield* h(e, n.appliedAtIso);
|
|
87
99
|
yield* e`
|
|
88
100
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
89
101
|
(${e("id")}, ${e("fingerprint")}, ${e("operations")},
|
|
@@ -97,93 +109,93 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
97
109
|
}])},
|
|
98
110
|
${n.appliedBy}, ${n.env}, ${"file"},
|
|
99
111
|
${n.durationMs}, ${r}, ${n.notes})
|
|
100
|
-
`.pipe(
|
|
101
|
-
}),
|
|
102
|
-
for (let n of e(t)) if (n instanceof
|
|
103
|
-
},
|
|
104
|
-
let r =
|
|
105
|
-
try: () =>
|
|
112
|
+
`.pipe(S.mapError((e) => new U(t.migration.id, t.file, e)));
|
|
113
|
+
}), J = (t) => {
|
|
114
|
+
for (let n of e(t)) if (n instanceof s) return n.reason;
|
|
115
|
+
}, Y = (e, t, n) => S.gen(function* () {
|
|
116
|
+
let r = x(t), i = r.ctx, a = e.migration.up(i), s = !S.isEffect(a), c = yield* (S.isEffect(a) ? a : S.tryPromise({
|
|
117
|
+
try: () => a,
|
|
106
118
|
catch: (e) => e
|
|
107
|
-
})).pipe(
|
|
108
|
-
let t =
|
|
109
|
-
return t === void 0 ?
|
|
119
|
+
})).pipe(S.as(void 0), S.catch((e) => {
|
|
120
|
+
let t = J(e);
|
|
121
|
+
return t === void 0 ? S.fail(e) : S.succeed(t);
|
|
110
122
|
}));
|
|
111
123
|
if (c === void 0) {
|
|
112
|
-
let t = yield*
|
|
113
|
-
if (t.length > 0) return yield*
|
|
124
|
+
let t = yield* y(n);
|
|
125
|
+
if (t.length > 0) return yield* S.fail(new o(e.migration.id, t));
|
|
114
126
|
}
|
|
115
127
|
return {
|
|
116
128
|
skipped: c,
|
|
117
129
|
promiseForm: s,
|
|
118
130
|
absent: r.absent()
|
|
119
131
|
};
|
|
120
|
-
}),
|
|
121
|
-
let
|
|
122
|
-
durationMs: Date.now() -
|
|
132
|
+
}), X = (e, t, n, i, a, o, s, l) => S.gen(function* () {
|
|
133
|
+
let u = Date.now(), d = (/* @__PURE__ */ new Date()).toISOString(), m = p(e), h = `migrations:file:${n.migration.id}`, _ = (e) => ({
|
|
134
|
+
durationMs: Date.now() - u,
|
|
123
135
|
notes: e.skipped === void 0 ? n.migration.description : `skipped: ${e.skipped}`
|
|
124
136
|
});
|
|
125
|
-
if (n.migration.transactional !== !1 && !
|
|
126
|
-
if (t.run === void 0) return yield*
|
|
127
|
-
let
|
|
128
|
-
|
|
129
|
-
let
|
|
137
|
+
if (n.migration.transactional !== !1 && !o) {
|
|
138
|
+
if (t.run === void 0) return yield* S.fail(/* @__PURE__ */ Error(`migration ${n.migration.id}: transactional: true needs a SQL-backed store`));
|
|
139
|
+
let o = m === "mysql" || m === "mariadb", u = `probe_${n.migration.id}_${Date.now().toString(36)}`;
|
|
140
|
+
o && (yield* g(e, m, s));
|
|
141
|
+
let p = (e) => e.executeUnprepared(`SELECT COUNT(*) AS n FROM \`${f}\` WHERE \`runId\` = ?`, [u], void 0), v = () => (l === void 0 ? S.scoped(S.flatMap(e.reserve, p)) : p(l)).pipe(S.map((e) => Number(e[0]?.n ?? 0) > 0)), y = yield* S.tryPromise({
|
|
130
142
|
try: () => t.transactional(async (t) => {
|
|
131
|
-
|
|
132
|
-
VALUES (${
|
|
133
|
-
let { ctx:
|
|
143
|
+
o && await t.run(e`INSERT INTO ${e(f)} (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")}, ${e("status")}, ${e("opKind")}, ${e("opTarget")}, ${e("payload")})
|
|
144
|
+
VALUES (${r("mop", u)}, ${u}, ${""}, ${0}, ${"pending"}, ${"probe"}, ${""}, ${"{}"})`);
|
|
145
|
+
let { ctx: s, expectations: c } = b({
|
|
134
146
|
sql: e,
|
|
135
147
|
store: t,
|
|
136
|
-
dialect:
|
|
148
|
+
dialect: m,
|
|
137
149
|
migrationId: n.migration.id,
|
|
138
|
-
appliedAt:
|
|
139
|
-
}),
|
|
140
|
-
return await t.run(
|
|
141
|
-
env:
|
|
142
|
-
appliedBy:
|
|
143
|
-
durationMs:
|
|
144
|
-
appliedAtIso:
|
|
145
|
-
notes:
|
|
146
|
-
})),
|
|
147
|
-
...
|
|
148
|
-
durationMs:
|
|
149
|
-
broken:
|
|
150
|
+
appliedAt: d
|
|
151
|
+
}), l = await t.run(Y(n, s, c)), p = o && await S.runPromise(v().pipe(S.provideService(w.SqlClient, e))), { durationMs: h, notes: g } = _(l);
|
|
152
|
+
return await t.run(q(e, n, {
|
|
153
|
+
env: i,
|
|
154
|
+
appliedBy: a,
|
|
155
|
+
durationMs: h,
|
|
156
|
+
appliedAtIso: d,
|
|
157
|
+
notes: p ? `${g} — transactional guarantee broken by the body (DDL on ${m})` : g
|
|
158
|
+
})), o && await t.run(e`DELETE FROM ${e(f)} WHERE ${e("runId")} = ${u}`), {
|
|
159
|
+
...l,
|
|
160
|
+
durationMs: h,
|
|
161
|
+
broken: p
|
|
150
162
|
};
|
|
151
163
|
}),
|
|
152
164
|
catch: (e) => e
|
|
153
165
|
});
|
|
154
|
-
return
|
|
155
|
-
durationMs:
|
|
156
|
-
skip:
|
|
166
|
+
return y.broken ? yield* S.fail(new c(n.migration.id, m)) : (y.skipped !== void 0 && (yield* S.logInfo(`migration ${n.migration.id} skipped: ${y.skipped}`).pipe(S.annotateLogs({ scope: h }))), {
|
|
167
|
+
durationMs: y.durationMs,
|
|
168
|
+
skip: y.skipped === void 0 ? void 0 : {
|
|
157
169
|
id: n.migration.id,
|
|
158
|
-
reason:
|
|
159
|
-
absent:
|
|
170
|
+
reason: y.skipped,
|
|
171
|
+
absent: y.absent
|
|
160
172
|
}
|
|
161
173
|
});
|
|
162
174
|
}
|
|
163
|
-
let { ctx:
|
|
175
|
+
let { ctx: v, expectations: y } = b({
|
|
164
176
|
sql: e,
|
|
165
177
|
store: t,
|
|
166
|
-
dialect:
|
|
178
|
+
dialect: m,
|
|
167
179
|
migrationId: n.migration.id,
|
|
168
|
-
appliedAt:
|
|
169
|
-
}),
|
|
170
|
-
return
|
|
171
|
-
env:
|
|
172
|
-
appliedBy:
|
|
173
|
-
durationMs:
|
|
174
|
-
appliedAtIso:
|
|
175
|
-
notes:
|
|
180
|
+
appliedAt: d
|
|
181
|
+
}), x = yield* Y(n, v, y), { durationMs: C, notes: T } = _(x);
|
|
182
|
+
return x.promiseForm && x.skipped === void 0 && C < 2 && (yield* S.logWarning(`migration ${n.migration.id}: up() resolved in ${C}ms — did the body \`await\` an \`effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(S.annotateLogs({ scope: h }))), x.skipped !== void 0 && (yield* S.logInfo(`migration ${n.migration.id} skipped: ${x.skipped}`).pipe(S.annotateLogs({ scope: h }))), yield* q(e, n, {
|
|
183
|
+
env: i,
|
|
184
|
+
appliedBy: a,
|
|
185
|
+
durationMs: C,
|
|
186
|
+
appliedAtIso: d,
|
|
187
|
+
notes: T
|
|
176
188
|
}), {
|
|
177
|
-
durationMs:
|
|
178
|
-
skip:
|
|
189
|
+
durationMs: C,
|
|
190
|
+
skip: x.skipped === void 0 ? void 0 : {
|
|
179
191
|
id: n.migration.id,
|
|
180
|
-
reason:
|
|
181
|
-
absent:
|
|
192
|
+
reason: x.skipped,
|
|
193
|
+
absent: x.absent
|
|
182
194
|
}
|
|
183
195
|
};
|
|
184
|
-
}),
|
|
185
|
-
let i = yield*
|
|
186
|
-
try: () =>
|
|
196
|
+
}), Z = (e, t, n, r) => S.gen(function* () {
|
|
197
|
+
let i = yield* S.tryPromise({
|
|
198
|
+
try: () => P(D(t, "migrations")),
|
|
187
199
|
catch: (e) => e
|
|
188
200
|
});
|
|
189
201
|
if (i.length === 0) return {
|
|
@@ -191,8 +203,8 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
191
203
|
alreadyApplied: [],
|
|
192
204
|
drifted: []
|
|
193
205
|
};
|
|
194
|
-
let a = yield*
|
|
195
|
-
try: () =>
|
|
206
|
+
let a = yield* S.tryPromise({
|
|
207
|
+
try: () => I(i, r),
|
|
196
208
|
catch: (e) => e
|
|
197
209
|
});
|
|
198
210
|
if (a.length === 0) return {
|
|
@@ -200,11 +212,11 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
200
212
|
alreadyApplied: [],
|
|
201
213
|
drifted: []
|
|
202
214
|
};
|
|
203
|
-
let o = new Map((yield*
|
|
215
|
+
let o = new Map((yield* z(e)).map((e) => [e.id, e.hash])), s = B(o, a), c = s.length >= 32 ? /* @__PURE__ */ new Map() : void 0;
|
|
204
216
|
if (c !== void 0) for (let e of a) c.has(e.migration.id) || c.set(e.migration.id, e);
|
|
205
217
|
for (let e of s) {
|
|
206
218
|
let t = c === void 0 ? a.find((t) => t.migration.id === e) : c.get(e), n = `${t?.file ?? e}:${t?.hash ?? ""}`;
|
|
207
|
-
|
|
219
|
+
V.has(n) || (V.add(n), k.warn("file migration: the body on disk is not the one that was applied — the file no longer describes this database", {
|
|
208
220
|
id: e,
|
|
209
221
|
file: t?.file
|
|
210
222
|
}));
|
|
@@ -215,11 +227,11 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
215
227
|
alreadyApplied: l.filter((e) => o.has(e.migration.id)),
|
|
216
228
|
drifted: s
|
|
217
229
|
};
|
|
218
|
-
}),
|
|
230
|
+
}), Q = (e, t, n, r) => Z(e, t, n, r).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), ee = (e, t, n) => Z(e, t, n).pipe(S.map((e) => e.pending.map((e) => ({
|
|
219
231
|
id: e.migration.id,
|
|
220
232
|
phase: e.migration.phase,
|
|
221
|
-
irreversible:
|
|
222
|
-
})))),
|
|
233
|
+
irreversible: l(e.migration.down)
|
|
234
|
+
})))), te = (e, t) => Z(e, t).pipe(S.map((e) => {
|
|
223
235
|
let t = new Set(e.drifted);
|
|
224
236
|
return [...e.alreadyApplied.map((e) => ({
|
|
225
237
|
id: e.migration.id,
|
|
@@ -232,17 +244,19 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
232
244
|
applied: !1,
|
|
233
245
|
bodyChanged: !1
|
|
234
246
|
}))].sort((e, t) => e.id < t.id ? -1 : 1);
|
|
235
|
-
})),
|
|
236
|
-
let { pending: n, alreadyApplied: r } = yield*
|
|
247
|
+
})), ne = (e, t) => S.gen(function* () {
|
|
248
|
+
let { pending: n, alreadyApplied: r } = yield* Z(e, t.projectRoot, t.phase), i = r.map((e) => e.migration.id);
|
|
237
249
|
if (n.length === 0) return {
|
|
238
250
|
applied: [],
|
|
239
251
|
skipped: i,
|
|
240
252
|
skips: []
|
|
241
253
|
};
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
254
|
+
let a = G(p(e), n.map((e) => e.migration.id));
|
|
255
|
+
if (a.length > 0) return yield* S.fail(new K(p(e), a));
|
|
256
|
+
yield* _(e, p(e), t.charset);
|
|
257
|
+
let o = yield* S.acquireUseRelease(d(e, { schema: t.lockSchema }), (r) => S.gen(function* () {
|
|
258
|
+
let i = new Set((yield* z(e)).map((e) => e.id)), a = n.filter((e) => !i.has(e.migration.id));
|
|
259
|
+
a.length < n.length && (yield* S.logInfo("file-based migrations applied by another process while this one waited for the migration lock").pipe(S.annotateLogs({
|
|
246
260
|
scope: "voltro:migrate",
|
|
247
261
|
ids: n.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id).join(",")
|
|
248
262
|
})));
|
|
@@ -250,17 +264,17 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
250
264
|
a.length > 0 && t.beforeExecute !== void 0 && (yield* t.beforeExecute);
|
|
251
265
|
let s = [];
|
|
252
266
|
for (let n of a) {
|
|
253
|
-
yield*
|
|
267
|
+
yield* S.logInfo("file-based migration applying").pipe(S.annotateLogs({
|
|
254
268
|
scope: "voltro:migrate",
|
|
255
269
|
id: n.migration.id,
|
|
256
270
|
file: n.file,
|
|
257
271
|
phase: n.migration.phase
|
|
258
272
|
}));
|
|
259
|
-
let { durationMs: i, skip: a } = yield*
|
|
273
|
+
let { durationMs: i, skip: a } = yield* X(e, t.store, n, t.env, t.appliedBy, t.enclosed === !0, t.charset, r.connection);
|
|
260
274
|
o.push({
|
|
261
275
|
id: n.migration.id,
|
|
262
276
|
durationMs: i
|
|
263
|
-
}), a !== void 0 && s.push(a), yield*
|
|
277
|
+
}), a !== void 0 && s.push(a), yield* S.logInfo("file-based migration applied").pipe(S.annotateLogs({
|
|
264
278
|
scope: "voltro:migrate",
|
|
265
279
|
id: n.migration.id,
|
|
266
280
|
durationMs: i,
|
|
@@ -271,39 +285,39 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
271
285
|
done: o,
|
|
272
286
|
skips: s
|
|
273
287
|
};
|
|
274
|
-
}), (e) => e.release.pipe(
|
|
288
|
+
}), (e) => e.release.pipe(S.orDie));
|
|
275
289
|
return {
|
|
276
|
-
applied:
|
|
290
|
+
applied: o.done,
|
|
277
291
|
skipped: i,
|
|
278
|
-
skips:
|
|
292
|
+
skips: o.skips
|
|
279
293
|
};
|
|
280
|
-
}),
|
|
294
|
+
}), $ = (e, t) => e`
|
|
281
295
|
SELECT ${e("id")}
|
|
282
296
|
FROM ${e("_voltro_migration_plans")}
|
|
283
297
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
284
|
-
`,
|
|
285
|
-
if (!(yield*
|
|
286
|
-
let n = yield*
|
|
287
|
-
try: () =>
|
|
298
|
+
`, re = (e, t) => S.gen(function* () {
|
|
299
|
+
if (!(yield* $(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
300
|
+
let n = yield* S.tryPromise({
|
|
301
|
+
try: () => P(D(t.projectRoot, "migrations")),
|
|
288
302
|
catch: (e) => e
|
|
289
|
-
}), r = (yield*
|
|
290
|
-
try: () =>
|
|
303
|
+
}), r = (yield* S.tryPromise({
|
|
304
|
+
try: () => I(n),
|
|
291
305
|
catch: (e) => e
|
|
292
306
|
})).find((e) => e.migration.id === t.id);
|
|
293
|
-
if (!r) return yield*
|
|
294
|
-
let
|
|
295
|
-
return
|
|
296
|
-
if ((yield*
|
|
297
|
-
let n = Date.now(), { ctx: i } =
|
|
307
|
+
if (!r) return yield* S.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
308
|
+
let i = l(r.migration.down);
|
|
309
|
+
return i === void 0 ? yield* S.acquireUseRelease(d(e, { schema: t.lockSchema }), () => S.gen(function* () {
|
|
310
|
+
if ((yield* $(e, t.id))[0] === void 0) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} was rolled back by another process while this one waited for the migration lock — nothing to do`));
|
|
311
|
+
let n = Date.now(), { ctx: i } = b({
|
|
298
312
|
sql: e,
|
|
299
313
|
store: t.store,
|
|
300
|
-
dialect:
|
|
314
|
+
dialect: p(e),
|
|
301
315
|
migrationId: t.id,
|
|
302
316
|
appliedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
303
317
|
});
|
|
304
318
|
t.beforeExecute !== void 0 && (yield* t.beforeExecute);
|
|
305
319
|
let a = r.migration.down(i);
|
|
306
|
-
|
|
320
|
+
S.isEffect(a) ? yield* a : yield* S.tryPromise({
|
|
307
321
|
try: () => a,
|
|
308
322
|
catch: (e) => e
|
|
309
323
|
});
|
|
@@ -312,7 +326,7 @@ var O = w({ scope: "voltro:migrate" }), k = (e) => S("sha256").update(e).digest(
|
|
|
312
326
|
id: t.id,
|
|
313
327
|
durationMs: o
|
|
314
328
|
};
|
|
315
|
-
}), (e) => e.release.pipe(
|
|
329
|
+
}), (e) => e.release.pipe(S.orDie)) : yield* S.fail(new a(t.id, i));
|
|
316
330
|
});
|
|
317
331
|
//#endregion
|
|
318
|
-
export {
|
|
332
|
+
export { i as FILE_MIGRATION_PATTERN, j as FRAMEWORK_MIGRATION_EDITS, U as FileMigrationLedgerError, K as MigrationIdTooLongError, M as acceptedBodyHashes, R as appliedFileMigrationIds, z as appliedFileMigrations, te as fileMigrationStatus, A as migrationBodyHash, Q as pendingFileMigrationIds, ee as pendingFileMigrationSummary, re as rollbackFileBasedMigration, ne as runFileBasedMigrations, G as unrecordableMigrationIds, P as walkMigrationFiles };
|