@voltro/data-transfer 0.43.0 → 0.43.2
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 +100 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +328 -252
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@ 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
|
|
6
|
-
import * as
|
|
7
|
-
import { PassThrough as
|
|
8
|
-
import { copyFile as
|
|
9
|
-
import { mkdir as
|
|
5
|
+
import { STORAGE_REFS_TABLE as C, fromNodeReadable as w, getObjectStream as T, putObjectStream as ee, toNodeReadable as te } from "@voltro/plugin-storage";
|
|
6
|
+
import * as E from "node:zlib";
|
|
7
|
+
import { PassThrough as D, Readable as ne } from "node:stream";
|
|
8
|
+
import { copyFile as re, createReadStream as O, createWriteStream as ie, existsSync as ae, unlinkSync as oe } from "node:fs";
|
|
9
|
+
import { mkdir as se, readdir as ce, stat as le } from "node:fs/promises";
|
|
10
10
|
import { basename as ue, delimiter as de, dirname as fe, join as k, resolve as pe, sep as me } from "node:path";
|
|
11
11
|
import { promisify as he } from "node:util";
|
|
12
12
|
import { spawn as ge } from "node:child_process";
|
|
@@ -56,7 +56,7 @@ var _e = (e) => {
|
|
|
56
56
|
return r.classes?.[e] ?? ve[e] ?? "redact";
|
|
57
57
|
}
|
|
58
58
|
return n?.safe ? r.onSafe ?? "keep" : n?.columnType === "id" || n?.columnType === "reference" ? "keep" : r.onUnclassified ?? "error";
|
|
59
|
-
},
|
|
59
|
+
}, j = (e, t) => b("sha256", e).update(t == null ? "∅" : String(t)).digest(), M = (e, t) => e.readUInt32BE(t * 4 % (e.length - 4)), N = [
|
|
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
|
+
], P = [
|
|
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
|
+
], be = [
|
|
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
|
+
], xe = [
|
|
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
|
+
], F = (e, t, n) => e[M(t, n) % e.length], Se = (e, t, n) => {
|
|
104
|
+
let r = j(n, `${e}:${String(t)}`), i = M(r, 1) % 1e4;
|
|
105
105
|
switch (e) {
|
|
106
|
-
case "email": return `${N
|
|
107
|
-
case "fullName": return `${N
|
|
108
|
-
case "firstName": return N
|
|
109
|
-
case "lastName": return
|
|
110
|
-
case "username": return `${N
|
|
111
|
-
case "phone": return `+1${String(
|
|
112
|
-
case "address": return `${
|
|
113
|
-
case "company": return
|
|
106
|
+
case "email": return `${F(N, r, 0).toLowerCase()}.${F(P, r, 2).toLowerCase()}${i}@example.com`;
|
|
107
|
+
case "fullName": return `${F(N, r, 0)} ${F(P, r, 1)}`;
|
|
108
|
+
case "firstName": return F(N, r, 0);
|
|
109
|
+
case "lastName": return F(P, r, 1);
|
|
110
|
+
case "username": return `${F(N, r, 0).toLowerCase()}${i}`;
|
|
111
|
+
case "phone": return `+1${String(M(r, 0) % 1e10).padStart(10, "0")}`;
|
|
112
|
+
case "address": return `${M(r, 0) % 9899 + 100} ${F(be, r, 1)} St`;
|
|
113
|
+
case "company": return F(xe, 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 `${M(r, 0) % 256}.${M(r, 1) % 256}.${M(r, 2) % 256}.${M(r, 3) % 254 + 1}`;
|
|
116
|
+
case "creditCard": return Ce(`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
|
+
}, Ce = (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,23 +124,23 @@ var _e = (e) => {
|
|
|
124
124
|
});
|
|
125
125
|
let r = (10 - n % 10) % 10;
|
|
126
126
|
return e.slice(0, 15) + String(r);
|
|
127
|
-
},
|
|
127
|
+
}, we = 864e5, Te = (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 = j(
|
|
130
|
+
let r = M(j(t, "date-shift-offset"), 0) % 730 - 365, i = new Date(n + r * we);
|
|
131
131
|
return e instanceof Date ? i : i.toISOString();
|
|
132
|
-
},
|
|
132
|
+
}, Ee = (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 j(t.seed, t.value).toString("hex").slice(0, 16);
|
|
139
|
+
if (e === "dateShift") return Te(t.value, t.seed);
|
|
140
|
+
if (typeof e == "object" && "fake" in e) return Se(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
|
+
}, De = (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", I = (e, t, n) => {
|
|
144
144
|
let r = {}, i = [], a = [];
|
|
145
145
|
for (let o of e) for (let e of o.columns) {
|
|
146
146
|
let s = `${o.name}.${e.name}`, c = ye(o.name, e.name, t[o.name]?.[e.name], n);
|
|
@@ -148,7 +148,7 @@ var _e = (e) => {
|
|
|
148
148
|
i.push(s);
|
|
149
149
|
continue;
|
|
150
150
|
}
|
|
151
|
-
if (!
|
|
151
|
+
if (!De(c)) {
|
|
152
152
|
a.push({
|
|
153
153
|
column: s,
|
|
154
154
|
action: c
|
|
@@ -162,7 +162,7 @@ var _e = (e) => {
|
|
|
162
162
|
unclassified: i,
|
|
163
163
|
invalid: a
|
|
164
164
|
};
|
|
165
|
-
},
|
|
165
|
+
}, Oe = [
|
|
166
166
|
{
|
|
167
167
|
name: "email",
|
|
168
168
|
re: /[\w.+-]+@[\w-]+\.[\w.-]+/
|
|
@@ -179,7 +179,7 @@ var _e = (e) => {
|
|
|
179
179
|
name: "creditCard",
|
|
180
180
|
re: /\b(?:\d[ -]?){13,16}\b/
|
|
181
181
|
}
|
|
182
|
-
],
|
|
182
|
+
], ke = (e, t, n) => {
|
|
183
183
|
let r = [], i = /* @__PURE__ */ new Set();
|
|
184
184
|
for (let [a, o] of Object.entries(n)) {
|
|
185
185
|
if (!a.startsWith(`${t}.`) || o !== "keep") continue;
|
|
@@ -187,7 +187,7 @@ var _e = (e) => {
|
|
|
187
187
|
for (let a of e) {
|
|
188
188
|
let e = a[n];
|
|
189
189
|
if (typeof e != "string" || e.length === 0) continue;
|
|
190
|
-
let o =
|
|
190
|
+
let o = Oe.find((t) => t.re.test(e));
|
|
191
191
|
if (o && !i.has(n)) {
|
|
192
192
|
i.add(n), r.push({
|
|
193
193
|
table: t,
|
|
@@ -200,9 +200,9 @@ var _e = (e) => {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
return r;
|
|
203
|
-
},
|
|
203
|
+
}, L = (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] = Ee(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
|
+
}, R = class extends s.TaggedError()("BundleError", {
|
|
214
214
|
reason: s.String,
|
|
215
215
|
path: s.optional(s.String)
|
|
216
|
-
}) {},
|
|
216
|
+
}) {}, Ae = class extends s.TaggedError()("CodecError", {
|
|
217
217
|
table: s.String,
|
|
218
218
|
reason: s.String
|
|
219
|
-
}) {},
|
|
219
|
+
}) {}, z = class extends s.TaggedError()("IntegrityError", {
|
|
220
220
|
what: s.String,
|
|
221
221
|
expected: s.String,
|
|
222
222
|
actual: s.String
|
|
223
|
-
}) {},
|
|
223
|
+
}) {}, je = class extends t.TaggedError("CompressionError") {}, B = class extends s.TaggedError()("ScopeError", { reason: s.String }) {}, Me = class extends s.TaggedError()("RowsRefusedError", {
|
|
224
224
|
rows: s.Array(s.Struct({
|
|
225
225
|
table: s.String,
|
|
226
226
|
id: s.String,
|
|
@@ -229,29 +229,29 @@ var _e = (e) => {
|
|
|
229
229
|
})),
|
|
230
230
|
primaryCount: s.Number,
|
|
231
231
|
totalCount: s.Number
|
|
232
|
-
}) {},
|
|
232
|
+
}) {}, Ne = class extends s.TaggedError()("SchemaDriftError", {
|
|
233
233
|
bundleFingerprint: s.String,
|
|
234
234
|
targetFingerprint: s.String,
|
|
235
235
|
diff: s.Array(s.String)
|
|
236
|
-
}) {},
|
|
236
|
+
}) {}, V = class extends t.TaggedError("NativeToolError") {
|
|
237
237
|
get message() {
|
|
238
238
|
let e = this.stderr?.trim();
|
|
239
239
|
return `${this.tool}: ${this.reason}${e ? `\n${e}` : ""}`;
|
|
240
240
|
}
|
|
241
|
-
},
|
|
241
|
+
}, Pe = class extends s.TaggedError()("MaskingError", {
|
|
242
242
|
unclassified: s.Array(s.String),
|
|
243
243
|
invalidActions: s.optional(s.Array(s.String))
|
|
244
|
-
}) {},
|
|
244
|
+
}) {}, Fe = class extends s.TaggedError()("ImportModeError", {
|
|
245
245
|
mode: s.String,
|
|
246
246
|
reason: s.String
|
|
247
|
-
}) {},
|
|
247
|
+
}) {}, Ie = class extends s.TaggedError()("CrossDialectError", {
|
|
248
248
|
sourceDialect: s.String,
|
|
249
249
|
targetDialect: s.String,
|
|
250
250
|
blocking: s.Array(s.String)
|
|
251
|
-
}) {},
|
|
251
|
+
}) {}, H = (e, t) => e.tables.find((e) => e.name === t)?.columns.find((e) => e.type === "id")?.name ?? "id", Le = (e, t) => (e.tables.find((e) => e.name === t)?.columns ?? []).filter((e) => e.references).map((e) => ({
|
|
252
252
|
col: e.name,
|
|
253
253
|
refTable: e.references.table
|
|
254
|
-
})),
|
|
254
|
+
})), Re = (e, t, r) => n.gen(function* () {
|
|
255
255
|
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
256
|
let t = s.get(e) ?? /* @__PURE__ */ new Set();
|
|
257
257
|
return s.set(e, t), t;
|
|
@@ -269,10 +269,10 @@ var _e = (e) => {
|
|
|
269
269
|
for (let t of n) d(t.refTable, e[t.col]);
|
|
270
270
|
};
|
|
271
271
|
}, g = (r, i) => {
|
|
272
|
-
let a = p(r,
|
|
272
|
+
let a = p(r, H(t, r), Le(t, r));
|
|
273
273
|
return c.runForEach(h(e, {
|
|
274
274
|
table: r,
|
|
275
|
-
pk:
|
|
275
|
+
pk: H(t, r),
|
|
276
276
|
...i === void 0 ? {} : { where: i }
|
|
277
277
|
}), (e) => n.sync(() => a(e)));
|
|
278
278
|
}, _ = n.gen(function* () {
|
|
@@ -281,7 +281,7 @@ var _e = (e) => {
|
|
|
281
281
|
l.clear();
|
|
282
282
|
for (let [n, r] of e) {
|
|
283
283
|
let e = [...r].filter((e) => !s.get(n)?.has(e));
|
|
284
|
-
e.length !== 0 && (yield* g(n, f(
|
|
284
|
+
e.length !== 0 && (yield* g(n, f(H(t, n), e)));
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
});
|
|
@@ -304,13 +304,13 @@ var _e = (e) => {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
return o;
|
|
307
|
-
}),
|
|
307
|
+
}), ze = (e, t) => ({
|
|
308
308
|
tables: [...e.keys()],
|
|
309
309
|
predicateFor: (n) => {
|
|
310
310
|
let r = e.get(n);
|
|
311
|
-
return r ? f(
|
|
311
|
+
return r ? f(H(t, n), [...r]) : void 0;
|
|
312
312
|
}
|
|
313
|
-
}),
|
|
313
|
+
}), U = "tenantId", Be = (e, t, r) => n.gen(function* () {
|
|
314
314
|
let i = t.tables.map((e) => e.name), a = new Map(t.tables.map((e) => [e.name, e]));
|
|
315
315
|
if (e.kind === "all") return {
|
|
316
316
|
tables: i,
|
|
@@ -318,7 +318,7 @@ var _e = (e) => {
|
|
|
318
318
|
};
|
|
319
319
|
if (e.kind === "tables") {
|
|
320
320
|
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
|
|
321
|
+
if (a.length > 0) return yield* n.fail(new B({ 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
322
|
let o = new Set(t);
|
|
323
323
|
return {
|
|
324
324
|
tables: i.filter((e) => o.has(e)),
|
|
@@ -326,30 +326,30 @@ var _e = (e) => {
|
|
|
326
326
|
};
|
|
327
327
|
}
|
|
328
328
|
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(
|
|
329
|
+
if (o === void 0 || o === "") return yield* n.fail(new B({ reason: "scope { kind: 'tenant' } requires a tenantId — pass --tenant <id> (CLI) or scope.tenantId (API). Refusing to fall back to an unfiltered export." }));
|
|
330
|
+
let s = r.tenantTables ? r.tenantTables.filter((e) => a.has(e)) : i.filter((e) => a.get(e)?.columns.some((e) => e.name === U) ?? !1);
|
|
331
|
+
if (s.length === 0) return yield* n.fail(new B({ reason: r.tenantTables ? "tenant scope: none of the provided tenantTables exist in the schema — nothing to filter." : `tenant scope: no table carries a '${U}' column — nothing to filter. A tenant export of a schema without tenant-scoped tables would be the full database; refusing.` }));
|
|
332
|
+
let c = yield* Re(r.store, t, {
|
|
333
|
+
seeds: Object.fromEntries(s.map((e) => [e, u(U, o)])),
|
|
334
334
|
pinned: s,
|
|
335
335
|
children: { roots: s }
|
|
336
336
|
}), l = [...c.entries()].filter(([, e]) => e.size > 0).map(([e]) => e), d = new Set(s);
|
|
337
337
|
return {
|
|
338
338
|
tables: [...s, ...l],
|
|
339
|
-
predicateFor: (e) => d.has(e) ? u(
|
|
339
|
+
predicateFor: (e) => d.has(e) ? u(U, o) : c.has(e) ? f(H(t, e), [...c.get(e)]) : void 0
|
|
340
340
|
};
|
|
341
|
-
}),
|
|
341
|
+
}), Ve = (e, t) => ({
|
|
342
342
|
list: t,
|
|
343
|
-
open: (t) =>
|
|
344
|
-
}),
|
|
345
|
-
write: (t, n, r) =>
|
|
343
|
+
open: (t) => T(e, t)
|
|
344
|
+
}), He = (e) => ({
|
|
345
|
+
write: (t, n, r) => ee(e, t, n, r),
|
|
346
346
|
has: (t) => e.head(t).pipe(n.map((e) => e !== null))
|
|
347
|
-
}),
|
|
347
|
+
}), Ue = (e, t) => n.tryPromise({
|
|
348
348
|
try: async () => {
|
|
349
349
|
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
350
|
u.update(e), d += e.length, n(null, e);
|
|
351
351
|
} });
|
|
352
|
-
await o(await
|
|
352
|
+
await o(await te(e.stream), f, n(l));
|
|
353
353
|
let p = u.digest("hex"), m = c.join(t, p);
|
|
354
354
|
try {
|
|
355
355
|
await r.access(m), await r.rm(l, { force: !0 });
|
|
@@ -362,23 +362,23 @@ var _e = (e) => {
|
|
|
362
362
|
contentType: e.contentType
|
|
363
363
|
};
|
|
364
364
|
},
|
|
365
|
-
catch: (e) => new
|
|
365
|
+
catch: (e) => new R({
|
|
366
366
|
reason: `asset write failed: ${String(e?.message ?? e)}`,
|
|
367
367
|
path: t
|
|
368
368
|
})
|
|
369
|
-
}),
|
|
369
|
+
}), We = (e, t, r) => n.gen(function* () {
|
|
370
370
|
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
371
|
yield* e.write(r.key, u, {
|
|
372
372
|
contentType: r.contentType,
|
|
373
373
|
totalSize: r.size
|
|
374
374
|
});
|
|
375
375
|
let d = l.digest("hex");
|
|
376
|
-
if (d !== r.sha256) return yield* n.fail(new
|
|
376
|
+
if (d !== r.sha256) return yield* n.fail(new z({
|
|
377
377
|
what: `asset ${r.key}`,
|
|
378
378
|
expected: r.sha256,
|
|
379
379
|
actual: d
|
|
380
380
|
}));
|
|
381
|
-
}),
|
|
381
|
+
}), Ge = () => typeof E.createZstdCompress == "function", Ke = (e) => e === "none" ? "none" : e === "gzip" ? "gzip" : Ge() ? "zstd" : "gzip", qe = (e) => e === "zstd" ? ".zst" : e === "gzip" ? ".gz" : "", Je = (e) => e === "zstd" ? E.createZstdCompress() : e === "gzip" ? E.createGzip() : new D(), Ye = (e) => e === "zstd" ? E.createZstdDecompress() : e === "gzip" ? E.createGunzip() : new D(), Xe = 1, Ze = s.Struct({
|
|
382
382
|
name: s.String,
|
|
383
383
|
file: s.String,
|
|
384
384
|
rowCount: s.Number,
|
|
@@ -388,11 +388,11 @@ var _e = (e) => {
|
|
|
388
388
|
value: s.String
|
|
389
389
|
}),
|
|
390
390
|
primaryKey: s.String
|
|
391
|
-
}),
|
|
391
|
+
}), Qe = s.Struct({
|
|
392
392
|
kind: s.Literal("all", "tenant", "tables"),
|
|
393
393
|
tenantId: s.optional(s.String),
|
|
394
394
|
tables: s.optional(s.Array(s.String))
|
|
395
|
-
}),
|
|
395
|
+
}), $e = s.Struct({
|
|
396
396
|
count: s.Number,
|
|
397
397
|
totalBytes: s.Number,
|
|
398
398
|
index: s.optional(s.String)
|
|
@@ -403,23 +403,23 @@ s.Struct({
|
|
|
403
403
|
size: s.Number,
|
|
404
404
|
contentType: s.String
|
|
405
405
|
});
|
|
406
|
-
var
|
|
406
|
+
var et = s.Struct({
|
|
407
407
|
formatVersion: s.Number,
|
|
408
408
|
createdAt: s.String,
|
|
409
409
|
source: s.Struct({
|
|
410
410
|
dialect: s.String,
|
|
411
411
|
schemaFingerprint: s.String
|
|
412
412
|
}),
|
|
413
|
-
scope:
|
|
413
|
+
scope: Qe,
|
|
414
414
|
consistency: s.Literal("live", "snapshot"),
|
|
415
415
|
compression: s.Literal("zstd", "gzip", "none"),
|
|
416
|
-
tables: s.Array(
|
|
417
|
-
assets:
|
|
416
|
+
tables: s.Array(Ze),
|
|
417
|
+
assets: $e,
|
|
418
418
|
masking: s.optional(s.Struct({
|
|
419
419
|
policyId: s.optional(s.String),
|
|
420
420
|
transformed: s.Array(s.String)
|
|
421
421
|
}))
|
|
422
|
-
}),
|
|
422
|
+
}), tt = s.encodeSync(s.parseJson(et)), nt = s.decodeUnknownSync(s.parseJson(et)), W = "manifest.json", rt = "README.md", it = "data", G = "assets", at = "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) => {
|
|
423
423
|
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
424
|
return `# Voltro data export
|
|
425
425
|
|
|
@@ -482,7 +482,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
482
482
|
let n = await import("node:fs/promises"), { randomUUID: r } = await import("node:crypto"), i = `${e}.tmp-${r()}`;
|
|
483
483
|
await n.writeFile(i, JSON.stringify(t)), await n.rename(i, e);
|
|
484
484
|
},
|
|
485
|
-
catch: (t) => new
|
|
485
|
+
catch: (t) => new R({
|
|
486
486
|
reason: `ledger write failed: ${String(t?.message ?? t)}`,
|
|
487
487
|
path: e
|
|
488
488
|
})
|
|
@@ -520,7 +520,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
520
520
|
return n;
|
|
521
521
|
}, Dt = new TextEncoder(), Ot = (e, t) => e.pipe(c.map((e) => Dt.encode(`${JSON.stringify(Tt(e, t))}\n`))), kt = (e, t, r) => e.pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.mapEffect((e) => n.try({
|
|
522
522
|
try: () => Et(JSON.parse(e), r),
|
|
523
|
-
catch: (e) => new
|
|
523
|
+
catch: (e) => new Ae({
|
|
524
524
|
table: t,
|
|
525
525
|
reason: String(e?.message ?? e)
|
|
526
526
|
})
|
|
@@ -585,7 +585,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
585
585
|
n(null, e);
|
|
586
586
|
} }), m = l.fromWeb(c.toReadableStream(e)), h = `${t}.tmp-${o()}`;
|
|
587
587
|
try {
|
|
588
|
-
await s(m, p,
|
|
588
|
+
await s(m, p, Je(r), n(h)), await i.rename(h, t);
|
|
589
589
|
} catch (e) {
|
|
590
590
|
throw await i.rm(h, { force: !0 }).catch(() => {}), e;
|
|
591
591
|
}
|
|
@@ -594,7 +594,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
594
594
|
checksum: d.digest("hex")
|
|
595
595
|
};
|
|
596
596
|
},
|
|
597
|
-
catch: (e) => new
|
|
597
|
+
catch: (e) => new R({
|
|
598
598
|
reason: `write table failed: ${J(e)}`,
|
|
599
599
|
path: t
|
|
600
600
|
})
|
|
@@ -602,7 +602,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
602
602
|
try: async () => {
|
|
603
603
|
await (await import("node:fs/promises")).appendFile(e, `${t}\n`);
|
|
604
604
|
},
|
|
605
|
-
catch: (t) => new
|
|
605
|
+
catch: (t) => new R({
|
|
606
606
|
reason: `append failed: ${J(t)}`,
|
|
607
607
|
path: e
|
|
608
608
|
})
|
|
@@ -610,8 +610,8 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
610
610
|
let r = [], i = t.ordered.length;
|
|
611
611
|
for (let a = 0; a < t.ordered.length; a++) {
|
|
612
612
|
let o = t.ordered[a], s = Mt(t.snapshot, o), l = Ft(t.snapshot, o);
|
|
613
|
-
if ("refusal" in l) return yield* n.fail(new
|
|
614
|
-
let u = l.column, d = `${
|
|
613
|
+
if ("refusal" in l) return yield* n.fail(new B({ reason: `export: ${l.refusal}` }));
|
|
614
|
+
let u = l.column, d = `${it}/${o}.ndjson${qe(t.compression)}`;
|
|
615
615
|
if (ht(t.ledger, o)) {
|
|
616
616
|
let e = t.ledger.tables[o];
|
|
617
617
|
K(t.onProgress, {
|
|
@@ -646,7 +646,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
646
646
|
chunkSize: t.chunkSize,
|
|
647
647
|
retry: t.retry,
|
|
648
648
|
...f === void 0 ? {} : { where: f }
|
|
649
|
-
}), m = Nt(t.snapshot, o), g = m.length === 0 ? p : p.pipe(c.map((e) => Pt(e, m))), _ = t.mask ? g.pipe(c.map((e) =>
|
|
649
|
+
}), m = Nt(t.snapshot, o), g = m.length === 0 ? p : p.pipe(c.map((e) => Pt(e, m))), _ = t.mask ? g.pipe(c.map((e) => L(e, o, t.mask.actions, t.mask.seed, s))) : g, { rowCount: v, checksum: y } = yield* ft("export", o, a, i, (e) => e.rowCount, It(Ot(_, s), t.bundleFile(d), t.compression));
|
|
650
650
|
t.ledger.tables[o] = {
|
|
651
651
|
rowCount: v,
|
|
652
652
|
checksum: y
|
|
@@ -679,32 +679,32 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
679
679
|
if (r.isFailure(o)) throw Error(e.pretty(o.cause));
|
|
680
680
|
return o.value;
|
|
681
681
|
}),
|
|
682
|
-
catch: (e) => e instanceof
|
|
682
|
+
catch: (e) => e instanceof R ? e : new R({ reason: `snapshot export failed: ${J(e)}` })
|
|
683
683
|
}), Vt = (e) => n.gen(function* () {
|
|
684
|
-
let t = e.scope ?? { kind: "all" }, r =
|
|
684
|
+
let t = e.scope ?? { kind: "all" }, r = Ke(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
685
|
yield* n.tryPromise({
|
|
686
686
|
try: async () => {
|
|
687
687
|
let t = await import("node:fs/promises");
|
|
688
|
-
await t.mkdir(u(
|
|
688
|
+
await t.mkdir(u(it), { recursive: !0 }), e.assets && await t.mkdir(u(G), { recursive: !0 });
|
|
689
689
|
},
|
|
690
|
-
catch: (t) => new
|
|
690
|
+
catch: (t) => new R({
|
|
691
691
|
reason: `mkdir failed: ${J(t)}`,
|
|
692
692
|
path: e.outDir
|
|
693
693
|
})
|
|
694
694
|
});
|
|
695
|
-
let d = u(ot), f = yield* mt(d), p = e.subset ?
|
|
695
|
+
let d = u(ot), f = yield* mt(d), p = e.subset ? ze(yield* Re(e.store, e.snapshot, e.subset), e.snapshot) : yield* Be(t, e.snapshot, {
|
|
696
696
|
store: e.store,
|
|
697
697
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
698
698
|
}), m = At(p.tables, e.snapshot), h = e.consistency ?? "live", _, v;
|
|
699
699
|
if (e.masking) {
|
|
700
|
-
let t = e.classification ?? A(e.snapshot), r =
|
|
700
|
+
let t = e.classification ?? A(e.snapshot), r = I(m.map((t) => ({
|
|
701
701
|
name: t,
|
|
702
702
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
703
703
|
name: e.name,
|
|
704
704
|
type: e.type
|
|
705
705
|
}))
|
|
706
706
|
})), t, e.masking);
|
|
707
|
-
if (r.unclassified.length > 0 || r.invalid.length > 0) return yield* n.fail(new
|
|
707
|
+
if (r.unclassified.length > 0 || r.invalid.length > 0) return yield* n.fail(new Pe({
|
|
708
708
|
unclassified: r.unclassified,
|
|
709
709
|
...r.invalid.length > 0 ? { invalidActions: r.invalid.map((e) => `${e.column}: ${JSON.stringify(e.action)}`) } : {}
|
|
710
710
|
}));
|
|
@@ -732,8 +732,8 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
732
732
|
...e.onProgress ? { onProgress: e.onProgress } : {}
|
|
733
733
|
}, b = h === "snapshot" ? yield* Bt(e.store, e.dialect, (e) => Rt(e, y)) : yield* Rt(e.store, y), x = 0, S = 0;
|
|
734
734
|
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) =>
|
|
735
|
+
let t = u(at);
|
|
736
|
+
yield* c.runForEach(e.assets.list(), (r) => r.key in f.assets ? n.void : e.assets.open(r.key).pipe(n.flatMap((e) => Ue(e, u(G))), n.flatMap((e) => {
|
|
737
737
|
let i = {
|
|
738
738
|
key: r.key,
|
|
739
739
|
sha256: e.sha256,
|
|
@@ -741,7 +741,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
741
741
|
contentType: e.contentType
|
|
742
742
|
};
|
|
743
743
|
return x++, S += e.size, f.assets[r.key] = !0, Lt(t, JSON.stringify(i)).pipe(n.andThen(q(d, f)));
|
|
744
|
-
}))).pipe(n.mapError((e) => e instanceof
|
|
744
|
+
}))).pipe(n.mapError((e) => e instanceof R ? e : new R({ reason: `asset export failed: ${String(e)}` })));
|
|
745
745
|
}
|
|
746
746
|
let C = {
|
|
747
747
|
formatVersion: 1,
|
|
@@ -757,7 +757,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
757
757
|
assets: x > 0 ? {
|
|
758
758
|
count: x,
|
|
759
759
|
totalBytes: S,
|
|
760
|
-
index:
|
|
760
|
+
index: at
|
|
761
761
|
} : {
|
|
762
762
|
count: 0,
|
|
763
763
|
totalBytes: 0
|
|
@@ -766,23 +766,42 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
766
766
|
};
|
|
767
767
|
return yield* n.tryPromise({
|
|
768
768
|
try: async () => {
|
|
769
|
-
await (await import("node:fs/promises")).writeFile(u(
|
|
769
|
+
await (await import("node:fs/promises")).writeFile(u(W), tt(C));
|
|
770
770
|
},
|
|
771
|
-
catch: (e) => new
|
|
771
|
+
catch: (e) => new R({
|
|
772
772
|
reason: `manifest write failed: ${J(e)}`,
|
|
773
|
-
path:
|
|
773
|
+
path: W
|
|
774
774
|
})
|
|
775
775
|
}), yield* n.tryPromise({
|
|
776
776
|
try: async () => {
|
|
777
777
|
let e = await import("node:fs/promises"), t = await import("node:os");
|
|
778
|
-
await e.writeFile(u(
|
|
778
|
+
await e.writeFile(u(rt), ct(C, { hostname: t.hostname() }));
|
|
779
779
|
},
|
|
780
|
-
catch: (e) => new
|
|
780
|
+
catch: (e) => new R({
|
|
781
781
|
reason: `readme write failed: ${J(e)}`,
|
|
782
|
-
path:
|
|
782
|
+
path: rt
|
|
783
783
|
})
|
|
784
784
|
}), C;
|
|
785
|
-
}), Ht = (e) => {
|
|
785
|
+
}), Ht = (e, t) => {
|
|
786
|
+
let n = new Set(t), r = [];
|
|
787
|
+
for (let t of e.tables) if (!n.has(t.name)) for (let e of t.columns) {
|
|
788
|
+
let i = e.references?.table;
|
|
789
|
+
i !== void 0 && n.has(i) && r.push({
|
|
790
|
+
from: t.name,
|
|
791
|
+
column: e.name,
|
|
792
|
+
to: i
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
return r;
|
|
796
|
+
}, Ut = (e) => {
|
|
797
|
+
let t = /* @__PURE__ */ new Map();
|
|
798
|
+
for (let n of e) t.set(n.from, [...t.get(n.from) ?? [], n]);
|
|
799
|
+
let n = [...t.entries()].map(([e, t]) => {
|
|
800
|
+
let n = t[0].rowCount, r = t.map((e) => `${e.column} → ${e.to}`).join(", ");
|
|
801
|
+
return ` ${e} (${n} row${n === 1 ? "" : "s"}): ${r}`;
|
|
802
|
+
});
|
|
803
|
+
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
|
+
}, Wt = (e) => {
|
|
786
805
|
switch (e) {
|
|
787
806
|
case "id":
|
|
788
807
|
case "text":
|
|
@@ -801,12 +820,12 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
801
820
|
case "raw": return "raw";
|
|
802
821
|
default: return "string";
|
|
803
822
|
}
|
|
804
|
-
},
|
|
823
|
+
}, Gt = {
|
|
805
824
|
vector: /* @__PURE__ */ new Set(["postgres"]),
|
|
806
825
|
array: /* @__PURE__ */ new Set(["postgres"]),
|
|
807
826
|
interval: /* @__PURE__ */ new Set(["postgres"])
|
|
808
|
-
},
|
|
809
|
-
let i =
|
|
827
|
+
}, Kt = (e, t, n, r) => {
|
|
828
|
+
let i = Wt(n);
|
|
810
829
|
if (i === "raw") return {
|
|
811
830
|
table: e,
|
|
812
831
|
column: t,
|
|
@@ -814,7 +833,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
814
833
|
severity: "block",
|
|
815
834
|
reason: `raw() is verbatim source-dialect SQL — it cannot be assumed valid on ${r}`
|
|
816
835
|
};
|
|
817
|
-
let a =
|
|
836
|
+
let a = Gt[i];
|
|
818
837
|
return !a || a.has(r) ? null : i === "array" || i === "interval" ? {
|
|
819
838
|
table: e,
|
|
820
839
|
column: t,
|
|
@@ -828,15 +847,15 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
828
847
|
severity: "block",
|
|
829
848
|
reason: `${i} columns require a ${[...a].join("/")} target; ${r} has no compatible column type`
|
|
830
849
|
};
|
|
831
|
-
},
|
|
850
|
+
}, qt = (e, t, n) => {
|
|
832
851
|
if (t === n) return [];
|
|
833
852
|
let r = [];
|
|
834
853
|
for (let t of e) for (let [e, i] of Object.entries(t.columnTypes)) {
|
|
835
|
-
let a =
|
|
854
|
+
let a = Kt(t.name, e, i, n);
|
|
836
855
|
a && r.push(a);
|
|
837
856
|
}
|
|
838
857
|
return r;
|
|
839
|
-
},
|
|
858
|
+
}, Jt = (e) => `[${e.severity}] ${e.table}.${e.column} (${e.type}): ${e.reason}`, Yt = (e) => {
|
|
840
859
|
let t = e.constraint ?? e.column, n = t === void 0 ? "" : ` ${t}`;
|
|
841
860
|
switch (e.kind) {
|
|
842
861
|
case "foreignKey": return `foreign key${n}: the referenced row does not exist (import it first, or check the bundle's table order)`;
|
|
@@ -845,22 +864,29 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
845
864
|
case "notNull": return `not-null constraint${n}: the column requires a value`;
|
|
846
865
|
case "check": return `check constraint${n}: the row does not satisfy it`;
|
|
847
866
|
}
|
|
848
|
-
},
|
|
867
|
+
}, Xt = (e) => {
|
|
849
868
|
let t = [e.dbCode, e.dbErrno ?? e.dbNumber].filter((e) => e !== void 0).map(String);
|
|
850
869
|
return t.length > 0 ? t.join("/") : void 0;
|
|
851
|
-
},
|
|
852
|
-
let t = d(e), n = l(t), r =
|
|
853
|
-
if (n !== void 0) return `${
|
|
870
|
+
}, Zt = (e) => {
|
|
871
|
+
let t = d(e), n = l(t), r = Xt(t), i = r === void 0 ? "" : ` [${r}]`;
|
|
872
|
+
if (n !== void 0) return `${Yt(n)}${i}`;
|
|
854
873
|
let a = typeof t.dbMessage == "string" ? t.dbMessage : void 0, o = e?.message, s = typeof o == "string" && o.length > 0 ? o : String(e), c = a !== void 0 && a !== s && !a.startsWith("SqlError:") ? a : s, u = c === "Failed to execute statement" ? `the database refused the write and the driver gave no detail${i}` : `${c}${i}`;
|
|
855
874
|
return u.length <= 300 ? u : `${u.slice(0, 300)}…`;
|
|
856
|
-
},
|
|
875
|
+
}, Qt = (e) => {
|
|
876
|
+
let t = d(e), n = l(t);
|
|
877
|
+
if (n?.kind === "foreignKeyInUse") {
|
|
878
|
+
let e = n.constraint ?? n.column, r = e === void 0 ? "" : ` ${e}`, i = Xt(t);
|
|
879
|
+
return `foreign key${r}: rows elsewhere still reference this table${i === void 0 ? "" : ` [${i}]`}`;
|
|
880
|
+
}
|
|
881
|
+
return Zt(e);
|
|
882
|
+
}, $t = (e, t) => e.tables.find((e) => e.name === t), en = (e, t) => new Map(($t(e, t)?.columns ?? []).map((e) => [e.name, e])), tn = (e, t) => {
|
|
857
883
|
let n = [];
|
|
858
884
|
for (let r of [...e.tables].sort((e, t) => e.name.localeCompare(t.name))) {
|
|
859
|
-
if (
|
|
885
|
+
if ($t(t, r.name) === void 0) {
|
|
860
886
|
n.push(`table '${r.name}' is in the bundle but MISSING from the target — its rows have nowhere to go`);
|
|
861
887
|
continue;
|
|
862
888
|
}
|
|
863
|
-
let e =
|
|
889
|
+
let e = en(t, r.name), i = new Map(r.columns.map((e) => [e.name, e]));
|
|
864
890
|
for (let [t, a] of i) {
|
|
865
891
|
let i = e.get(t);
|
|
866
892
|
if (i === void 0) {
|
|
@@ -872,7 +898,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
872
898
|
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`);
|
|
873
899
|
}
|
|
874
900
|
return n.length > 30 ? [...n.slice(0, 30), `… and ${n.length - 30} more difference(s)`] : n;
|
|
875
|
-
},
|
|
901
|
+
}, nn = (e, t, n) => {
|
|
876
902
|
let r = g(t);
|
|
877
903
|
if (r === e || n === void 0) return {
|
|
878
904
|
drifted: !1,
|
|
@@ -880,28 +906,28 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
880
906
|
targetFingerprint: r,
|
|
881
907
|
diff: []
|
|
882
908
|
};
|
|
883
|
-
let i =
|
|
909
|
+
let i = tn(n, t);
|
|
884
910
|
return {
|
|
885
911
|
drifted: i.length > 0,
|
|
886
912
|
bundleFingerprint: e,
|
|
887
913
|
targetFingerprint: r,
|
|
888
914
|
diff: i
|
|
889
915
|
};
|
|
890
|
-
},
|
|
916
|
+
}, rn = 200, an = (e) => n.tryPromise({
|
|
891
917
|
try: async () => {
|
|
892
918
|
let t = await import("node:fs/promises"), n = await import("node:path");
|
|
893
|
-
return
|
|
919
|
+
return nt(await t.readFile(n.join(e, W), "utf8"));
|
|
894
920
|
},
|
|
895
|
-
catch: (e) => new
|
|
921
|
+
catch: (e) => new R({
|
|
896
922
|
reason: `manifest read/parse failed: ${String(e?.message ?? e)}`,
|
|
897
|
-
path:
|
|
923
|
+
path: W
|
|
898
924
|
})
|
|
899
|
-
}),
|
|
900
|
-
let i = yield* n.promise(() => import("node:path")), a = yield*
|
|
901
|
-
if (a.formatVersion !== 1) return yield* n.fail(new
|
|
925
|
+
}), on = (t) => n.gen(function* () {
|
|
926
|
+
let i = yield* n.promise(() => import("node:path")), a = yield* an(t.bundleDir);
|
|
927
|
+
if (a.formatVersion !== 1) return yield* n.fail(new R({ reason: `unsupported bundle formatVersion ${a.formatVersion} (expected 1)` }));
|
|
902
928
|
if (t.tables !== void 0) {
|
|
903
929
|
let e = new Set(a.tables.map((e) => e.name)), r = t.tables.filter((t) => !e.has(t));
|
|
904
|
-
if (r.length > 0) return yield* n.fail(new
|
|
930
|
+
if (r.length > 0) return yield* n.fail(new R({ reason: `--tables names ${r.length} table(s) this bundle does not carry: ${r.join(", ")}. The bundle carries: ${[...e].sort().join(", ")}.` }));
|
|
905
931
|
}
|
|
906
932
|
let o = t.tables === void 0 ? void 0 : new Set(t.tables), s = o === void 0 ? a : {
|
|
907
933
|
...a,
|
|
@@ -918,9 +944,9 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
918
944
|
unique: !1,
|
|
919
945
|
hasDefault: !1
|
|
920
946
|
}))
|
|
921
|
-
})) }, r =
|
|
947
|
+
})) }, r = nn(s.source.schemaFingerprint, t.targetSnapshot, e);
|
|
922
948
|
if (r.drifted) {
|
|
923
|
-
if (!t.force) return yield* n.fail(new
|
|
949
|
+
if (!t.force) return yield* n.fail(new Ne({
|
|
924
950
|
bundleFingerprint: r.bundleFingerprint,
|
|
925
951
|
targetFingerprint: r.targetFingerprint,
|
|
926
952
|
diff: r.diff
|
|
@@ -929,18 +955,49 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
929
955
|
}
|
|
930
956
|
}
|
|
931
957
|
if (t.targetDialect && t.targetDialect !== s.source.dialect) {
|
|
932
|
-
let e =
|
|
933
|
-
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new
|
|
958
|
+
let e = qt(s.tables, s.source.dialect, t.targetDialect).filter((e) => e.severity === "block");
|
|
959
|
+
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new Ie({
|
|
934
960
|
sourceDialect: s.source.dialect,
|
|
935
961
|
targetDialect: t.targetDialect,
|
|
936
|
-
blocking: e.map(
|
|
962
|
+
blocking: e.map(Jt)
|
|
937
963
|
}));
|
|
938
964
|
}
|
|
939
965
|
let l = t.verify ?? !0, u = t.mode ?? "upsert", d = t.onConflict ?? "skip", f = t.ledgerPath ?? i.join(t.bundleDir, ".import..ledger.json"), m = yield* mt(f);
|
|
940
|
-
if (u === "replace" && s.scope.kind !== "all") return yield* n.fail(new
|
|
966
|
+
if (u === "replace" && s.scope.kind !== "all") return yield* n.fail(new Fe({
|
|
941
967
|
mode: u,
|
|
942
968
|
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.`
|
|
943
969
|
}));
|
|
970
|
+
if (u === "replace") {
|
|
971
|
+
let e = s.tables.map((e) => e.name), r = t.store.incomingForeignKeys ? yield* n.tryPromise({
|
|
972
|
+
try: () => t.store.incomingForeignKeys(e),
|
|
973
|
+
catch: (e) => new R({ reason: `foreign-key pre-flight failed: ${Qt(e)}` })
|
|
974
|
+
}) : t.targetSnapshot === void 0 ? [] : Ht(t.targetSnapshot, e), i = [], a = /* @__PURE__ */ new Map();
|
|
975
|
+
for (let e of r) {
|
|
976
|
+
if (!a.has(e.from)) {
|
|
977
|
+
let r = yield* n.tryPromise({
|
|
978
|
+
try: () => t.store.query({
|
|
979
|
+
table: e.from,
|
|
980
|
+
predicate: void 0,
|
|
981
|
+
order: [],
|
|
982
|
+
take: void 0,
|
|
983
|
+
skip: void 0,
|
|
984
|
+
projection: []
|
|
985
|
+
}),
|
|
986
|
+
catch: () => new R({ reason: `unreadable: ${e.from}` })
|
|
987
|
+
}).pipe(n.map((e) => e.length), n.orElseSucceed(() => 0));
|
|
988
|
+
a.set(e.from, r);
|
|
989
|
+
}
|
|
990
|
+
let r = a.get(e.from) ?? 0;
|
|
991
|
+
r > 0 && i.push({
|
|
992
|
+
...e,
|
|
993
|
+
rowCount: r
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
if (i.length > 0) return yield* n.fail(new Fe({
|
|
997
|
+
mode: u,
|
|
998
|
+
reason: Ut(i)
|
|
999
|
+
}));
|
|
1000
|
+
}
|
|
944
1001
|
if (t.dryRun === !0) return s;
|
|
945
1002
|
let h = /* @__PURE__ */ new Map();
|
|
946
1003
|
for (let e of t.targetSnapshot?.tables ?? []) {
|
|
@@ -956,16 +1013,16 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
956
1013
|
}, _ = (e, t, n) => {
|
|
957
1014
|
let r = t.name, i = t.primaryKey, a = g(r, n);
|
|
958
1015
|
return u === "append" ? d === "fail" ? e.insert(r, a) : e.insertIgnore(r, a, { conflictColumns: [i] }) : u === "replace" ? e.insert(r, a) : e.upsert(r, a, { conflictColumns: [i] });
|
|
959
|
-
}, v = (e, t, r = !0) => n.tryPromise({
|
|
1016
|
+
}, v = (e, t) => e.savepoint ? e.savepoint(t) : t(), y = (e, t, r = !0) => n.tryPromise({
|
|
960
1017
|
try: e,
|
|
961
|
-
catch: (e) =>
|
|
962
|
-
}).pipe(n.map(() => !0), n.catchAll((e) => n.sync(() => (r && (t.reason = e), !1)))),
|
|
1018
|
+
catch: (e) => Zt(e)
|
|
1019
|
+
}).pipe(n.map(() => !0), n.catchAll((e) => n.sync(() => (r && (t.reason = e), !1)))), b = (e) => {
|
|
963
1020
|
let t = Object.entries(e.entry.columnTypes).filter(([t, n]) => n === "reference" && e.row[t] !== null && e.row[t] !== void 0).map(([e]) => e);
|
|
964
1021
|
if (t.length !== 0) return {
|
|
965
1022
|
...e.row,
|
|
966
1023
|
...Object.fromEntries(t.map((e) => [e, null]))
|
|
967
1024
|
};
|
|
968
|
-
},
|
|
1025
|
+
}, x = (e) => {
|
|
969
1026
|
let t = new Set(e.map((e) => String(e.row[e.entry.primaryKey]))), n = (e) => Object.entries(e.entry.columnTypes).some(([n, r]) => {
|
|
970
1027
|
if (r !== "reference") return !1;
|
|
971
1028
|
let i = e.row[n];
|
|
@@ -976,32 +1033,36 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
976
1033
|
reason: e.reason,
|
|
977
1034
|
derived: n(e)
|
|
978
1035
|
}));
|
|
979
|
-
return new
|
|
1036
|
+
return new Me({
|
|
980
1037
|
rows: [...r.filter((e) => !e.derived), ...r.filter((e) => e.derived)].slice(0, 20),
|
|
981
1038
|
primaryCount: r.filter((e) => !e.derived).length,
|
|
982
1039
|
totalCount: e.length
|
|
983
1040
|
});
|
|
984
|
-
},
|
|
1041
|
+
}, S = (e, t) => n.gen(function* () {
|
|
985
1042
|
let r = t, i = [], a = !0;
|
|
986
1043
|
for (; r.length > 0 && a;) {
|
|
987
1044
|
a = !1;
|
|
988
1045
|
let t = [];
|
|
989
|
-
for (let n of r) (yield* v(() => _(e, n.entry, n.row), n)) ? a = !0 : t.push(n);
|
|
1046
|
+
for (let n of r) (yield* y(() => v(e, () => _(e, n.entry, n.row)), n)) ? a = !0 : t.push(n);
|
|
990
1047
|
if (!a && t.length > 0) for (let n = t.length - 1; n >= 0; n--) {
|
|
991
|
-
let r = t[n], o =
|
|
992
|
-
o !== void 0 && (yield* v(() => _(e, r.entry, o), r, !1)) && (i.push(r), t.splice(n, 1), a = !0);
|
|
1048
|
+
let r = t[n], o = b(r);
|
|
1049
|
+
o !== void 0 && (yield* y(() => v(e, () => _(e, r.entry, o)), r, !1)) && (i.push(r), t.splice(n, 1), a = !0);
|
|
993
1050
|
}
|
|
994
1051
|
r = t;
|
|
995
1052
|
}
|
|
996
|
-
for (let t of i) (yield* v(() => e.upsert(t.entry.name, t.row, { conflictColumns: [t.entry.primaryKey] }), t)) || (r = [...r, t]);
|
|
997
|
-
if (r.length > 0) return yield* n.fail(
|
|
998
|
-
}),
|
|
1053
|
+
for (let t of i) (yield* y(() => v(e, () => e.upsert(t.entry.name, t.row, { conflictColumns: [t.entry.primaryKey] })), t)) || (r = [...r, t]);
|
|
1054
|
+
if (r.length > 0) return yield* n.fail(x(r));
|
|
1055
|
+
}), C = (e, r) => n.gen(function* () {
|
|
999
1056
|
if (u === "replace" && !(r && m.truncated)) {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1057
|
+
let t = [...s.tables].reverse().map((e) => e.name), i = !r, a = e.emptyTables ? () => e.emptyTables(t) : i ? async () => {
|
|
1058
|
+
for (let t of [...s.tables].reverse()) await e.deleteMany(t.name, { where: p(t.primaryKey) });
|
|
1059
|
+
} : () => e.transactional(async (e) => {
|
|
1060
|
+
for (let t of [...s.tables].reverse()) await e.deleteMany(t.name, { where: p(t.primaryKey) });
|
|
1003
1061
|
});
|
|
1004
|
-
|
|
1062
|
+
yield* n.tryPromise({
|
|
1063
|
+
try: a,
|
|
1064
|
+
catch: (e) => new R({ reason: `emptying the target for --mode replace failed (nothing was deleted): ${Qt(e)}` })
|
|
1065
|
+
}), r && (m.truncated = !0, yield* q(f, m));
|
|
1005
1066
|
}
|
|
1006
1067
|
let a = [], o = [], d = [], h = s.tables.length;
|
|
1007
1068
|
for (let p = 0; p < s.tables.length; p++) {
|
|
@@ -1018,7 +1079,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1018
1079
|
});
|
|
1019
1080
|
continue;
|
|
1020
1081
|
}
|
|
1021
|
-
let
|
|
1082
|
+
let y = i.join(t.bundleDir, g.file);
|
|
1022
1083
|
K(t.onProgress, {
|
|
1023
1084
|
phase: "import",
|
|
1024
1085
|
table: g.name,
|
|
@@ -1028,17 +1089,17 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1028
1089
|
rowsDone: 0,
|
|
1029
1090
|
total: g.rowCount
|
|
1030
1091
|
});
|
|
1031
|
-
let
|
|
1032
|
-
let { createHash: r } = yield* n.promise(() => import("node:crypto")), i = r("sha256"), o = 0, l = w("bundle", () =>
|
|
1092
|
+
let b = a.length, x = n.gen(function* () {
|
|
1093
|
+
let { createHash: r } = yield* n.promise(() => import("node:crypto")), i = r("sha256"), o = 0, l = w("bundle", () => O(y).pipe(Ye(s.compression))).pipe(c.tap((e) => n.sync(() => i.update(e)))), d = async (t) => {
|
|
1033
1094
|
let n = {
|
|
1034
1095
|
entry: g,
|
|
1035
1096
|
row: t,
|
|
1036
1097
|
reason: ""
|
|
1037
1098
|
};
|
|
1038
1099
|
try {
|
|
1039
|
-
await _(e, g, t);
|
|
1100
|
+
await v(e, () => _(e, g, t));
|
|
1040
1101
|
} catch (e) {
|
|
1041
|
-
n.reason =
|
|
1102
|
+
n.reason = Zt(e), a.push(n);
|
|
1042
1103
|
}
|
|
1043
1104
|
}, f = yield* n.promise(async () => {
|
|
1044
1105
|
let n = t.copyLoader;
|
|
@@ -1057,7 +1118,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1057
1118
|
} catch {
|
|
1058
1119
|
return !1;
|
|
1059
1120
|
}
|
|
1060
|
-
}), p = Object.keys(g.columnTypes), m = Math.max(1, t.copyBatchSize ?? 5e3), h = [],
|
|
1121
|
+
}), p = Object.keys(g.columnTypes), m = Math.max(1, t.copyBatchSize ?? 5e3), h = [], b = async () => {
|
|
1061
1122
|
if (h.length === 0) return;
|
|
1062
1123
|
let e = h;
|
|
1063
1124
|
h = [];
|
|
@@ -1072,28 +1133,43 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1072
1133
|
f = !1, t.onWarn?.(`bulk COPY into ${g.name} failed (${String(n?.message ?? n)}); falling back to per-row writes for this table`);
|
|
1073
1134
|
for (let t of e) await d(t);
|
|
1074
1135
|
}
|
|
1136
|
+
}, x = Math.max(1, t.savepointBatchSize ?? 200), S = typeof e.savepoint == "function", C = [], T = async () => {
|
|
1137
|
+
if (C.length === 0) return;
|
|
1138
|
+
let t = C;
|
|
1139
|
+
C = [];
|
|
1140
|
+
try {
|
|
1141
|
+
await e.savepoint(async () => {
|
|
1142
|
+
for (let n of t) await _(e, g, n);
|
|
1143
|
+
});
|
|
1144
|
+
} catch {
|
|
1145
|
+
for (let e of t) await d(e);
|
|
1146
|
+
}
|
|
1075
1147
|
};
|
|
1076
1148
|
return yield* c.runForEach(kt(l, g.name, g.columnTypes), (e) => n.promise(async () => {
|
|
1077
1149
|
if (o++, f) {
|
|
1078
|
-
h.push(e), h.length >= m && await
|
|
1150
|
+
h.push(e), h.length >= m && await b();
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
if (S) {
|
|
1154
|
+
C.push(e), C.length >= x && await T();
|
|
1079
1155
|
return;
|
|
1080
1156
|
}
|
|
1081
1157
|
await d(e);
|
|
1082
|
-
})), yield* n.promise(
|
|
1158
|
+
})), yield* n.promise(T), yield* n.promise(b), {
|
|
1083
1159
|
rowCount: o,
|
|
1084
1160
|
checksum: i.digest("hex")
|
|
1085
1161
|
};
|
|
1086
|
-
}), { rowCount:
|
|
1162
|
+
}), { rowCount: S, checksum: C } = yield* ft("import", g.name, p, h, (e) => e.rowCount, x);
|
|
1087
1163
|
if (l) {
|
|
1088
|
-
if (
|
|
1164
|
+
if (C !== g.checksum) return yield* n.fail(new z({
|
|
1089
1165
|
what: `table ${g.name} checksum`,
|
|
1090
1166
|
expected: g.checksum,
|
|
1091
|
-
actual:
|
|
1167
|
+
actual: C
|
|
1092
1168
|
}));
|
|
1093
|
-
if (
|
|
1169
|
+
if (S !== g.rowCount) return yield* n.fail(new z({
|
|
1094
1170
|
what: `table ${g.name} rowCount`,
|
|
1095
1171
|
expected: String(g.rowCount),
|
|
1096
|
-
actual: String(
|
|
1172
|
+
actual: String(S)
|
|
1097
1173
|
}));
|
|
1098
1174
|
}
|
|
1099
1175
|
K(t.onProgress, {
|
|
@@ -1102,17 +1178,17 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1102
1178
|
index: p,
|
|
1103
1179
|
tableCount: h,
|
|
1104
1180
|
event: "done",
|
|
1105
|
-
rowsDone:
|
|
1181
|
+
rowsDone: S,
|
|
1106
1182
|
total: g.rowCount
|
|
1107
|
-
}), r && (a.length >
|
|
1183
|
+
}), r && (a.length > b ? o.push({
|
|
1108
1184
|
name: g.name,
|
|
1109
|
-
rowCount:
|
|
1185
|
+
rowCount: S
|
|
1110
1186
|
}) : (m.tables[g.name] = {
|
|
1111
|
-
rowCount:
|
|
1187
|
+
rowCount: S,
|
|
1112
1188
|
checksum: g.checksum
|
|
1113
1189
|
}, yield* q(f, m)));
|
|
1114
1190
|
}
|
|
1115
|
-
if (a.length > 0 && (yield*
|
|
1191
|
+
if (a.length > 0 && (yield* S(e, a)), r && o.length > 0) {
|
|
1116
1192
|
for (let e of o) {
|
|
1117
1193
|
let t = s.tables.find((t) => t.name === e.name);
|
|
1118
1194
|
m.tables[e.name] = {
|
|
@@ -1129,25 +1205,25 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1129
1205
|
});
|
|
1130
1206
|
if (t.atomic ? yield* n.tryPromise({
|
|
1131
1207
|
try: () => t.store.transactional(async (t) => {
|
|
1132
|
-
let i = await n.runPromiseExit(
|
|
1208
|
+
let i = await n.runPromiseExit(C(t, !1));
|
|
1133
1209
|
if (r.isFailure(i)) throw Error(e.pretty(i.cause));
|
|
1134
1210
|
}),
|
|
1135
|
-
catch: (e) => new
|
|
1136
|
-
}) : yield*
|
|
1137
|
-
let e = t.assets, r = i.join(t.bundleDir,
|
|
1138
|
-
yield* c.runForEach(o, (t) => t.key in m.assets ? n.void :
|
|
1211
|
+
catch: (e) => new R({ reason: `atomic import failed (rolled back): ${String(e?.message ?? e)}` })
|
|
1212
|
+
}) : yield* C(t.store, !0), t.assets && s.assets.index && !t.assetsAlreadyRestored) {
|
|
1213
|
+
let e = t.assets, r = i.join(t.bundleDir, G), a = i.join(t.bundleDir, s.assets.index ?? "assets/index.ndjson"), o = w("bundle", () => O(a)).pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.map((e) => JSON.parse(e)));
|
|
1214
|
+
yield* c.runForEach(o, (t) => t.key in m.assets ? n.void : We(e, r, t).pipe(n.andThen(n.sync(() => {
|
|
1139
1215
|
m.assets[t.key] = !0;
|
|
1140
1216
|
})), n.andThen(q(f, m))));
|
|
1141
1217
|
}
|
|
1142
1218
|
return s;
|
|
1143
|
-
}),
|
|
1219
|
+
}), sn = (e) => e, cn = (e) => {
|
|
1144
1220
|
if (e.allowLive || e.liveInstance === null || e.sameTarget === "different") return { refuse: !1 };
|
|
1145
1221
|
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.";
|
|
1146
1222
|
return {
|
|
1147
1223
|
refuse: !0,
|
|
1148
1224
|
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).`
|
|
1149
1225
|
};
|
|
1150
|
-
}, Y = Buffer.from("VBUNDLE2"),
|
|
1226
|
+
}, Y = Buffer.from("VBUNDLE2"), ln = 0, un = 1, dn = 2, fn = 32, pn = async (e) => {
|
|
1151
1227
|
let t = [], n = async (r) => {
|
|
1152
1228
|
let i;
|
|
1153
1229
|
try {
|
|
@@ -1161,21 +1237,21 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1161
1237
|
}
|
|
1162
1238
|
};
|
|
1163
1239
|
return await n(""), t.sort();
|
|
1164
|
-
},
|
|
1240
|
+
}, mn = (e, t) => {
|
|
1165
1241
|
let n = Buffer.from(e, "utf8"), r = Buffer.alloc(5 + n.length + 8);
|
|
1166
|
-
return r.writeUInt8(
|
|
1167
|
-
},
|
|
1242
|
+
return r.writeUInt8(un, 0), r.writeUInt32BE(n.length, 1), n.copy(r, 5), r.writeBigUInt64BE(BigInt(t), 5 + n.length), r;
|
|
1243
|
+
}, hn = (e, t, n) => {
|
|
1168
1244
|
let r = Buffer.from(e, "utf8"), i = Buffer.from(t, "utf8"), a = Buffer.alloc(5 + r.length + 2 + i.length + 8), o = 0;
|
|
1169
|
-
return a.writeUInt8(
|
|
1245
|
+
return a.writeUInt8(dn, 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;
|
|
1170
1246
|
};
|
|
1171
|
-
async function*
|
|
1247
|
+
async function* gn(e) {
|
|
1172
1248
|
yield new Uint8Array(Y);
|
|
1173
|
-
for (let t of await
|
|
1249
|
+
for (let t of await pn(e.dir)) {
|
|
1174
1250
|
let n = k(e.dir, t), r = await le(n);
|
|
1175
|
-
if (yield new Uint8Array(
|
|
1251
|
+
if (yield new Uint8Array(mn(t, r.size)), r.size > 0) for await (let e of O(n)) yield new Uint8Array(e);
|
|
1176
1252
|
}
|
|
1177
1253
|
if (e.blobs) for await (let t of e.blobs.list()) {
|
|
1178
|
-
yield new Uint8Array(
|
|
1254
|
+
yield new Uint8Array(hn(t.key, t.contentType, t.size));
|
|
1179
1255
|
let n = y("sha256"), r = 0;
|
|
1180
1256
|
for await (let i of e.blobs.open(t.key)) {
|
|
1181
1257
|
let e = Buffer.from(i);
|
|
@@ -1184,11 +1260,11 @@ async function* fn(e) {
|
|
|
1184
1260
|
if (r !== t.size) throw Error(`blob '${t.key}' size mismatch: header ${t.size}, streamed ${r}`);
|
|
1185
1261
|
yield new Uint8Array(n.digest());
|
|
1186
1262
|
}
|
|
1187
|
-
yield new Uint8Array(Buffer.from([
|
|
1263
|
+
yield new Uint8Array(Buffer.from([ln]));
|
|
1188
1264
|
}
|
|
1189
|
-
var
|
|
1265
|
+
var _n = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), vn = (e) => new Promise((t) => e.end(t)), yn = async (e, t) => {
|
|
1190
1266
|
let n = pe(t.dir);
|
|
1191
|
-
await
|
|
1267
|
+
await se(n, { recursive: !0 });
|
|
1192
1268
|
let r = Buffer.alloc(0), i = e[Symbol.asyncIterator](), a = !1, o = async () => {
|
|
1193
1269
|
let { value: e, done: t } = await i.next();
|
|
1194
1270
|
return t ? (a = !0, !1) : (r = r.length === 0 ? Buffer.from(e) : Buffer.concat([r, Buffer.from(e)]), !0);
|
|
@@ -1203,8 +1279,8 @@ var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn
|
|
|
1203
1279
|
for (;;) {
|
|
1204
1280
|
await s(1);
|
|
1205
1281
|
let e = c(1).readUInt8(0);
|
|
1206
|
-
if (e ===
|
|
1207
|
-
if (e ===
|
|
1282
|
+
if (e === ln) return;
|
|
1283
|
+
if (e === un) {
|
|
1208
1284
|
await s(4);
|
|
1209
1285
|
let e = c(4).readUInt32BE(0);
|
|
1210
1286
|
await s(e);
|
|
@@ -1212,15 +1288,15 @@ var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn
|
|
|
1212
1288
|
await s(8);
|
|
1213
1289
|
let i = c(8).readBigUInt64BE(0), a = pe(n, t);
|
|
1214
1290
|
if (a !== n && !a.startsWith(n + me)) throw Error(`archive path '${t}' escapes the destination`);
|
|
1215
|
-
await
|
|
1216
|
-
let o =
|
|
1291
|
+
await se(fe(a), { recursive: !0 });
|
|
1292
|
+
let o = ie(a);
|
|
1217
1293
|
for (; i > 0n;) {
|
|
1218
1294
|
r.length === 0 && await s(1);
|
|
1219
1295
|
let e = i < BigInt(r.length) ? Number(i) : r.length;
|
|
1220
|
-
await
|
|
1296
|
+
await _n(o, c(e)), i -= BigInt(e);
|
|
1221
1297
|
}
|
|
1222
|
-
await
|
|
1223
|
-
} else if (e ===
|
|
1298
|
+
await vn(o);
|
|
1299
|
+
} else if (e === dn) {
|
|
1224
1300
|
await s(4);
|
|
1225
1301
|
let e = c(4).readUInt32BE(0);
|
|
1226
1302
|
await s(e);
|
|
@@ -1230,24 +1306,24 @@ var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn
|
|
|
1230
1306
|
await s(i);
|
|
1231
1307
|
let a = c(i).toString("utf8");
|
|
1232
1308
|
await s(8);
|
|
1233
|
-
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = y("sha256"), d = new
|
|
1309
|
+
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = y("sha256"), d = new D(), f = l ? Promise.resolve() : t.blobs.write(n, d, {
|
|
1234
1310
|
contentType: a,
|
|
1235
1311
|
size: Number(o)
|
|
1236
1312
|
}), p = o;
|
|
1237
1313
|
for (; p > 0n;) {
|
|
1238
1314
|
r.length === 0 && await s(1);
|
|
1239
1315
|
let e = p < BigInt(r.length) ? Number(p) : r.length, t = c(e);
|
|
1240
|
-
u.update(t), l || await
|
|
1316
|
+
u.update(t), l || await _n(d, t), p -= BigInt(e);
|
|
1241
1317
|
}
|
|
1242
|
-
l ? d.destroy() : await
|
|
1243
|
-
let m = c(
|
|
1318
|
+
l ? d.destroy() : await vn(d), await f, await s(fn);
|
|
1319
|
+
let m = c(fn);
|
|
1244
1320
|
if (!u.digest().equals(m)) throw Error(`blob '${n}' failed integrity (sha mismatch)`);
|
|
1245
1321
|
} else throw Error(`unknown bundle entry kind ${e}`);
|
|
1246
1322
|
}
|
|
1247
1323
|
} finally {
|
|
1248
1324
|
a || await Promise.resolve(i.return?.()).catch(() => void 0);
|
|
1249
1325
|
}
|
|
1250
|
-
},
|
|
1326
|
+
}, bn = async (e, t) => {
|
|
1251
1327
|
let n = new Set(t), r = /* @__PURE__ */ new Map(), i = Buffer.alloc(0), a = e[Symbol.asyncIterator](), o = async () => {
|
|
1252
1328
|
let { value: e, done: t } = await a.next();
|
|
1253
1329
|
return !t && (i = i.length === 0 ? Buffer.from(e) : Buffer.concat([i, Buffer.from(e)]), !0);
|
|
@@ -1269,8 +1345,8 @@ var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn
|
|
|
1269
1345
|
if (!await s(Y.length) || !c(Y.length).equals(Y)) throw Error("not a bundle archive (bad magic)");
|
|
1270
1346
|
for (; await s(1);) {
|
|
1271
1347
|
let e = c(1).readUInt8(0);
|
|
1272
|
-
if (e ===
|
|
1273
|
-
if (e !==
|
|
1348
|
+
if (e === ln || e === dn) break;
|
|
1349
|
+
if (e !== un) throw Error(`unknown bundle entry kind ${e}`);
|
|
1274
1350
|
if (!await s(4)) break;
|
|
1275
1351
|
let t = c(4).readUInt32BE(0);
|
|
1276
1352
|
if (!await s(t)) break;
|
|
@@ -1280,20 +1356,20 @@ var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn
|
|
|
1280
1356
|
if (a === null || n.has(i) && (r.set(i, a), n.delete(i), n.size === 0)) break;
|
|
1281
1357
|
}
|
|
1282
1358
|
return r;
|
|
1283
|
-
},
|
|
1359
|
+
}, xn = (e, t) => yn(e, {
|
|
1284
1360
|
dir: t,
|
|
1285
|
-
blobs:
|
|
1286
|
-
}),
|
|
1361
|
+
blobs: Sn(t)
|
|
1362
|
+
}), Sn = (e) => {
|
|
1287
1363
|
let t = /* @__PURE__ */ new Set();
|
|
1288
1364
|
return {
|
|
1289
1365
|
has: async (e) => t.has(e),
|
|
1290
1366
|
write: async (n, r, i) => {
|
|
1291
1367
|
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c = k(e, "assets");
|
|
1292
|
-
await
|
|
1368
|
+
await se(c, { recursive: !0 });
|
|
1293
1369
|
let l = y("sha256"), u = 0, d = new s({ transform(e, t, n) {
|
|
1294
1370
|
l.update(e), u += e.length, n(null, e);
|
|
1295
1371
|
} }), f = k(c, `.tmp-${Date.now()}-${t.size}`);
|
|
1296
|
-
await o(r, d,
|
|
1372
|
+
await o(r, d, ie(f));
|
|
1297
1373
|
let p = l.digest("hex");
|
|
1298
1374
|
await a.rename(f, k(c, p)), await a.appendFile(k(c, "index.ndjson"), `${JSON.stringify({
|
|
1299
1375
|
key: n,
|
|
@@ -1303,33 +1379,33 @@ var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn
|
|
|
1303
1379
|
})}\n`), t.add(n);
|
|
1304
1380
|
}
|
|
1305
1381
|
};
|
|
1306
|
-
},
|
|
1382
|
+
}, Cn = he(S), wn = Buffer.from("VENC1\0\0\0"), Tn = 32, En = 16, Dn = 7, X = 16, On = 262144, Z = {
|
|
1307
1383
|
N: 32768,
|
|
1308
1384
|
r: 8,
|
|
1309
1385
|
p: 1
|
|
1310
|
-
},
|
|
1386
|
+
}, kn = 134217728, Q = 43, An = (e, t, n) => {
|
|
1311
1387
|
let r = Buffer.alloc(12);
|
|
1312
|
-
return e.copy(r, 0, 0,
|
|
1388
|
+
return e.copy(r, 0, 0, Dn), r.writeUInt32BE(t >>> 0, Dn), r.writeUInt8(+!!n, 11), r;
|
|
1313
1389
|
};
|
|
1314
|
-
async function*
|
|
1390
|
+
async function* jn(e, t) {
|
|
1315
1391
|
if (!t) throw Error("encryptStream: a non-empty passphrase is required");
|
|
1316
|
-
let n = x(
|
|
1392
|
+
let n = x(En), r = x(Dn), i = await Cn(t, n, Tn, {
|
|
1317
1393
|
...Z,
|
|
1318
|
-
maxmem:
|
|
1394
|
+
maxmem: kn
|
|
1319
1395
|
}), a = Buffer.alloc(Q);
|
|
1320
|
-
|
|
1396
|
+
wn.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);
|
|
1321
1397
|
let o = 0, s = (e, t) => {
|
|
1322
|
-
let n = _("aes-256-gcm", i,
|
|
1398
|
+
let n = _("aes-256-gcm", i, An(r, o, t));
|
|
1323
1399
|
o === 0 && n.setAAD(a);
|
|
1324
1400
|
let s = Buffer.concat([n.update(e), n.final()]), c = n.getAuthTag();
|
|
1325
1401
|
o++;
|
|
1326
1402
|
let l = Buffer.alloc(5 + s.length + X);
|
|
1327
1403
|
return l.writeUInt8(+!!t, 0), l.writeUInt32BE(s.length + X, 1), s.copy(l, 5), c.copy(l, 5 + s.length), new Uint8Array(l);
|
|
1328
1404
|
}, c = Buffer.alloc(0);
|
|
1329
|
-
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length >
|
|
1405
|
+
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length > On;) yield s(c.subarray(0, On), !1), c = c.subarray(On);
|
|
1330
1406
|
yield s(c, !0);
|
|
1331
1407
|
}
|
|
1332
|
-
async function*
|
|
1408
|
+
async function* Mn(e, t) {
|
|
1333
1409
|
if (!t) throw Error("decryptStream: a non-empty passphrase is required");
|
|
1334
1410
|
let n = e[Symbol.asyncIterator](), r = Buffer.alloc(0), i = !1, a = async () => {
|
|
1335
1411
|
let { value: e, done: t } = await n.next();
|
|
@@ -1340,12 +1416,12 @@ async function* On(e, t) {
|
|
|
1340
1416
|
};
|
|
1341
1417
|
if (!await o(Q)) throw Error("encrypted bundle truncated (no header)");
|
|
1342
1418
|
let s = r.subarray(0, Q);
|
|
1343
|
-
if (!s.subarray(0, 8).equals(
|
|
1344
|
-
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
|
|
1419
|
+
if (!s.subarray(0, 8).equals(wn)) throw Error("not an encrypted bundle (bad magic / wrong passphrase target)");
|
|
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 Cn(t, d, Tn, {
|
|
1345
1421
|
N: c,
|
|
1346
1422
|
r: l,
|
|
1347
1423
|
p: u,
|
|
1348
|
-
maxmem:
|
|
1424
|
+
maxmem: kn
|
|
1349
1425
|
});
|
|
1350
1426
|
r = r.subarray(Q);
|
|
1351
1427
|
let m = 0, h = !1;
|
|
@@ -1360,7 +1436,7 @@ async function* On(e, t) {
|
|
|
1360
1436
|
if (!await o(5 + t)) throw Error("encrypted bundle truncated (frame body)");
|
|
1361
1437
|
let n = r.subarray(5, 5 + t - X), i = r.subarray(5 + t - X, 5 + t);
|
|
1362
1438
|
r = r.subarray(5 + t);
|
|
1363
|
-
let a = v("aes-256-gcm", p,
|
|
1439
|
+
let a = v("aes-256-gcm", p, An(f, m, e));
|
|
1364
1440
|
m === 0 && a.setAAD(s), a.setAuthTag(i);
|
|
1365
1441
|
let c = Buffer.concat([a.update(n), a.final()]);
|
|
1366
1442
|
m++, e && (h = !0), c.length > 0 && (yield new Uint8Array(c));
|
|
@@ -1368,7 +1444,7 @@ async function* On(e, t) {
|
|
|
1368
1444
|
}
|
|
1369
1445
|
//#endregion
|
|
1370
1446
|
//#region src/blobStorage.ts
|
|
1371
|
-
var
|
|
1447
|
+
var Nn = (e, t) => ({
|
|
1372
1448
|
list: () => {
|
|
1373
1449
|
let e = t();
|
|
1374
1450
|
return { async *[Symbol.asyncIterator]() {
|
|
@@ -1381,29 +1457,29 @@ var kn = (e, t) => ({
|
|
|
1381
1457
|
} };
|
|
1382
1458
|
},
|
|
1383
1459
|
open: (t) => ({ async *[Symbol.asyncIterator]() {
|
|
1384
|
-
let r = await n.runPromise(
|
|
1460
|
+
let r = await n.runPromise(T(e, t)), i = await te(r.stream);
|
|
1385
1461
|
for await (let e of i) yield e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
1386
1462
|
} })
|
|
1387
|
-
}),
|
|
1463
|
+
}), Pn = (e, t) => Nn(e, () => h(t, {
|
|
1388
1464
|
table: C,
|
|
1389
1465
|
chunkSize: 500
|
|
1390
1466
|
}).pipe(c.map((e) => ({
|
|
1391
1467
|
key: String(e.key),
|
|
1392
1468
|
contentType: String(e.contentType ?? "application/octet-stream"),
|
|
1393
1469
|
size: Number(e.size ?? 0)
|
|
1394
|
-
})))),
|
|
1470
|
+
})))), Fn = (e) => ({
|
|
1395
1471
|
has: (t) => n.runPromise(e.head(t).pipe(n.map((e) => e !== null))),
|
|
1396
1472
|
write: async (t, r, i) => {
|
|
1397
|
-
let a = w("storage", () =>
|
|
1398
|
-
await n.runPromise(
|
|
1473
|
+
let a = w("storage", () => ne.from(r));
|
|
1474
|
+
await n.runPromise(ee(e, t, a, {
|
|
1399
1475
|
contentType: i.contentType,
|
|
1400
1476
|
totalSize: i.size
|
|
1401
1477
|
}));
|
|
1402
1478
|
}
|
|
1403
|
-
}),
|
|
1479
|
+
}), In = (e, t) => {
|
|
1404
1480
|
let n = t === "dump" ? "mariadb-dump" : "mariadb", r = t === "dump" ? "mysqldump" : "mysql";
|
|
1405
|
-
return e === "mariadb" &&
|
|
1406
|
-
},
|
|
1481
|
+
return e === "mariadb" && Ln(n) ? n : r;
|
|
1482
|
+
}, Ln = (e) => (process.env.PATH ?? "").split(de).filter((e) => e !== "").some((t) => ae(k(t, e))), Rn = (e) => {
|
|
1407
1483
|
switch (e) {
|
|
1408
1484
|
case "postgres": return "db.dump";
|
|
1409
1485
|
case "mysql":
|
|
@@ -1413,7 +1489,7 @@ var kn = (e, t) => ({
|
|
|
1413
1489
|
case "mssql": return "db.bacpac";
|
|
1414
1490
|
default: return "db.dump";
|
|
1415
1491
|
}
|
|
1416
|
-
},
|
|
1492
|
+
}, zn = (e) => e.filename ?? e.database ?? ((e.url ?? "").replace(/^file:/, "") || "app.sqlite"), $ = (e) => {
|
|
1417
1493
|
if (e.host || e.database) return {
|
|
1418
1494
|
host: e.host ?? "localhost",
|
|
1419
1495
|
port: e.port ?? 3306,
|
|
@@ -1429,7 +1505,7 @@ var kn = (e, t) => ({
|
|
|
1429
1505
|
password: decodeURIComponent(t.password) || "",
|
|
1430
1506
|
database: t.pathname.replace(/^\//, "") || ""
|
|
1431
1507
|
};
|
|
1432
|
-
},
|
|
1508
|
+
}, Bn = (e) => `Server=${e.host},${e.port};Database=${e.database};User ID=${e.username};Password=${e.password};TrustServerCertificate=True`, Vn = (e, t, n) => {
|
|
1433
1509
|
switch (e) {
|
|
1434
1510
|
case "postgres": {
|
|
1435
1511
|
if (t.url) return {
|
|
@@ -1476,7 +1552,7 @@ var kn = (e, t) => ({
|
|
|
1476
1552
|
let r = $(t);
|
|
1477
1553
|
return {
|
|
1478
1554
|
kind: "spawn",
|
|
1479
|
-
tool:
|
|
1555
|
+
tool: In(e, "dump"),
|
|
1480
1556
|
args: [
|
|
1481
1557
|
"--single-transaction",
|
|
1482
1558
|
"--routines",
|
|
@@ -1498,7 +1574,7 @@ var kn = (e, t) => ({
|
|
|
1498
1574
|
case "sqlite":
|
|
1499
1575
|
case "turso": return {
|
|
1500
1576
|
kind: "copy",
|
|
1501
|
-
from:
|
|
1577
|
+
from: zn(t),
|
|
1502
1578
|
to: n
|
|
1503
1579
|
};
|
|
1504
1580
|
case "mssql": return {
|
|
@@ -1506,7 +1582,7 @@ var kn = (e, t) => ({
|
|
|
1506
1582
|
tool: "sqlpackage",
|
|
1507
1583
|
args: [
|
|
1508
1584
|
"/Action:Export",
|
|
1509
|
-
`/SourceConnectionString:${
|
|
1585
|
+
`/SourceConnectionString:${Bn($({
|
|
1510
1586
|
...t,
|
|
1511
1587
|
port: t.port ?? 1433
|
|
1512
1588
|
}))}`,
|
|
@@ -1514,12 +1590,12 @@ var kn = (e, t) => ({
|
|
|
1514
1590
|
],
|
|
1515
1591
|
env: {}
|
|
1516
1592
|
};
|
|
1517
|
-
default: throw new
|
|
1593
|
+
default: throw new V({
|
|
1518
1594
|
tool: "backup",
|
|
1519
1595
|
reason: `no native backup for dialect '${e}'`
|
|
1520
1596
|
});
|
|
1521
1597
|
}
|
|
1522
|
-
},
|
|
1598
|
+
}, Hn = (e, t, n) => {
|
|
1523
1599
|
switch (e) {
|
|
1524
1600
|
case "postgres": {
|
|
1525
1601
|
if (t.url) return {
|
|
@@ -1564,7 +1640,7 @@ var kn = (e, t) => ({
|
|
|
1564
1640
|
let r = $(t);
|
|
1565
1641
|
return {
|
|
1566
1642
|
kind: "spawn",
|
|
1567
|
-
tool:
|
|
1643
|
+
tool: In(e, "client"),
|
|
1568
1644
|
args: [
|
|
1569
1645
|
"--protocol=TCP",
|
|
1570
1646
|
"-h",
|
|
@@ -1583,14 +1659,14 @@ var kn = (e, t) => ({
|
|
|
1583
1659
|
case "turso": return {
|
|
1584
1660
|
kind: "copy",
|
|
1585
1661
|
from: n,
|
|
1586
|
-
to:
|
|
1662
|
+
to: zn(t)
|
|
1587
1663
|
};
|
|
1588
1664
|
case "mssql": return {
|
|
1589
1665
|
kind: "spawn",
|
|
1590
1666
|
tool: "sqlpackage",
|
|
1591
1667
|
args: [
|
|
1592
1668
|
"/Action:Import",
|
|
1593
|
-
`/TargetConnectionString:${
|
|
1669
|
+
`/TargetConnectionString:${Bn($({
|
|
1594
1670
|
...t,
|
|
1595
1671
|
port: t.port ?? 1433
|
|
1596
1672
|
}))}`,
|
|
@@ -1598,13 +1674,13 @@ var kn = (e, t) => ({
|
|
|
1598
1674
|
],
|
|
1599
1675
|
env: {}
|
|
1600
1676
|
};
|
|
1601
|
-
default: throw new
|
|
1677
|
+
default: throw new V({
|
|
1602
1678
|
tool: "restore",
|
|
1603
1679
|
reason: `no native restore for dialect '${e}'`
|
|
1604
1680
|
});
|
|
1605
1681
|
}
|
|
1606
|
-
},
|
|
1607
|
-
|
|
1682
|
+
}, Un = (e) => e.kind === "copy" ? n.async((t) => {
|
|
1683
|
+
re(e.from, e.to, (r) => t(r ? n.fail(new V({
|
|
1608
1684
|
tool: "copy",
|
|
1609
1685
|
reason: `copy ${e.from} → ${e.to}: ${r.message}`
|
|
1610
1686
|
})) : n.void));
|
|
@@ -1622,14 +1698,14 @@ var kn = (e, t) => ({
|
|
|
1622
1698
|
}), i = "";
|
|
1623
1699
|
r.stderr?.on("data", (e) => {
|
|
1624
1700
|
i += String(e);
|
|
1625
|
-
}), e.stdoutFile && r.stdout && r.stdout.pipe(
|
|
1701
|
+
}), e.stdoutFile && r.stdout && r.stdout.pipe(ie(e.stdoutFile)), e.stdinFile && r.stdin && O(e.stdinFile).pipe(r.stdin);
|
|
1626
1702
|
let a = () => {
|
|
1627
1703
|
if (e.stdoutFile !== void 0) try {
|
|
1628
|
-
|
|
1704
|
+
oe(e.stdoutFile);
|
|
1629
1705
|
} catch {}
|
|
1630
1706
|
};
|
|
1631
1707
|
r.on("error", (r) => {
|
|
1632
|
-
a(), t(n.fail(new
|
|
1708
|
+
a(), t(n.fail(new V({
|
|
1633
1709
|
tool: e.tool,
|
|
1634
1710
|
reason: `failed to launch (is '${e.tool}' installed + on PATH?): ${r.message}`
|
|
1635
1711
|
})));
|
|
@@ -1638,17 +1714,17 @@ var kn = (e, t) => ({
|
|
|
1638
1714
|
t(n.void);
|
|
1639
1715
|
return;
|
|
1640
1716
|
}
|
|
1641
|
-
a(), t(n.fail(new
|
|
1717
|
+
a(), t(n.fail(new V({
|
|
1642
1718
|
tool: e.tool,
|
|
1643
1719
|
reason: `exited with code ${r}` + (e.stdoutFile === void 0 ? "" : ` — the partial ${ue(e.stdoutFile)} was removed, so it cannot be mistaken for a backup`),
|
|
1644
1720
|
stderr: i.slice(-2e3)
|
|
1645
1721
|
})));
|
|
1646
1722
|
});
|
|
1647
|
-
}),
|
|
1648
|
-
let t = yield*
|
|
1723
|
+
}), Wn = (e) => typeof e == "object" && e ? "fake" in e ? `fake:${e.fake}` : "custom" : String(e), Gn = (e) => n.gen(function* () {
|
|
1724
|
+
let t = yield* Be(e.scope ?? { kind: "all" }, e.snapshot, {
|
|
1649
1725
|
store: e.store,
|
|
1650
1726
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
1651
|
-
}), r = At(t.tables, e.snapshot), i = e.classification ?? A(e.snapshot), a = e.sampleSize ?? 20, o =
|
|
1727
|
+
}), r = At(t.tables, e.snapshot), i = e.classification ?? A(e.snapshot), a = e.sampleSize ?? 20, o = I(r.map((t) => ({
|
|
1652
1728
|
name: t,
|
|
1653
1729
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
1654
1730
|
name: e.name,
|
|
@@ -1660,15 +1736,15 @@ var kn = (e, t) => ({
|
|
|
1660
1736
|
table: i,
|
|
1661
1737
|
chunkSize: a,
|
|
1662
1738
|
...r === void 0 ? {} : { where: r }
|
|
1663
|
-
}).pipe(c.take(a), c.runCollect, n.map((e) => [...e])), d = u.map((t) =>
|
|
1664
|
-
l.push(...
|
|
1739
|
+
}).pipe(c.take(a), c.runCollect, n.map((e) => [...e])), d = u.map((t) => L(t, i, o.actions, e.masking.seed));
|
|
1740
|
+
l.push(...ke(d, i, o.actions));
|
|
1665
1741
|
let f = u[0], p = d[0], m = [];
|
|
1666
1742
|
if (f && p) for (let [e, t] of Object.entries(o.actions)) {
|
|
1667
1743
|
if (!e.startsWith(`${i}.`) || t === "keep") continue;
|
|
1668
1744
|
let n = e.slice(i.length + 1);
|
|
1669
1745
|
m.push({
|
|
1670
1746
|
column: n,
|
|
1671
|
-
action:
|
|
1747
|
+
action: Wn(t),
|
|
1672
1748
|
before: f[n],
|
|
1673
1749
|
after: p[n]
|
|
1674
1750
|
});
|
|
@@ -1683,7 +1759,7 @@ var kn = (e, t) => ({
|
|
|
1683
1759
|
leaks: l,
|
|
1684
1760
|
unclassified: o.unclassified
|
|
1685
1761
|
};
|
|
1686
|
-
}),
|
|
1762
|
+
}), Kn = (e, t) => {
|
|
1687
1763
|
let n = new Map(t.map((e) => [e.name, e])), r = [], i = {};
|
|
1688
1764
|
for (let t of e) {
|
|
1689
1765
|
let e = n.get(t.name);
|
|
@@ -1738,7 +1814,7 @@ var kn = (e, t) => ({
|
|
|
1738
1814
|
skipColumns: i,
|
|
1739
1815
|
refuse: r.some((e) => e.verdict === "refuse")
|
|
1740
1816
|
};
|
|
1741
|
-
},
|
|
1817
|
+
}, qn = (e) => {
|
|
1742
1818
|
if (e.findings.length === 0) return [" schema matches the bundle"];
|
|
1743
1819
|
let t = {
|
|
1744
1820
|
safe: "✓",
|
|
@@ -1749,4 +1825,4 @@ var kn = (e, t) => ({
|
|
|
1749
1825
|
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;
|
|
1750
1826
|
};
|
|
1751
1827
|
//#endregion
|
|
1752
|
-
export {
|
|
1828
|
+
export { G as ASSETS_DIR, at as ASSET_INDEX_FILE, R as BundleError, Ae as CodecError, je as CompressionError, Ie as CrossDialectError, it as DATA_DIR, ve as DEFAULT_CLASS_ACTIONS, Xe as FORMAT_VERSION, Fe as ImportModeError, z as IntegrityError, ot as LEDGER_FILE, W as MANIFEST_FILE, Pe as MaskingError, V as NativeToolError, Me as RowsRefusedError, rn as SAVEPOINT_BATCH_SIZE, Ne as SchemaDriftError, B as ScopeError, Ee as applyAction, cn as assessLiveImport, gt as assetDone, Rn as backupArtifactName, Vn as backupCommand, Wt as canonicalType, qt as checkPortability, nn as checkSchemaDrift, A as classificationFromSnapshot, Kn as classifyImportDrift, qe as compressionExt, Re as computeSubsetIds, nt as decodeManifest, Et as decodeRow, wt as decodeValue, Mn as decryptStream, sn as defineDataProfile, tn as diffSnapshots, Sn as dirBlobSink, pt as emptyLedger, tt as encodeManifest, Tt as encodeRow, St as encodeValue, jn as encryptStream, qn as formatImportDrift, Jt as formatIssue, Ge as hasZstd, Je as makeCompressor, Ye as makeDecompressor, L as maskRow, kt as ndjsonToRows, Ut as outsideReferenceRefusal, Ht as outsideReferencesInto, gn as packBundle, bn as peekBundle, Ke as pickCompression, I as planMasking, Gn as previewMasking, mt as readLedger, ye as resolveAction, Be as resolveScope, We as restoreAssetFromCas, Hn as restoreCommand, Ot as rowsToNdjson, Vt as runExport, on as runImport, Un as runNativeStep, ke as scanForLeaks, He as storageAssetSink, Ve as storageAssetSource, Fn as storageBlobSink, Nn as storageBlobSource, Pn as storageRefsBlobSource, ze as subsetToScope, ht as tableDone, At as topoSortTables, yn as unpackBundle, xn as unpackBundleToDir, Ue as writeAssetToCas, q as writeLedger };
|