@voltro/data-transfer 0.32.0 → 0.34.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 +2006 -0
- package/THIRD-PARTY-NOTICES.md +1 -29
- package/dist/index.d.ts +15 -5
- package/dist/index.js +296 -276
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -4,14 +4,14 @@ import { fingerprintSchema as m } from "@voltro/database/sql";
|
|
|
4
4
|
import { createCipheriv as h, createDecipheriv as g, createHash as _, createHmac as v, randomBytes as y, scrypt as b } from "node:crypto";
|
|
5
5
|
import { STORAGE_REFS_TABLE as x, fromNodeReadable as S, getObjectStream as C, putObjectStream as ee, toNodeReadable as te } from "@voltro/plugin-storage";
|
|
6
6
|
import * as w from "node:zlib";
|
|
7
|
-
import { PassThrough as
|
|
8
|
-
import { copyFile as
|
|
9
|
-
import { mkdir as
|
|
10
|
-
import { delimiter as
|
|
11
|
-
import { promisify as
|
|
12
|
-
import { spawn as
|
|
7
|
+
import { PassThrough as ne, Readable as re } from "node:stream";
|
|
8
|
+
import { copyFile as ie, createReadStream as T, createWriteStream as ae, existsSync as oe, unlinkSync as se } from "node:fs";
|
|
9
|
+
import { mkdir as ce, readdir as le, stat as ue } from "node:fs/promises";
|
|
10
|
+
import { basename as de, delimiter as fe, dirname as pe, join as E, resolve as me, sep as he } from "node:path";
|
|
11
|
+
import { promisify as ge } from "node:util";
|
|
12
|
+
import { spawn as _e } from "node:child_process";
|
|
13
13
|
//#region src/consistency.ts
|
|
14
|
-
var
|
|
14
|
+
var ve = (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 he = (e) => {
|
|
|
21
21
|
case "turso": return [];
|
|
22
22
|
default: return [];
|
|
23
23
|
}
|
|
24
|
-
},
|
|
24
|
+
}, ye = {
|
|
25
25
|
email: { fake: "email" },
|
|
26
26
|
fullName: { fake: "fullName" },
|
|
27
27
|
firstName: { fake: "firstName" },
|
|
@@ -36,7 +36,7 @@ var he = (e) => {
|
|
|
36
36
|
date: "dateShift",
|
|
37
37
|
secret: "null",
|
|
38
38
|
freeText: "redact"
|
|
39
|
-
},
|
|
39
|
+
}, D = (e) => {
|
|
40
40
|
let t = {};
|
|
41
41
|
for (let n of e.tables) {
|
|
42
42
|
let e = {};
|
|
@@ -48,15 +48,15 @@ var he = (e) => {
|
|
|
48
48
|
t[n.name] = e;
|
|
49
49
|
}
|
|
50
50
|
return t;
|
|
51
|
-
},
|
|
51
|
+
}, be = (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] ?? ye[e] ?? "redact";
|
|
57
57
|
}
|
|
58
58
|
return n?.safe ? r.onSafe ?? "keep" : n?.columnType === "id" || n?.columnType === "reference" ? "keep" : r.onUnclassified ?? "error";
|
|
59
|
-
},
|
|
59
|
+
}, xe = (e, t) => v("sha256", e).update(t == null ? "∅" : String(t)).digest(), O = (e, t) => e.readUInt32BE(t * 4 % (e.length - 4)), k = [
|
|
60
60
|
"Ada",
|
|
61
61
|
"Alan",
|
|
62
62
|
"Grace",
|
|
@@ -69,7 +69,7 @@ var he = (e) => {
|
|
|
69
69
|
"Guido",
|
|
70
70
|
"Margaret",
|
|
71
71
|
"Bjarne"
|
|
72
|
-
],
|
|
72
|
+
], A = [
|
|
73
73
|
"Lovelace",
|
|
74
74
|
"Turing",
|
|
75
75
|
"Hopper",
|
|
@@ -82,7 +82,7 @@ var he = (e) => {
|
|
|
82
82
|
"Rossum",
|
|
83
83
|
"Hamilton",
|
|
84
84
|
"Stroustrup"
|
|
85
|
-
],
|
|
85
|
+
], Se = [
|
|
86
86
|
"Maple",
|
|
87
87
|
"Oak",
|
|
88
88
|
"Cedar",
|
|
@@ -91,7 +91,7 @@ var he = (e) => {
|
|
|
91
91
|
"Birch",
|
|
92
92
|
"Willow",
|
|
93
93
|
"Ash"
|
|
94
|
-
],
|
|
94
|
+
], Ce = [
|
|
95
95
|
"Initech",
|
|
96
96
|
"Hooli",
|
|
97
97
|
"Umbrella",
|
|
@@ -100,23 +100,23 @@ var he = (e) => {
|
|
|
100
100
|
"Soylent",
|
|
101
101
|
"Stark",
|
|
102
102
|
"Wayne"
|
|
103
|
-
],
|
|
104
|
-
let r =
|
|
103
|
+
], j = (e, t, n) => e[O(t, n) % e.length], we = (e, t, n) => {
|
|
104
|
+
let r = xe(n, `${e}:${String(t)}`), i = O(r, 1) % 1e4;
|
|
105
105
|
switch (e) {
|
|
106
|
-
case "email": return `${
|
|
107
|
-
case "fullName": return `${
|
|
108
|
-
case "firstName": return
|
|
109
|
-
case "lastName": return
|
|
110
|
-
case "username": return `${
|
|
111
|
-
case "phone": return `+1${String(
|
|
112
|
-
case "address": return `${
|
|
113
|
-
case "company": return
|
|
106
|
+
case "email": return `${j(k, r, 0).toLowerCase()}.${j(A, r, 2).toLowerCase()}${i}@example.com`;
|
|
107
|
+
case "fullName": return `${j(k, r, 0)} ${j(A, r, 1)}`;
|
|
108
|
+
case "firstName": return j(k, r, 0);
|
|
109
|
+
case "lastName": return j(A, r, 1);
|
|
110
|
+
case "username": return `${j(k, r, 0).toLowerCase()}${i}`;
|
|
111
|
+
case "phone": return `+1${String(O(r, 0) % 1e10).padStart(10, "0")}`;
|
|
112
|
+
case "address": return `${O(r, 0) % 9899 + 100} ${j(Se, r, 1)} St`;
|
|
113
|
+
case "company": return j(Ce, 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 `${O(r, 0) % 256}.${O(r, 1) % 256}.${O(r, 2) % 256}.${O(r, 3) % 254 + 1}`;
|
|
116
|
+
case "creditCard": return Te(`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
|
+
}, Te = (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,26 +124,26 @@ var he = (e) => {
|
|
|
124
124
|
});
|
|
125
125
|
let r = (10 - n % 10) % 10;
|
|
126
126
|
return e.slice(0, 15) + String(r);
|
|
127
|
-
},
|
|
127
|
+
}, Ee = 864e5, De = (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 = O(xe(t, "date-shift-offset"), 0) % 730 - 365, i = new Date(n + r * Ee);
|
|
131
131
|
return e instanceof Date ? i : i.toISOString();
|
|
132
|
-
},
|
|
132
|
+
}, Oe = (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
|
-
return e === "keep" ? t.value : e === "null" ? null : e === "redact" ? t.columnType === "text" || typeof t.value == "string" ? "[redacted]" : null : e === "hash" ?
|
|
136
|
-
},
|
|
135
|
+
return e === "keep" ? t.value : e === "null" ? null : e === "redact" ? t.columnType === "text" || typeof t.value == "string" ? "[redacted]" : null : e === "hash" ? xe(t.seed, t.value).toString("hex").slice(0, 16) : e === "dateShift" ? De(t.value, t.seed) : typeof e == "object" && "fake" in e ? we(e.fake, t.value, t.seed) : typeof e == "object" && "custom" in e ? e.custom(t) : t.value;
|
|
136
|
+
}, M = (e, t, n) => {
|
|
137
137
|
let r = {}, i = [];
|
|
138
138
|
for (let a of e) for (let e of a.columns) {
|
|
139
|
-
let o = `${a.name}.${e.name}`, s =
|
|
139
|
+
let o = `${a.name}.${e.name}`, s = be(a.name, e.name, t[a.name]?.[e.name], n);
|
|
140
140
|
s === "error" ? i.push(o) : r[o] = s;
|
|
141
141
|
}
|
|
142
142
|
return {
|
|
143
143
|
actions: r,
|
|
144
144
|
unclassified: i
|
|
145
145
|
};
|
|
146
|
-
},
|
|
146
|
+
}, ke = [
|
|
147
147
|
{
|
|
148
148
|
name: "email",
|
|
149
149
|
re: /[\w.+-]+@[\w-]+\.[\w.-]+/
|
|
@@ -160,7 +160,7 @@ var he = (e) => {
|
|
|
160
160
|
name: "creditCard",
|
|
161
161
|
re: /\b(?:\d[ -]?){13,16}\b/
|
|
162
162
|
}
|
|
163
|
-
],
|
|
163
|
+
], Ae = (e, t, n) => {
|
|
164
164
|
let r = [], i = /* @__PURE__ */ new Set();
|
|
165
165
|
for (let [a, o] of Object.entries(n)) {
|
|
166
166
|
if (!a.startsWith(`${t}.`) || o !== "keep") continue;
|
|
@@ -168,7 +168,7 @@ var he = (e) => {
|
|
|
168
168
|
for (let a of e) {
|
|
169
169
|
let e = a[n];
|
|
170
170
|
if (typeof e != "string" || e.length === 0) continue;
|
|
171
|
-
let o =
|
|
171
|
+
let o = ke.find((t) => t.re.test(e));
|
|
172
172
|
if (o && !i.has(n)) {
|
|
173
173
|
i.add(n), r.push({
|
|
174
174
|
table: t,
|
|
@@ -181,9 +181,9 @@ var he = (e) => {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
return r;
|
|
184
|
-
},
|
|
184
|
+
}, je = (e, t, n, r, i) => {
|
|
185
185
|
let a = {};
|
|
186
|
-
for (let [o, s] of Object.entries(e)) a[o] =
|
|
186
|
+
for (let [o, s] of Object.entries(e)) a[o] = Oe(n[`${t}.${o}`] ?? "keep", {
|
|
187
187
|
value: s,
|
|
188
188
|
table: t,
|
|
189
189
|
column: o,
|
|
@@ -191,43 +191,43 @@ var he = (e) => {
|
|
|
191
191
|
...i?.[o] ? { columnType: i[o] } : {}
|
|
192
192
|
});
|
|
193
193
|
return a;
|
|
194
|
-
},
|
|
194
|
+
}, N = class extends s.TaggedError()("BundleError", {
|
|
195
195
|
reason: s.String,
|
|
196
196
|
path: s.optional(s.String)
|
|
197
|
-
}) {},
|
|
197
|
+
}) {}, Me = class extends s.TaggedError()("CodecError", {
|
|
198
198
|
table: s.String,
|
|
199
199
|
reason: s.String
|
|
200
|
-
}) {},
|
|
200
|
+
}) {}, P = class extends s.TaggedError()("IntegrityError", {
|
|
201
201
|
what: s.String,
|
|
202
202
|
expected: s.String,
|
|
203
203
|
actual: s.String
|
|
204
|
-
}) {},
|
|
204
|
+
}) {}, Ne = class extends t.TaggedError("CompressionError") {}, F = class extends s.TaggedError()("ScopeError", { reason: s.String }) {}, Pe = class extends s.TaggedError()("DanglingReferenceError", {
|
|
205
205
|
rows: s.Array(s.Struct({
|
|
206
206
|
table: s.String,
|
|
207
207
|
id: s.String,
|
|
208
208
|
reason: s.String
|
|
209
209
|
})),
|
|
210
210
|
totalCount: s.Number
|
|
211
|
-
}) {},
|
|
211
|
+
}) {}, Fe = class extends s.TaggedError()("SchemaDriftError", {
|
|
212
212
|
bundleFingerprint: s.String,
|
|
213
213
|
targetFingerprint: s.String,
|
|
214
214
|
diff: s.Array(s.String)
|
|
215
|
-
}) {},
|
|
215
|
+
}) {}, I = class extends t.TaggedError("NativeToolError") {
|
|
216
216
|
get message() {
|
|
217
217
|
let e = this.stderr?.trim();
|
|
218
218
|
return `${this.tool}: ${this.reason}${e ? `\n${e}` : ""}`;
|
|
219
219
|
}
|
|
220
|
-
},
|
|
220
|
+
}, Ie = class extends s.TaggedError()("MaskingError", { unclassified: s.Array(s.String) }) {}, Le = class extends s.TaggedError()("ImportModeError", {
|
|
221
221
|
mode: s.String,
|
|
222
222
|
reason: s.String
|
|
223
|
-
}) {},
|
|
223
|
+
}) {}, Re = class extends s.TaggedError()("CrossDialectError", {
|
|
224
224
|
sourceDialect: s.String,
|
|
225
225
|
targetDialect: s.String,
|
|
226
226
|
blocking: s.Array(s.String)
|
|
227
|
-
}) {},
|
|
227
|
+
}) {}, L = (e, t) => e.tables.find((e) => e.name === t)?.columns.find((e) => e.type === "id")?.name ?? "id", ze = (e, t) => (e.tables.find((e) => e.name === t)?.columns ?? []).filter((e) => e.references).map((e) => ({
|
|
228
228
|
col: e.name,
|
|
229
229
|
refTable: e.references.table
|
|
230
|
-
})),
|
|
230
|
+
})), Be = (e, t, r) => n.gen(function* () {
|
|
231
231
|
let i = r.maxDepth ?? 12, a = new Set(r.pinned ?? []), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), d = (e) => {
|
|
232
232
|
let t = s.get(e) ?? /* @__PURE__ */ new Set();
|
|
233
233
|
return s.set(e, t), t;
|
|
@@ -245,10 +245,10 @@ var he = (e) => {
|
|
|
245
245
|
for (let t of n) m(t.refTable, e[t.col]);
|
|
246
246
|
};
|
|
247
247
|
}, g = (r, i) => {
|
|
248
|
-
let a = h(r,
|
|
248
|
+
let a = h(r, L(t, r), ze(t, r));
|
|
249
249
|
return c.runForEach(p(e, {
|
|
250
250
|
table: r,
|
|
251
|
-
pk:
|
|
251
|
+
pk: L(t, r),
|
|
252
252
|
...i === void 0 ? {} : { where: i }
|
|
253
253
|
}), (e) => n.sync(() => a(e)));
|
|
254
254
|
}, _ = n.gen(function* () {
|
|
@@ -257,7 +257,7 @@ var he = (e) => {
|
|
|
257
257
|
l.clear();
|
|
258
258
|
for (let [n, r] of e) {
|
|
259
259
|
let e = [...r].filter((e) => !s.get(n)?.has(e));
|
|
260
|
-
e.length !== 0 && (yield* g(n, u(
|
|
260
|
+
e.length !== 0 && (yield* g(n, u(L(t, n), e)));
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
});
|
|
@@ -280,13 +280,13 @@ var he = (e) => {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
return o;
|
|
283
|
-
}),
|
|
283
|
+
}), Ve = (e, t) => ({
|
|
284
284
|
tables: [...e.keys()],
|
|
285
285
|
predicateFor: (n) => {
|
|
286
286
|
let r = e.get(n);
|
|
287
|
-
return r ? u(
|
|
287
|
+
return r ? u(L(t, n), [...r]) : void 0;
|
|
288
288
|
}
|
|
289
|
-
}),
|
|
289
|
+
}), R = "tenantId", He = (e, t, r) => n.gen(function* () {
|
|
290
290
|
let i = t.tables.map((e) => e.name), a = new Map(t.tables.map((e) => [e.name, e]));
|
|
291
291
|
if (e.kind === "all") return {
|
|
292
292
|
tables: i,
|
|
@@ -300,25 +300,25 @@ var he = (e) => {
|
|
|
300
300
|
};
|
|
301
301
|
}
|
|
302
302
|
let o = e.tenantId;
|
|
303
|
-
if (o === void 0 || o === "") return yield* n.fail(new
|
|
304
|
-
let s = r.tenantTables ? r.tenantTables.filter((e) => a.has(e)) : i.filter((e) => a.get(e)?.columns.some((e) => e.name ===
|
|
305
|
-
if (s.length === 0) return yield* n.fail(new
|
|
306
|
-
let c = yield*
|
|
307
|
-
seeds: Object.fromEntries(s.map((e) => [e, l(
|
|
303
|
+
if (o === void 0 || o === "") return yield* n.fail(new F({ reason: "scope { kind: 'tenant' } requires a tenantId — pass --tenant <id> (CLI) or scope.tenantId (API). Refusing to fall back to an unfiltered export." }));
|
|
304
|
+
let s = r.tenantTables ? r.tenantTables.filter((e) => a.has(e)) : i.filter((e) => a.get(e)?.columns.some((e) => e.name === R) ?? !1);
|
|
305
|
+
if (s.length === 0) return yield* n.fail(new F({ reason: r.tenantTables ? "tenant scope: none of the provided tenantTables exist in the schema — nothing to filter." : `tenant scope: no table carries a '${R}' column — nothing to filter. A tenant export of a schema without tenant-scoped tables would be the full database; refusing.` }));
|
|
306
|
+
let c = yield* Be(r.store, t, {
|
|
307
|
+
seeds: Object.fromEntries(s.map((e) => [e, l(R, o)])),
|
|
308
308
|
pinned: s,
|
|
309
309
|
children: { roots: s }
|
|
310
310
|
}), d = [...c.entries()].filter(([, e]) => e.size > 0).map(([e]) => e), f = new Set(s);
|
|
311
311
|
return {
|
|
312
312
|
tables: [...s, ...d],
|
|
313
|
-
predicateFor: (e) => f.has(e) ? l(
|
|
313
|
+
predicateFor: (e) => f.has(e) ? l(R, o) : c.has(e) ? u(L(t, e), [...c.get(e)]) : void 0
|
|
314
314
|
};
|
|
315
|
-
}),
|
|
315
|
+
}), Ue = (e, t) => ({
|
|
316
316
|
list: t,
|
|
317
317
|
open: (t) => C(e, t)
|
|
318
|
-
}),
|
|
318
|
+
}), We = (e) => ({
|
|
319
319
|
write: (t, n, r) => ee(e, t, n, r),
|
|
320
320
|
has: (t) => e.head(t).pipe(n.map((e) => e !== null))
|
|
321
|
-
}),
|
|
321
|
+
}), Ge = (e, t) => n.tryPromise({
|
|
322
322
|
try: async () => {
|
|
323
323
|
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) {
|
|
324
324
|
u.update(e), d += e.length, n(null, e);
|
|
@@ -336,23 +336,23 @@ var he = (e) => {
|
|
|
336
336
|
contentType: e.contentType
|
|
337
337
|
};
|
|
338
338
|
},
|
|
339
|
-
catch: (e) => new
|
|
339
|
+
catch: (e) => new N({
|
|
340
340
|
reason: `asset write failed: ${String(e?.message ?? e)}`,
|
|
341
341
|
path: t
|
|
342
342
|
})
|
|
343
|
-
}),
|
|
343
|
+
}), Ke = (e, t, r) => n.gen(function* () {
|
|
344
344
|
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 = S("bundle", () => a(s)).pipe(c.tap((e) => n.sync(() => l.update(e))));
|
|
345
345
|
yield* e.write(r.key, u, {
|
|
346
346
|
contentType: r.contentType,
|
|
347
347
|
totalSize: r.size
|
|
348
348
|
});
|
|
349
349
|
let d = l.digest("hex");
|
|
350
|
-
if (d !== r.sha256) return yield* n.fail(new
|
|
350
|
+
if (d !== r.sha256) return yield* n.fail(new P({
|
|
351
351
|
what: `asset ${r.key}`,
|
|
352
352
|
expected: r.sha256,
|
|
353
353
|
actual: d
|
|
354
354
|
}));
|
|
355
|
-
}),
|
|
355
|
+
}), qe = () => typeof w.createZstdCompress == "function", Je = (e) => e === "none" ? "none" : e === "gzip" ? "gzip" : qe() ? "zstd" : "gzip", Ye = (e) => e === "zstd" ? ".zst" : e === "gzip" ? ".gz" : "", Xe = (e) => e === "zstd" ? w.createZstdCompress() : e === "gzip" ? w.createGzip() : new ne(), Ze = (e) => e === "zstd" ? w.createZstdDecompress() : e === "gzip" ? w.createGunzip() : new ne(), Qe = 1, $e = s.Struct({
|
|
356
356
|
name: s.String,
|
|
357
357
|
file: s.String,
|
|
358
358
|
rowCount: s.Number,
|
|
@@ -362,11 +362,11 @@ var he = (e) => {
|
|
|
362
362
|
value: s.String
|
|
363
363
|
}),
|
|
364
364
|
primaryKey: s.String
|
|
365
|
-
}),
|
|
365
|
+
}), et = s.Struct({
|
|
366
366
|
kind: s.Literal("all", "tenant", "tables"),
|
|
367
367
|
tenantId: s.optional(s.String),
|
|
368
368
|
tables: s.optional(s.Array(s.String))
|
|
369
|
-
}),
|
|
369
|
+
}), tt = s.Struct({
|
|
370
370
|
count: s.Number,
|
|
371
371
|
totalBytes: s.Number,
|
|
372
372
|
index: s.optional(s.String)
|
|
@@ -377,23 +377,23 @@ s.Struct({
|
|
|
377
377
|
size: s.Number,
|
|
378
378
|
contentType: s.String
|
|
379
379
|
});
|
|
380
|
-
var
|
|
380
|
+
var nt = s.Struct({
|
|
381
381
|
formatVersion: s.Number,
|
|
382
382
|
createdAt: s.String,
|
|
383
383
|
source: s.Struct({
|
|
384
384
|
dialect: s.String,
|
|
385
385
|
schemaFingerprint: s.String
|
|
386
386
|
}),
|
|
387
|
-
scope:
|
|
387
|
+
scope: et,
|
|
388
388
|
consistency: s.Literal("live", "snapshot"),
|
|
389
389
|
compression: s.Literal("zstd", "gzip", "none"),
|
|
390
|
-
tables: s.Array(
|
|
391
|
-
assets:
|
|
390
|
+
tables: s.Array($e),
|
|
391
|
+
assets: tt,
|
|
392
392
|
masking: s.optional(s.Struct({
|
|
393
393
|
policyId: s.optional(s.String),
|
|
394
394
|
transformed: s.Array(s.String)
|
|
395
395
|
}))
|
|
396
|
-
}),
|
|
396
|
+
}), rt = s.encodeSync(s.parseJson(nt)), it = s.decodeUnknownSync(s.parseJson(nt)), z = "manifest.json", at = "README.md", B = "data", V = "assets", H = "assets/index.ndjson", ot = ".ledger.json", st = (e) => e.kind === "tenant" ? `tenant \`${e.tenantId}\`` : e.kind === "tables" ? `tables \`${(e.tables ?? []).join(", ")}\`` : "all tables", ct = (e, t) => {
|
|
397
397
|
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");
|
|
398
398
|
return `# Voltro data export
|
|
399
399
|
|
|
@@ -407,7 +407,7 @@ The machine-readable manifest is \`manifest.json\`; this file is a human summary
|
|
|
407
407
|
| **Format version** | ${e.formatVersion} |
|
|
408
408
|
| **Consistency** | ${e.consistency} |
|
|
409
409
|
| **Compression** | ${e.compression} |
|
|
410
|
-
| **Scope** | ${
|
|
410
|
+
| **Scope** | ${st(e.scope)} |
|
|
411
411
|
| **Tables** | ${e.tables.length} |
|
|
412
412
|
| **Rows (total)** | ${n} |
|
|
413
413
|
| **Assets** | ${a} |
|
|
@@ -432,39 +432,39 @@ voltro data import <this-directory>
|
|
|
432
432
|
voltro data import <this-directory> --target api --api-url <url> --token <secret>
|
|
433
433
|
\`\`\`
|
|
434
434
|
`;
|
|
435
|
-
},
|
|
435
|
+
}, lt = i.counter("voltro_data_transfer_rows", { description: "Rows exported/imported by @voltro/data-transfer, tagged by phase + table." }), ut = a.exponential({
|
|
436
436
|
start: .01,
|
|
437
437
|
factor: 2,
|
|
438
438
|
count: 16
|
|
439
|
-
}),
|
|
439
|
+
}), dt = i.histogram("voltro_data_transfer_table_seconds", ut, "Per-table export/import duration in seconds, tagged by phase."), U = (e, t) => {
|
|
440
440
|
if (e) try {
|
|
441
441
|
e(t);
|
|
442
442
|
} catch {}
|
|
443
|
-
},
|
|
443
|
+
}, ft = (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(dt.pipe(i.tagged("phase", e), i.update((s - r) / 1e3)), lt.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: {
|
|
444
444
|
table: t,
|
|
445
445
|
index: r,
|
|
446
446
|
tableCount: a,
|
|
447
447
|
phase: e
|
|
448
|
-
} })),
|
|
448
|
+
} })), pt = () => ({
|
|
449
449
|
tables: {},
|
|
450
450
|
assets: {}
|
|
451
|
-
}),
|
|
451
|
+
}), W = (e) => n.tryPromise(async () => {
|
|
452
452
|
let t = await (await import("node:fs/promises")).readFile(e, "utf8");
|
|
453
453
|
return JSON.parse(t);
|
|
454
|
-
}).pipe(n.orElseSucceed(
|
|
454
|
+
}).pipe(n.orElseSucceed(pt)), G = (e, t) => n.tryPromise({
|
|
455
455
|
try: async () => {
|
|
456
456
|
let n = await import("node:fs/promises"), { randomUUID: r } = await import("node:crypto"), i = `${e}.tmp-${r()}`;
|
|
457
457
|
await n.writeFile(i, JSON.stringify(t)), await n.rename(i, e);
|
|
458
458
|
},
|
|
459
|
-
catch: (t) => new
|
|
459
|
+
catch: (t) => new N({
|
|
460
460
|
reason: `ledger write failed: ${String(t?.message ?? t)}`,
|
|
461
461
|
path: e
|
|
462
462
|
})
|
|
463
|
-
}),
|
|
463
|
+
}), mt = (e, t) => t in e.tables, ht = (e, t) => t in e.assets, gt = /* @__PURE__ */ new Set([
|
|
464
464
|
"json",
|
|
465
465
|
"array",
|
|
466
466
|
"vector"
|
|
467
|
-
]),
|
|
467
|
+
]), _t = (e) => typeof e == "object" && !!e && !Array.isArray(e) && typeof e.$v == "string", vt = (e) => Buffer.from(e).toString("base64"), yt = (e) => new Uint8Array(Buffer.from(e, "base64")), bt = (e) => e instanceof Date ? e.toISOString() : typeof e == "number" ? new Date(e).toISOString() : String(e), xt = (e, t) => e == null ? null : t !== void 0 && gt.has(t) ? e : t === "bytes" ? vt(e) : t === "timestamp" || t === "date" ? bt(e) : typeof e == "bigint" ? {
|
|
468
468
|
$v: "bigint",
|
|
469
469
|
d: e.toString()
|
|
470
470
|
} : typeof e == "number" && !Number.isFinite(e) ? {
|
|
@@ -475,30 +475,30 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
475
475
|
d: e.toISOString()
|
|
476
476
|
} : e instanceof Uint8Array ? {
|
|
477
477
|
$v: "bytes",
|
|
478
|
-
d:
|
|
479
|
-
} : e,
|
|
478
|
+
d: vt(e)
|
|
479
|
+
} : e, St = (e) => {
|
|
480
480
|
switch (e.$v) {
|
|
481
481
|
case "bigint": return BigInt(e.d);
|
|
482
482
|
case "number": return Number(e.d);
|
|
483
483
|
case "date": return new Date(e.d);
|
|
484
|
-
case "bytes": return
|
|
484
|
+
case "bytes": return yt(e.d);
|
|
485
485
|
default: return e;
|
|
486
486
|
}
|
|
487
|
-
},
|
|
487
|
+
}, Ct = (e, t) => e == null ? null : t !== void 0 && gt.has(t) ? e : _t(e) ? St(e) : t === "bytes" ? yt(e) : t === "timestamp" || t === "date" ? new Date(e) : e, wt = (e, t) => {
|
|
488
488
|
let n = {};
|
|
489
|
-
for (let [r, i] of Object.entries(e)) n[r] =
|
|
489
|
+
for (let [r, i] of Object.entries(e)) n[r] = xt(i, t[r]);
|
|
490
490
|
return n;
|
|
491
|
-
},
|
|
491
|
+
}, Tt = (e, t) => {
|
|
492
492
|
let n = {};
|
|
493
|
-
for (let [r, i] of Object.entries(e)) n[r] =
|
|
493
|
+
for (let [r, i] of Object.entries(e)) n[r] = Ct(i, t[r]);
|
|
494
494
|
return n;
|
|
495
|
-
},
|
|
496
|
-
try: () =>
|
|
497
|
-
catch: (e) => new
|
|
495
|
+
}, Et = new TextEncoder(), Dt = (e, t) => e.pipe(c.map((e) => Et.encode(`${JSON.stringify(wt(e, t))}\n`))), Ot = (e, t, r) => e.pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.mapEffect((e) => n.try({
|
|
496
|
+
try: () => Tt(JSON.parse(e), r),
|
|
497
|
+
catch: (e) => new Me({
|
|
498
498
|
table: t,
|
|
499
499
|
reason: String(e?.message ?? e)
|
|
500
500
|
})
|
|
501
|
-
}))),
|
|
501
|
+
}))), K = (e, t) => {
|
|
502
502
|
let n = new Set(e), r = /* @__PURE__ */ new Map();
|
|
503
503
|
for (let e of t.tables) {
|
|
504
504
|
if (!n.has(e.name)) continue;
|
|
@@ -518,11 +518,11 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
518
518
|
};
|
|
519
519
|
for (let t of e) n.has(t) && s(t);
|
|
520
520
|
return i;
|
|
521
|
-
},
|
|
521
|
+
}, kt = (e, t) => {
|
|
522
522
|
let n = e.tables.find((e) => e.name === t), r = {};
|
|
523
523
|
for (let e of n?.columns ?? []) r[e.name] = e.type;
|
|
524
524
|
return r;
|
|
525
|
-
},
|
|
525
|
+
}, At = (e, t) => e.tables.find((e) => e.name === t)?.columns.find((e) => e.type === "id")?.name ?? "id", jt = (e, t, r) => n.tryPromise({
|
|
526
526
|
try: async () => {
|
|
527
527
|
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) {
|
|
528
528
|
d.update(e);
|
|
@@ -531,7 +531,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
531
531
|
n(null, e);
|
|
532
532
|
} }), m = l.fromWeb(c.toReadableStream(e)), h = `${t}.tmp-${o()}`;
|
|
533
533
|
try {
|
|
534
|
-
await s(m, p,
|
|
534
|
+
await s(m, p, Xe(r), n(h)), await i.rename(h, t);
|
|
535
535
|
} catch (e) {
|
|
536
536
|
throw await i.rm(h, { force: !0 }).catch(() => {}), e;
|
|
537
537
|
}
|
|
@@ -540,25 +540,25 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
540
540
|
checksum: d.digest("hex")
|
|
541
541
|
};
|
|
542
542
|
},
|
|
543
|
-
catch: (e) => new
|
|
543
|
+
catch: (e) => new N({
|
|
544
544
|
reason: `write table failed: ${String(e?.message ?? e)}`,
|
|
545
545
|
path: t
|
|
546
546
|
})
|
|
547
|
-
}),
|
|
547
|
+
}), Mt = (e, t) => n.tryPromise({
|
|
548
548
|
try: async () => {
|
|
549
549
|
await (await import("node:fs/promises")).appendFile(e, `${t}\n`);
|
|
550
550
|
},
|
|
551
|
-
catch: (t) => new
|
|
551
|
+
catch: (t) => new N({
|
|
552
552
|
reason: `append failed: ${String(t?.message ?? t)}`,
|
|
553
553
|
path: e
|
|
554
554
|
})
|
|
555
|
-
}),
|
|
555
|
+
}), Nt = (e, t) => n.gen(function* () {
|
|
556
556
|
let n = [], r = t.ordered.length;
|
|
557
557
|
for (let i = 0; i < t.ordered.length; i++) {
|
|
558
|
-
let a = t.ordered[i], o =
|
|
559
|
-
if (
|
|
558
|
+
let a = t.ordered[i], o = kt(t.snapshot, a), s = At(t.snapshot, a), l = `${B}/${a}.ndjson${Ye(t.compression)}`;
|
|
559
|
+
if (mt(t.ledger, a)) {
|
|
560
560
|
let e = t.ledger.tables[a];
|
|
561
|
-
|
|
561
|
+
U(t.onProgress, {
|
|
562
562
|
phase: "export",
|
|
563
563
|
table: a,
|
|
564
564
|
index: i,
|
|
@@ -576,7 +576,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
576
576
|
});
|
|
577
577
|
continue;
|
|
578
578
|
}
|
|
579
|
-
|
|
579
|
+
U(t.onProgress, {
|
|
580
580
|
phase: "export",
|
|
581
581
|
table: a,
|
|
582
582
|
index: i,
|
|
@@ -590,11 +590,11 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
590
590
|
chunkSize: t.chunkSize,
|
|
591
591
|
retry: t.retry,
|
|
592
592
|
...u === void 0 ? {} : { where: u }
|
|
593
|
-
}), f = t.mask ? d.pipe(c.map((e) =>
|
|
593
|
+
}), f = t.mask ? d.pipe(c.map((e) => je(e, a, t.mask.actions, t.mask.seed, o))) : d, { rowCount: m, checksum: h } = yield* ft("export", a, i, r, (e) => e.rowCount, jt(Dt(f, o), t.bundleFile(l), t.compression));
|
|
594
594
|
t.ledger.tables[a] = {
|
|
595
595
|
rowCount: m,
|
|
596
596
|
checksum: h
|
|
597
|
-
}, yield*
|
|
597
|
+
}, yield* G(t.ledgerPath, t.ledger), U(t.onProgress, {
|
|
598
598
|
phase: "export",
|
|
599
599
|
table: a,
|
|
600
600
|
index: i,
|
|
@@ -612,43 +612,43 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
612
612
|
});
|
|
613
613
|
}
|
|
614
614
|
return n;
|
|
615
|
-
}),
|
|
615
|
+
}), Pt = (e) => ({
|
|
616
616
|
_tag: "RawSqlFragment",
|
|
617
617
|
strings: [e],
|
|
618
618
|
values: []
|
|
619
|
-
}),
|
|
619
|
+
}), Ft = (t, i, a) => n.tryPromise({
|
|
620
620
|
try: () => t.transactional(async (t) => {
|
|
621
|
-
if (t.raw) for (let e of
|
|
621
|
+
if (t.raw) for (let e of ve(i)) await t.raw(Pt(e));
|
|
622
622
|
let o = await n.runPromiseExit(a(t));
|
|
623
623
|
if (r.isFailure(o)) throw Error(e.pretty(o.cause));
|
|
624
624
|
return o.value;
|
|
625
625
|
}),
|
|
626
|
-
catch: (e) => e instanceof
|
|
627
|
-
}),
|
|
628
|
-
let t = e.scope ?? { kind: "all" }, r =
|
|
626
|
+
catch: (e) => e instanceof N ? e : new N({ reason: `snapshot export failed: ${String(e?.message ?? e)}` })
|
|
627
|
+
}), It = (e) => n.gen(function* () {
|
|
628
|
+
let t = e.scope ?? { kind: "all" }, r = Je(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);
|
|
629
629
|
yield* n.tryPromise({
|
|
630
630
|
try: async () => {
|
|
631
631
|
let t = await import("node:fs/promises");
|
|
632
|
-
await t.mkdir(u(
|
|
632
|
+
await t.mkdir(u(B), { recursive: !0 }), e.assets && await t.mkdir(u(V), { recursive: !0 });
|
|
633
633
|
},
|
|
634
|
-
catch: (t) => new
|
|
634
|
+
catch: (t) => new N({
|
|
635
635
|
reason: `mkdir failed: ${String(t?.message ?? t)}`,
|
|
636
636
|
path: e.outDir
|
|
637
637
|
})
|
|
638
638
|
});
|
|
639
|
-
let d = u(
|
|
639
|
+
let d = u(ot), f = yield* W(d), p = e.subset ? Ve(yield* Be(e.store, e.snapshot, e.subset), e.snapshot) : yield* He(t, e.snapshot, {
|
|
640
640
|
store: e.store,
|
|
641
641
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
642
|
-
}), h =
|
|
642
|
+
}), h = K(p.tables, e.snapshot), g = e.consistency ?? "live", _, v;
|
|
643
643
|
if (e.masking) {
|
|
644
|
-
let t = e.classification ??
|
|
644
|
+
let t = e.classification ?? D(e.snapshot), r = M(h.map((t) => ({
|
|
645
645
|
name: t,
|
|
646
646
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
647
647
|
name: e.name,
|
|
648
648
|
type: e.type
|
|
649
649
|
}))
|
|
650
650
|
})), t, e.masking);
|
|
651
|
-
if (r.unclassified.length > 0) return yield* n.fail(new
|
|
651
|
+
if (r.unclassified.length > 0) return yield* n.fail(new Ie({ unclassified: r.unclassified }));
|
|
652
652
|
v = {
|
|
653
653
|
actions: r.actions,
|
|
654
654
|
seed: e.masking.seed
|
|
@@ -671,18 +671,18 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
671
671
|
bundleFile: u,
|
|
672
672
|
...v ? { mask: v } : {},
|
|
673
673
|
...e.onProgress ? { onProgress: e.onProgress } : {}
|
|
674
|
-
}, b = g === "snapshot" ? yield*
|
|
674
|
+
}, b = g === "snapshot" ? yield* Ft(e.store, e.dialect, (e) => Nt(e, y)) : yield* Nt(e.store, y), x = 0, S = 0;
|
|
675
675
|
if (e.assets) {
|
|
676
|
-
let t = u(
|
|
677
|
-
yield* c.runForEach(e.assets.list(), (r) => r.key in f.assets ? n.void : e.assets.open(r.key).pipe(n.flatMap((e) =>
|
|
676
|
+
let t = u(H);
|
|
677
|
+
yield* c.runForEach(e.assets.list(), (r) => r.key in f.assets ? n.void : e.assets.open(r.key).pipe(n.flatMap((e) => Ge(e, u(V))), n.flatMap((e) => {
|
|
678
678
|
let i = {
|
|
679
679
|
key: r.key,
|
|
680
680
|
sha256: e.sha256,
|
|
681
681
|
size: e.size,
|
|
682
682
|
contentType: e.contentType
|
|
683
683
|
};
|
|
684
|
-
return x++, S += e.size, f.assets[r.key] = !0,
|
|
685
|
-
}))).pipe(n.mapError((e) => e instanceof
|
|
684
|
+
return x++, S += e.size, f.assets[r.key] = !0, Mt(t, JSON.stringify(i)).pipe(n.andThen(G(d, f)));
|
|
685
|
+
}))).pipe(n.mapError((e) => e instanceof N ? e : new N({ reason: `asset export failed: ${String(e)}` })));
|
|
686
686
|
}
|
|
687
687
|
let C = {
|
|
688
688
|
formatVersion: 1,
|
|
@@ -698,7 +698,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
698
698
|
assets: x > 0 ? {
|
|
699
699
|
count: x,
|
|
700
700
|
totalBytes: S,
|
|
701
|
-
index:
|
|
701
|
+
index: H
|
|
702
702
|
} : {
|
|
703
703
|
count: 0,
|
|
704
704
|
totalBytes: 0
|
|
@@ -707,23 +707,23 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
707
707
|
};
|
|
708
708
|
return yield* n.tryPromise({
|
|
709
709
|
try: async () => {
|
|
710
|
-
await (await import("node:fs/promises")).writeFile(u(
|
|
710
|
+
await (await import("node:fs/promises")).writeFile(u(z), rt(C));
|
|
711
711
|
},
|
|
712
|
-
catch: (e) => new
|
|
712
|
+
catch: (e) => new N({
|
|
713
713
|
reason: `manifest write failed: ${String(e?.message ?? e)}`,
|
|
714
|
-
path:
|
|
714
|
+
path: z
|
|
715
715
|
})
|
|
716
716
|
}), yield* n.tryPromise({
|
|
717
717
|
try: async () => {
|
|
718
718
|
let e = await import("node:fs/promises"), t = await import("node:os");
|
|
719
|
-
await e.writeFile(u(
|
|
719
|
+
await e.writeFile(u(at), ct(C, { hostname: t.hostname() }));
|
|
720
720
|
},
|
|
721
|
-
catch: (e) => new
|
|
721
|
+
catch: (e) => new N({
|
|
722
722
|
reason: `readme write failed: ${String(e?.message ?? e)}`,
|
|
723
|
-
path:
|
|
723
|
+
path: at
|
|
724
724
|
})
|
|
725
725
|
}), C;
|
|
726
|
-
}),
|
|
726
|
+
}), Lt = (e) => {
|
|
727
727
|
switch (e) {
|
|
728
728
|
case "id":
|
|
729
729
|
case "text":
|
|
@@ -742,12 +742,12 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
742
742
|
case "raw": return "raw";
|
|
743
743
|
default: return "string";
|
|
744
744
|
}
|
|
745
|
-
},
|
|
745
|
+
}, Rt = {
|
|
746
746
|
vector: /* @__PURE__ */ new Set(["postgres"]),
|
|
747
747
|
array: /* @__PURE__ */ new Set(["postgres"]),
|
|
748
748
|
interval: /* @__PURE__ */ new Set(["postgres"])
|
|
749
|
-
},
|
|
750
|
-
let i =
|
|
749
|
+
}, zt = (e, t, n, r) => {
|
|
750
|
+
let i = Lt(n);
|
|
751
751
|
if (i === "raw") return {
|
|
752
752
|
table: e,
|
|
753
753
|
column: t,
|
|
@@ -755,7 +755,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
755
755
|
severity: "block",
|
|
756
756
|
reason: `raw() is verbatim source-dialect SQL — it cannot be assumed valid on ${r}`
|
|
757
757
|
};
|
|
758
|
-
let a =
|
|
758
|
+
let a = Rt[i];
|
|
759
759
|
return !a || a.has(r) ? null : i === "array" || i === "interval" ? {
|
|
760
760
|
table: e,
|
|
761
761
|
column: t,
|
|
@@ -769,20 +769,20 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
769
769
|
severity: "block",
|
|
770
770
|
reason: `${i} columns require a ${[...a].join("/")} target; ${r} has no compatible column type`
|
|
771
771
|
};
|
|
772
|
-
},
|
|
772
|
+
}, Bt = (e, t, n) => {
|
|
773
773
|
if (t === n) return [];
|
|
774
774
|
let r = [];
|
|
775
775
|
for (let t of e) for (let [e, i] of Object.entries(t.columnTypes)) {
|
|
776
|
-
let a =
|
|
776
|
+
let a = zt(t.name, e, i, n);
|
|
777
777
|
a && r.push(a);
|
|
778
778
|
}
|
|
779
779
|
return r;
|
|
780
|
-
},
|
|
780
|
+
}, Vt = (e) => `[${e.severity}] ${e.table}.${e.column} (${e.type}): ${e.reason}`, Ht = (e, t) => new Map((e.tables.find((e) => e.name === t)?.columns ?? []).map((e) => [e.name, e.type])), Ut = (e, t) => {
|
|
781
781
|
let n = [], r = new Set(e.tables.map((e) => e.name)), i = new Set(t.tables.map((e) => e.name));
|
|
782
782
|
for (let e of [...r].filter((e) => !i.has(e)).sort()) n.push(`table '${e}' is in the bundle but MISSING from the target`);
|
|
783
783
|
for (let e of [...i].filter((e) => !r.has(e)).sort()) n.push(`table '${e}' is in the target but NOT in the bundle (import leaves it untouched)`);
|
|
784
784
|
for (let a of [...r].filter((e) => i.has(e)).sort()) {
|
|
785
|
-
let r =
|
|
785
|
+
let r = Ht(e, a), i = Ht(t, a);
|
|
786
786
|
for (let [e] of r) i.has(e) || n.push(`${a}.${e}: in the bundle, MISSING from the target`);
|
|
787
787
|
for (let [e] of i) r.has(e) || n.push(`${a}.${e}: in the target, not in the bundle`);
|
|
788
788
|
for (let [e, t] of r) {
|
|
@@ -791,7 +791,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
791
791
|
}
|
|
792
792
|
}
|
|
793
793
|
return n.length > 30 ? [...n.slice(0, 30), `… and ${n.length - 30} more difference(s)`] : n.length > 0 ? n : ["the schema shape differs (indexes, nullability, or defaults) — the specific change is below the table/column granularity shown here"];
|
|
794
|
-
},
|
|
794
|
+
}, Wt = (e, t, n) => {
|
|
795
795
|
let r = m(t);
|
|
796
796
|
return r === e ? {
|
|
797
797
|
drifted: !1,
|
|
@@ -802,20 +802,20 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
802
802
|
drifted: !0,
|
|
803
803
|
bundleFingerprint: e,
|
|
804
804
|
targetFingerprint: r,
|
|
805
|
-
diff: n ?
|
|
805
|
+
diff: n ? Ut(n, t) : ["the target schema fingerprint does not match the bundle (no source schema available to itemise the diff — the manifest records only the fingerprint)"]
|
|
806
806
|
};
|
|
807
|
-
},
|
|
807
|
+
}, Gt = (e) => n.tryPromise({
|
|
808
808
|
try: async () => {
|
|
809
809
|
let t = await import("node:fs/promises"), n = await import("node:path");
|
|
810
|
-
return
|
|
810
|
+
return it(await t.readFile(n.join(e, z), "utf8"));
|
|
811
811
|
},
|
|
812
|
-
catch: (e) => new
|
|
812
|
+
catch: (e) => new N({
|
|
813
813
|
reason: `manifest read/parse failed: ${String(e?.message ?? e)}`,
|
|
814
|
-
path:
|
|
814
|
+
path: z
|
|
815
815
|
})
|
|
816
|
-
}),
|
|
817
|
-
let i = yield* n.promise(() => import("node:path")), a = yield*
|
|
818
|
-
if (a.formatVersion !== 1) return yield* n.fail(new
|
|
816
|
+
}), Kt = (t) => n.gen(function* () {
|
|
817
|
+
let i = yield* n.promise(() => import("node:path")), a = yield* Gt(t.bundleDir);
|
|
818
|
+
if (a.formatVersion !== 1) return yield* n.fail(new N({ reason: `unsupported bundle formatVersion ${a.formatVersion} (expected 1)` }));
|
|
819
819
|
if (t.targetSnapshot) {
|
|
820
820
|
let e = { tables: a.tables.map((e) => ({
|
|
821
821
|
name: e.name,
|
|
@@ -827,9 +827,9 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
827
827
|
unique: !1,
|
|
828
828
|
hasDefault: !1
|
|
829
829
|
}))
|
|
830
|
-
})) }, r =
|
|
830
|
+
})) }, r = Wt(a.source.schemaFingerprint, t.targetSnapshot, e);
|
|
831
831
|
if (r.drifted) {
|
|
832
|
-
if (!t.force) return yield* n.fail(new
|
|
832
|
+
if (!t.force) return yield* n.fail(new Fe({
|
|
833
833
|
bundleFingerprint: r.bundleFingerprint,
|
|
834
834
|
targetFingerprint: r.targetFingerprint,
|
|
835
835
|
diff: r.diff
|
|
@@ -838,15 +838,15 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
838
838
|
}
|
|
839
839
|
}
|
|
840
840
|
if (t.targetDialect && t.targetDialect !== a.source.dialect) {
|
|
841
|
-
let e =
|
|
842
|
-
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new
|
|
841
|
+
let e = Bt(a.tables, a.source.dialect, t.targetDialect).filter((e) => e.severity === "block");
|
|
842
|
+
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new Re({
|
|
843
843
|
sourceDialect: a.source.dialect,
|
|
844
844
|
targetDialect: t.targetDialect,
|
|
845
|
-
blocking: e.map(
|
|
845
|
+
blocking: e.map(Vt)
|
|
846
846
|
}));
|
|
847
847
|
}
|
|
848
|
-
let o = t.verify ?? !0, s = t.mode ?? "upsert", l = t.onConflict ?? "skip", u = t.ledgerPath ?? i.join(t.bundleDir, ".import..ledger.json"), f = yield*
|
|
849
|
-
if (s === "replace" && a.scope.kind !== "all") return yield* n.fail(new
|
|
848
|
+
let o = t.verify ?? !0, s = t.mode ?? "upsert", l = t.onConflict ?? "skip", u = t.ledgerPath ?? i.join(t.bundleDir, ".import..ledger.json"), f = yield* W(u);
|
|
849
|
+
if (s === "replace" && a.scope.kind !== "all") return yield* n.fail(new Le({
|
|
850
850
|
mode: s,
|
|
851
851
|
reason: `replace refuses a partial bundle (scope='${a.scope.kind}') — truncating would delete rows not in the bundle. Use --mode upsert, or re-export with full scope.`
|
|
852
852
|
}));
|
|
@@ -875,7 +875,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
875
875
|
r = t;
|
|
876
876
|
}
|
|
877
877
|
for (let t of i) (yield* m(() => e.upsert(t.entry.name, t.row, { conflictColumns: [t.entry.primaryKey] }), t)) || (r = [...r, t]);
|
|
878
|
-
if (r.length > 0) return yield* n.fail(new
|
|
878
|
+
if (r.length > 0) return yield* n.fail(new Pe({
|
|
879
879
|
rows: r.slice(0, 20).map((e) => ({
|
|
880
880
|
table: e.entry.name,
|
|
881
881
|
id: String(e.row[e.entry.primaryKey]),
|
|
@@ -887,15 +887,15 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
887
887
|
if (s === "replace" && !(r && f.truncated)) {
|
|
888
888
|
for (let t of [...a.tables].reverse()) yield* n.tryPromise({
|
|
889
889
|
try: () => e.deleteMany(t.name, { where: d(t.primaryKey) }),
|
|
890
|
-
catch: (e) => new
|
|
890
|
+
catch: (e) => new N({ reason: `truncate ${t.name} failed: ${String(e?.message ?? e)}` })
|
|
891
891
|
});
|
|
892
|
-
r && (f.truncated = !0, yield*
|
|
892
|
+
r && (f.truncated = !0, yield* G(u, f));
|
|
893
893
|
}
|
|
894
894
|
let l = [], h = [], _ = a.tables.length;
|
|
895
895
|
for (let s = 0; s < a.tables.length; s++) {
|
|
896
896
|
let d = a.tables[s];
|
|
897
897
|
if (r && d.name in f.tables) {
|
|
898
|
-
|
|
898
|
+
U(t.onProgress, {
|
|
899
899
|
phase: "import",
|
|
900
900
|
table: d.name,
|
|
901
901
|
index: s,
|
|
@@ -907,7 +907,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
907
907
|
continue;
|
|
908
908
|
}
|
|
909
909
|
let g = i.join(t.bundleDir, d.file);
|
|
910
|
-
|
|
910
|
+
U(t.onProgress, {
|
|
911
911
|
phase: "import",
|
|
912
912
|
table: d.name,
|
|
913
913
|
index: s,
|
|
@@ -917,8 +917,8 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
917
917
|
total: d.rowCount
|
|
918
918
|
});
|
|
919
919
|
let v = l.length, y = n.gen(function* () {
|
|
920
|
-
let { createHash: t } = yield* n.promise(() => import("node:crypto")), r = t("sha256"), i = 0, o = S("bundle", () =>
|
|
921
|
-
return yield* c.runForEach(
|
|
920
|
+
let { createHash: t } = yield* n.promise(() => import("node:crypto")), r = t("sha256"), i = 0, o = S("bundle", () => T(g).pipe(Ze(a.compression))).pipe(c.tap((e) => n.sync(() => r.update(e))));
|
|
921
|
+
return yield* c.runForEach(Ot(o, d.name, d.columnTypes), (t) => {
|
|
922
922
|
i++;
|
|
923
923
|
let r = {
|
|
924
924
|
entry: d,
|
|
@@ -932,20 +932,20 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
932
932
|
rowCount: i,
|
|
933
933
|
checksum: r.digest("hex")
|
|
934
934
|
};
|
|
935
|
-
}), { rowCount: b, checksum: x } = yield*
|
|
935
|
+
}), { rowCount: b, checksum: x } = yield* ft("import", d.name, s, _, (e) => e.rowCount, y);
|
|
936
936
|
if (o) {
|
|
937
|
-
if (x !== d.checksum) return yield* n.fail(new
|
|
937
|
+
if (x !== d.checksum) return yield* n.fail(new P({
|
|
938
938
|
what: `table ${d.name} checksum`,
|
|
939
939
|
expected: d.checksum,
|
|
940
940
|
actual: x
|
|
941
941
|
}));
|
|
942
|
-
if (b !== d.rowCount) return yield* n.fail(new
|
|
942
|
+
if (b !== d.rowCount) return yield* n.fail(new P({
|
|
943
943
|
what: `table ${d.name} rowCount`,
|
|
944
944
|
expected: String(d.rowCount),
|
|
945
945
|
actual: String(b)
|
|
946
946
|
}));
|
|
947
947
|
}
|
|
948
|
-
|
|
948
|
+
U(t.onProgress, {
|
|
949
949
|
phase: "import",
|
|
950
950
|
table: d.name,
|
|
951
951
|
index: s,
|
|
@@ -959,7 +959,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
959
959
|
}) : (f.tables[d.name] = {
|
|
960
960
|
rowCount: b,
|
|
961
961
|
checksum: d.checksum
|
|
962
|
-
}, yield*
|
|
962
|
+
}, yield* G(u, f)));
|
|
963
963
|
}
|
|
964
964
|
if (l.length > 0 && (yield* g(e, l)), r && h.length > 0) {
|
|
965
965
|
for (let e of h) {
|
|
@@ -969,7 +969,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
969
969
|
checksum: t.checksum
|
|
970
970
|
};
|
|
971
971
|
}
|
|
972
|
-
yield*
|
|
972
|
+
yield* G(u, f);
|
|
973
973
|
}
|
|
974
974
|
});
|
|
975
975
|
if (t.atomic ? yield* n.tryPromise({
|
|
@@ -977,22 +977,26 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
977
977
|
let i = await n.runPromiseExit(_(t, !1));
|
|
978
978
|
if (r.isFailure(i)) throw Error(e.pretty(i.cause));
|
|
979
979
|
}),
|
|
980
|
-
catch: (e) => new
|
|
980
|
+
catch: (e) => new N({ reason: `atomic import failed (rolled back): ${String(e?.message ?? e)}` })
|
|
981
981
|
}) : yield* _(t.store, !0), t.assets && a.assets.index && !t.assetsAlreadyRestored) {
|
|
982
|
-
let e = t.assets, r = i.join(t.bundleDir,
|
|
983
|
-
yield* c.runForEach(s, (t) => t.key in f.assets ? n.void :
|
|
982
|
+
let e = t.assets, r = i.join(t.bundleDir, V), o = i.join(t.bundleDir, a.assets.index ?? "assets/index.ndjson"), s = S("bundle", () => T(o)).pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.map((e) => JSON.parse(e)));
|
|
983
|
+
yield* c.runForEach(s, (t) => t.key in f.assets ? n.void : Ke(e, r, t).pipe(n.andThen(n.sync(() => {
|
|
984
984
|
f.assets[t.key] = !0;
|
|
985
|
-
})), n.andThen(
|
|
985
|
+
})), n.andThen(G(u, f))));
|
|
986
986
|
}
|
|
987
987
|
return a;
|
|
988
|
-
}),
|
|
989
|
-
refuse: !
|
|
990
|
-
|
|
991
|
-
|
|
988
|
+
}), qt = (e) => e, Jt = (e) => {
|
|
989
|
+
if (e.allowLive || e.liveInstance === null || e.sameTarget === "different") return { refuse: !1 };
|
|
990
|
+
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.";
|
|
991
|
+
return {
|
|
992
|
+
refuse: !0,
|
|
993
|
+
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).`
|
|
994
|
+
};
|
|
995
|
+
}, q = Buffer.from("VBUNDLE2"), J = 0, Y = 1, Yt = 2, Xt = 32, Zt = async (e) => {
|
|
992
996
|
let t = [], n = async (r) => {
|
|
993
997
|
let i;
|
|
994
998
|
try {
|
|
995
|
-
i = await
|
|
999
|
+
i = await le(E(e, r), { withFileTypes: !0 });
|
|
996
1000
|
} catch {
|
|
997
1001
|
return;
|
|
998
1002
|
}
|
|
@@ -1002,21 +1006,21 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1002
1006
|
}
|
|
1003
1007
|
};
|
|
1004
1008
|
return await n(""), t.sort();
|
|
1005
|
-
},
|
|
1009
|
+
}, Qt = (e, t) => {
|
|
1006
1010
|
let n = Buffer.from(e, "utf8"), r = Buffer.alloc(5 + n.length + 8);
|
|
1007
|
-
return r.writeUInt8(
|
|
1008
|
-
},
|
|
1011
|
+
return r.writeUInt8(Y, 0), r.writeUInt32BE(n.length, 1), n.copy(r, 5), r.writeBigUInt64BE(BigInt(t), 5 + n.length), r;
|
|
1012
|
+
}, $t = (e, t, n) => {
|
|
1009
1013
|
let r = Buffer.from(e, "utf8"), i = Buffer.from(t, "utf8"), a = Buffer.alloc(5 + r.length + 2 + i.length + 8), o = 0;
|
|
1010
|
-
return a.writeUInt8(
|
|
1014
|
+
return a.writeUInt8(Yt, 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;
|
|
1011
1015
|
};
|
|
1012
|
-
async function*
|
|
1013
|
-
yield new Uint8Array(
|
|
1014
|
-
for (let t of await
|
|
1015
|
-
let n =
|
|
1016
|
-
if (yield new Uint8Array(
|
|
1016
|
+
async function* en(e) {
|
|
1017
|
+
yield new Uint8Array(q);
|
|
1018
|
+
for (let t of await Zt(e.dir)) {
|
|
1019
|
+
let n = E(e.dir, t), r = await ue(n);
|
|
1020
|
+
if (yield new Uint8Array(Qt(t, r.size)), r.size > 0) for await (let e of T(n)) yield new Uint8Array(e);
|
|
1017
1021
|
}
|
|
1018
1022
|
if (e.blobs) for await (let t of e.blobs.list()) {
|
|
1019
|
-
yield new Uint8Array(
|
|
1023
|
+
yield new Uint8Array($t(t.key, t.contentType, t.size));
|
|
1020
1024
|
let n = _("sha256"), r = 0;
|
|
1021
1025
|
for await (let i of e.blobs.open(t.key)) {
|
|
1022
1026
|
let e = Buffer.from(i);
|
|
@@ -1025,11 +1029,11 @@ async function* $t(e) {
|
|
|
1025
1029
|
if (r !== t.size) throw Error(`blob '${t.key}' size mismatch: header ${t.size}, streamed ${r}`);
|
|
1026
1030
|
yield new Uint8Array(n.digest());
|
|
1027
1031
|
}
|
|
1028
|
-
yield new Uint8Array(Buffer.from([
|
|
1032
|
+
yield new Uint8Array(Buffer.from([J]));
|
|
1029
1033
|
}
|
|
1030
|
-
var
|
|
1031
|
-
let n =
|
|
1032
|
-
await
|
|
1034
|
+
var tn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), nn = (e) => new Promise((t) => e.end(t)), rn = async (e, t) => {
|
|
1035
|
+
let n = me(t.dir);
|
|
1036
|
+
await ce(n, { recursive: !0 });
|
|
1033
1037
|
let r = Buffer.alloc(0), i = e[Symbol.asyncIterator](), a = !1, o = async () => {
|
|
1034
1038
|
let { value: e, done: t } = await i.next();
|
|
1035
1039
|
return t ? (a = !0, !1) : (r = r.length === 0 ? Buffer.from(e) : Buffer.concat([r, Buffer.from(e)]), !0);
|
|
@@ -1040,28 +1044,28 @@ var en = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), tn
|
|
|
1040
1044
|
return r = r.subarray(e), t;
|
|
1041
1045
|
};
|
|
1042
1046
|
try {
|
|
1043
|
-
if (await s(
|
|
1047
|
+
if (await s(q.length), !c(q.length).equals(q)) throw Error("not a bundle archive (bad magic)");
|
|
1044
1048
|
for (;;) {
|
|
1045
1049
|
await s(1);
|
|
1046
1050
|
let e = c(1).readUInt8(0);
|
|
1047
|
-
if (e ===
|
|
1048
|
-
if (e ===
|
|
1051
|
+
if (e === J) return;
|
|
1052
|
+
if (e === Y) {
|
|
1049
1053
|
await s(4);
|
|
1050
1054
|
let e = c(4).readUInt32BE(0);
|
|
1051
1055
|
await s(e);
|
|
1052
1056
|
let t = c(e).toString("utf8");
|
|
1053
1057
|
await s(8);
|
|
1054
|
-
let i = c(8).readBigUInt64BE(0), a =
|
|
1055
|
-
if (a !== n && !a.startsWith(n +
|
|
1056
|
-
await
|
|
1057
|
-
let o =
|
|
1058
|
+
let i = c(8).readBigUInt64BE(0), a = me(n, t);
|
|
1059
|
+
if (a !== n && !a.startsWith(n + he)) throw Error(`archive path '${t}' escapes the destination`);
|
|
1060
|
+
await ce(pe(a), { recursive: !0 });
|
|
1061
|
+
let o = ae(a);
|
|
1058
1062
|
for (; i > 0n;) {
|
|
1059
1063
|
r.length === 0 && await s(1);
|
|
1060
1064
|
let e = i < BigInt(r.length) ? Number(i) : r.length;
|
|
1061
|
-
await
|
|
1065
|
+
await tn(o, c(e)), i -= BigInt(e);
|
|
1062
1066
|
}
|
|
1063
|
-
await
|
|
1064
|
-
} else if (e ===
|
|
1067
|
+
await nn(o);
|
|
1068
|
+
} else if (e === Yt) {
|
|
1065
1069
|
await s(4);
|
|
1066
1070
|
let e = c(4).readUInt32BE(0);
|
|
1067
1071
|
await s(e);
|
|
@@ -1071,24 +1075,24 @@ var en = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), tn
|
|
|
1071
1075
|
await s(i);
|
|
1072
1076
|
let a = c(i).toString("utf8");
|
|
1073
1077
|
await s(8);
|
|
1074
|
-
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = _("sha256"), d = new
|
|
1078
|
+
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = _("sha256"), d = new ne(), f = l ? Promise.resolve() : t.blobs.write(n, d, {
|
|
1075
1079
|
contentType: a,
|
|
1076
1080
|
size: Number(o)
|
|
1077
1081
|
}), p = o;
|
|
1078
1082
|
for (; p > 0n;) {
|
|
1079
1083
|
r.length === 0 && await s(1);
|
|
1080
1084
|
let e = p < BigInt(r.length) ? Number(p) : r.length, t = c(e);
|
|
1081
|
-
u.update(t), l || await
|
|
1085
|
+
u.update(t), l || await tn(d, t), p -= BigInt(e);
|
|
1082
1086
|
}
|
|
1083
|
-
l ? d.destroy() : await
|
|
1084
|
-
let m = c(
|
|
1087
|
+
l ? d.destroy() : await nn(d), await f, await s(Xt);
|
|
1088
|
+
let m = c(Xt);
|
|
1085
1089
|
if (!u.digest().equals(m)) throw Error(`blob '${n}' failed integrity (sha mismatch)`);
|
|
1086
1090
|
} else throw Error(`unknown bundle entry kind ${e}`);
|
|
1087
1091
|
}
|
|
1088
1092
|
} finally {
|
|
1089
1093
|
a || await Promise.resolve(i.return?.()).catch(() => void 0);
|
|
1090
1094
|
}
|
|
1091
|
-
},
|
|
1095
|
+
}, an = async (e, t) => {
|
|
1092
1096
|
let n = new Set(t), r = /* @__PURE__ */ new Map(), i = Buffer.alloc(0), a = e[Symbol.asyncIterator](), o = async () => {
|
|
1093
1097
|
let { value: e, done: t } = await a.next();
|
|
1094
1098
|
return t ? !1 : (i = i.length === 0 ? Buffer.from(e) : Buffer.concat([i, Buffer.from(e)]), !0);
|
|
@@ -1107,11 +1111,11 @@ var en = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), tn
|
|
|
1107
1111
|
}
|
|
1108
1112
|
return Buffer.concat(t);
|
|
1109
1113
|
};
|
|
1110
|
-
if (!await s(
|
|
1114
|
+
if (!await s(q.length) || !c(q.length).equals(q)) throw Error("not a bundle archive (bad magic)");
|
|
1111
1115
|
for (; await s(1);) {
|
|
1112
1116
|
let e = c(1).readUInt8(0);
|
|
1113
|
-
if (e ===
|
|
1114
|
-
if (e !==
|
|
1117
|
+
if (e === J || e === Yt) break;
|
|
1118
|
+
if (e !== Y) throw Error(`unknown bundle entry kind ${e}`);
|
|
1115
1119
|
if (!await s(4)) break;
|
|
1116
1120
|
let t = c(4).readUInt32BE(0);
|
|
1117
1121
|
if (!await s(t)) break;
|
|
@@ -1121,22 +1125,22 @@ var en = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), tn
|
|
|
1121
1125
|
if (a === null || n.has(i) && (r.set(i, a), n.delete(i), n.size === 0)) break;
|
|
1122
1126
|
}
|
|
1123
1127
|
return r;
|
|
1124
|
-
},
|
|
1128
|
+
}, on = (e, t) => rn(e, {
|
|
1125
1129
|
dir: t,
|
|
1126
|
-
blobs:
|
|
1127
|
-
}),
|
|
1130
|
+
blobs: sn(t)
|
|
1131
|
+
}), sn = (e) => {
|
|
1128
1132
|
let t = /* @__PURE__ */ new Set();
|
|
1129
1133
|
return {
|
|
1130
1134
|
has: async (e) => t.has(e),
|
|
1131
1135
|
write: async (n, r, i) => {
|
|
1132
|
-
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c =
|
|
1133
|
-
await
|
|
1136
|
+
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c = E(e, "assets");
|
|
1137
|
+
await ce(c, { recursive: !0 });
|
|
1134
1138
|
let l = _("sha256"), u = 0, d = new s({ transform(e, t, n) {
|
|
1135
1139
|
l.update(e), u += e.length, n(null, e);
|
|
1136
|
-
} }), f =
|
|
1137
|
-
await o(r, d,
|
|
1140
|
+
} }), f = E(c, `.tmp-${Date.now()}-${t.size}`);
|
|
1141
|
+
await o(r, d, ae(f));
|
|
1138
1142
|
let p = l.digest("hex");
|
|
1139
|
-
await a.rename(f,
|
|
1143
|
+
await a.rename(f, E(c, p)), await a.appendFile(E(c, "index.ndjson"), `${JSON.stringify({
|
|
1140
1144
|
key: n,
|
|
1141
1145
|
sha256: p,
|
|
1142
1146
|
size: u,
|
|
@@ -1144,33 +1148,33 @@ var en = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), tn
|
|
|
1144
1148
|
})}\n`), t.add(n);
|
|
1145
1149
|
}
|
|
1146
1150
|
};
|
|
1147
|
-
},
|
|
1151
|
+
}, cn = ge(b), ln = Buffer.from("VENC1\0\0\0"), un = 32, dn = 16, fn = 7, X = 16, pn = 256 * 1024, Z = {
|
|
1148
1152
|
N: 32768,
|
|
1149
1153
|
r: 8,
|
|
1150
1154
|
p: 1
|
|
1151
|
-
},
|
|
1155
|
+
}, mn = 128 * 1024 * 1024, Q = 43, hn = (e, t, n) => {
|
|
1152
1156
|
let r = Buffer.alloc(12);
|
|
1153
|
-
return e.copy(r, 0, 0,
|
|
1157
|
+
return e.copy(r, 0, 0, fn), r.writeUInt32BE(t >>> 0, fn), r.writeUInt8(+!!n, 11), r;
|
|
1154
1158
|
};
|
|
1155
|
-
async function*
|
|
1159
|
+
async function* gn(e, t) {
|
|
1156
1160
|
if (!t) throw Error("encryptStream: a non-empty passphrase is required");
|
|
1157
|
-
let n = y(
|
|
1161
|
+
let n = y(dn), r = y(fn), i = await cn(t, n, un, {
|
|
1158
1162
|
...Z,
|
|
1159
|
-
maxmem:
|
|
1163
|
+
maxmem: mn
|
|
1160
1164
|
}), a = Buffer.alloc(Q);
|
|
1161
|
-
|
|
1165
|
+
ln.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);
|
|
1162
1166
|
let o = 0, s = (e, t) => {
|
|
1163
|
-
let n = h("aes-256-gcm", i,
|
|
1167
|
+
let n = h("aes-256-gcm", i, hn(r, o, t));
|
|
1164
1168
|
o === 0 && n.setAAD(a);
|
|
1165
1169
|
let s = Buffer.concat([n.update(e), n.final()]), c = n.getAuthTag();
|
|
1166
1170
|
o++;
|
|
1167
|
-
let l = Buffer.alloc(5 + s.length +
|
|
1168
|
-
return l.writeUInt8(+!!t, 0), l.writeUInt32BE(s.length +
|
|
1171
|
+
let l = Buffer.alloc(5 + s.length + X);
|
|
1172
|
+
return l.writeUInt8(+!!t, 0), l.writeUInt32BE(s.length + X, 1), s.copy(l, 5), c.copy(l, 5 + s.length), new Uint8Array(l);
|
|
1169
1173
|
}, c = Buffer.alloc(0);
|
|
1170
|
-
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length >
|
|
1174
|
+
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length > pn;) yield s(c.subarray(0, pn), !1), c = c.subarray(pn);
|
|
1171
1175
|
yield s(c, !0);
|
|
1172
1176
|
}
|
|
1173
|
-
async function*
|
|
1177
|
+
async function* _n(e, t) {
|
|
1174
1178
|
if (!t) throw Error("decryptStream: a non-empty passphrase is required");
|
|
1175
1179
|
let n = e[Symbol.asyncIterator](), r = Buffer.alloc(0), i = !1, a = async () => {
|
|
1176
1180
|
let { value: e, done: t } = await n.next();
|
|
@@ -1181,12 +1185,12 @@ async function* hn(e, t) {
|
|
|
1181
1185
|
};
|
|
1182
1186
|
if (!await o(Q)) throw Error("encrypted bundle truncated (no header)");
|
|
1183
1187
|
let s = r.subarray(0, Q);
|
|
1184
|
-
if (!s.subarray(0, 8).equals(
|
|
1185
|
-
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
|
|
1188
|
+
if (!s.subarray(0, 8).equals(ln)) throw Error("not an encrypted bundle (bad magic / wrong passphrase target)");
|
|
1189
|
+
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 cn(t, d, un, {
|
|
1186
1190
|
N: c,
|
|
1187
1191
|
r: l,
|
|
1188
1192
|
p: u,
|
|
1189
|
-
maxmem:
|
|
1193
|
+
maxmem: mn
|
|
1190
1194
|
});
|
|
1191
1195
|
r = r.subarray(Q);
|
|
1192
1196
|
let m = 0, h = !1;
|
|
@@ -1197,11 +1201,11 @@ async function* hn(e, t) {
|
|
|
1197
1201
|
}
|
|
1198
1202
|
if (h) throw Error("encrypted bundle has trailing data after the final frame");
|
|
1199
1203
|
let e = r.readUInt8(0) === 1, t = r.readUInt32BE(1);
|
|
1200
|
-
if (t <
|
|
1204
|
+
if (t < X) throw Error("encrypted bundle corrupt (short frame)");
|
|
1201
1205
|
if (!await o(5 + t)) throw Error("encrypted bundle truncated (frame body)");
|
|
1202
|
-
let n = r.subarray(5, 5 + t -
|
|
1206
|
+
let n = r.subarray(5, 5 + t - X), i = r.subarray(5 + t - X, 5 + t);
|
|
1203
1207
|
r = r.subarray(5 + t);
|
|
1204
|
-
let a = g("aes-256-gcm", p,
|
|
1208
|
+
let a = g("aes-256-gcm", p, hn(f, m, e));
|
|
1205
1209
|
m === 0 && a.setAAD(s), a.setAuthTag(i);
|
|
1206
1210
|
let c = Buffer.concat([a.update(n), a.final()]);
|
|
1207
1211
|
m++, e && (h = !0), c.length > 0 && (yield new Uint8Array(c));
|
|
@@ -1209,7 +1213,7 @@ async function* hn(e, t) {
|
|
|
1209
1213
|
}
|
|
1210
1214
|
//#endregion
|
|
1211
1215
|
//#region src/blobStorage.ts
|
|
1212
|
-
var
|
|
1216
|
+
var vn = (e, t) => ({
|
|
1213
1217
|
list: () => {
|
|
1214
1218
|
let e = t();
|
|
1215
1219
|
return { async *[Symbol.asyncIterator]() {
|
|
@@ -1225,26 +1229,26 @@ var gn = (e, t) => ({
|
|
|
1225
1229
|
let r = await te((await n.runPromise(C(e, t))).stream);
|
|
1226
1230
|
for await (let e of r) yield e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
1227
1231
|
} })
|
|
1228
|
-
}),
|
|
1232
|
+
}), yn = (e, t) => vn(e, () => p(t, {
|
|
1229
1233
|
table: x,
|
|
1230
1234
|
chunkSize: 500
|
|
1231
1235
|
}).pipe(c.map((e) => ({
|
|
1232
1236
|
key: String(e.key),
|
|
1233
1237
|
contentType: String(e.contentType ?? "application/octet-stream"),
|
|
1234
1238
|
size: Number(e.size ?? 0)
|
|
1235
|
-
})))),
|
|
1239
|
+
})))), bn = (e) => ({
|
|
1236
1240
|
has: (t) => n.runPromise(e.head(t).pipe(n.map((e) => e !== null))),
|
|
1237
1241
|
write: async (t, r, i) => {
|
|
1238
|
-
let a = S("storage", () =>
|
|
1242
|
+
let a = S("storage", () => re.from(r));
|
|
1239
1243
|
await n.runPromise(ee(e, t, a, {
|
|
1240
1244
|
contentType: i.contentType,
|
|
1241
1245
|
totalSize: i.size
|
|
1242
1246
|
}));
|
|
1243
1247
|
}
|
|
1244
|
-
}),
|
|
1248
|
+
}), xn = (e, t) => {
|
|
1245
1249
|
let n = t === "dump" ? "mariadb-dump" : "mariadb", r = t === "dump" ? "mysqldump" : "mysql";
|
|
1246
|
-
return e === "mariadb" &&
|
|
1247
|
-
},
|
|
1250
|
+
return e === "mariadb" && Sn(n) ? n : r;
|
|
1251
|
+
}, Sn = (e) => (process.env.PATH ?? "").split(fe).filter((e) => e !== "").some((t) => oe(E(t, e))), Cn = (e) => {
|
|
1248
1252
|
switch (e) {
|
|
1249
1253
|
case "postgres": return "db.dump";
|
|
1250
1254
|
case "mysql":
|
|
@@ -1254,7 +1258,7 @@ var gn = (e, t) => ({
|
|
|
1254
1258
|
case "mssql": return "db.bacpac";
|
|
1255
1259
|
default: return "db.dump";
|
|
1256
1260
|
}
|
|
1257
|
-
},
|
|
1261
|
+
}, wn = (e) => e.filename ?? e.database ?? ((e.url ?? "").replace(/^file:/, "") || "app.sqlite"), $ = (e) => {
|
|
1258
1262
|
if (e.host || e.database) return {
|
|
1259
1263
|
host: e.host ?? "localhost",
|
|
1260
1264
|
port: e.port ?? 3306,
|
|
@@ -1270,7 +1274,7 @@ var gn = (e, t) => ({
|
|
|
1270
1274
|
password: decodeURIComponent(t.password) || "",
|
|
1271
1275
|
database: t.pathname.replace(/^\//, "") || ""
|
|
1272
1276
|
};
|
|
1273
|
-
},
|
|
1277
|
+
}, Tn = (e) => `Server=${e.host},${e.port};Database=${e.database};User ID=${e.username};Password=${e.password};TrustServerCertificate=True`, En = (e, t, n) => {
|
|
1274
1278
|
switch (e) {
|
|
1275
1279
|
case "postgres": {
|
|
1276
1280
|
if (t.url) return {
|
|
@@ -1317,12 +1321,13 @@ var gn = (e, t) => ({
|
|
|
1317
1321
|
let r = $(t);
|
|
1318
1322
|
return {
|
|
1319
1323
|
kind: "spawn",
|
|
1320
|
-
tool:
|
|
1324
|
+
tool: xn(e, "dump"),
|
|
1321
1325
|
args: [
|
|
1322
1326
|
"--single-transaction",
|
|
1323
1327
|
"--routines",
|
|
1324
1328
|
"--triggers",
|
|
1325
1329
|
"--no-tablespaces",
|
|
1330
|
+
"--protocol=TCP",
|
|
1326
1331
|
"-h",
|
|
1327
1332
|
r.host,
|
|
1328
1333
|
"-P",
|
|
@@ -1338,7 +1343,7 @@ var gn = (e, t) => ({
|
|
|
1338
1343
|
case "sqlite":
|
|
1339
1344
|
case "turso": return {
|
|
1340
1345
|
kind: "copy",
|
|
1341
|
-
from:
|
|
1346
|
+
from: wn(t),
|
|
1342
1347
|
to: n
|
|
1343
1348
|
};
|
|
1344
1349
|
case "mssql": return {
|
|
@@ -1346,7 +1351,7 @@ var gn = (e, t) => ({
|
|
|
1346
1351
|
tool: "sqlpackage",
|
|
1347
1352
|
args: [
|
|
1348
1353
|
"/Action:Export",
|
|
1349
|
-
`/SourceConnectionString:${
|
|
1354
|
+
`/SourceConnectionString:${Tn($({
|
|
1350
1355
|
...t,
|
|
1351
1356
|
port: t.port ?? 1433
|
|
1352
1357
|
}))}`,
|
|
@@ -1354,12 +1359,12 @@ var gn = (e, t) => ({
|
|
|
1354
1359
|
],
|
|
1355
1360
|
env: {}
|
|
1356
1361
|
};
|
|
1357
|
-
default: throw new
|
|
1362
|
+
default: throw new I({
|
|
1358
1363
|
tool: "backup",
|
|
1359
1364
|
reason: `no native backup for dialect '${e}'`
|
|
1360
1365
|
});
|
|
1361
1366
|
}
|
|
1362
|
-
},
|
|
1367
|
+
}, Dn = (e, t, n) => {
|
|
1363
1368
|
switch (e) {
|
|
1364
1369
|
case "postgres": {
|
|
1365
1370
|
if (t.url) return {
|
|
@@ -1404,8 +1409,9 @@ var gn = (e, t) => ({
|
|
|
1404
1409
|
let r = $(t);
|
|
1405
1410
|
return {
|
|
1406
1411
|
kind: "spawn",
|
|
1407
|
-
tool:
|
|
1412
|
+
tool: xn(e, "client"),
|
|
1408
1413
|
args: [
|
|
1414
|
+
"--protocol=TCP",
|
|
1409
1415
|
"-h",
|
|
1410
1416
|
r.host,
|
|
1411
1417
|
"-P",
|
|
@@ -1422,14 +1428,14 @@ var gn = (e, t) => ({
|
|
|
1422
1428
|
case "turso": return {
|
|
1423
1429
|
kind: "copy",
|
|
1424
1430
|
from: n,
|
|
1425
|
-
to:
|
|
1431
|
+
to: wn(t)
|
|
1426
1432
|
};
|
|
1427
1433
|
case "mssql": return {
|
|
1428
1434
|
kind: "spawn",
|
|
1429
1435
|
tool: "sqlpackage",
|
|
1430
1436
|
args: [
|
|
1431
1437
|
"/Action:Import",
|
|
1432
|
-
`/TargetConnectionString:${
|
|
1438
|
+
`/TargetConnectionString:${Tn($({
|
|
1433
1439
|
...t,
|
|
1434
1440
|
port: t.port ?? 1433
|
|
1435
1441
|
}))}`,
|
|
@@ -1437,18 +1443,18 @@ var gn = (e, t) => ({
|
|
|
1437
1443
|
],
|
|
1438
1444
|
env: {}
|
|
1439
1445
|
};
|
|
1440
|
-
default: throw new
|
|
1446
|
+
default: throw new I({
|
|
1441
1447
|
tool: "restore",
|
|
1442
1448
|
reason: `no native restore for dialect '${e}'`
|
|
1443
1449
|
});
|
|
1444
1450
|
}
|
|
1445
|
-
},
|
|
1446
|
-
|
|
1451
|
+
}, On = (e) => e.kind === "copy" ? n.async((t) => {
|
|
1452
|
+
ie(e.from, e.to, (r) => t(r ? n.fail(new I({
|
|
1447
1453
|
tool: "copy",
|
|
1448
1454
|
reason: `copy ${e.from} → ${e.to}: ${r.message}`
|
|
1449
1455
|
})) : n.void));
|
|
1450
1456
|
}) : n.async((t) => {
|
|
1451
|
-
let r =
|
|
1457
|
+
let r = _e(e.tool, [...e.args], {
|
|
1452
1458
|
env: {
|
|
1453
1459
|
...process.env,
|
|
1454
1460
|
...e.env
|
|
@@ -1461,19 +1467,33 @@ var gn = (e, t) => ({
|
|
|
1461
1467
|
}), i = "";
|
|
1462
1468
|
r.stderr?.on("data", (e) => {
|
|
1463
1469
|
i += String(e);
|
|
1464
|
-
}), e.stdoutFile && r.stdout && r.stdout.pipe(
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1470
|
+
}), e.stdoutFile && r.stdout && r.stdout.pipe(ae(e.stdoutFile)), e.stdinFile && r.stdin && T(e.stdinFile).pipe(r.stdin);
|
|
1471
|
+
let a = () => {
|
|
1472
|
+
if (e.stdoutFile !== void 0) try {
|
|
1473
|
+
se(e.stdoutFile);
|
|
1474
|
+
} catch {}
|
|
1475
|
+
};
|
|
1476
|
+
r.on("error", (r) => {
|
|
1477
|
+
a(), t(n.fail(new I({
|
|
1478
|
+
tool: e.tool,
|
|
1479
|
+
reason: `failed to launch (is '${e.tool}' installed + on PATH?): ${r.message}`
|
|
1480
|
+
})));
|
|
1481
|
+
}), r.on("close", (r) => {
|
|
1482
|
+
if (r === 0) {
|
|
1483
|
+
t(n.void);
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
a(), t(n.fail(new I({
|
|
1487
|
+
tool: e.tool,
|
|
1488
|
+
reason: `exited with code ${r}` + (e.stdoutFile === void 0 ? "" : ` — the partial ${de(e.stdoutFile)} was removed, so it cannot be mistaken for a backup`),
|
|
1489
|
+
stderr: i.slice(-2e3)
|
|
1490
|
+
})));
|
|
1491
|
+
});
|
|
1492
|
+
}), kn = (e) => typeof e == "object" && e ? "fake" in e ? `fake:${e.fake}` : "custom" : String(e), An = (e) => n.gen(function* () {
|
|
1493
|
+
let t = yield* He(e.scope ?? { kind: "all" }, e.snapshot, {
|
|
1474
1494
|
store: e.store,
|
|
1475
1495
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
1476
|
-
}), r =
|
|
1496
|
+
}), r = K(t.tables, e.snapshot), i = e.classification ?? D(e.snapshot), a = e.sampleSize ?? 20, o = M(r.map((t) => ({
|
|
1477
1497
|
name: t,
|
|
1478
1498
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
1479
1499
|
name: e.name,
|
|
@@ -1485,15 +1505,15 @@ var gn = (e, t) => ({
|
|
|
1485
1505
|
table: i,
|
|
1486
1506
|
chunkSize: a,
|
|
1487
1507
|
...r === void 0 ? {} : { where: r }
|
|
1488
|
-
}).pipe(c.take(a), c.runCollect, n.map((e) => [...e])), d = u.map((t) =>
|
|
1489
|
-
l.push(...
|
|
1508
|
+
}).pipe(c.take(a), c.runCollect, n.map((e) => [...e])), d = u.map((t) => je(t, i, o.actions, e.masking.seed));
|
|
1509
|
+
l.push(...Ae(d, i, o.actions));
|
|
1490
1510
|
let f = u[0], m = d[0], h = [];
|
|
1491
1511
|
if (f && m) for (let [e, t] of Object.entries(o.actions)) {
|
|
1492
1512
|
if (!e.startsWith(`${i}.`) || t === "keep") continue;
|
|
1493
1513
|
let n = e.slice(i.length + 1);
|
|
1494
1514
|
h.push({
|
|
1495
1515
|
column: n,
|
|
1496
|
-
action:
|
|
1516
|
+
action: kn(t),
|
|
1497
1517
|
before: f[n],
|
|
1498
1518
|
after: m[n]
|
|
1499
1519
|
});
|
|
@@ -1508,7 +1528,7 @@ var gn = (e, t) => ({
|
|
|
1508
1528
|
leaks: l,
|
|
1509
1529
|
unclassified: o.unclassified
|
|
1510
1530
|
};
|
|
1511
|
-
}),
|
|
1531
|
+
}), jn = (e, t) => {
|
|
1512
1532
|
let n = new Map(t.map((e) => [e.name, e])), r = [], i = {};
|
|
1513
1533
|
for (let t of e) {
|
|
1514
1534
|
let e = n.get(t.name);
|
|
@@ -1563,7 +1583,7 @@ var gn = (e, t) => ({
|
|
|
1563
1583
|
skipColumns: i,
|
|
1564
1584
|
refuse: r.some((e) => e.verdict === "refuse")
|
|
1565
1585
|
};
|
|
1566
|
-
},
|
|
1586
|
+
}, Mn = (e) => {
|
|
1567
1587
|
if (e.findings.length === 0) return [" schema matches the bundle"];
|
|
1568
1588
|
let t = {
|
|
1569
1589
|
safe: "✓",
|
|
@@ -1574,4 +1594,4 @@ var gn = (e, t) => ({
|
|
|
1574
1594
|
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;
|
|
1575
1595
|
};
|
|
1576
1596
|
//#endregion
|
|
1577
|
-
export {
|
|
1597
|
+
export { V as ASSETS_DIR, H as ASSET_INDEX_FILE, N as BundleError, Me as CodecError, Ne as CompressionError, Re as CrossDialectError, B as DATA_DIR, ye as DEFAULT_CLASS_ACTIONS, Pe as DanglingReferenceError, Qe as FORMAT_VERSION, Le as ImportModeError, P as IntegrityError, ot as LEDGER_FILE, z as MANIFEST_FILE, Ie as MaskingError, I as NativeToolError, Fe as SchemaDriftError, F as ScopeError, Oe as applyAction, Jt as assessLiveImport, ht as assetDone, Cn as backupArtifactName, En as backupCommand, Lt as canonicalType, Bt as checkPortability, Wt as checkSchemaDrift, D as classificationFromSnapshot, jn as classifyImportDrift, Ye as compressionExt, Be as computeSubsetIds, it as decodeManifest, Tt as decodeRow, Ct as decodeValue, _n as decryptStream, qt as defineDataProfile, Ut as diffSnapshots, sn as dirBlobSink, pt as emptyLedger, rt as encodeManifest, wt as encodeRow, xt as encodeValue, gn as encryptStream, Mn as formatImportDrift, Vt as formatIssue, qe as hasZstd, Xe as makeCompressor, Ze as makeDecompressor, je as maskRow, Ot as ndjsonToRows, en as packBundle, an as peekBundle, Je as pickCompression, M as planMasking, An as previewMasking, W as readLedger, be as resolveAction, He as resolveScope, Ke as restoreAssetFromCas, Dn as restoreCommand, Dt as rowsToNdjson, It as runExport, Kt as runImport, On as runNativeStep, Ae as scanForLeaks, We as storageAssetSink, Ue as storageAssetSource, bn as storageBlobSink, vn as storageBlobSource, yn as storageRefsBlobSource, Ve as subsetToScope, mt as tableDone, K as topoSortTables, rn as unpackBundle, on as unpackBundleToDir, Ge as writeAssetToCas, G as writeLedger };
|