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