@voltro/data-transfer 0.43.2 → 0.44.1
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 +50 -0
- package/dist/index.d.ts +51 -1
- package/dist/index.js +435 -392
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,16 +2,16 @@ import { Cause as e, Data as t, Effect as n, Exit as r, Metric as i, MetricBound
|
|
|
2
2
|
import { classifyConstraintViolation as l, eq as u, extractDbCause as d, inSet as f, isNotNull as p, or as m, streamTable as h } from "@voltro/database";
|
|
3
3
|
import { fingerprintSchema as g } from "@voltro/database/sql";
|
|
4
4
|
import { createCipheriv as _, createDecipheriv as v, createHash as y, createHmac as b, randomBytes as x, scrypt as S } from "node:crypto";
|
|
5
|
-
import { STORAGE_REFS_TABLE as C, fromNodeReadable as w, getObjectStream as T, putObjectStream as
|
|
6
|
-
import * as
|
|
7
|
-
import { PassThrough as
|
|
8
|
-
import { copyFile as
|
|
9
|
-
import { mkdir as
|
|
10
|
-
import { basename as
|
|
11
|
-
import { promisify as
|
|
12
|
-
import { spawn as
|
|
5
|
+
import { STORAGE_REFS_TABLE as C, fromNodeReadable as w, getObjectStream as T, putObjectStream as E, toNodeReadable as D } from "@voltro/plugin-storage";
|
|
6
|
+
import * as O from "node:zlib";
|
|
7
|
+
import { PassThrough as k, Readable as ee } from "node:stream";
|
|
8
|
+
import { copyFile as A, createReadStream as j, createWriteStream as M, existsSync as te, unlinkSync as ne } from "node:fs";
|
|
9
|
+
import { mkdir as re, readdir as ie, stat as ae } from "node:fs/promises";
|
|
10
|
+
import { basename as oe, delimiter as se, dirname as ce, join as N, resolve as le, sep as ue } from "node:path";
|
|
11
|
+
import { promisify as de } from "node:util";
|
|
12
|
+
import { spawn as fe } from "node:child_process";
|
|
13
13
|
//#region src/consistency.ts
|
|
14
|
-
var
|
|
14
|
+
var pe = (e) => {
|
|
15
15
|
switch (e) {
|
|
16
16
|
case "postgres": return ["SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"];
|
|
17
17
|
case "mysql":
|
|
@@ -21,7 +21,7 @@ var _e = (e) => {
|
|
|
21
21
|
case "turso": return [];
|
|
22
22
|
default: return [];
|
|
23
23
|
}
|
|
24
|
-
},
|
|
24
|
+
}, me = {
|
|
25
25
|
email: { fake: "email" },
|
|
26
26
|
fullName: { fake: "fullName" },
|
|
27
27
|
firstName: { fake: "firstName" },
|
|
@@ -36,7 +36,7 @@ var _e = (e) => {
|
|
|
36
36
|
date: "dateShift",
|
|
37
37
|
secret: "null",
|
|
38
38
|
freeText: "redact"
|
|
39
|
-
},
|
|
39
|
+
}, he = (e) => {
|
|
40
40
|
let t = {};
|
|
41
41
|
for (let n of e.tables) {
|
|
42
42
|
let e = {};
|
|
@@ -48,15 +48,15 @@ var _e = (e) => {
|
|
|
48
48
|
t[n.name] = e;
|
|
49
49
|
}
|
|
50
50
|
return t;
|
|
51
|
-
},
|
|
51
|
+
}, ge = (e, t, n, r) => {
|
|
52
52
|
let i = r.columns?.[`${e}.${t}`];
|
|
53
53
|
if (i) return i;
|
|
54
54
|
if (n?.sensitive) {
|
|
55
55
|
let e = n.sensitive.class;
|
|
56
|
-
return r.classes?.[e] ??
|
|
56
|
+
return r.classes?.[e] ?? me[e] ?? "redact";
|
|
57
57
|
}
|
|
58
58
|
return n?.safe ? r.onSafe ?? "keep" : n?.columnType === "id" || n?.columnType === "reference" ? "keep" : r.onUnclassified ?? "error";
|
|
59
|
-
},
|
|
59
|
+
}, _e = (e, t) => b("sha256", e).update(t == null ? "∅" : String(t)).digest(), P = (e, t) => e.readUInt32BE(t * 4 % (e.length - 4)), F = [
|
|
60
60
|
"Ada",
|
|
61
61
|
"Alan",
|
|
62
62
|
"Grace",
|
|
@@ -69,7 +69,7 @@ var _e = (e) => {
|
|
|
69
69
|
"Guido",
|
|
70
70
|
"Margaret",
|
|
71
71
|
"Bjarne"
|
|
72
|
-
],
|
|
72
|
+
], ve = [
|
|
73
73
|
"Lovelace",
|
|
74
74
|
"Turing",
|
|
75
75
|
"Hopper",
|
|
@@ -82,7 +82,7 @@ var _e = (e) => {
|
|
|
82
82
|
"Rossum",
|
|
83
83
|
"Hamilton",
|
|
84
84
|
"Stroustrup"
|
|
85
|
-
],
|
|
85
|
+
], ye = [
|
|
86
86
|
"Maple",
|
|
87
87
|
"Oak",
|
|
88
88
|
"Cedar",
|
|
@@ -91,7 +91,7 @@ var _e = (e) => {
|
|
|
91
91
|
"Birch",
|
|
92
92
|
"Willow",
|
|
93
93
|
"Ash"
|
|
94
|
-
],
|
|
94
|
+
], be = [
|
|
95
95
|
"Initech",
|
|
96
96
|
"Hooli",
|
|
97
97
|
"Umbrella",
|
|
@@ -100,23 +100,23 @@ var _e = (e) => {
|
|
|
100
100
|
"Soylent",
|
|
101
101
|
"Stark",
|
|
102
102
|
"Wayne"
|
|
103
|
-
],
|
|
104
|
-
let r =
|
|
103
|
+
], I = (e, t, n) => e[P(t, n) % e.length], xe = (e, t, n) => {
|
|
104
|
+
let r = _e(n, `${e}:${String(t)}`), i = P(r, 1) % 1e4;
|
|
105
105
|
switch (e) {
|
|
106
|
-
case "email": return `${F
|
|
107
|
-
case "fullName": return `${F
|
|
108
|
-
case "firstName": return F
|
|
109
|
-
case "lastName": return
|
|
110
|
-
case "username": return `${F
|
|
111
|
-
case "phone": return `+1${String(
|
|
112
|
-
case "address": return `${
|
|
113
|
-
case "company": return
|
|
106
|
+
case "email": return `${I(F, r, 0).toLowerCase()}.${I(ve, r, 2).toLowerCase()}${i}@example.com`;
|
|
107
|
+
case "fullName": return `${I(F, r, 0)} ${I(ve, r, 1)}`;
|
|
108
|
+
case "firstName": return I(F, r, 0);
|
|
109
|
+
case "lastName": return I(ve, r, 1);
|
|
110
|
+
case "username": return `${I(F, r, 0).toLowerCase()}${i}`;
|
|
111
|
+
case "phone": return `+1${String(P(r, 0) % 1e10).padStart(10, "0")}`;
|
|
112
|
+
case "address": return `${P(r, 0) % 9899 + 100} ${I(ye, r, 1)} St`;
|
|
113
|
+
case "company": return I(be, r, 0);
|
|
114
114
|
case "url": return `https://example.com/${r.toString("hex").slice(0, 12)}`;
|
|
115
|
-
case "ip": return `${
|
|
116
|
-
case "creditCard": return
|
|
115
|
+
case "ip": return `${P(r, 0) % 256}.${P(r, 1) % 256}.${P(r, 2) % 256}.${P(r, 3) % 254 + 1}`;
|
|
116
|
+
case "creditCard": return Se(`4${r.toString("hex").replace(/\D/g, "").padEnd(14, "0").slice(0, 14)}`);
|
|
117
117
|
default: return `${e}_${r.toString("hex").slice(0, 8)}`;
|
|
118
118
|
}
|
|
119
|
-
},
|
|
119
|
+
}, Se = (e) => {
|
|
120
120
|
let t = e.slice(0, 15).split("").map(Number), n = 0;
|
|
121
121
|
t.forEach((e, t) => {
|
|
122
122
|
let r = e;
|
|
@@ -124,31 +124,31 @@ var _e = (e) => {
|
|
|
124
124
|
});
|
|
125
125
|
let r = (10 - n % 10) % 10;
|
|
126
126
|
return e.slice(0, 15) + String(r);
|
|
127
|
-
},
|
|
127
|
+
}, Ce = 864e5, we = (e, t) => {
|
|
128
128
|
let n = e instanceof Date ? e.getTime() : Date.parse(String(e));
|
|
129
129
|
if (Number.isNaN(n)) return e;
|
|
130
|
-
let r =
|
|
130
|
+
let r = P(_e(t, "date-shift-offset"), 0) % 730 - 365, i = new Date(n + r * Ce);
|
|
131
131
|
return e instanceof Date ? i : i.toISOString();
|
|
132
|
-
},
|
|
132
|
+
}, Te = (e, t) => {
|
|
133
133
|
if (t.value === null || t.value === void 0) return null;
|
|
134
134
|
if (e === "error") throw Error(`masking: unresolved 'error' action for ${t.table}.${t.column}`);
|
|
135
135
|
if (e === "keep") return t.value;
|
|
136
136
|
if (e === "null") return null;
|
|
137
137
|
if (e === "redact") return t.columnType === "text" || typeof t.value == "string" ? "[redacted]" : null;
|
|
138
|
-
if (e === "hash") return
|
|
139
|
-
if (e === "dateShift") return
|
|
140
|
-
if (typeof e == "object" && "fake" in e) return
|
|
138
|
+
if (e === "hash") return _e(t.seed, t.value).toString("hex").slice(0, 16);
|
|
139
|
+
if (e === "dateShift") return we(t.value, t.seed);
|
|
140
|
+
if (typeof e == "object" && "fake" in e) return xe(e.fake, t.value, t.seed);
|
|
141
141
|
if (typeof e == "object" && "custom" in e) return e.custom(t);
|
|
142
142
|
throw Error(`masking: '${t.table}.${t.column}' resolved to an action this build does not understand (${JSON.stringify(e)}). Refusing to copy the value through. Valid actions: 'keep' | 'null' | 'redact' | 'hash' | 'dateShift' | { fake: '<class>' } | { custom: fn }.`);
|
|
143
|
-
},
|
|
143
|
+
}, Ee = (e) => typeof e == "string" ? e === "keep" || e === "null" || e === "redact" || e === "hash" || e === "dateShift" || e === "error" : typeof e != "object" || !e ? !1 : "fake" in e ? typeof e.fake == "string" : "custom" in e && typeof e.custom == "function", De = (e, t, n) => {
|
|
144
144
|
let r = {}, i = [], a = [];
|
|
145
145
|
for (let o of e) for (let e of o.columns) {
|
|
146
|
-
let s = `${o.name}.${e.name}`, c =
|
|
146
|
+
let s = `${o.name}.${e.name}`, c = ge(o.name, e.name, t[o.name]?.[e.name], n);
|
|
147
147
|
if (c === "error") {
|
|
148
148
|
i.push(s);
|
|
149
149
|
continue;
|
|
150
150
|
}
|
|
151
|
-
if (!
|
|
151
|
+
if (!Ee(c)) {
|
|
152
152
|
a.push({
|
|
153
153
|
column: s,
|
|
154
154
|
action: c
|
|
@@ -200,9 +200,9 @@ var _e = (e) => {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
return r;
|
|
203
|
-
},
|
|
203
|
+
}, Ae = (e, t, n, r, i) => {
|
|
204
204
|
let a = {};
|
|
205
|
-
for (let [o, s] of Object.entries(e)) a[o] =
|
|
205
|
+
for (let [o, s] of Object.entries(e)) a[o] = Te(n[`${t}.${o}`] ?? "keep", {
|
|
206
206
|
value: s,
|
|
207
207
|
table: t,
|
|
208
208
|
column: o,
|
|
@@ -210,17 +210,17 @@ var _e = (e) => {
|
|
|
210
210
|
...i?.[o] ? { columnType: i[o] } : {}
|
|
211
211
|
});
|
|
212
212
|
return a;
|
|
213
|
-
},
|
|
213
|
+
}, L = class extends s.TaggedError()("BundleError", {
|
|
214
214
|
reason: s.String,
|
|
215
215
|
path: s.optional(s.String)
|
|
216
|
-
}) {},
|
|
216
|
+
}) {}, je = class extends s.TaggedError()("CodecError", {
|
|
217
217
|
table: s.String,
|
|
218
218
|
reason: s.String
|
|
219
|
-
}) {},
|
|
219
|
+
}) {}, R = class extends s.TaggedError()("IntegrityError", {
|
|
220
220
|
what: s.String,
|
|
221
221
|
expected: s.String,
|
|
222
222
|
actual: s.String
|
|
223
|
-
}) {},
|
|
223
|
+
}) {}, Me = class extends t.TaggedError("CompressionError") {}, z = class extends s.TaggedError()("ScopeError", { reason: s.String }) {}, Ne = class extends s.TaggedError()("RowsRefusedError", {
|
|
224
224
|
rows: s.Array(s.Struct({
|
|
225
225
|
table: s.String,
|
|
226
226
|
id: s.String,
|
|
@@ -228,30 +228,35 @@ var _e = (e) => {
|
|
|
228
228
|
derived: s.Boolean
|
|
229
229
|
})),
|
|
230
230
|
primaryCount: s.Number,
|
|
231
|
-
totalCount: s.Number
|
|
232
|
-
|
|
231
|
+
totalCount: s.Number,
|
|
232
|
+
byTable: s.Array(s.Struct({
|
|
233
|
+
table: s.String,
|
|
234
|
+
refused: s.Number,
|
|
235
|
+
primary: s.Number
|
|
236
|
+
}))
|
|
237
|
+
}) {}, Pe = class extends s.TaggedError()("SchemaDriftError", {
|
|
233
238
|
bundleFingerprint: s.String,
|
|
234
239
|
targetFingerprint: s.String,
|
|
235
240
|
diff: s.Array(s.String)
|
|
236
|
-
}) {},
|
|
241
|
+
}) {}, B = class extends t.TaggedError("NativeToolError") {
|
|
237
242
|
get message() {
|
|
238
243
|
let e = this.stderr?.trim();
|
|
239
244
|
return `${this.tool}: ${this.reason}${e ? `\n${e}` : ""}`;
|
|
240
245
|
}
|
|
241
|
-
},
|
|
246
|
+
}, Fe = class extends s.TaggedError()("MaskingError", {
|
|
242
247
|
unclassified: s.Array(s.String),
|
|
243
248
|
invalidActions: s.optional(s.Array(s.String))
|
|
244
|
-
}) {},
|
|
249
|
+
}) {}, Ie = class extends s.TaggedError()("ImportModeError", {
|
|
245
250
|
mode: s.String,
|
|
246
251
|
reason: s.String
|
|
247
|
-
}) {},
|
|
252
|
+
}) {}, Le = class extends s.TaggedError()("CrossDialectError", {
|
|
248
253
|
sourceDialect: s.String,
|
|
249
254
|
targetDialect: s.String,
|
|
250
255
|
blocking: s.Array(s.String)
|
|
251
|
-
}) {},
|
|
256
|
+
}) {}, V = (e, t) => e.tables.find((e) => e.name === t)?.columns.find((e) => e.type === "id")?.name ?? "id", Re = (e, t) => (e.tables.find((e) => e.name === t)?.columns ?? []).filter((e) => e.references).map((e) => ({
|
|
252
257
|
col: e.name,
|
|
253
258
|
refTable: e.references.table
|
|
254
|
-
})),
|
|
259
|
+
})), ze = (e, t, r) => n.gen(function* () {
|
|
255
260
|
let i = r.maxDepth ?? 12, a = new Set(r.pinned ?? []), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = (e) => {
|
|
256
261
|
let t = s.get(e) ?? /* @__PURE__ */ new Set();
|
|
257
262
|
return s.set(e, t), t;
|
|
@@ -269,10 +274,10 @@ var _e = (e) => {
|
|
|
269
274
|
for (let t of n) d(t.refTable, e[t.col]);
|
|
270
275
|
};
|
|
271
276
|
}, g = (r, i) => {
|
|
272
|
-
let a = p(r,
|
|
277
|
+
let a = p(r, V(t, r), Re(t, r));
|
|
273
278
|
return c.runForEach(h(e, {
|
|
274
279
|
table: r,
|
|
275
|
-
pk:
|
|
280
|
+
pk: V(t, r),
|
|
276
281
|
...i === void 0 ? {} : { where: i }
|
|
277
282
|
}), (e) => n.sync(() => a(e)));
|
|
278
283
|
}, _ = n.gen(function* () {
|
|
@@ -281,7 +286,7 @@ var _e = (e) => {
|
|
|
281
286
|
l.clear();
|
|
282
287
|
for (let [n, r] of e) {
|
|
283
288
|
let e = [...r].filter((e) => !s.get(n)?.has(e));
|
|
284
|
-
e.length !== 0 && (yield* g(n, f(
|
|
289
|
+
e.length !== 0 && (yield* g(n, f(V(t, n), e)));
|
|
285
290
|
}
|
|
286
291
|
}
|
|
287
292
|
});
|
|
@@ -304,13 +309,13 @@ var _e = (e) => {
|
|
|
304
309
|
}
|
|
305
310
|
}
|
|
306
311
|
return o;
|
|
307
|
-
}),
|
|
312
|
+
}), Be = (e, t) => ({
|
|
308
313
|
tables: [...e.keys()],
|
|
309
314
|
predicateFor: (n) => {
|
|
310
315
|
let r = e.get(n);
|
|
311
|
-
return r ? f(
|
|
316
|
+
return r ? f(V(t, n), [...r]) : void 0;
|
|
312
317
|
}
|
|
313
|
-
}),
|
|
318
|
+
}), H = "tenantId", Ve = (e, t, r) => n.gen(function* () {
|
|
314
319
|
let i = t.tables.map((e) => e.name), a = new Map(t.tables.map((e) => [e.name, e]));
|
|
315
320
|
if (e.kind === "all") return {
|
|
316
321
|
tables: i,
|
|
@@ -318,7 +323,7 @@ var _e = (e) => {
|
|
|
318
323
|
};
|
|
319
324
|
if (e.kind === "tables") {
|
|
320
325
|
let t = e.tables ?? [], r = new Set(i), a = t.filter((e) => !r.has(e));
|
|
321
|
-
if (a.length > 0) return yield* n.fail(new
|
|
326
|
+
if (a.length > 0) return yield* n.fail(new z({ reason: `scope { kind: 'tables' } names ${a.length} table(s) that are not in the schema: ${a.join(", ")}. Refusing to write a bundle that silently omits them. Known tables: ${i.length}.` }));
|
|
322
327
|
let o = new Set(t);
|
|
323
328
|
return {
|
|
324
329
|
tables: i.filter((e) => o.has(e)),
|
|
@@ -326,30 +331,30 @@ var _e = (e) => {
|
|
|
326
331
|
};
|
|
327
332
|
}
|
|
328
333
|
let o = e.tenantId;
|
|
329
|
-
if (o === void 0 || o === "") return yield* n.fail(new
|
|
330
|
-
let s = r.tenantTables ? r.tenantTables.filter((e) => a.has(e)) : i.filter((e) => a.get(e)?.columns.some((e) => e.name ===
|
|
331
|
-
if (s.length === 0) return yield* n.fail(new
|
|
332
|
-
let c = yield*
|
|
333
|
-
seeds: Object.fromEntries(s.map((e) => [e, u(
|
|
334
|
+
if (o === void 0 || o === "") return yield* n.fail(new z({ reason: "scope { kind: 'tenant' } requires a tenantId — pass --tenant <id> (CLI) or scope.tenantId (API). Refusing to fall back to an unfiltered export." }));
|
|
335
|
+
let s = r.tenantTables ? r.tenantTables.filter((e) => a.has(e)) : i.filter((e) => a.get(e)?.columns.some((e) => e.name === H) ?? !1);
|
|
336
|
+
if (s.length === 0) return yield* n.fail(new z({ reason: r.tenantTables ? "tenant scope: none of the provided tenantTables exist in the schema — nothing to filter." : `tenant scope: no table carries a '${H}' column — nothing to filter. A tenant export of a schema without tenant-scoped tables would be the full database; refusing.` }));
|
|
337
|
+
let c = yield* ze(r.store, t, {
|
|
338
|
+
seeds: Object.fromEntries(s.map((e) => [e, u(H, o)])),
|
|
334
339
|
pinned: s,
|
|
335
340
|
children: { roots: s }
|
|
336
341
|
}), l = [...c.entries()].filter(([, e]) => e.size > 0).map(([e]) => e), d = new Set(s);
|
|
337
342
|
return {
|
|
338
343
|
tables: [...s, ...l],
|
|
339
|
-
predicateFor: (e) => d.has(e) ? u(
|
|
344
|
+
predicateFor: (e) => d.has(e) ? u(H, o) : c.has(e) ? f(V(t, e), [...c.get(e)]) : void 0
|
|
340
345
|
};
|
|
341
|
-
}),
|
|
346
|
+
}), He = (e, t) => ({
|
|
342
347
|
list: t,
|
|
343
348
|
open: (t) => T(e, t)
|
|
344
|
-
}),
|
|
345
|
-
write: (t, n, r) =>
|
|
349
|
+
}), Ue = (e) => ({
|
|
350
|
+
write: (t, n, r) => E(e, t, n, r),
|
|
346
351
|
has: (t) => e.head(t).pipe(n.map((e) => e !== null))
|
|
347
|
-
}),
|
|
352
|
+
}), We = (e, t) => n.tryPromise({
|
|
348
353
|
try: async () => {
|
|
349
354
|
let { createWriteStream: n } = await import("node:fs"), r = await import("node:fs/promises"), { createHash: i, randomUUID: a } = await import("node:crypto"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c = await import("node:path"), l = c.join(t, `.tmp-${a()}`), u = i("sha256"), d = 0, f = new s({ transform(e, t, n) {
|
|
350
355
|
u.update(e), d += e.length, n(null, e);
|
|
351
356
|
} });
|
|
352
|
-
await o(await
|
|
357
|
+
await o(await D(e.stream), f, n(l));
|
|
353
358
|
let p = u.digest("hex"), m = c.join(t, p);
|
|
354
359
|
try {
|
|
355
360
|
await r.access(m), await r.rm(l, { force: !0 });
|
|
@@ -362,23 +367,23 @@ var _e = (e) => {
|
|
|
362
367
|
contentType: e.contentType
|
|
363
368
|
};
|
|
364
369
|
},
|
|
365
|
-
catch: (e) => new
|
|
370
|
+
catch: (e) => new L({
|
|
366
371
|
reason: `asset write failed: ${String(e?.message ?? e)}`,
|
|
367
372
|
path: t
|
|
368
373
|
})
|
|
369
|
-
}),
|
|
374
|
+
}), Ge = (e, t, r) => n.gen(function* () {
|
|
370
375
|
let i = yield* n.promise(() => import("node:path")), { createReadStream: a } = yield* n.promise(() => import("node:fs")), { createHash: o } = yield* n.promise(() => import("node:crypto")), s = i.join(t, r.sha256), l = o("sha256"), u = w("bundle", () => a(s)).pipe(c.tap((e) => n.sync(() => l.update(e))));
|
|
371
376
|
yield* e.write(r.key, u, {
|
|
372
377
|
contentType: r.contentType,
|
|
373
378
|
totalSize: r.size
|
|
374
379
|
});
|
|
375
380
|
let d = l.digest("hex");
|
|
376
|
-
if (d !== r.sha256) return yield* n.fail(new
|
|
381
|
+
if (d !== r.sha256) return yield* n.fail(new R({
|
|
377
382
|
what: `asset ${r.key}`,
|
|
378
383
|
expected: r.sha256,
|
|
379
384
|
actual: d
|
|
380
385
|
}));
|
|
381
|
-
}),
|
|
386
|
+
}), Ke = () => typeof O.createZstdCompress == "function", qe = (e) => e === "none" ? "none" : e === "gzip" ? "gzip" : Ke() ? "zstd" : "gzip", Je = (e) => e === "zstd" ? ".zst" : e === "gzip" ? ".gz" : "", Ye = (e) => e === "zstd" ? O.createZstdCompress() : e === "gzip" ? O.createGzip() : new k(), Xe = (e) => e === "zstd" ? O.createZstdDecompress() : e === "gzip" ? O.createGunzip() : new k(), Ze = 1, Qe = s.Struct({
|
|
382
387
|
name: s.String,
|
|
383
388
|
file: s.String,
|
|
384
389
|
rowCount: s.Number,
|
|
@@ -388,11 +393,11 @@ var _e = (e) => {
|
|
|
388
393
|
value: s.String
|
|
389
394
|
}),
|
|
390
395
|
primaryKey: s.String
|
|
391
|
-
}),
|
|
396
|
+
}), $e = s.Struct({
|
|
392
397
|
kind: s.Literal("all", "tenant", "tables"),
|
|
393
398
|
tenantId: s.optional(s.String),
|
|
394
399
|
tables: s.optional(s.Array(s.String))
|
|
395
|
-
}),
|
|
400
|
+
}), et = s.Struct({
|
|
396
401
|
count: s.Number,
|
|
397
402
|
totalBytes: s.Number,
|
|
398
403
|
index: s.optional(s.String)
|
|
@@ -403,23 +408,23 @@ s.Struct({
|
|
|
403
408
|
size: s.Number,
|
|
404
409
|
contentType: s.String
|
|
405
410
|
});
|
|
406
|
-
var
|
|
411
|
+
var tt = s.Struct({
|
|
407
412
|
formatVersion: s.Number,
|
|
408
413
|
createdAt: s.String,
|
|
409
414
|
source: s.Struct({
|
|
410
415
|
dialect: s.String,
|
|
411
416
|
schemaFingerprint: s.String
|
|
412
417
|
}),
|
|
413
|
-
scope:
|
|
418
|
+
scope: $e,
|
|
414
419
|
consistency: s.Literal("live", "snapshot"),
|
|
415
420
|
compression: s.Literal("zstd", "gzip", "none"),
|
|
416
|
-
tables: s.Array(
|
|
417
|
-
assets:
|
|
421
|
+
tables: s.Array(Qe),
|
|
422
|
+
assets: et,
|
|
418
423
|
masking: s.optional(s.Struct({
|
|
419
424
|
policyId: s.optional(s.String),
|
|
420
425
|
transformed: s.Array(s.String)
|
|
421
426
|
}))
|
|
422
|
-
}),
|
|
427
|
+
}), nt = s.encodeSync(s.parseJson(tt)), rt = s.decodeUnknownSync(s.parseJson(tt)), U = "manifest.json", it = "README.md", at = "data", W = "assets", ot = "assets/index.ndjson", st = ".ledger.json", ct = (e) => e.kind === "tenant" ? `tenant \`${e.tenantId}\`` : e.kind === "tables" ? `tables \`${(e.tables ?? []).join(", ")}\`` : "all tables", lt = (e, t) => {
|
|
423
428
|
let n = e.tables.reduce((e, t) => e + t.rowCount, 0), r = e.masking ? `✅ **Masked at the source** — ${e.masking.transformed.length} column(s) transformed${e.masking.policyId ? ` (policy \`${e.masking.policyId}\`)` : ""}. Personal data was replaced with realistic, referentially-consistent fakes before any byte was written.` : "⚠️ **NOT masked — this bundle contains REAL data (PII included).** Treat it as production data: do not copy it into a lower environment or share it without review. To produce a safe copy, re-export under a masking profile (`--profile`).", i = e.masking && e.masking.transformed.length > 0 ? `\n\nMasked columns: ${e.masking.transformed.map((e) => `\`${e}\``).join(", ")}.` : "", a = e.assets.count > 0 ? `${e.assets.count} object(s), ${e.assets.totalBytes} bytes` : "none", o = e.tables.map((e) => `| \`${e.name}\` | ${e.rowCount} |`).join("\n");
|
|
424
429
|
return `# Voltro data export
|
|
425
430
|
|
|
@@ -433,7 +438,7 @@ The machine-readable manifest is \`manifest.json\`; this file is a human summary
|
|
|
433
438
|
| **Format version** | ${e.formatVersion} |
|
|
434
439
|
| **Consistency** | ${e.consistency} |
|
|
435
440
|
| **Compression** | ${e.compression} |
|
|
436
|
-
| **Scope** | ${
|
|
441
|
+
| **Scope** | ${ct(e.scope)} |
|
|
437
442
|
| **Tables** | ${e.tables.length} |
|
|
438
443
|
| **Rows (total)** | ${n} |
|
|
439
444
|
| **Assets** | ${a} |
|
|
@@ -458,39 +463,39 @@ voltro data import <this-directory>
|
|
|
458
463
|
voltro data import <this-directory> --target api --api-url <url> --token <secret>
|
|
459
464
|
\`\`\`
|
|
460
465
|
`;
|
|
461
|
-
},
|
|
466
|
+
}, ut = i.counter("voltro_data_transfer_rows", { description: "Rows exported/imported by @voltro/data-transfer, tagged by phase + table." }), dt = a.exponential({
|
|
462
467
|
start: .01,
|
|
463
468
|
factor: 2,
|
|
464
469
|
count: 16
|
|
465
|
-
}),
|
|
470
|
+
}), ft = i.histogram("voltro_data_transfer_table_seconds", dt, "Per-table export/import duration in seconds, tagged by phase."), G = (e, t) => {
|
|
466
471
|
if (e) try {
|
|
467
472
|
e(t);
|
|
468
473
|
} catch {}
|
|
469
|
-
},
|
|
474
|
+
}, pt = (e, t, r, a, o, s) => n.Do.pipe(n.bind("start", () => n.clockWith((e) => e.currentTimeMillis)), n.bind("result", () => s), n.tap(({ start: r, result: a }) => n.clockWith((e) => e.currentTimeMillis).pipe(n.flatMap((s) => n.zipRight(ft.pipe(i.tagged("phase", e), i.update((s - r) / 1e3)), ut.pipe(i.tagged("phase", e), i.tagged("table", t), i.update(o(a))))))), n.map(({ result: e }) => e), n.withSpan(`data-transfer.${e}.table`, { attributes: {
|
|
470
475
|
table: t,
|
|
471
476
|
index: r,
|
|
472
477
|
tableCount: a,
|
|
473
478
|
phase: e
|
|
474
|
-
} })),
|
|
479
|
+
} })), mt = () => ({
|
|
475
480
|
tables: {},
|
|
476
481
|
assets: {}
|
|
477
|
-
}),
|
|
482
|
+
}), ht = (e) => n.tryPromise(async () => {
|
|
478
483
|
let t = await (await import("node:fs/promises")).readFile(e, "utf8");
|
|
479
484
|
return JSON.parse(t);
|
|
480
|
-
}).pipe(n.orElseSucceed(
|
|
485
|
+
}).pipe(n.orElseSucceed(mt)), K = (e, t) => n.tryPromise({
|
|
481
486
|
try: async () => {
|
|
482
487
|
let n = await import("node:fs/promises"), { randomUUID: r } = await import("node:crypto"), i = `${e}.tmp-${r()}`;
|
|
483
488
|
await n.writeFile(i, JSON.stringify(t)), await n.rename(i, e);
|
|
484
489
|
},
|
|
485
|
-
catch: (t) => new
|
|
490
|
+
catch: (t) => new L({
|
|
486
491
|
reason: `ledger write failed: ${String(t?.message ?? t)}`,
|
|
487
492
|
path: e
|
|
488
493
|
})
|
|
489
|
-
}),
|
|
494
|
+
}), gt = (e, t) => t in e.tables, _t = (e, t) => t in e.assets, vt = /* @__PURE__ */ new Set([
|
|
490
495
|
"json",
|
|
491
496
|
"array",
|
|
492
497
|
"vector"
|
|
493
|
-
]),
|
|
498
|
+
]), yt = (e) => typeof e == "object" && !!e && !Array.isArray(e) && typeof e.$v == "string", bt = (e) => Buffer.from(e).toString("base64"), xt = (e) => new Uint8Array(Buffer.from(e, "base64")), St = (e) => e instanceof Date ? e.toISOString() : typeof e == "number" ? new Date(e).toISOString() : String(e), Ct = (e, t) => e == null ? null : t !== void 0 && vt.has(t) ? e : t === "bytes" ? bt(e) : t === "timestamp" || t === "date" ? St(e) : typeof e == "bigint" ? {
|
|
494
499
|
$v: "bigint",
|
|
495
500
|
d: e.toString()
|
|
496
501
|
} : typeof e == "number" && !Number.isFinite(e) ? {
|
|
@@ -501,30 +506,30 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
501
506
|
d: e.toISOString()
|
|
502
507
|
} : e instanceof Uint8Array ? {
|
|
503
508
|
$v: "bytes",
|
|
504
|
-
d:
|
|
505
|
-
} : e,
|
|
509
|
+
d: bt(e)
|
|
510
|
+
} : e, wt = (e) => {
|
|
506
511
|
switch (e.$v) {
|
|
507
512
|
case "bigint": return BigInt(e.d);
|
|
508
513
|
case "number": return Number(e.d);
|
|
509
514
|
case "date": return new Date(e.d);
|
|
510
|
-
case "bytes": return
|
|
515
|
+
case "bytes": return xt(e.d);
|
|
511
516
|
default: return e;
|
|
512
517
|
}
|
|
513
|
-
},
|
|
518
|
+
}, Tt = (e, t) => e == null ? null : t !== void 0 && vt.has(t) ? e : yt(e) ? wt(e) : t === "bytes" ? xt(e) : t === "timestamp" || t === "date" ? new Date(e) : e, Et = (e, t) => {
|
|
514
519
|
let n = {};
|
|
515
|
-
for (let [r, i] of Object.entries(e)) n[r] =
|
|
520
|
+
for (let [r, i] of Object.entries(e)) n[r] = Ct(i, t[r]);
|
|
516
521
|
return n;
|
|
517
|
-
},
|
|
522
|
+
}, Dt = (e, t) => {
|
|
518
523
|
let n = {};
|
|
519
|
-
for (let [r, i] of Object.entries(e)) n[r] =
|
|
524
|
+
for (let [r, i] of Object.entries(e)) n[r] = Tt(i, t[r]);
|
|
520
525
|
return n;
|
|
521
|
-
},
|
|
522
|
-
try: () =>
|
|
523
|
-
catch: (e) => new
|
|
526
|
+
}, Ot = new TextEncoder(), kt = (e, t) => e.pipe(c.map((e) => Ot.encode(`${JSON.stringify(Et(e, t))}\n`))), At = (e, t, r) => e.pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.mapEffect((e) => n.try({
|
|
527
|
+
try: () => Dt(JSON.parse(e), r),
|
|
528
|
+
catch: (e) => new je({
|
|
524
529
|
table: t,
|
|
525
530
|
reason: String(e?.message ?? e)
|
|
526
531
|
})
|
|
527
|
-
}))),
|
|
532
|
+
}))), jt = (e, t) => {
|
|
528
533
|
let n = new Set(e), r = /* @__PURE__ */ new Map();
|
|
529
534
|
for (let e of t.tables) {
|
|
530
535
|
if (!n.has(e.name)) continue;
|
|
@@ -544,39 +549,39 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
544
549
|
};
|
|
545
550
|
for (let t of e) n.has(t) && s(t);
|
|
546
551
|
return i;
|
|
547
|
-
},
|
|
552
|
+
}, q = (e) => {
|
|
548
553
|
let t = e, n = [];
|
|
549
554
|
typeof t?._tag == "string" && t._tag !== "" && n.push(t._tag);
|
|
550
555
|
let r = typeof t?.message == "string" ? t.message.trim() : "";
|
|
551
|
-
if (r === "" ? t?.cause !== void 0 && t.cause !== null && n.push(
|
|
556
|
+
if (r === "" ? t?.cause !== void 0 && t.cause !== null && n.push(q(t.cause)) : n.push(r), n.length === 0) {
|
|
552
557
|
let t = String(e ?? "").trim();
|
|
553
|
-
return t === "" || t === "[object Object]" ?
|
|
558
|
+
return t === "" || t === "[object Object]" ? Mt(e) : t;
|
|
554
559
|
}
|
|
555
560
|
return n.join(": ");
|
|
556
|
-
},
|
|
561
|
+
}, Mt = (e) => {
|
|
557
562
|
try {
|
|
558
563
|
let t = JSON.stringify(e);
|
|
559
564
|
return t === void 0 || t === "{}" ? "unknown error (no message, cause or tag)" : t;
|
|
560
565
|
} catch {
|
|
561
566
|
return "unknown error (not serialisable)";
|
|
562
567
|
}
|
|
563
|
-
},
|
|
568
|
+
}, Nt = (e, t) => {
|
|
564
569
|
let n = e.tables.find((e) => e.name === t), r = {};
|
|
565
570
|
for (let e of n?.columns ?? []) e.generatedAs === void 0 && (r[e.name] = e.type);
|
|
566
571
|
return r;
|
|
567
|
-
},
|
|
572
|
+
}, Pt = (e, t) => (e.tables.find((e) => e.name === t)?.columns ?? []).filter((e) => e.generatedAs !== void 0).map((e) => e.name), Ft = (e, t) => {
|
|
568
573
|
if (t.length === 0) return e;
|
|
569
574
|
let n = { ...e };
|
|
570
575
|
for (let e of t) delete n[e];
|
|
571
576
|
return n;
|
|
572
|
-
},
|
|
577
|
+
}, It = (e, t) => {
|
|
573
578
|
let n = e.tables.find((e) => e.name === t);
|
|
574
579
|
if (n === void 0) return { refusal: `${t}: not in the schema snapshot, so its primary key is unknown.` };
|
|
575
580
|
let r = n.columns.find((e) => e.type === "id");
|
|
576
581
|
if (r !== void 0) return { column: r.name };
|
|
577
582
|
let i = n.indexes.find((e) => e.name === `${t}_pkey`)?.columns ?? n.primaryKey ?? [];
|
|
578
583
|
return i.length === 1 ? { column: i[0] } : i.length > 1 ? { refusal: `${t}: composite primary key (${i.join(", ")}). Keyset export orders by ONE column; ordering by the first alone would split equal values across pages and drop or duplicate rows. Exclude this table from the scope, or give it a single-column key.` } : { refusal: `${t}: no primary key, so there is no stable order to paginate by. A keyset export would return rows in an order the database may change between pages. Exclude this table from the scope.` };
|
|
579
|
-
},
|
|
584
|
+
}, Lt = (e, t, r) => n.tryPromise({
|
|
580
585
|
try: async () => {
|
|
581
586
|
let { createWriteStream: n } = await import("node:fs"), i = await import("node:fs/promises"), { createHash: a, randomUUID: o } = await import("node:crypto"), { pipeline: s } = await import("node:stream/promises"), { Readable: l, Transform: u } = await import("node:stream"), d = a("sha256"), f = 0, p = new u({ transform(e, t, n) {
|
|
582
587
|
d.update(e);
|
|
@@ -585,7 +590,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
585
590
|
n(null, e);
|
|
586
591
|
} }), m = l.fromWeb(c.toReadableStream(e)), h = `${t}.tmp-${o()}`;
|
|
587
592
|
try {
|
|
588
|
-
await s(m, p,
|
|
593
|
+
await s(m, p, Ye(r), n(h)), await i.rename(h, t);
|
|
589
594
|
} catch (e) {
|
|
590
595
|
throw await i.rm(h, { force: !0 }).catch(() => {}), e;
|
|
591
596
|
}
|
|
@@ -594,27 +599,27 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
594
599
|
checksum: d.digest("hex")
|
|
595
600
|
};
|
|
596
601
|
},
|
|
597
|
-
catch: (e) => new
|
|
598
|
-
reason: `write table failed: ${
|
|
602
|
+
catch: (e) => new L({
|
|
603
|
+
reason: `write table failed: ${q(e)}`,
|
|
599
604
|
path: t
|
|
600
605
|
})
|
|
601
|
-
}),
|
|
606
|
+
}), Rt = (e, t) => n.tryPromise({
|
|
602
607
|
try: async () => {
|
|
603
608
|
await (await import("node:fs/promises")).appendFile(e, `${t}\n`);
|
|
604
609
|
},
|
|
605
|
-
catch: (t) => new
|
|
606
|
-
reason: `append failed: ${
|
|
610
|
+
catch: (t) => new L({
|
|
611
|
+
reason: `append failed: ${q(t)}`,
|
|
607
612
|
path: e
|
|
608
613
|
})
|
|
609
|
-
}),
|
|
614
|
+
}), zt = (e, t) => n.gen(function* () {
|
|
610
615
|
let r = [], i = t.ordered.length;
|
|
611
616
|
for (let a = 0; a < t.ordered.length; a++) {
|
|
612
|
-
let o = t.ordered[a], s =
|
|
613
|
-
if ("refusal" in l) return yield* n.fail(new
|
|
614
|
-
let u = l.column, d = `${
|
|
615
|
-
if (
|
|
617
|
+
let o = t.ordered[a], s = Nt(t.snapshot, o), l = It(t.snapshot, o);
|
|
618
|
+
if ("refusal" in l) return yield* n.fail(new z({ reason: `export: ${l.refusal}` }));
|
|
619
|
+
let u = l.column, d = `${at}/${o}.ndjson${Je(t.compression)}`;
|
|
620
|
+
if (gt(t.ledger, o)) {
|
|
616
621
|
let e = t.ledger.tables[o];
|
|
617
|
-
|
|
622
|
+
G(t.onProgress, {
|
|
618
623
|
phase: "export",
|
|
619
624
|
table: o,
|
|
620
625
|
index: a,
|
|
@@ -632,7 +637,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
632
637
|
});
|
|
633
638
|
continue;
|
|
634
639
|
}
|
|
635
|
-
|
|
640
|
+
G(t.onProgress, {
|
|
636
641
|
phase: "export",
|
|
637
642
|
table: o,
|
|
638
643
|
index: a,
|
|
@@ -646,11 +651,11 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
646
651
|
chunkSize: t.chunkSize,
|
|
647
652
|
retry: t.retry,
|
|
648
653
|
...f === void 0 ? {} : { where: f }
|
|
649
|
-
}), m =
|
|
654
|
+
}), m = Pt(t.snapshot, o), g = m.length === 0 ? p : p.pipe(c.map((e) => Ft(e, m))), _ = t.mask ? g.pipe(c.map((e) => Ae(e, o, t.mask.actions, t.mask.seed, s))) : g, { rowCount: v, checksum: y } = yield* pt("export", o, a, i, (e) => e.rowCount, Lt(kt(_, s), t.bundleFile(d), t.compression));
|
|
650
655
|
t.ledger.tables[o] = {
|
|
651
656
|
rowCount: v,
|
|
652
657
|
checksum: y
|
|
653
|
-
}, yield*
|
|
658
|
+
}, yield* K(t.ledgerPath, t.ledger), G(t.onProgress, {
|
|
654
659
|
phase: "export",
|
|
655
660
|
table: o,
|
|
656
661
|
index: a,
|
|
@@ -668,43 +673,43 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
668
673
|
});
|
|
669
674
|
}
|
|
670
675
|
return r;
|
|
671
|
-
}),
|
|
676
|
+
}), Bt = (e) => ({
|
|
672
677
|
_tag: "RawSqlFragment",
|
|
673
678
|
strings: [e],
|
|
674
679
|
values: []
|
|
675
|
-
}),
|
|
680
|
+
}), Vt = (t, i, a) => n.tryPromise({
|
|
676
681
|
try: () => t.transactional(async (t) => {
|
|
677
|
-
if (t.raw) for (let e of
|
|
682
|
+
if (t.raw) for (let e of pe(i)) await t.raw(Bt(e));
|
|
678
683
|
let o = await n.runPromiseExit(a(t));
|
|
679
684
|
if (r.isFailure(o)) throw Error(e.pretty(o.cause));
|
|
680
685
|
return o.value;
|
|
681
686
|
}),
|
|
682
|
-
catch: (e) => e instanceof
|
|
683
|
-
}),
|
|
684
|
-
let t = e.scope ?? { kind: "all" }, r =
|
|
687
|
+
catch: (e) => e instanceof L ? e : new L({ reason: `snapshot export failed: ${q(e)}` })
|
|
688
|
+
}), Ht = (e) => n.gen(function* () {
|
|
689
|
+
let t = e.scope ?? { kind: "all" }, r = qe(e.compression), i = e.chunkSize ?? 1e3, a = e.retryTimes ?? 5, s = o.exponential("50 millis").pipe(o.jittered, o.intersect(o.recurs(a))), l = yield* n.promise(() => import("node:path")), u = (t) => l.join(e.outDir, t);
|
|
685
690
|
yield* n.tryPromise({
|
|
686
691
|
try: async () => {
|
|
687
692
|
let t = await import("node:fs/promises");
|
|
688
|
-
await t.mkdir(u(
|
|
693
|
+
await t.mkdir(u(at), { recursive: !0 }), e.assets && await t.mkdir(u(W), { recursive: !0 });
|
|
689
694
|
},
|
|
690
|
-
catch: (t) => new
|
|
691
|
-
reason: `mkdir failed: ${
|
|
695
|
+
catch: (t) => new L({
|
|
696
|
+
reason: `mkdir failed: ${q(t)}`,
|
|
692
697
|
path: e.outDir
|
|
693
698
|
})
|
|
694
699
|
});
|
|
695
|
-
let d = u(
|
|
700
|
+
let d = u(st), f = yield* ht(d), p = e.subset ? Be(yield* ze(e.store, e.snapshot, e.subset), e.snapshot) : yield* Ve(t, e.snapshot, {
|
|
696
701
|
store: e.store,
|
|
697
702
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
698
|
-
}), m =
|
|
703
|
+
}), m = jt(p.tables, e.snapshot), h = e.consistency ?? "live", _, v;
|
|
699
704
|
if (e.masking) {
|
|
700
|
-
let t = e.classification ??
|
|
705
|
+
let t = e.classification ?? he(e.snapshot), r = De(m.map((t) => ({
|
|
701
706
|
name: t,
|
|
702
707
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
703
708
|
name: e.name,
|
|
704
709
|
type: e.type
|
|
705
710
|
}))
|
|
706
711
|
})), t, e.masking);
|
|
707
|
-
if (r.unclassified.length > 0 || r.invalid.length > 0) return yield* n.fail(new
|
|
712
|
+
if (r.unclassified.length > 0 || r.invalid.length > 0) return yield* n.fail(new Fe({
|
|
708
713
|
unclassified: r.unclassified,
|
|
709
714
|
...r.invalid.length > 0 ? { invalidActions: r.invalid.map((e) => `${e.column}: ${JSON.stringify(e.action)}`) } : {}
|
|
710
715
|
}));
|
|
@@ -730,18 +735,18 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
730
735
|
bundleFile: u,
|
|
731
736
|
...v ? { mask: v } : {},
|
|
732
737
|
...e.onProgress ? { onProgress: e.onProgress } : {}
|
|
733
|
-
}, b = h === "snapshot" ? yield*
|
|
738
|
+
}, b = h === "snapshot" ? yield* Vt(e.store, e.dialect, (e) => zt(e, y)) : yield* zt(e.store, y), x = 0, S = 0;
|
|
734
739
|
if (e.assets) {
|
|
735
|
-
let t = u(
|
|
736
|
-
yield* c.runForEach(e.assets.list(), (r) => r.key in f.assets ? n.void : e.assets.open(r.key).pipe(n.flatMap((e) =>
|
|
740
|
+
let t = u(ot);
|
|
741
|
+
yield* c.runForEach(e.assets.list(), (r) => r.key in f.assets ? n.void : e.assets.open(r.key).pipe(n.flatMap((e) => We(e, u(W))), n.flatMap((e) => {
|
|
737
742
|
let i = {
|
|
738
743
|
key: r.key,
|
|
739
744
|
sha256: e.sha256,
|
|
740
745
|
size: e.size,
|
|
741
746
|
contentType: e.contentType
|
|
742
747
|
};
|
|
743
|
-
return x++, S += e.size, f.assets[r.key] = !0,
|
|
744
|
-
}))).pipe(n.mapError((e) => e instanceof
|
|
748
|
+
return x++, S += e.size, f.assets[r.key] = !0, Rt(t, JSON.stringify(i)).pipe(n.andThen(K(d, f)));
|
|
749
|
+
}))).pipe(n.mapError((e) => e instanceof L ? e : new L({ reason: `asset export failed: ${String(e)}` })));
|
|
745
750
|
}
|
|
746
751
|
let C = {
|
|
747
752
|
formatVersion: 1,
|
|
@@ -757,7 +762,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
757
762
|
assets: x > 0 ? {
|
|
758
763
|
count: x,
|
|
759
764
|
totalBytes: S,
|
|
760
|
-
index:
|
|
765
|
+
index: ot
|
|
761
766
|
} : {
|
|
762
767
|
count: 0,
|
|
763
768
|
totalBytes: 0
|
|
@@ -766,23 +771,23 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
766
771
|
};
|
|
767
772
|
return yield* n.tryPromise({
|
|
768
773
|
try: async () => {
|
|
769
|
-
await (await import("node:fs/promises")).writeFile(u(
|
|
774
|
+
await (await import("node:fs/promises")).writeFile(u(U), nt(C));
|
|
770
775
|
},
|
|
771
|
-
catch: (e) => new
|
|
772
|
-
reason: `manifest write failed: ${
|
|
773
|
-
path:
|
|
776
|
+
catch: (e) => new L({
|
|
777
|
+
reason: `manifest write failed: ${q(e)}`,
|
|
778
|
+
path: U
|
|
774
779
|
})
|
|
775
780
|
}), yield* n.tryPromise({
|
|
776
781
|
try: async () => {
|
|
777
782
|
let e = await import("node:fs/promises"), t = await import("node:os");
|
|
778
|
-
await e.writeFile(u(
|
|
783
|
+
await e.writeFile(u(it), lt(C, { hostname: t.hostname() }));
|
|
779
784
|
},
|
|
780
|
-
catch: (e) => new
|
|
781
|
-
reason: `readme write failed: ${
|
|
782
|
-
path:
|
|
785
|
+
catch: (e) => new L({
|
|
786
|
+
reason: `readme write failed: ${q(e)}`,
|
|
787
|
+
path: it
|
|
783
788
|
})
|
|
784
789
|
}), C;
|
|
785
|
-
}),
|
|
790
|
+
}), Ut = (e, t) => {
|
|
786
791
|
let n = new Set(t), r = [];
|
|
787
792
|
for (let t of e.tables) if (!n.has(t.name)) for (let e of t.columns) {
|
|
788
793
|
let i = e.references?.table;
|
|
@@ -793,7 +798,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
793
798
|
});
|
|
794
799
|
}
|
|
795
800
|
return r;
|
|
796
|
-
},
|
|
801
|
+
}, Wt = (e) => {
|
|
797
802
|
let t = /* @__PURE__ */ new Map();
|
|
798
803
|
for (let n of e) t.set(n.from, [...t.get(n.from) ?? [], n]);
|
|
799
804
|
let n = [...t.entries()].map(([e, t]) => {
|
|
@@ -801,7 +806,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
801
806
|
return ` ${e} (${n} row${n === 1 ? "" : "s"}): ${r}`;
|
|
802
807
|
});
|
|
803
808
|
return `replace cannot empty this target: ${t.size} table(s) OUTSIDE the bundle hold rows that reference tables INSIDE it. Emptying the bundle's tables would leave those rows pointing at nothing, and the bundle cannot restore them.\n${n.join("\n")}\nNothing has been deleted. Either re-export with a scope that includes those tables, or use --mode upsert if those rows are meant to survive.`;
|
|
804
|
-
},
|
|
809
|
+
}, Gt = (e) => {
|
|
805
810
|
switch (e) {
|
|
806
811
|
case "id":
|
|
807
812
|
case "text":
|
|
@@ -820,12 +825,12 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
820
825
|
case "raw": return "raw";
|
|
821
826
|
default: return "string";
|
|
822
827
|
}
|
|
823
|
-
},
|
|
828
|
+
}, Kt = {
|
|
824
829
|
vector: /* @__PURE__ */ new Set(["postgres"]),
|
|
825
830
|
array: /* @__PURE__ */ new Set(["postgres"]),
|
|
826
831
|
interval: /* @__PURE__ */ new Set(["postgres"])
|
|
827
|
-
},
|
|
828
|
-
let i =
|
|
832
|
+
}, qt = (e, t, n, r) => {
|
|
833
|
+
let i = Gt(n);
|
|
829
834
|
if (i === "raw") return {
|
|
830
835
|
table: e,
|
|
831
836
|
column: t,
|
|
@@ -833,7 +838,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
833
838
|
severity: "block",
|
|
834
839
|
reason: `raw() is verbatim source-dialect SQL — it cannot be assumed valid on ${r}`
|
|
835
840
|
};
|
|
836
|
-
let a =
|
|
841
|
+
let a = Kt[i];
|
|
837
842
|
return !a || a.has(r) ? null : i === "array" || i === "interval" ? {
|
|
838
843
|
table: e,
|
|
839
844
|
column: t,
|
|
@@ -847,15 +852,15 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
847
852
|
severity: "block",
|
|
848
853
|
reason: `${i} columns require a ${[...a].join("/")} target; ${r} has no compatible column type`
|
|
849
854
|
};
|
|
850
|
-
},
|
|
855
|
+
}, Jt = (e, t, n) => {
|
|
851
856
|
if (t === n) return [];
|
|
852
857
|
let r = [];
|
|
853
858
|
for (let t of e) for (let [e, i] of Object.entries(t.columnTypes)) {
|
|
854
|
-
let a =
|
|
859
|
+
let a = qt(t.name, e, i, n);
|
|
855
860
|
a && r.push(a);
|
|
856
861
|
}
|
|
857
862
|
return r;
|
|
858
|
-
},
|
|
863
|
+
}, Yt = (e) => `[${e.severity}] ${e.table}.${e.column} (${e.type}): ${e.reason}`, Xt = (e) => {
|
|
859
864
|
let t = e.constraint ?? e.column, n = t === void 0 ? "" : ` ${t}`;
|
|
860
865
|
switch (e.kind) {
|
|
861
866
|
case "foreignKey": return `foreign key${n}: the referenced row does not exist (import it first, or check the bundle's table order)`;
|
|
@@ -864,29 +869,37 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
864
869
|
case "notNull": return `not-null constraint${n}: the column requires a value`;
|
|
865
870
|
case "check": return `check constraint${n}: the row does not satisfy it`;
|
|
866
871
|
}
|
|
867
|
-
},
|
|
872
|
+
}, Zt = (e) => {
|
|
868
873
|
let t = [e.dbCode, e.dbErrno ?? e.dbNumber].filter((e) => e !== void 0).map(String);
|
|
869
874
|
return t.length > 0 ? t.join("/") : void 0;
|
|
870
|
-
},
|
|
871
|
-
let t =
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
875
|
+
}, J = "Failed to execute statement", Qt = (e) => {
|
|
876
|
+
let t = (e.split("\n", 1)[0] ?? "").trim();
|
|
877
|
+
for (; t.startsWith("(FiberFailure)");) t = t.slice(14).trim();
|
|
878
|
+
return t === `SqlError: ${J}` ? J : t;
|
|
879
|
+
}, $t = (e) => {
|
|
880
|
+
let t = String(e?.stack ?? e), n = t.length <= 1200 ? t : `${t.slice(0, 1200)}…`, r = (e, t) => ({
|
|
881
|
+
reason: e.length <= 300 ? e : `${e.slice(0, 300)}…`,
|
|
882
|
+
unclassified: t,
|
|
883
|
+
raw: n
|
|
884
|
+
}), i = d(e), a = l(i), o = Zt(i), s = o === void 0 ? "" : ` [${o}]`;
|
|
885
|
+
if (a !== void 0) return r(`${Xt(a)}${s}`, !1);
|
|
886
|
+
let c = typeof i.dbMessage == "string" ? i.dbMessage : void 0, u = e?.message, f = Qt(typeof u == "string" && u.length > 0 ? u : String(e)), p = c !== void 0 && c !== f && !c.startsWith("SqlError:") ? c : f, m = typeof i.dbCauseChain == "string" ? i.dbCauseChain : void 0, h = m !== void 0 && /[←‖]/.test(m) ? ` (via ${m})` : "";
|
|
887
|
+
return r(p === J || p.length === 0 ? `the database refused the write and the driver gave no detail${s}${h}` : `${p}${s}`, p === J || p.length === 0);
|
|
888
|
+
}, en = (e) => $t(e).reason, tn = (e) => {
|
|
876
889
|
let t = d(e), n = l(t);
|
|
877
890
|
if (n?.kind === "foreignKeyInUse") {
|
|
878
|
-
let e = n.constraint ?? n.column, r = e === void 0 ? "" : ` ${e}`, i =
|
|
891
|
+
let e = n.constraint ?? n.column, r = e === void 0 ? "" : ` ${e}`, i = Zt(t);
|
|
879
892
|
return `foreign key${r}: rows elsewhere still reference this table${i === void 0 ? "" : ` [${i}]`}`;
|
|
880
893
|
}
|
|
881
|
-
return
|
|
882
|
-
},
|
|
894
|
+
return en(e);
|
|
895
|
+
}, nn = (e, t) => e.tables.find((e) => e.name === t), rn = (e, t) => new Map((nn(e, t)?.columns ?? []).map((e) => [e.name, e])), an = (e, t) => {
|
|
883
896
|
let n = [];
|
|
884
897
|
for (let r of [...e.tables].sort((e, t) => e.name.localeCompare(t.name))) {
|
|
885
|
-
if (
|
|
898
|
+
if (nn(t, r.name) === void 0) {
|
|
886
899
|
n.push(`table '${r.name}' is in the bundle but MISSING from the target — its rows have nowhere to go`);
|
|
887
900
|
continue;
|
|
888
901
|
}
|
|
889
|
-
let e =
|
|
902
|
+
let e = rn(t, r.name), i = new Map(r.columns.map((e) => [e.name, e]));
|
|
890
903
|
for (let [t, a] of i) {
|
|
891
904
|
let i = e.get(t);
|
|
892
905
|
if (i === void 0) {
|
|
@@ -898,7 +911,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
898
911
|
for (let [t, a] of e) i.has(t) || !a.nullable && !a.hasDefault && n.push(`${r.name}.${t}: the target requires it (NOT NULL, no default) and the bundle carries no value — every row of this table would fail`);
|
|
899
912
|
}
|
|
900
913
|
return n.length > 30 ? [...n.slice(0, 30), `… and ${n.length - 30} more difference(s)`] : n;
|
|
901
|
-
},
|
|
914
|
+
}, on = (e, t, n) => {
|
|
902
915
|
let r = g(t);
|
|
903
916
|
if (r === e || n === void 0) return {
|
|
904
917
|
drifted: !1,
|
|
@@ -906,28 +919,28 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
906
919
|
targetFingerprint: r,
|
|
907
920
|
diff: []
|
|
908
921
|
};
|
|
909
|
-
let i =
|
|
922
|
+
let i = an(n, t);
|
|
910
923
|
return {
|
|
911
924
|
drifted: i.length > 0,
|
|
912
925
|
bundleFingerprint: e,
|
|
913
926
|
targetFingerprint: r,
|
|
914
927
|
diff: i
|
|
915
928
|
};
|
|
916
|
-
},
|
|
929
|
+
}, sn = 200, cn = (e) => n.tryPromise({
|
|
917
930
|
try: async () => {
|
|
918
931
|
let t = await import("node:fs/promises"), n = await import("node:path");
|
|
919
|
-
return
|
|
932
|
+
return rt(await t.readFile(n.join(e, U), "utf8"));
|
|
920
933
|
},
|
|
921
|
-
catch: (e) => new
|
|
934
|
+
catch: (e) => new L({
|
|
922
935
|
reason: `manifest read/parse failed: ${String(e?.message ?? e)}`,
|
|
923
|
-
path:
|
|
936
|
+
path: U
|
|
924
937
|
})
|
|
925
|
-
}),
|
|
926
|
-
let i = yield* n.promise(() => import("node:path")), a = yield*
|
|
927
|
-
if (a.formatVersion !== 1) return yield* n.fail(new
|
|
938
|
+
}), ln = (t) => n.gen(function* () {
|
|
939
|
+
let i = yield* n.promise(() => import("node:path")), a = yield* cn(t.bundleDir);
|
|
940
|
+
if (a.formatVersion !== 1) return yield* n.fail(new L({ reason: `unsupported bundle formatVersion ${a.formatVersion} (expected 1)` }));
|
|
928
941
|
if (t.tables !== void 0) {
|
|
929
942
|
let e = new Set(a.tables.map((e) => e.name)), r = t.tables.filter((t) => !e.has(t));
|
|
930
|
-
if (r.length > 0) return yield* n.fail(new
|
|
943
|
+
if (r.length > 0) return yield* n.fail(new L({ reason: `--tables names ${r.length} table(s) this bundle does not carry: ${r.join(", ")}. The bundle carries: ${[...e].sort().join(", ")}.` }));
|
|
931
944
|
}
|
|
932
945
|
let o = t.tables === void 0 ? void 0 : new Set(t.tables), s = o === void 0 ? a : {
|
|
933
946
|
...a,
|
|
@@ -944,9 +957,9 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
944
957
|
unique: !1,
|
|
945
958
|
hasDefault: !1
|
|
946
959
|
}))
|
|
947
|
-
})) }, r =
|
|
960
|
+
})) }, r = on(s.source.schemaFingerprint, t.targetSnapshot, e);
|
|
948
961
|
if (r.drifted) {
|
|
949
|
-
if (!t.force) return yield* n.fail(new
|
|
962
|
+
if (!t.force) return yield* n.fail(new Pe({
|
|
950
963
|
bundleFingerprint: r.bundleFingerprint,
|
|
951
964
|
targetFingerprint: r.targetFingerprint,
|
|
952
965
|
diff: r.diff
|
|
@@ -955,23 +968,23 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
955
968
|
}
|
|
956
969
|
}
|
|
957
970
|
if (t.targetDialect && t.targetDialect !== s.source.dialect) {
|
|
958
|
-
let e =
|
|
959
|
-
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new
|
|
971
|
+
let e = Jt(s.tables, s.source.dialect, t.targetDialect).filter((e) => e.severity === "block");
|
|
972
|
+
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new Le({
|
|
960
973
|
sourceDialect: s.source.dialect,
|
|
961
974
|
targetDialect: t.targetDialect,
|
|
962
|
-
blocking: e.map(
|
|
975
|
+
blocking: e.map(Yt)
|
|
963
976
|
}));
|
|
964
977
|
}
|
|
965
|
-
let l = t.verify ?? !0, u = t.mode ?? "upsert", d = t.onConflict ?? "skip",
|
|
966
|
-
if (u === "replace" && s.scope.kind !== "all") return yield* n.fail(new
|
|
978
|
+
let l = t.verify ?? !0, u = t.mode ?? "upsert", d = t.atomic ?? u === "replace", f = t.onConflict ?? "skip", m = t.ledgerPath ?? i.join(t.bundleDir, ".import..ledger.json"), h = yield* ht(m);
|
|
979
|
+
if (u === "replace" && s.scope.kind !== "all") return yield* n.fail(new Ie({
|
|
967
980
|
mode: u,
|
|
968
981
|
reason: `replace refuses a partial bundle (scope='${s.scope.kind}') — truncating would delete rows not in the bundle. Use --mode upsert, or re-export with full scope.`
|
|
969
982
|
}));
|
|
970
983
|
if (u === "replace") {
|
|
971
984
|
let e = s.tables.map((e) => e.name), r = t.store.incomingForeignKeys ? yield* n.tryPromise({
|
|
972
985
|
try: () => t.store.incomingForeignKeys(e),
|
|
973
|
-
catch: (e) => new
|
|
974
|
-
}) : t.targetSnapshot === void 0 ? [] :
|
|
986
|
+
catch: (e) => new L({ reason: `foreign-key pre-flight failed: ${tn(e)}` })
|
|
987
|
+
}) : t.targetSnapshot === void 0 ? [] : Ut(t.targetSnapshot, e), i = [], a = /* @__PURE__ */ new Map();
|
|
975
988
|
for (let e of r) {
|
|
976
989
|
if (!a.has(e.from)) {
|
|
977
990
|
let r = yield* n.tryPromise({
|
|
@@ -983,7 +996,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
983
996
|
skip: void 0,
|
|
984
997
|
projection: []
|
|
985
998
|
}),
|
|
986
|
-
catch: () => new
|
|
999
|
+
catch: () => new L({ reason: `unreadable: ${e.from}` })
|
|
987
1000
|
}).pipe(n.map((e) => e.length), n.orElseSucceed(() => 0));
|
|
988
1001
|
a.set(e.from, r);
|
|
989
1002
|
}
|
|
@@ -993,36 +1006,45 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
993
1006
|
rowCount: r
|
|
994
1007
|
});
|
|
995
1008
|
}
|
|
996
|
-
if (i.length > 0) return yield* n.fail(new
|
|
1009
|
+
if (i.length > 0) return yield* n.fail(new Ie({
|
|
997
1010
|
mode: u,
|
|
998
|
-
reason:
|
|
1011
|
+
reason: Wt(i)
|
|
999
1012
|
}));
|
|
1000
1013
|
}
|
|
1001
|
-
if (t.dryRun === !0) return
|
|
1002
|
-
|
|
1014
|
+
if (t.dryRun === !0) return {
|
|
1015
|
+
manifest: s,
|
|
1016
|
+
tablesWritten: 0,
|
|
1017
|
+
rowsWritten: 0,
|
|
1018
|
+
tablesSkipped: 0,
|
|
1019
|
+
rowsSkipped: 0,
|
|
1020
|
+
fullyResumed: !1
|
|
1021
|
+
};
|
|
1022
|
+
let g = /* @__PURE__ */ new Map();
|
|
1003
1023
|
for (let e of t.targetSnapshot?.tables ?? []) {
|
|
1004
1024
|
let t = e.columns.filter((e) => e.generatedAs !== void 0).map((e) => e.name);
|
|
1005
|
-
t.length > 0 &&
|
|
1025
|
+
t.length > 0 && g.set(e.name, t);
|
|
1006
1026
|
}
|
|
1007
|
-
let
|
|
1008
|
-
let n =
|
|
1027
|
+
let _ = (e, t) => {
|
|
1028
|
+
let n = g.get(e);
|
|
1009
1029
|
if (n === void 0) return t;
|
|
1010
1030
|
let r;
|
|
1011
1031
|
for (let e of n) e in t && (r ??= { ...t }, delete r[e]);
|
|
1012
1032
|
return r ?? t;
|
|
1013
|
-
},
|
|
1014
|
-
let
|
|
1015
|
-
return u === "append" ?
|
|
1016
|
-
},
|
|
1033
|
+
}, v = (e, t, n, r = !1) => {
|
|
1034
|
+
let i = t.name, a = t.primaryKey, o = _(i, n);
|
|
1035
|
+
return u === "append" ? f === "fail" ? e.insert(i, o) : e.insertIgnore(i, o, { conflictColumns: [a] }) : u === "replace" ? r ? e.upsert(i, o, { conflictColumns: [a] }) : e.insert(i, o) : e.upsert(i, o, { conflictColumns: [a] });
|
|
1036
|
+
}, y = (e, t) => e.savepoint ? e.savepoint(t) : t(), b = 0, x = (e, n, r) => {
|
|
1037
|
+
r.unclassified && (b++, !(b > 3) && t.onWarn?.(`row refused with no driver detail — table '${e.name}', row '${String(n.id ?? "?")}'. The full rendering follows so the LAYER that refused is on the record; it is logged, never returned. ${r.raw}` + (b === 3 ? " (further unclassified refusals are counted, not logged)" : "")));
|
|
1038
|
+
}, S = (e, t, r = !0) => n.tryPromise({
|
|
1017
1039
|
try: e,
|
|
1018
|
-
catch: (e) =>
|
|
1019
|
-
}).pipe(n.map(() => !0), n.catchAll((e) => n.sync(() => (r && (t.reason = e), !1)))),
|
|
1040
|
+
catch: (e) => $t(e)
|
|
1041
|
+
}).pipe(n.map(() => !0), n.catchAll((e) => n.sync(() => (r && (t.reason = e.reason, x(t.entry, t.row, e)), !1)))), C = (e) => {
|
|
1020
1042
|
let t = Object.entries(e.entry.columnTypes).filter(([t, n]) => n === "reference" && e.row[t] !== null && e.row[t] !== void 0).map(([e]) => e);
|
|
1021
1043
|
if (t.length !== 0) return {
|
|
1022
1044
|
...e.row,
|
|
1023
1045
|
...Object.fromEntries(t.map((e) => [e, null]))
|
|
1024
1046
|
};
|
|
1025
|
-
},
|
|
1047
|
+
}, T = (e) => {
|
|
1026
1048
|
let t = new Set(e.map((e) => String(e.row[e.entry.primaryKey]))), n = (e) => Object.entries(e.entry.columnTypes).some(([n, r]) => {
|
|
1027
1049
|
if (r !== "reference") return !1;
|
|
1028
1050
|
let i = e.row[n];
|
|
@@ -1032,28 +1054,40 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1032
1054
|
id: String(e.row[e.entry.primaryKey]),
|
|
1033
1055
|
reason: e.reason,
|
|
1034
1056
|
derived: n(e)
|
|
1035
|
-
}));
|
|
1036
|
-
|
|
1037
|
-
|
|
1057
|
+
})), i = [...r.filter((e) => !e.derived), ...r.filter((e) => e.derived)], a = /* @__PURE__ */ new Map();
|
|
1058
|
+
for (let e of r) {
|
|
1059
|
+
let t = a.get(e.table) ?? {
|
|
1060
|
+
refused: 0,
|
|
1061
|
+
primary: 0
|
|
1062
|
+
};
|
|
1063
|
+
t.refused++, e.derived || t.primary++, a.set(e.table, t);
|
|
1064
|
+
}
|
|
1065
|
+
return new Ne({
|
|
1066
|
+
rows: i.slice(0, 20),
|
|
1038
1067
|
primaryCount: r.filter((e) => !e.derived).length,
|
|
1039
|
-
totalCount: e.length
|
|
1068
|
+
totalCount: e.length,
|
|
1069
|
+
byTable: [...a.entries()].map(([e, t]) => ({
|
|
1070
|
+
table: e,
|
|
1071
|
+
refused: t.refused,
|
|
1072
|
+
primary: t.primary
|
|
1073
|
+
})).sort((e, t) => t.refused - e.refused || e.table.localeCompare(t.table)).slice(0, 100)
|
|
1040
1074
|
});
|
|
1041
|
-
},
|
|
1075
|
+
}, E = (e, t) => n.gen(function* () {
|
|
1042
1076
|
let r = t, i = [], a = !0;
|
|
1043
1077
|
for (; r.length > 0 && a;) {
|
|
1044
1078
|
a = !1;
|
|
1045
1079
|
let t = [];
|
|
1046
|
-
for (let n of r) (yield*
|
|
1080
|
+
for (let n of r) (yield* S(() => y(e, () => v(e, n.entry, n.row, !0)), n)) ? a = !0 : t.push(n);
|
|
1047
1081
|
if (!a && t.length > 0) for (let n = t.length - 1; n >= 0; n--) {
|
|
1048
|
-
let r = t[n], o =
|
|
1049
|
-
o !== void 0 && (yield*
|
|
1082
|
+
let r = t[n], o = C(r);
|
|
1083
|
+
o !== void 0 && (yield* S(() => y(e, () => v(e, r.entry, o, !0)), r, !1)) && (i.push(r), t.splice(n, 1), a = !0);
|
|
1050
1084
|
}
|
|
1051
1085
|
r = t;
|
|
1052
1086
|
}
|
|
1053
|
-
for (let t of i) (yield*
|
|
1054
|
-
if (r.length > 0) return yield* n.fail(
|
|
1055
|
-
}),
|
|
1056
|
-
if (u === "replace" && !(r &&
|
|
1087
|
+
for (let t of i) (yield* S(() => y(e, () => e.upsert(t.entry.name, t.row, { conflictColumns: [t.entry.primaryKey] })), t)) || (r = [...r, t]);
|
|
1088
|
+
if (r.length > 0) return yield* n.fail(T(r));
|
|
1089
|
+
}), D = !1, O = 0, k = 0, ee = 0, A = 0, M = (e, r) => n.gen(function* () {
|
|
1090
|
+
if (u === "replace" && !(r && h.truncated)) {
|
|
1057
1091
|
let t = [...s.tables].reverse().map((e) => e.name), i = !r, a = e.emptyTables ? () => e.emptyTables(t) : i ? async () => {
|
|
1058
1092
|
for (let t of [...s.tables].reverse()) await e.deleteMany(t.name, { where: p(t.primaryKey) });
|
|
1059
1093
|
} : () => e.transactional(async (e) => {
|
|
@@ -1061,54 +1095,56 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1061
1095
|
});
|
|
1062
1096
|
yield* n.tryPromise({
|
|
1063
1097
|
try: a,
|
|
1064
|
-
catch: (e) => new
|
|
1065
|
-
}), r && (
|
|
1098
|
+
catch: (e) => new L({ reason: `emptying the target for --mode replace failed (nothing was deleted): ${tn(e)}` })
|
|
1099
|
+
}), r && (h.truncated = !0, yield* K(m, h));
|
|
1066
1100
|
}
|
|
1067
|
-
let a = [], o = [],
|
|
1101
|
+
let a = [], o = [], f = [], g = s.tables.length;
|
|
1068
1102
|
for (let p = 0; p < s.tables.length; p++) {
|
|
1069
|
-
let
|
|
1070
|
-
if (r &&
|
|
1071
|
-
|
|
1103
|
+
let _ = s.tables[p];
|
|
1104
|
+
if (r && _.name in h.tables) {
|
|
1105
|
+
f.push(_.name), A++, ee += h.tables[_.name].rowCount, G(t.onProgress, {
|
|
1072
1106
|
phase: "import",
|
|
1073
|
-
table:
|
|
1107
|
+
table: _.name,
|
|
1074
1108
|
index: p,
|
|
1075
|
-
tableCount:
|
|
1109
|
+
tableCount: g,
|
|
1076
1110
|
event: "done",
|
|
1077
|
-
rowsDone:
|
|
1078
|
-
total:
|
|
1111
|
+
rowsDone: h.tables[_.name].rowCount,
|
|
1112
|
+
total: _.rowCount
|
|
1079
1113
|
});
|
|
1080
1114
|
continue;
|
|
1081
1115
|
}
|
|
1082
|
-
let
|
|
1083
|
-
|
|
1116
|
+
let b = i.join(t.bundleDir, _.file);
|
|
1117
|
+
G(t.onProgress, {
|
|
1084
1118
|
phase: "import",
|
|
1085
|
-
table:
|
|
1119
|
+
table: _.name,
|
|
1086
1120
|
index: p,
|
|
1087
|
-
tableCount:
|
|
1121
|
+
tableCount: g,
|
|
1088
1122
|
event: "start",
|
|
1089
1123
|
rowsDone: 0,
|
|
1090
|
-
total:
|
|
1124
|
+
total: _.rowCount
|
|
1091
1125
|
});
|
|
1092
|
-
let
|
|
1093
|
-
let { createHash: r } = yield* n.promise(() => import("node:crypto")), i = r("sha256"), o = 0, l = w("bundle", () =>
|
|
1126
|
+
let S = a.length, C = n.gen(function* () {
|
|
1127
|
+
let { createHash: r } = yield* n.promise(() => import("node:crypto")), i = r("sha256"), o = 0, l = w("bundle", () => j(b).pipe(Xe(s.compression))).pipe(c.tap((e) => n.sync(() => i.update(e)))), f = async (t) => {
|
|
1094
1128
|
let n = {
|
|
1095
|
-
entry:
|
|
1129
|
+
entry: _,
|
|
1096
1130
|
row: t,
|
|
1097
1131
|
reason: ""
|
|
1098
1132
|
};
|
|
1099
1133
|
try {
|
|
1100
|
-
await
|
|
1134
|
+
await y(e, () => v(e, _, t));
|
|
1101
1135
|
} catch (e) {
|
|
1102
|
-
|
|
1136
|
+
let r = $t(e);
|
|
1137
|
+
n.reason = r.reason, x(_, t, r), a.push(n);
|
|
1103
1138
|
}
|
|
1104
|
-
},
|
|
1139
|
+
}, p = yield* n.promise(async () => {
|
|
1105
1140
|
let n = t.copyLoader;
|
|
1106
|
-
if (!n || n.dialect !== "postgres"
|
|
1141
|
+
if (!n || n.dialect !== "postgres") return !1;
|
|
1142
|
+
if (d) return D || (D = !0, t.onWarn?.("bulk COPY is off for this run: it needs its own connection and this import runs in ONE transaction (the default for --mode replace, so a failure mid-load cannot leave the target emptied and unfilled). Pass --no-atomic to trade that guarantee back for COPY.")), !1;
|
|
1107
1143
|
if (u === "replace") return !0;
|
|
1108
1144
|
if (u !== "upsert") return !1;
|
|
1109
1145
|
try {
|
|
1110
1146
|
return (await e.query({
|
|
1111
|
-
table:
|
|
1147
|
+
table: _.name,
|
|
1112
1148
|
predicate: void 0,
|
|
1113
1149
|
order: [],
|
|
1114
1150
|
take: 1,
|
|
@@ -1118,116 +1154,123 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1118
1154
|
} catch {
|
|
1119
1155
|
return !1;
|
|
1120
1156
|
}
|
|
1121
|
-
}),
|
|
1122
|
-
if (
|
|
1123
|
-
let e =
|
|
1124
|
-
|
|
1157
|
+
}), m = Object.keys(_.columnTypes), h = Math.max(1, t.copyBatchSize ?? 5e3), g = [], S = async () => {
|
|
1158
|
+
if (g.length === 0) return;
|
|
1159
|
+
let e = g;
|
|
1160
|
+
g = [];
|
|
1125
1161
|
try {
|
|
1126
1162
|
await t.copyLoader.copyInto({
|
|
1127
|
-
table:
|
|
1128
|
-
columns:
|
|
1129
|
-
columnTypes:
|
|
1163
|
+
table: _.name,
|
|
1164
|
+
columns: m,
|
|
1165
|
+
columnTypes: _.columnTypes,
|
|
1130
1166
|
rows: e
|
|
1131
1167
|
});
|
|
1132
1168
|
} catch (n) {
|
|
1133
|
-
|
|
1134
|
-
for (let t of e) await
|
|
1169
|
+
p = !1, t.onWarn?.(`bulk COPY into ${_.name} failed (${String(n?.message ?? n)}); falling back to per-row writes for this table`);
|
|
1170
|
+
for (let t of e) await f(t);
|
|
1135
1171
|
}
|
|
1136
|
-
},
|
|
1137
|
-
if (
|
|
1138
|
-
let t =
|
|
1139
|
-
|
|
1172
|
+
}, C = Math.max(1, t.savepointBatchSize ?? 200), T = typeof e.savepoint == "function", E = [], O = async () => {
|
|
1173
|
+
if (E.length === 0) return;
|
|
1174
|
+
let t = E;
|
|
1175
|
+
E = [];
|
|
1140
1176
|
try {
|
|
1141
1177
|
await e.savepoint(async () => {
|
|
1142
|
-
for (let n of t) await
|
|
1178
|
+
for (let n of t) await v(e, _, n);
|
|
1143
1179
|
});
|
|
1144
1180
|
} catch {
|
|
1145
|
-
for (let e of t) await
|
|
1181
|
+
for (let e of t) await f(e);
|
|
1146
1182
|
}
|
|
1147
1183
|
};
|
|
1148
|
-
return yield* c.runForEach(
|
|
1149
|
-
if (o++,
|
|
1150
|
-
|
|
1184
|
+
return yield* c.runForEach(At(l, _.name, _.columnTypes), (e) => n.promise(async () => {
|
|
1185
|
+
if (o++, p) {
|
|
1186
|
+
g.push(e), g.length >= h && await S();
|
|
1151
1187
|
return;
|
|
1152
1188
|
}
|
|
1153
|
-
if (
|
|
1154
|
-
|
|
1189
|
+
if (T) {
|
|
1190
|
+
E.push(e), E.length >= C && await O();
|
|
1155
1191
|
return;
|
|
1156
1192
|
}
|
|
1157
|
-
await
|
|
1158
|
-
})), yield* n.promise(
|
|
1193
|
+
await f(e);
|
|
1194
|
+
})), yield* n.promise(O), yield* n.promise(S), {
|
|
1159
1195
|
rowCount: o,
|
|
1160
1196
|
checksum: i.digest("hex")
|
|
1161
1197
|
};
|
|
1162
|
-
}), { rowCount:
|
|
1198
|
+
}), { rowCount: T, checksum: E } = yield* pt("import", _.name, p, g, (e) => e.rowCount, C);
|
|
1163
1199
|
if (l) {
|
|
1164
|
-
if (
|
|
1165
|
-
what: `table ${
|
|
1166
|
-
expected:
|
|
1167
|
-
actual:
|
|
1200
|
+
if (E !== _.checksum) return yield* n.fail(new R({
|
|
1201
|
+
what: `table ${_.name} checksum`,
|
|
1202
|
+
expected: _.checksum,
|
|
1203
|
+
actual: E
|
|
1168
1204
|
}));
|
|
1169
|
-
if (
|
|
1170
|
-
what: `table ${
|
|
1171
|
-
expected: String(
|
|
1172
|
-
actual: String(
|
|
1205
|
+
if (T !== _.rowCount) return yield* n.fail(new R({
|
|
1206
|
+
what: `table ${_.name} rowCount`,
|
|
1207
|
+
expected: String(_.rowCount),
|
|
1208
|
+
actual: String(T)
|
|
1173
1209
|
}));
|
|
1174
1210
|
}
|
|
1175
|
-
|
|
1211
|
+
G(t.onProgress, {
|
|
1176
1212
|
phase: "import",
|
|
1177
|
-
table:
|
|
1213
|
+
table: _.name,
|
|
1178
1214
|
index: p,
|
|
1179
|
-
tableCount:
|
|
1215
|
+
tableCount: g,
|
|
1180
1216
|
event: "done",
|
|
1181
|
-
rowsDone:
|
|
1182
|
-
total:
|
|
1183
|
-
}), r && (a.length >
|
|
1184
|
-
name:
|
|
1185
|
-
rowCount:
|
|
1186
|
-
}) : (
|
|
1187
|
-
rowCount:
|
|
1188
|
-
checksum:
|
|
1189
|
-
}, yield*
|
|
1217
|
+
rowsDone: T,
|
|
1218
|
+
total: _.rowCount
|
|
1219
|
+
}), k++, O += T, r && (a.length > S ? o.push({
|
|
1220
|
+
name: _.name,
|
|
1221
|
+
rowCount: T
|
|
1222
|
+
}) : (h.tables[_.name] = {
|
|
1223
|
+
rowCount: T,
|
|
1224
|
+
checksum: _.checksum
|
|
1225
|
+
}, yield* K(m, h)));
|
|
1190
1226
|
}
|
|
1191
|
-
if (a.length > 0 && (yield*
|
|
1227
|
+
if (a.length > 0 && (yield* E(e, a)), r && o.length > 0) {
|
|
1192
1228
|
for (let e of o) {
|
|
1193
1229
|
let t = s.tables.find((t) => t.name === e.name);
|
|
1194
|
-
|
|
1230
|
+
h.tables[e.name] = {
|
|
1195
1231
|
rowCount: e.rowCount,
|
|
1196
1232
|
checksum: t.checksum
|
|
1197
1233
|
};
|
|
1198
1234
|
}
|
|
1199
|
-
yield*
|
|
1235
|
+
yield* K(m, h);
|
|
1200
1236
|
}
|
|
1201
|
-
if (
|
|
1202
|
-
let e =
|
|
1203
|
-
t.onWarn?.(`resume: ${
|
|
1237
|
+
if (f.length > 0) {
|
|
1238
|
+
let e = f.length === s.tables.length;
|
|
1239
|
+
t.onWarn?.(`resume: ${f.length} of ${s.tables.length} table(s) were already applied by an earlier run of THIS bundle directory, so this run wrote NO rows for them${e ? " — that is every table in the bundle, so nothing was written at all" : ""}. Tables: ${f.join(", ")}. Delete ${m} to force a full re-import.`);
|
|
1204
1240
|
}
|
|
1205
1241
|
});
|
|
1206
|
-
if (
|
|
1242
|
+
if (d ? yield* n.tryPromise({
|
|
1207
1243
|
try: () => t.store.transactional(async (t) => {
|
|
1208
|
-
let i = await n.runPromiseExit(
|
|
1244
|
+
let i = await n.runPromiseExit(M(t, !1));
|
|
1209
1245
|
if (r.isFailure(i)) throw Error(e.pretty(i.cause));
|
|
1210
1246
|
}),
|
|
1211
|
-
catch: (e) => new
|
|
1212
|
-
}) : yield*
|
|
1213
|
-
let e = t.assets, r = i.join(t.bundleDir,
|
|
1214
|
-
yield* c.runForEach(o, (t) => t.key in
|
|
1215
|
-
|
|
1216
|
-
})), n.andThen(
|
|
1247
|
+
catch: (e) => new L({ reason: `atomic import failed (rolled back): ${String(e?.message ?? e)}` })
|
|
1248
|
+
}) : yield* M(t.store, !0), t.assets && s.assets.index && !t.assetsAlreadyRestored) {
|
|
1249
|
+
let e = t.assets, r = i.join(t.bundleDir, W), a = i.join(t.bundleDir, s.assets.index ?? "assets/index.ndjson"), o = w("bundle", () => j(a)).pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.map((e) => JSON.parse(e)));
|
|
1250
|
+
yield* c.runForEach(o, (t) => t.key in h.assets ? n.void : Ge(e, r, t).pipe(n.andThen(n.sync(() => {
|
|
1251
|
+
h.assets[t.key] = !0;
|
|
1252
|
+
})), n.andThen(K(m, h))));
|
|
1217
1253
|
}
|
|
1218
|
-
return
|
|
1219
|
-
|
|
1254
|
+
return {
|
|
1255
|
+
manifest: s,
|
|
1256
|
+
tablesWritten: k,
|
|
1257
|
+
rowsWritten: O,
|
|
1258
|
+
tablesSkipped: A,
|
|
1259
|
+
rowsSkipped: ee,
|
|
1260
|
+
fullyResumed: k === 0 && A > 0
|
|
1261
|
+
};
|
|
1262
|
+
}), un = (e) => e, dn = (e) => {
|
|
1220
1263
|
if (e.allowLive || e.liveInstance === null || e.sameTarget === "different") return { refuse: !1 };
|
|
1221
1264
|
let t = e.targetLabel === void 0 ? "" : ` Target: ${e.targetLabel}.`, n = e.sameTarget === "same" ? " That instance is connected to the SAME database." : " We could not confirm which database that instance is connected to, so this is refused on the conservative reading — an older instance, or one whose connection could not be parsed, reports nothing to compare.";
|
|
1222
1265
|
return {
|
|
1223
1266
|
refuse: !0,
|
|
1224
1267
|
message: `refusing to write into a target with a LIVE instance (${e.liveInstance}).${t}${n} A direct import is an uncoordinated concurrent writer — readers see partial state, the reactive layer either storms or goes stale, and rows race with live writes. Re-run with --allow-live to override, or use a live-safe strategy (shadow-swap for replace, or the api target).`
|
|
1225
1268
|
};
|
|
1226
|
-
}, Y = Buffer.from("VBUNDLE2"),
|
|
1269
|
+
}, Y = Buffer.from("VBUNDLE2"), fn = 0, pn = 1, mn = 2, hn = 32, gn = async (e) => {
|
|
1227
1270
|
let t = [], n = async (r) => {
|
|
1228
1271
|
let i;
|
|
1229
1272
|
try {
|
|
1230
|
-
i = await
|
|
1273
|
+
i = await ie(N(e, r), { withFileTypes: !0 });
|
|
1231
1274
|
} catch {
|
|
1232
1275
|
return;
|
|
1233
1276
|
}
|
|
@@ -1237,21 +1280,21 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1237
1280
|
}
|
|
1238
1281
|
};
|
|
1239
1282
|
return await n(""), t.sort();
|
|
1240
|
-
},
|
|
1283
|
+
}, _n = (e, t) => {
|
|
1241
1284
|
let n = Buffer.from(e, "utf8"), r = Buffer.alloc(5 + n.length + 8);
|
|
1242
|
-
return r.writeUInt8(
|
|
1243
|
-
},
|
|
1285
|
+
return r.writeUInt8(pn, 0), r.writeUInt32BE(n.length, 1), n.copy(r, 5), r.writeBigUInt64BE(BigInt(t), 5 + n.length), r;
|
|
1286
|
+
}, vn = (e, t, n) => {
|
|
1244
1287
|
let r = Buffer.from(e, "utf8"), i = Buffer.from(t, "utf8"), a = Buffer.alloc(5 + r.length + 2 + i.length + 8), o = 0;
|
|
1245
|
-
return a.writeUInt8(
|
|
1288
|
+
return a.writeUInt8(mn, o), o += 1, a.writeUInt32BE(r.length, o), o += 4, r.copy(a, o), o += r.length, a.writeUInt16BE(i.length, o), o += 2, i.copy(a, o), o += i.length, a.writeBigUInt64BE(BigInt(n), o), a;
|
|
1246
1289
|
};
|
|
1247
|
-
async function*
|
|
1290
|
+
async function* yn(e) {
|
|
1248
1291
|
yield new Uint8Array(Y);
|
|
1249
|
-
for (let t of await
|
|
1250
|
-
let n =
|
|
1251
|
-
if (yield new Uint8Array(
|
|
1292
|
+
for (let t of await gn(e.dir)) {
|
|
1293
|
+
let n = N(e.dir, t), r = await ae(n);
|
|
1294
|
+
if (yield new Uint8Array(_n(t, r.size)), r.size > 0) for await (let e of j(n)) yield new Uint8Array(e);
|
|
1252
1295
|
}
|
|
1253
1296
|
if (e.blobs) for await (let t of e.blobs.list()) {
|
|
1254
|
-
yield new Uint8Array(
|
|
1297
|
+
yield new Uint8Array(vn(t.key, t.contentType, t.size));
|
|
1255
1298
|
let n = y("sha256"), r = 0;
|
|
1256
1299
|
for await (let i of e.blobs.open(t.key)) {
|
|
1257
1300
|
let e = Buffer.from(i);
|
|
@@ -1260,11 +1303,11 @@ async function* gn(e) {
|
|
|
1260
1303
|
if (r !== t.size) throw Error(`blob '${t.key}' size mismatch: header ${t.size}, streamed ${r}`);
|
|
1261
1304
|
yield new Uint8Array(n.digest());
|
|
1262
1305
|
}
|
|
1263
|
-
yield new Uint8Array(Buffer.from([
|
|
1306
|
+
yield new Uint8Array(Buffer.from([fn]));
|
|
1264
1307
|
}
|
|
1265
|
-
var
|
|
1266
|
-
let n =
|
|
1267
|
-
await
|
|
1308
|
+
var bn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), xn = (e) => new Promise((t) => e.end(t)), Sn = async (e, t) => {
|
|
1309
|
+
let n = le(t.dir);
|
|
1310
|
+
await re(n, { recursive: !0 });
|
|
1268
1311
|
let r = Buffer.alloc(0), i = e[Symbol.asyncIterator](), a = !1, o = async () => {
|
|
1269
1312
|
let { value: e, done: t } = await i.next();
|
|
1270
1313
|
return t ? (a = !0, !1) : (r = r.length === 0 ? Buffer.from(e) : Buffer.concat([r, Buffer.from(e)]), !0);
|
|
@@ -1279,24 +1322,24 @@ var _n = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), vn
|
|
|
1279
1322
|
for (;;) {
|
|
1280
1323
|
await s(1);
|
|
1281
1324
|
let e = c(1).readUInt8(0);
|
|
1282
|
-
if (e ===
|
|
1283
|
-
if (e ===
|
|
1325
|
+
if (e === fn) return;
|
|
1326
|
+
if (e === pn) {
|
|
1284
1327
|
await s(4);
|
|
1285
1328
|
let e = c(4).readUInt32BE(0);
|
|
1286
1329
|
await s(e);
|
|
1287
1330
|
let t = c(e).toString("utf8");
|
|
1288
1331
|
await s(8);
|
|
1289
|
-
let i = c(8).readBigUInt64BE(0), a =
|
|
1290
|
-
if (a !== n && !a.startsWith(n +
|
|
1291
|
-
await
|
|
1292
|
-
let o =
|
|
1332
|
+
let i = c(8).readBigUInt64BE(0), a = le(n, t);
|
|
1333
|
+
if (a !== n && !a.startsWith(n + ue)) throw Error(`archive path '${t}' escapes the destination`);
|
|
1334
|
+
await re(ce(a), { recursive: !0 });
|
|
1335
|
+
let o = M(a);
|
|
1293
1336
|
for (; i > 0n;) {
|
|
1294
1337
|
r.length === 0 && await s(1);
|
|
1295
1338
|
let e = i < BigInt(r.length) ? Number(i) : r.length;
|
|
1296
|
-
await
|
|
1339
|
+
await bn(o, c(e)), i -= BigInt(e);
|
|
1297
1340
|
}
|
|
1298
|
-
await
|
|
1299
|
-
} else if (e ===
|
|
1341
|
+
await xn(o);
|
|
1342
|
+
} else if (e === mn) {
|
|
1300
1343
|
await s(4);
|
|
1301
1344
|
let e = c(4).readUInt32BE(0);
|
|
1302
1345
|
await s(e);
|
|
@@ -1306,24 +1349,24 @@ var _n = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), vn
|
|
|
1306
1349
|
await s(i);
|
|
1307
1350
|
let a = c(i).toString("utf8");
|
|
1308
1351
|
await s(8);
|
|
1309
|
-
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = y("sha256"), d = new
|
|
1352
|
+
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = y("sha256"), d = new k(), f = l ? Promise.resolve() : t.blobs.write(n, d, {
|
|
1310
1353
|
contentType: a,
|
|
1311
1354
|
size: Number(o)
|
|
1312
1355
|
}), p = o;
|
|
1313
1356
|
for (; p > 0n;) {
|
|
1314
1357
|
r.length === 0 && await s(1);
|
|
1315
1358
|
let e = p < BigInt(r.length) ? Number(p) : r.length, t = c(e);
|
|
1316
|
-
u.update(t), l || await
|
|
1359
|
+
u.update(t), l || await bn(d, t), p -= BigInt(e);
|
|
1317
1360
|
}
|
|
1318
|
-
l ? d.destroy() : await
|
|
1319
|
-
let m = c(
|
|
1361
|
+
l ? d.destroy() : await xn(d), await f, await s(hn);
|
|
1362
|
+
let m = c(hn);
|
|
1320
1363
|
if (!u.digest().equals(m)) throw Error(`blob '${n}' failed integrity (sha mismatch)`);
|
|
1321
1364
|
} else throw Error(`unknown bundle entry kind ${e}`);
|
|
1322
1365
|
}
|
|
1323
1366
|
} finally {
|
|
1324
1367
|
a || await Promise.resolve(i.return?.()).catch(() => void 0);
|
|
1325
1368
|
}
|
|
1326
|
-
},
|
|
1369
|
+
}, Cn = async (e, t) => {
|
|
1327
1370
|
let n = new Set(t), r = /* @__PURE__ */ new Map(), i = Buffer.alloc(0), a = e[Symbol.asyncIterator](), o = async () => {
|
|
1328
1371
|
let { value: e, done: t } = await a.next();
|
|
1329
1372
|
return !t && (i = i.length === 0 ? Buffer.from(e) : Buffer.concat([i, Buffer.from(e)]), !0);
|
|
@@ -1345,8 +1388,8 @@ var _n = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), vn
|
|
|
1345
1388
|
if (!await s(Y.length) || !c(Y.length).equals(Y)) throw Error("not a bundle archive (bad magic)");
|
|
1346
1389
|
for (; await s(1);) {
|
|
1347
1390
|
let e = c(1).readUInt8(0);
|
|
1348
|
-
if (e ===
|
|
1349
|
-
if (e !==
|
|
1391
|
+
if (e === fn || e === mn) break;
|
|
1392
|
+
if (e !== pn) throw Error(`unknown bundle entry kind ${e}`);
|
|
1350
1393
|
if (!await s(4)) break;
|
|
1351
1394
|
let t = c(4).readUInt32BE(0);
|
|
1352
1395
|
if (!await s(t)) break;
|
|
@@ -1356,22 +1399,22 @@ var _n = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), vn
|
|
|
1356
1399
|
if (a === null || n.has(i) && (r.set(i, a), n.delete(i), n.size === 0)) break;
|
|
1357
1400
|
}
|
|
1358
1401
|
return r;
|
|
1359
|
-
},
|
|
1402
|
+
}, wn = (e, t) => Sn(e, {
|
|
1360
1403
|
dir: t,
|
|
1361
|
-
blobs:
|
|
1362
|
-
}),
|
|
1404
|
+
blobs: Tn(t)
|
|
1405
|
+
}), Tn = (e) => {
|
|
1363
1406
|
let t = /* @__PURE__ */ new Set();
|
|
1364
1407
|
return {
|
|
1365
1408
|
has: async (e) => t.has(e),
|
|
1366
1409
|
write: async (n, r, i) => {
|
|
1367
|
-
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c =
|
|
1368
|
-
await
|
|
1410
|
+
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c = N(e, "assets");
|
|
1411
|
+
await re(c, { recursive: !0 });
|
|
1369
1412
|
let l = y("sha256"), u = 0, d = new s({ transform(e, t, n) {
|
|
1370
1413
|
l.update(e), u += e.length, n(null, e);
|
|
1371
|
-
} }), f =
|
|
1372
|
-
await o(r, d,
|
|
1414
|
+
} }), f = N(c, `.tmp-${Date.now()}-${t.size}`);
|
|
1415
|
+
await o(r, d, M(f));
|
|
1373
1416
|
let p = l.digest("hex");
|
|
1374
|
-
await a.rename(f,
|
|
1417
|
+
await a.rename(f, N(c, p)), await a.appendFile(N(c, "index.ndjson"), `${JSON.stringify({
|
|
1375
1418
|
key: n,
|
|
1376
1419
|
sha256: p,
|
|
1377
1420
|
size: u,
|
|
@@ -1379,33 +1422,33 @@ var _n = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), vn
|
|
|
1379
1422
|
})}\n`), t.add(n);
|
|
1380
1423
|
}
|
|
1381
1424
|
};
|
|
1382
|
-
},
|
|
1425
|
+
}, En = de(S), Dn = Buffer.from("VENC1\0\0\0"), On = 32, kn = 16, An = 7, X = 16, jn = 262144, Z = {
|
|
1383
1426
|
N: 32768,
|
|
1384
1427
|
r: 8,
|
|
1385
1428
|
p: 1
|
|
1386
|
-
},
|
|
1429
|
+
}, Mn = 134217728, Q = 43, Nn = (e, t, n) => {
|
|
1387
1430
|
let r = Buffer.alloc(12);
|
|
1388
|
-
return e.copy(r, 0, 0,
|
|
1431
|
+
return e.copy(r, 0, 0, An), r.writeUInt32BE(t >>> 0, An), r.writeUInt8(+!!n, 11), r;
|
|
1389
1432
|
};
|
|
1390
|
-
async function*
|
|
1433
|
+
async function* Pn(e, t) {
|
|
1391
1434
|
if (!t) throw Error("encryptStream: a non-empty passphrase is required");
|
|
1392
|
-
let n = x(
|
|
1435
|
+
let n = x(kn), r = x(An), i = await En(t, n, On, {
|
|
1393
1436
|
...Z,
|
|
1394
|
-
maxmem:
|
|
1437
|
+
maxmem: Mn
|
|
1395
1438
|
}), a = Buffer.alloc(Q);
|
|
1396
|
-
|
|
1439
|
+
Dn.copy(a, 0), a.writeUInt32BE(Z.N, 8), a.writeUInt32BE(Z.r, 12), a.writeUInt32BE(Z.p, 16), n.copy(a, 20), r.copy(a, 36), yield new Uint8Array(a);
|
|
1397
1440
|
let o = 0, s = (e, t) => {
|
|
1398
|
-
let n = _("aes-256-gcm", i,
|
|
1441
|
+
let n = _("aes-256-gcm", i, Nn(r, o, t));
|
|
1399
1442
|
o === 0 && n.setAAD(a);
|
|
1400
1443
|
let s = Buffer.concat([n.update(e), n.final()]), c = n.getAuthTag();
|
|
1401
1444
|
o++;
|
|
1402
1445
|
let l = Buffer.alloc(5 + s.length + X);
|
|
1403
1446
|
return l.writeUInt8(+!!t, 0), l.writeUInt32BE(s.length + X, 1), s.copy(l, 5), c.copy(l, 5 + s.length), new Uint8Array(l);
|
|
1404
1447
|
}, c = Buffer.alloc(0);
|
|
1405
|
-
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length >
|
|
1448
|
+
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length > jn;) yield s(c.subarray(0, jn), !1), c = c.subarray(jn);
|
|
1406
1449
|
yield s(c, !0);
|
|
1407
1450
|
}
|
|
1408
|
-
async function*
|
|
1451
|
+
async function* Fn(e, t) {
|
|
1409
1452
|
if (!t) throw Error("decryptStream: a non-empty passphrase is required");
|
|
1410
1453
|
let n = e[Symbol.asyncIterator](), r = Buffer.alloc(0), i = !1, a = async () => {
|
|
1411
1454
|
let { value: e, done: t } = await n.next();
|
|
@@ -1416,12 +1459,12 @@ async function* Mn(e, t) {
|
|
|
1416
1459
|
};
|
|
1417
1460
|
if (!await o(Q)) throw Error("encrypted bundle truncated (no header)");
|
|
1418
1461
|
let s = r.subarray(0, Q);
|
|
1419
|
-
if (!s.subarray(0, 8).equals(
|
|
1420
|
-
let c = s.readUInt32BE(8), l = s.readUInt32BE(12), u = s.readUInt32BE(16), d = Buffer.from(s.subarray(20, 36)), f = Buffer.from(s.subarray(36, Q)), p = await
|
|
1462
|
+
if (!s.subarray(0, 8).equals(Dn)) throw Error("not an encrypted bundle (bad magic / wrong passphrase target)");
|
|
1463
|
+
let c = s.readUInt32BE(8), l = s.readUInt32BE(12), u = s.readUInt32BE(16), d = Buffer.from(s.subarray(20, 36)), f = Buffer.from(s.subarray(36, Q)), p = await En(t, d, On, {
|
|
1421
1464
|
N: c,
|
|
1422
1465
|
r: l,
|
|
1423
1466
|
p: u,
|
|
1424
|
-
maxmem:
|
|
1467
|
+
maxmem: Mn
|
|
1425
1468
|
});
|
|
1426
1469
|
r = r.subarray(Q);
|
|
1427
1470
|
let m = 0, h = !1;
|
|
@@ -1436,7 +1479,7 @@ async function* Mn(e, t) {
|
|
|
1436
1479
|
if (!await o(5 + t)) throw Error("encrypted bundle truncated (frame body)");
|
|
1437
1480
|
let n = r.subarray(5, 5 + t - X), i = r.subarray(5 + t - X, 5 + t);
|
|
1438
1481
|
r = r.subarray(5 + t);
|
|
1439
|
-
let a = v("aes-256-gcm", p,
|
|
1482
|
+
let a = v("aes-256-gcm", p, Nn(f, m, e));
|
|
1440
1483
|
m === 0 && a.setAAD(s), a.setAuthTag(i);
|
|
1441
1484
|
let c = Buffer.concat([a.update(n), a.final()]);
|
|
1442
1485
|
m++, e && (h = !0), c.length > 0 && (yield new Uint8Array(c));
|
|
@@ -1444,7 +1487,7 @@ async function* Mn(e, t) {
|
|
|
1444
1487
|
}
|
|
1445
1488
|
//#endregion
|
|
1446
1489
|
//#region src/blobStorage.ts
|
|
1447
|
-
var
|
|
1490
|
+
var In = (e, t) => ({
|
|
1448
1491
|
list: () => {
|
|
1449
1492
|
let e = t();
|
|
1450
1493
|
return { async *[Symbol.asyncIterator]() {
|
|
@@ -1457,29 +1500,29 @@ var Nn = (e, t) => ({
|
|
|
1457
1500
|
} };
|
|
1458
1501
|
},
|
|
1459
1502
|
open: (t) => ({ async *[Symbol.asyncIterator]() {
|
|
1460
|
-
let r = await n.runPromise(T(e, t)), i = await
|
|
1503
|
+
let r = await n.runPromise(T(e, t)), i = await D(r.stream);
|
|
1461
1504
|
for await (let e of i) yield e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
1462
1505
|
} })
|
|
1463
|
-
}),
|
|
1506
|
+
}), Ln = (e, t) => In(e, () => h(t, {
|
|
1464
1507
|
table: C,
|
|
1465
1508
|
chunkSize: 500
|
|
1466
1509
|
}).pipe(c.map((e) => ({
|
|
1467
1510
|
key: String(e.key),
|
|
1468
1511
|
contentType: String(e.contentType ?? "application/octet-stream"),
|
|
1469
1512
|
size: Number(e.size ?? 0)
|
|
1470
|
-
})))),
|
|
1513
|
+
})))), Rn = (e) => ({
|
|
1471
1514
|
has: (t) => n.runPromise(e.head(t).pipe(n.map((e) => e !== null))),
|
|
1472
1515
|
write: async (t, r, i) => {
|
|
1473
|
-
let a = w("storage", () =>
|
|
1474
|
-
await n.runPromise(
|
|
1516
|
+
let a = w("storage", () => ee.from(r));
|
|
1517
|
+
await n.runPromise(E(e, t, a, {
|
|
1475
1518
|
contentType: i.contentType,
|
|
1476
1519
|
totalSize: i.size
|
|
1477
1520
|
}));
|
|
1478
1521
|
}
|
|
1479
|
-
}),
|
|
1522
|
+
}), zn = (e, t) => {
|
|
1480
1523
|
let n = t === "dump" ? "mariadb-dump" : "mariadb", r = t === "dump" ? "mysqldump" : "mysql";
|
|
1481
|
-
return e === "mariadb" &&
|
|
1482
|
-
},
|
|
1524
|
+
return e === "mariadb" && Bn(n) ? n : r;
|
|
1525
|
+
}, Bn = (e) => (process.env.PATH ?? "").split(se).filter((e) => e !== "").some((t) => te(N(t, e))), Vn = (e) => {
|
|
1483
1526
|
switch (e) {
|
|
1484
1527
|
case "postgres": return "db.dump";
|
|
1485
1528
|
case "mysql":
|
|
@@ -1489,7 +1532,7 @@ var Nn = (e, t) => ({
|
|
|
1489
1532
|
case "mssql": return "db.bacpac";
|
|
1490
1533
|
default: return "db.dump";
|
|
1491
1534
|
}
|
|
1492
|
-
},
|
|
1535
|
+
}, Hn = (e) => e.filename ?? e.database ?? ((e.url ?? "").replace(/^file:/, "") || "app.sqlite"), $ = (e) => {
|
|
1493
1536
|
if (e.host || e.database) return {
|
|
1494
1537
|
host: e.host ?? "localhost",
|
|
1495
1538
|
port: e.port ?? 3306,
|
|
@@ -1505,7 +1548,7 @@ var Nn = (e, t) => ({
|
|
|
1505
1548
|
password: decodeURIComponent(t.password) || "",
|
|
1506
1549
|
database: t.pathname.replace(/^\//, "") || ""
|
|
1507
1550
|
};
|
|
1508
|
-
},
|
|
1551
|
+
}, Un = (e) => `Server=${e.host},${e.port};Database=${e.database};User ID=${e.username};Password=${e.password};TrustServerCertificate=True`, Wn = (e, t, n) => {
|
|
1509
1552
|
switch (e) {
|
|
1510
1553
|
case "postgres": {
|
|
1511
1554
|
if (t.url) return {
|
|
@@ -1552,7 +1595,7 @@ var Nn = (e, t) => ({
|
|
|
1552
1595
|
let r = $(t);
|
|
1553
1596
|
return {
|
|
1554
1597
|
kind: "spawn",
|
|
1555
|
-
tool:
|
|
1598
|
+
tool: zn(e, "dump"),
|
|
1556
1599
|
args: [
|
|
1557
1600
|
"--single-transaction",
|
|
1558
1601
|
"--routines",
|
|
@@ -1574,7 +1617,7 @@ var Nn = (e, t) => ({
|
|
|
1574
1617
|
case "sqlite":
|
|
1575
1618
|
case "turso": return {
|
|
1576
1619
|
kind: "copy",
|
|
1577
|
-
from:
|
|
1620
|
+
from: Hn(t),
|
|
1578
1621
|
to: n
|
|
1579
1622
|
};
|
|
1580
1623
|
case "mssql": return {
|
|
@@ -1582,7 +1625,7 @@ var Nn = (e, t) => ({
|
|
|
1582
1625
|
tool: "sqlpackage",
|
|
1583
1626
|
args: [
|
|
1584
1627
|
"/Action:Export",
|
|
1585
|
-
`/SourceConnectionString:${
|
|
1628
|
+
`/SourceConnectionString:${Un($({
|
|
1586
1629
|
...t,
|
|
1587
1630
|
port: t.port ?? 1433
|
|
1588
1631
|
}))}`,
|
|
@@ -1590,12 +1633,12 @@ var Nn = (e, t) => ({
|
|
|
1590
1633
|
],
|
|
1591
1634
|
env: {}
|
|
1592
1635
|
};
|
|
1593
|
-
default: throw new
|
|
1636
|
+
default: throw new B({
|
|
1594
1637
|
tool: "backup",
|
|
1595
1638
|
reason: `no native backup for dialect '${e}'`
|
|
1596
1639
|
});
|
|
1597
1640
|
}
|
|
1598
|
-
},
|
|
1641
|
+
}, Gn = (e, t, n) => {
|
|
1599
1642
|
switch (e) {
|
|
1600
1643
|
case "postgres": {
|
|
1601
1644
|
if (t.url) return {
|
|
@@ -1640,7 +1683,7 @@ var Nn = (e, t) => ({
|
|
|
1640
1683
|
let r = $(t);
|
|
1641
1684
|
return {
|
|
1642
1685
|
kind: "spawn",
|
|
1643
|
-
tool:
|
|
1686
|
+
tool: zn(e, "client"),
|
|
1644
1687
|
args: [
|
|
1645
1688
|
"--protocol=TCP",
|
|
1646
1689
|
"-h",
|
|
@@ -1659,14 +1702,14 @@ var Nn = (e, t) => ({
|
|
|
1659
1702
|
case "turso": return {
|
|
1660
1703
|
kind: "copy",
|
|
1661
1704
|
from: n,
|
|
1662
|
-
to:
|
|
1705
|
+
to: Hn(t)
|
|
1663
1706
|
};
|
|
1664
1707
|
case "mssql": return {
|
|
1665
1708
|
kind: "spawn",
|
|
1666
1709
|
tool: "sqlpackage",
|
|
1667
1710
|
args: [
|
|
1668
1711
|
"/Action:Import",
|
|
1669
|
-
`/TargetConnectionString:${
|
|
1712
|
+
`/TargetConnectionString:${Un($({
|
|
1670
1713
|
...t,
|
|
1671
1714
|
port: t.port ?? 1433
|
|
1672
1715
|
}))}`,
|
|
@@ -1674,18 +1717,18 @@ var Nn = (e, t) => ({
|
|
|
1674
1717
|
],
|
|
1675
1718
|
env: {}
|
|
1676
1719
|
};
|
|
1677
|
-
default: throw new
|
|
1720
|
+
default: throw new B({
|
|
1678
1721
|
tool: "restore",
|
|
1679
1722
|
reason: `no native restore for dialect '${e}'`
|
|
1680
1723
|
});
|
|
1681
1724
|
}
|
|
1682
|
-
},
|
|
1683
|
-
|
|
1725
|
+
}, Kn = (e) => e.kind === "copy" ? n.async((t) => {
|
|
1726
|
+
A(e.from, e.to, (r) => t(r ? n.fail(new B({
|
|
1684
1727
|
tool: "copy",
|
|
1685
1728
|
reason: `copy ${e.from} → ${e.to}: ${r.message}`
|
|
1686
1729
|
})) : n.void));
|
|
1687
1730
|
}) : n.async((t) => {
|
|
1688
|
-
let r =
|
|
1731
|
+
let r = fe(e.tool, [...e.args], {
|
|
1689
1732
|
env: {
|
|
1690
1733
|
...process.env,
|
|
1691
1734
|
...e.env
|
|
@@ -1698,14 +1741,14 @@ var Nn = (e, t) => ({
|
|
|
1698
1741
|
}), i = "";
|
|
1699
1742
|
r.stderr?.on("data", (e) => {
|
|
1700
1743
|
i += String(e);
|
|
1701
|
-
}), e.stdoutFile && r.stdout && r.stdout.pipe(
|
|
1744
|
+
}), e.stdoutFile && r.stdout && r.stdout.pipe(M(e.stdoutFile)), e.stdinFile && r.stdin && j(e.stdinFile).pipe(r.stdin);
|
|
1702
1745
|
let a = () => {
|
|
1703
1746
|
if (e.stdoutFile !== void 0) try {
|
|
1704
|
-
|
|
1747
|
+
ne(e.stdoutFile);
|
|
1705
1748
|
} catch {}
|
|
1706
1749
|
};
|
|
1707
1750
|
r.on("error", (r) => {
|
|
1708
|
-
a(), t(n.fail(new
|
|
1751
|
+
a(), t(n.fail(new B({
|
|
1709
1752
|
tool: e.tool,
|
|
1710
1753
|
reason: `failed to launch (is '${e.tool}' installed + on PATH?): ${r.message}`
|
|
1711
1754
|
})));
|
|
@@ -1714,17 +1757,17 @@ var Nn = (e, t) => ({
|
|
|
1714
1757
|
t(n.void);
|
|
1715
1758
|
return;
|
|
1716
1759
|
}
|
|
1717
|
-
a(), t(n.fail(new
|
|
1760
|
+
a(), t(n.fail(new B({
|
|
1718
1761
|
tool: e.tool,
|
|
1719
|
-
reason: `exited with code ${r}` + (e.stdoutFile === void 0 ? "" : ` — the partial ${
|
|
1762
|
+
reason: `exited with code ${r}` + (e.stdoutFile === void 0 ? "" : ` — the partial ${oe(e.stdoutFile)} was removed, so it cannot be mistaken for a backup`),
|
|
1720
1763
|
stderr: i.slice(-2e3)
|
|
1721
1764
|
})));
|
|
1722
1765
|
});
|
|
1723
|
-
}),
|
|
1724
|
-
let t = yield*
|
|
1766
|
+
}), qn = (e) => typeof e == "object" && e ? "fake" in e ? `fake:${e.fake}` : "custom" : String(e), Jn = (e) => n.gen(function* () {
|
|
1767
|
+
let t = yield* Ve(e.scope ?? { kind: "all" }, e.snapshot, {
|
|
1725
1768
|
store: e.store,
|
|
1726
1769
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
1727
|
-
}), r =
|
|
1770
|
+
}), r = jt(t.tables, e.snapshot), i = e.classification ?? he(e.snapshot), a = e.sampleSize ?? 20, o = De(r.map((t) => ({
|
|
1728
1771
|
name: t,
|
|
1729
1772
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
1730
1773
|
name: e.name,
|
|
@@ -1736,7 +1779,7 @@ var Nn = (e, t) => ({
|
|
|
1736
1779
|
table: i,
|
|
1737
1780
|
chunkSize: a,
|
|
1738
1781
|
...r === void 0 ? {} : { where: r }
|
|
1739
|
-
}).pipe(c.take(a), c.runCollect, n.map((e) => [...e])), d = u.map((t) =>
|
|
1782
|
+
}).pipe(c.take(a), c.runCollect, n.map((e) => [...e])), d = u.map((t) => Ae(t, i, o.actions, e.masking.seed));
|
|
1740
1783
|
l.push(...ke(d, i, o.actions));
|
|
1741
1784
|
let f = u[0], p = d[0], m = [];
|
|
1742
1785
|
if (f && p) for (let [e, t] of Object.entries(o.actions)) {
|
|
@@ -1744,7 +1787,7 @@ var Nn = (e, t) => ({
|
|
|
1744
1787
|
let n = e.slice(i.length + 1);
|
|
1745
1788
|
m.push({
|
|
1746
1789
|
column: n,
|
|
1747
|
-
action:
|
|
1790
|
+
action: qn(t),
|
|
1748
1791
|
before: f[n],
|
|
1749
1792
|
after: p[n]
|
|
1750
1793
|
});
|
|
@@ -1759,7 +1802,7 @@ var Nn = (e, t) => ({
|
|
|
1759
1802
|
leaks: l,
|
|
1760
1803
|
unclassified: o.unclassified
|
|
1761
1804
|
};
|
|
1762
|
-
}),
|
|
1805
|
+
}), Yn = (e, t) => {
|
|
1763
1806
|
let n = new Map(t.map((e) => [e.name, e])), r = [], i = {};
|
|
1764
1807
|
for (let t of e) {
|
|
1765
1808
|
let e = n.get(t.name);
|
|
@@ -1814,7 +1857,7 @@ var Nn = (e, t) => ({
|
|
|
1814
1857
|
skipColumns: i,
|
|
1815
1858
|
refuse: r.some((e) => e.verdict === "refuse")
|
|
1816
1859
|
};
|
|
1817
|
-
},
|
|
1860
|
+
}, Xn = (e) => {
|
|
1818
1861
|
if (e.findings.length === 0) return [" schema matches the bundle"];
|
|
1819
1862
|
let t = {
|
|
1820
1863
|
safe: "✓",
|
|
@@ -1825,4 +1868,4 @@ var Nn = (e, t) => ({
|
|
|
1825
1868
|
return n.push(""), n.push(` discarded: ${r("value-dropped")} defaulted: ${r("filled-by-default")} refused: ${r("refuse")}`), e.refuse && (n.push(""), n.push(" REFUSED — no row was written. These are the differences that would make"), n.push(" imported rows WRONG rather than merely incomplete.")), n;
|
|
1826
1869
|
};
|
|
1827
1870
|
//#endregion
|
|
1828
|
-
export {
|
|
1871
|
+
export { W as ASSETS_DIR, ot as ASSET_INDEX_FILE, L as BundleError, je as CodecError, Me as CompressionError, Le as CrossDialectError, at as DATA_DIR, me as DEFAULT_CLASS_ACTIONS, Ze as FORMAT_VERSION, Ie as ImportModeError, R as IntegrityError, st as LEDGER_FILE, U as MANIFEST_FILE, Fe as MaskingError, B as NativeToolError, Ne as RowsRefusedError, sn as SAVEPOINT_BATCH_SIZE, Pe as SchemaDriftError, z as ScopeError, Te as applyAction, dn as assessLiveImport, _t as assetDone, Vn as backupArtifactName, Wn as backupCommand, Gt as canonicalType, Jt as checkPortability, on as checkSchemaDrift, he as classificationFromSnapshot, Yn as classifyImportDrift, Je as compressionExt, ze as computeSubsetIds, rt as decodeManifest, Dt as decodeRow, Tt as decodeValue, Fn as decryptStream, un as defineDataProfile, an as diffSnapshots, Tn as dirBlobSink, mt as emptyLedger, nt as encodeManifest, Et as encodeRow, Ct as encodeValue, Pn as encryptStream, Xn as formatImportDrift, Yt as formatIssue, Ke as hasZstd, Ye as makeCompressor, Xe as makeDecompressor, Ae as maskRow, At as ndjsonToRows, Wt as outsideReferenceRefusal, Ut as outsideReferencesInto, yn as packBundle, Cn as peekBundle, qe as pickCompression, De as planMasking, Jn as previewMasking, ht as readLedger, ge as resolveAction, Ve as resolveScope, Ge as restoreAssetFromCas, Gn as restoreCommand, kt as rowsToNdjson, Ht as runExport, ln as runImport, Kn as runNativeStep, ke as scanForLeaks, Ue as storageAssetSink, He as storageAssetSource, Rn as storageBlobSink, In as storageBlobSource, Ln as storageRefsBlobSource, Be as subsetToScope, gt as tableDone, jt as topoSortTables, Sn as unpackBundle, wn as unpackBundleToDir, We as writeAssetToCas, K as writeLedger };
|