@voltro/data-transfer 0.42.0 → 0.43.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 +91 -0
- package/dist/index.d.ts +41 -23
- package/dist/index.js +258 -231
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Cause as e, Data as t, Effect as n, Exit as r, Metric as i, MetricBoundaries as a, Schedule as o, Schema as s, Stream as c } from "effect";
|
|
2
2
|
import { classifyConstraintViolation as l, eq as u, extractDbCause as d, inSet as f, isNotNull as p, or as m, streamTable as h } from "@voltro/database";
|
|
3
3
|
import { fingerprintSchema as g } from "@voltro/database/sql";
|
|
4
|
-
import { createCipheriv as _, createDecipheriv as v, createHash as y, createHmac 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
|
|
4
|
+
import { createCipheriv as _, createDecipheriv as v, createHash as y, createHmac as b, randomBytes as x, scrypt as S } from "node:crypto";
|
|
5
|
+
import { STORAGE_REFS_TABLE as C, fromNodeReadable as w, getObjectStream as ee, putObjectStream as te, toNodeReadable as ne } from "@voltro/plugin-storage";
|
|
6
|
+
import * as T from "node:zlib";
|
|
7
|
+
import { PassThrough as re, Readable as ie } from "node:stream";
|
|
8
|
+
import { copyFile as ae, createReadStream as E, createWriteStream as D, existsSync as oe, unlinkSync as se } from "node:fs";
|
|
9
|
+
import { mkdir as O, readdir as ce, stat as le } from "node:fs/promises";
|
|
10
|
+
import { basename as ue, delimiter as de, dirname as fe, join as k, resolve as pe, sep as me } from "node:path";
|
|
11
|
+
import { promisify as he } from "node:util";
|
|
12
|
+
import { spawn as ge } from "node:child_process";
|
|
13
13
|
//#region src/consistency.ts
|
|
14
|
-
var
|
|
14
|
+
var _e = (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 ve = (e) => {
|
|
|
21
21
|
case "turso": return [];
|
|
22
22
|
default: return [];
|
|
23
23
|
}
|
|
24
|
-
},
|
|
24
|
+
}, ve = {
|
|
25
25
|
email: { fake: "email" },
|
|
26
26
|
fullName: { fake: "fullName" },
|
|
27
27
|
firstName: { fake: "firstName" },
|
|
@@ -36,7 +36,7 @@ var ve = (e) => {
|
|
|
36
36
|
date: "dateShift",
|
|
37
37
|
secret: "null",
|
|
38
38
|
freeText: "redact"
|
|
39
|
-
},
|
|
39
|
+
}, A = (e) => {
|
|
40
40
|
let t = {};
|
|
41
41
|
for (let n of e.tables) {
|
|
42
42
|
let e = {};
|
|
@@ -48,15 +48,15 @@ var ve = (e) => {
|
|
|
48
48
|
t[n.name] = e;
|
|
49
49
|
}
|
|
50
50
|
return t;
|
|
51
|
-
},
|
|
51
|
+
}, ye = (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] ?? ve[e] ?? "redact";
|
|
57
57
|
}
|
|
58
58
|
return n?.safe ? r.onSafe ?? "keep" : n?.columnType === "id" || n?.columnType === "reference" ? "keep" : r.onUnclassified ?? "error";
|
|
59
|
-
},
|
|
59
|
+
}, be = (e, t) => b("sha256", e).update(t == null ? "∅" : String(t)).digest(), j = (e, t) => e.readUInt32BE(t * 4 % (e.length - 4)), M = [
|
|
60
60
|
"Ada",
|
|
61
61
|
"Alan",
|
|
62
62
|
"Grace",
|
|
@@ -101,7 +101,7 @@ var ve = (e) => {
|
|
|
101
101
|
"Stark",
|
|
102
102
|
"Wayne"
|
|
103
103
|
], N = (e, t, n) => e[j(t, n) % e.length], we = (e, t, n) => {
|
|
104
|
-
let r =
|
|
104
|
+
let r = be(n, `${e}:${String(t)}`), i = j(r, 1) % 1e4;
|
|
105
105
|
switch (e) {
|
|
106
106
|
case "email": return `${N(M, r, 0).toLowerCase()}.${N(xe, r, 2).toLowerCase()}${i}@example.com`;
|
|
107
107
|
case "fullName": return `${N(M, r, 0)} ${N(xe, r, 1)}`;
|
|
@@ -127,7 +127,7 @@ var ve = (e) => {
|
|
|
127
127
|
}, Ee = 864e5, De = (e, t) => {
|
|
128
128
|
let n = e instanceof Date ? e.getTime() : Date.parse(String(e));
|
|
129
129
|
if (Number.isNaN(n)) return e;
|
|
130
|
-
let r = j(
|
|
130
|
+
let r = j(be(t, "date-shift-offset"), 0) % 730 - 365, i = new Date(n + r * Ee);
|
|
131
131
|
return e instanceof Date ? i : i.toISOString();
|
|
132
132
|
}, Oe = (e, t) => {
|
|
133
133
|
if (t.value === null || t.value === void 0) return null;
|
|
@@ -135,7 +135,7 @@ var ve = (e) => {
|
|
|
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
|
|
138
|
+
if (e === "hash") return be(t.seed, t.value).toString("hex").slice(0, 16);
|
|
139
139
|
if (e === "dateShift") return De(t.value, t.seed);
|
|
140
140
|
if (typeof e == "object" && "fake" in e) return we(e.fake, t.value, t.seed);
|
|
141
141
|
if (typeof e == "object" && "custom" in e) return e.custom(t);
|
|
@@ -143,7 +143,7 @@ var ve = (e) => {
|
|
|
143
143
|
}, ke = (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", Ae = (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 = ye(o.name, e.name, t[o.name]?.[e.name], n);
|
|
147
147
|
if (c === "error") {
|
|
148
148
|
i.push(s);
|
|
149
149
|
continue;
|
|
@@ -220,12 +220,14 @@ var ve = (e) => {
|
|
|
220
220
|
what: s.String,
|
|
221
221
|
expected: s.String,
|
|
222
222
|
actual: s.String
|
|
223
|
-
}) {}, Fe = class extends t.TaggedError("CompressionError") {}, I = class extends s.TaggedError()("ScopeError", { reason: s.String }) {}, Ie = class extends s.TaggedError()("
|
|
223
|
+
}) {}, Fe = class extends t.TaggedError("CompressionError") {}, I = class extends s.TaggedError()("ScopeError", { reason: s.String }) {}, Ie = class extends s.TaggedError()("RowsRefusedError", {
|
|
224
224
|
rows: s.Array(s.Struct({
|
|
225
225
|
table: s.String,
|
|
226
226
|
id: s.String,
|
|
227
|
-
reason: s.String
|
|
227
|
+
reason: s.String,
|
|
228
|
+
derived: s.Boolean
|
|
228
229
|
})),
|
|
230
|
+
primaryCount: s.Number,
|
|
229
231
|
totalCount: s.Number
|
|
230
232
|
}) {}, Le = class extends s.TaggedError()("SchemaDriftError", {
|
|
231
233
|
bundleFingerprint: s.String,
|
|
@@ -338,16 +340,16 @@ var ve = (e) => {
|
|
|
338
340
|
};
|
|
339
341
|
}), Ue = (e, t) => ({
|
|
340
342
|
list: t,
|
|
341
|
-
open: (t) =>
|
|
343
|
+
open: (t) => ee(e, t)
|
|
342
344
|
}), We = (e) => ({
|
|
343
|
-
write: (t, n, r) =>
|
|
345
|
+
write: (t, n, r) => te(e, t, n, r),
|
|
344
346
|
has: (t) => e.head(t).pipe(n.map((e) => e !== null))
|
|
345
347
|
}), Ge = (e, t) => n.tryPromise({
|
|
346
348
|
try: async () => {
|
|
347
349
|
let { createWriteStream: n } = await import("node:fs"), r = await import("node:fs/promises"), { createHash: i, randomUUID: a } = await import("node:crypto"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c = await import("node:path"), l = c.join(t, `.tmp-${a()}`), u = i("sha256"), d = 0, f = new s({ transform(e, t, n) {
|
|
348
350
|
u.update(e), d += e.length, n(null, e);
|
|
349
351
|
} });
|
|
350
|
-
await o(await
|
|
352
|
+
await o(await ne(e.stream), f, n(l));
|
|
351
353
|
let p = u.digest("hex"), m = c.join(t, p);
|
|
352
354
|
try {
|
|
353
355
|
await r.access(m), await r.rm(l, { force: !0 });
|
|
@@ -365,7 +367,7 @@ var ve = (e) => {
|
|
|
365
367
|
path: t
|
|
366
368
|
})
|
|
367
369
|
}), Ke = (e, t, r) => n.gen(function* () {
|
|
368
|
-
let i = yield* n.promise(() => import("node:path")), { createReadStream: a } = yield* n.promise(() => import("node:fs")), { createHash: o } = yield* n.promise(() => import("node:crypto")), s = i.join(t, r.sha256), l = o("sha256"), u =
|
|
370
|
+
let i = yield* n.promise(() => import("node:path")), { createReadStream: a } = yield* n.promise(() => import("node:fs")), { createHash: o } = yield* n.promise(() => import("node:crypto")), s = i.join(t, r.sha256), l = o("sha256"), u = w("bundle", () => a(s)).pipe(c.tap((e) => n.sync(() => l.update(e))));
|
|
369
371
|
yield* e.write(r.key, u, {
|
|
370
372
|
contentType: r.contentType,
|
|
371
373
|
totalSize: r.size
|
|
@@ -376,7 +378,7 @@ var ve = (e) => {
|
|
|
376
378
|
expected: r.sha256,
|
|
377
379
|
actual: d
|
|
378
380
|
}));
|
|
379
|
-
}), qe = () => typeof
|
|
381
|
+
}), qe = () => typeof T.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" ? T.createZstdCompress() : e === "gzip" ? T.createGzip() : new re(), Ze = (e) => e === "zstd" ? T.createZstdDecompress() : e === "gzip" ? T.createGunzip() : new re(), Qe = 1, $e = s.Struct({
|
|
380
382
|
name: s.String,
|
|
381
383
|
file: s.String,
|
|
382
384
|
rowCount: s.Number,
|
|
@@ -560,16 +562,21 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
560
562
|
}
|
|
561
563
|
}, Mt = (e, t) => {
|
|
562
564
|
let n = e.tables.find((e) => e.name === t), r = {};
|
|
563
|
-
for (let e of n?.columns ?? []) r[e.name] = e.type;
|
|
565
|
+
for (let e of n?.columns ?? []) e.generatedAs === void 0 && (r[e.name] = e.type);
|
|
564
566
|
return r;
|
|
565
|
-
}, Nt = (e, t) => {
|
|
567
|
+
}, Nt = (e, t) => (e.tables.find((e) => e.name === t)?.columns ?? []).filter((e) => e.generatedAs !== void 0).map((e) => e.name), Pt = (e, t) => {
|
|
568
|
+
if (t.length === 0) return e;
|
|
569
|
+
let n = { ...e };
|
|
570
|
+
for (let e of t) delete n[e];
|
|
571
|
+
return n;
|
|
572
|
+
}, Ft = (e, t) => {
|
|
566
573
|
let n = e.tables.find((e) => e.name === t);
|
|
567
574
|
if (n === void 0) return { refusal: `${t}: not in the schema snapshot, so its primary key is unknown.` };
|
|
568
575
|
let r = n.columns.find((e) => e.type === "id");
|
|
569
576
|
if (r !== void 0) return { column: r.name };
|
|
570
577
|
let i = n.indexes.find((e) => e.name === `${t}_pkey`)?.columns ?? n.primaryKey ?? [];
|
|
571
578
|
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.` };
|
|
572
|
-
},
|
|
579
|
+
}, It = (e, t, r) => n.tryPromise({
|
|
573
580
|
try: async () => {
|
|
574
581
|
let { createWriteStream: n } = await import("node:fs"), i = await import("node:fs/promises"), { createHash: a, randomUUID: o } = await import("node:crypto"), { pipeline: s } = await import("node:stream/promises"), { Readable: l, Transform: u } = await import("node:stream"), d = a("sha256"), f = 0, p = new u({ transform(e, t, n) {
|
|
575
582
|
d.update(e);
|
|
@@ -591,7 +598,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
591
598
|
reason: `write table failed: ${J(e)}`,
|
|
592
599
|
path: t
|
|
593
600
|
})
|
|
594
|
-
}),
|
|
601
|
+
}), Lt = (e, t) => n.tryPromise({
|
|
595
602
|
try: async () => {
|
|
596
603
|
await (await import("node:fs/promises")).appendFile(e, `${t}\n`);
|
|
597
604
|
},
|
|
@@ -599,10 +606,10 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
599
606
|
reason: `append failed: ${J(t)}`,
|
|
600
607
|
path: e
|
|
601
608
|
})
|
|
602
|
-
}),
|
|
609
|
+
}), Rt = (e, t) => n.gen(function* () {
|
|
603
610
|
let r = [], i = t.ordered.length;
|
|
604
611
|
for (let a = 0; a < t.ordered.length; a++) {
|
|
605
|
-
let o = t.ordered[a], s = Mt(t.snapshot, o), l =
|
|
612
|
+
let o = t.ordered[a], s = Mt(t.snapshot, o), l = Ft(t.snapshot, o);
|
|
606
613
|
if ("refusal" in l) return yield* n.fail(new I({ reason: `export: ${l.refusal}` }));
|
|
607
614
|
let u = l.column, d = `${U}/${o}.ndjson${Ye(t.compression)}`;
|
|
608
615
|
if (ht(t.ledger, o)) {
|
|
@@ -639,41 +646,41 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
639
646
|
chunkSize: t.chunkSize,
|
|
640
647
|
retry: t.retry,
|
|
641
648
|
...f === void 0 ? {} : { where: f }
|
|
642
|
-
}), m = t.
|
|
649
|
+
}), m = Nt(t.snapshot, o), g = m.length === 0 ? p : p.pipe(c.map((e) => Pt(e, m))), _ = t.mask ? g.pipe(c.map((e) => Ne(e, o, t.mask.actions, t.mask.seed, s))) : g, { rowCount: v, checksum: y } = yield* ft("export", o, a, i, (e) => e.rowCount, It(Ot(_, s), t.bundleFile(d), t.compression));
|
|
643
650
|
t.ledger.tables[o] = {
|
|
644
|
-
rowCount:
|
|
645
|
-
checksum:
|
|
651
|
+
rowCount: v,
|
|
652
|
+
checksum: y
|
|
646
653
|
}, yield* q(t.ledgerPath, t.ledger), K(t.onProgress, {
|
|
647
654
|
phase: "export",
|
|
648
655
|
table: o,
|
|
649
656
|
index: a,
|
|
650
657
|
tableCount: i,
|
|
651
658
|
event: "done",
|
|
652
|
-
rowsDone:
|
|
653
|
-
total:
|
|
659
|
+
rowsDone: v,
|
|
660
|
+
total: v
|
|
654
661
|
}), r.push({
|
|
655
662
|
name: o,
|
|
656
663
|
file: d,
|
|
657
|
-
rowCount:
|
|
658
|
-
checksum:
|
|
664
|
+
rowCount: v,
|
|
665
|
+
checksum: y,
|
|
659
666
|
columnTypes: s,
|
|
660
667
|
primaryKey: u
|
|
661
668
|
});
|
|
662
669
|
}
|
|
663
670
|
return r;
|
|
664
|
-
}),
|
|
671
|
+
}), zt = (e) => ({
|
|
665
672
|
_tag: "RawSqlFragment",
|
|
666
673
|
strings: [e],
|
|
667
674
|
values: []
|
|
668
|
-
}),
|
|
675
|
+
}), Bt = (t, i, a) => n.tryPromise({
|
|
669
676
|
try: () => t.transactional(async (t) => {
|
|
670
|
-
if (t.raw) for (let e of
|
|
677
|
+
if (t.raw) for (let e of _e(i)) await t.raw(zt(e));
|
|
671
678
|
let o = await n.runPromiseExit(a(t));
|
|
672
679
|
if (r.isFailure(o)) throw Error(e.pretty(o.cause));
|
|
673
680
|
return o.value;
|
|
674
681
|
}),
|
|
675
682
|
catch: (e) => e instanceof P ? e : new P({ reason: `snapshot export failed: ${J(e)}` })
|
|
676
|
-
}),
|
|
683
|
+
}), Vt = (e) => n.gen(function* () {
|
|
677
684
|
let t = e.scope ?? { kind: "all" }, r = Je(e.compression), i = e.chunkSize ?? 1e3, a = e.retryTimes ?? 5, s = o.exponential("50 millis").pipe(o.jittered, o.intersect(o.recurs(a))), l = yield* n.promise(() => import("node:path")), u = (t) => l.join(e.outDir, t);
|
|
678
685
|
yield* n.tryPromise({
|
|
679
686
|
try: async () => {
|
|
@@ -690,7 +697,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
690
697
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
691
698
|
}), m = At(p.tables, e.snapshot), h = e.consistency ?? "live", _, v;
|
|
692
699
|
if (e.masking) {
|
|
693
|
-
let t = e.classification ??
|
|
700
|
+
let t = e.classification ?? A(e.snapshot), r = Ae(m.map((t) => ({
|
|
694
701
|
name: t,
|
|
695
702
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
696
703
|
name: e.name,
|
|
@@ -723,7 +730,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
723
730
|
bundleFile: u,
|
|
724
731
|
...v ? { mask: v } : {},
|
|
725
732
|
...e.onProgress ? { onProgress: e.onProgress } : {}
|
|
726
|
-
},
|
|
733
|
+
}, b = h === "snapshot" ? yield* Bt(e.store, e.dialect, (e) => Rt(e, y)) : yield* Rt(e.store, y), x = 0, S = 0;
|
|
727
734
|
if (e.assets) {
|
|
728
735
|
let t = u(G);
|
|
729
736
|
yield* c.runForEach(e.assets.list(), (r) => r.key in f.assets ? n.void : e.assets.open(r.key).pipe(n.flatMap((e) => Ge(e, u(W))), n.flatMap((e) => {
|
|
@@ -733,10 +740,10 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
733
740
|
size: e.size,
|
|
734
741
|
contentType: e.contentType
|
|
735
742
|
};
|
|
736
|
-
return
|
|
743
|
+
return x++, S += e.size, f.assets[r.key] = !0, Lt(t, JSON.stringify(i)).pipe(n.andThen(q(d, f)));
|
|
737
744
|
}))).pipe(n.mapError((e) => e instanceof P ? e : new P({ reason: `asset export failed: ${String(e)}` })));
|
|
738
745
|
}
|
|
739
|
-
let
|
|
746
|
+
let C = {
|
|
740
747
|
formatVersion: 1,
|
|
741
748
|
createdAt: e.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
742
749
|
source: {
|
|
@@ -746,10 +753,10 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
746
753
|
scope: t,
|
|
747
754
|
consistency: h,
|
|
748
755
|
compression: r,
|
|
749
|
-
tables:
|
|
750
|
-
assets:
|
|
751
|
-
count:
|
|
752
|
-
totalBytes:
|
|
756
|
+
tables: b,
|
|
757
|
+
assets: x > 0 ? {
|
|
758
|
+
count: x,
|
|
759
|
+
totalBytes: S,
|
|
753
760
|
index: G
|
|
754
761
|
} : {
|
|
755
762
|
count: 0,
|
|
@@ -759,7 +766,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
759
766
|
};
|
|
760
767
|
return yield* n.tryPromise({
|
|
761
768
|
try: async () => {
|
|
762
|
-
await (await import("node:fs/promises")).writeFile(u(H), rt(
|
|
769
|
+
await (await import("node:fs/promises")).writeFile(u(H), rt(C));
|
|
763
770
|
},
|
|
764
771
|
catch: (e) => new P({
|
|
765
772
|
reason: `manifest write failed: ${J(e)}`,
|
|
@@ -768,14 +775,14 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
768
775
|
}), yield* n.tryPromise({
|
|
769
776
|
try: async () => {
|
|
770
777
|
let e = await import("node:fs/promises"), t = await import("node:os");
|
|
771
|
-
await e.writeFile(u(at), ct(
|
|
778
|
+
await e.writeFile(u(at), ct(C, { hostname: t.hostname() }));
|
|
772
779
|
},
|
|
773
780
|
catch: (e) => new P({
|
|
774
781
|
reason: `readme write failed: ${J(e)}`,
|
|
775
782
|
path: at
|
|
776
783
|
})
|
|
777
|
-
}),
|
|
778
|
-
}),
|
|
784
|
+
}), C;
|
|
785
|
+
}), Ht = (e) => {
|
|
779
786
|
switch (e) {
|
|
780
787
|
case "id":
|
|
781
788
|
case "text":
|
|
@@ -794,12 +801,12 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
794
801
|
case "raw": return "raw";
|
|
795
802
|
default: return "string";
|
|
796
803
|
}
|
|
797
|
-
},
|
|
804
|
+
}, Ut = {
|
|
798
805
|
vector: /* @__PURE__ */ new Set(["postgres"]),
|
|
799
806
|
array: /* @__PURE__ */ new Set(["postgres"]),
|
|
800
807
|
interval: /* @__PURE__ */ new Set(["postgres"])
|
|
801
|
-
},
|
|
802
|
-
let i =
|
|
808
|
+
}, Wt = (e, t, n, r) => {
|
|
809
|
+
let i = Ht(n);
|
|
803
810
|
if (i === "raw") return {
|
|
804
811
|
table: e,
|
|
805
812
|
column: t,
|
|
@@ -807,7 +814,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
807
814
|
severity: "block",
|
|
808
815
|
reason: `raw() is verbatim source-dialect SQL — it cannot be assumed valid on ${r}`
|
|
809
816
|
};
|
|
810
|
-
let a =
|
|
817
|
+
let a = Ut[i];
|
|
811
818
|
return !a || a.has(r) ? null : i === "array" || i === "interval" ? {
|
|
812
819
|
table: e,
|
|
813
820
|
column: t,
|
|
@@ -821,15 +828,15 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
821
828
|
severity: "block",
|
|
822
829
|
reason: `${i} columns require a ${[...a].join("/")} target; ${r} has no compatible column type`
|
|
823
830
|
};
|
|
824
|
-
},
|
|
831
|
+
}, Gt = (e, t, n) => {
|
|
825
832
|
if (t === n) return [];
|
|
826
833
|
let r = [];
|
|
827
834
|
for (let t of e) for (let [e, i] of Object.entries(t.columnTypes)) {
|
|
828
|
-
let a =
|
|
835
|
+
let a = Wt(t.name, e, i, n);
|
|
829
836
|
a && r.push(a);
|
|
830
837
|
}
|
|
831
838
|
return r;
|
|
832
|
-
},
|
|
839
|
+
}, Kt = (e) => `[${e.severity}] ${e.table}.${e.column} (${e.type}): ${e.reason}`, qt = (e) => {
|
|
833
840
|
let t = e.constraint ?? e.column, n = t === void 0 ? "" : ` ${t}`;
|
|
834
841
|
switch (e.kind) {
|
|
835
842
|
case "foreignKey": return `foreign key${n}: the referenced row does not exist (import it first, or check the bundle's table order)`;
|
|
@@ -838,22 +845,22 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
838
845
|
case "notNull": return `not-null constraint${n}: the column requires a value`;
|
|
839
846
|
case "check": return `check constraint${n}: the row does not satisfy it`;
|
|
840
847
|
}
|
|
841
|
-
},
|
|
848
|
+
}, Jt = (e) => {
|
|
842
849
|
let t = [e.dbCode, e.dbErrno ?? e.dbNumber].filter((e) => e !== void 0).map(String);
|
|
843
850
|
return t.length > 0 ? t.join("/") : void 0;
|
|
844
|
-
},
|
|
845
|
-
let t = d(e), n = l(t), r =
|
|
846
|
-
if (n !== void 0) return `${
|
|
851
|
+
}, Yt = (e) => {
|
|
852
|
+
let t = d(e), n = l(t), r = Jt(t), i = r === void 0 ? "" : ` [${r}]`;
|
|
853
|
+
if (n !== void 0) return `${qt(n)}${i}`;
|
|
847
854
|
let a = typeof t.dbMessage == "string" ? t.dbMessage : void 0, o = e?.message, s = typeof o == "string" && o.length > 0 ? o : String(e), c = a !== void 0 && a !== s && !a.startsWith("SqlError:") ? a : s, u = c === "Failed to execute statement" ? `the database refused the write and the driver gave no detail${i}` : `${c}${i}`;
|
|
848
855
|
return u.length <= 300 ? u : `${u.slice(0, 300)}…`;
|
|
849
|
-
},
|
|
856
|
+
}, Xt = (e, t) => e.tables.find((e) => e.name === t), Zt = (e, t) => new Map((Xt(e, t)?.columns ?? []).map((e) => [e.name, e])), Qt = (e, t) => {
|
|
850
857
|
let n = [];
|
|
851
858
|
for (let r of [...e.tables].sort((e, t) => e.name.localeCompare(t.name))) {
|
|
852
|
-
if (
|
|
859
|
+
if (Xt(t, r.name) === void 0) {
|
|
853
860
|
n.push(`table '${r.name}' is in the bundle but MISSING from the target — its rows have nowhere to go`);
|
|
854
861
|
continue;
|
|
855
862
|
}
|
|
856
|
-
let e =
|
|
863
|
+
let e = Zt(t, r.name), i = new Map(r.columns.map((e) => [e.name, e]));
|
|
857
864
|
for (let [t, a] of i) {
|
|
858
865
|
let i = e.get(t);
|
|
859
866
|
if (i === void 0) {
|
|
@@ -865,7 +872,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
865
872
|
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`);
|
|
866
873
|
}
|
|
867
874
|
return n.length > 30 ? [...n.slice(0, 30), `… and ${n.length - 30} more difference(s)`] : n;
|
|
868
|
-
},
|
|
875
|
+
}, $t = (e, t, n) => {
|
|
869
876
|
let r = g(t);
|
|
870
877
|
if (r === e || n === void 0) return {
|
|
871
878
|
drifted: !1,
|
|
@@ -873,14 +880,14 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
873
880
|
targetFingerprint: r,
|
|
874
881
|
diff: []
|
|
875
882
|
};
|
|
876
|
-
let i =
|
|
883
|
+
let i = Qt(n, t);
|
|
877
884
|
return {
|
|
878
885
|
drifted: i.length > 0,
|
|
879
886
|
bundleFingerprint: e,
|
|
880
887
|
targetFingerprint: r,
|
|
881
888
|
diff: i
|
|
882
889
|
};
|
|
883
|
-
},
|
|
890
|
+
}, en = (e) => n.tryPromise({
|
|
884
891
|
try: async () => {
|
|
885
892
|
let t = await import("node:fs/promises"), n = await import("node:path");
|
|
886
893
|
return it(await t.readFile(n.join(e, H), "utf8"));
|
|
@@ -889,8 +896,8 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
889
896
|
reason: `manifest read/parse failed: ${String(e?.message ?? e)}`,
|
|
890
897
|
path: H
|
|
891
898
|
})
|
|
892
|
-
}),
|
|
893
|
-
let i = yield* n.promise(() => import("node:path")), a = yield*
|
|
899
|
+
}), tn = (t) => n.gen(function* () {
|
|
900
|
+
let i = yield* n.promise(() => import("node:path")), a = yield* en(t.bundleDir);
|
|
894
901
|
if (a.formatVersion !== 1) return yield* n.fail(new P({ reason: `unsupported bundle formatVersion ${a.formatVersion} (expected 1)` }));
|
|
895
902
|
if (t.tables !== void 0) {
|
|
896
903
|
let e = new Set(a.tables.map((e) => e.name)), r = t.tables.filter((t) => !e.has(t));
|
|
@@ -911,7 +918,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
911
918
|
unique: !1,
|
|
912
919
|
hasDefault: !1
|
|
913
920
|
}))
|
|
914
|
-
})) }, r =
|
|
921
|
+
})) }, r = $t(s.source.schemaFingerprint, t.targetSnapshot, e);
|
|
915
922
|
if (r.drifted) {
|
|
916
923
|
if (!t.force) return yield* n.fail(new Le({
|
|
917
924
|
bundleFingerprint: r.bundleFingerprint,
|
|
@@ -922,11 +929,11 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
922
929
|
}
|
|
923
930
|
}
|
|
924
931
|
if (t.targetDialect && t.targetDialect !== s.source.dialect) {
|
|
925
|
-
let e =
|
|
932
|
+
let e = Gt(s.tables, s.source.dialect, t.targetDialect).filter((e) => e.severity === "block");
|
|
926
933
|
if (e.length > 0 && !t.allowIncompatible) return yield* n.fail(new Be({
|
|
927
934
|
sourceDialect: s.source.dialect,
|
|
928
935
|
targetDialect: t.targetDialect,
|
|
929
|
-
blocking: e.map(
|
|
936
|
+
blocking: e.map(Kt)
|
|
930
937
|
}));
|
|
931
938
|
}
|
|
932
939
|
let l = t.verify ?? !0, u = t.mode ?? "upsert", d = t.onConflict ?? "skip", f = t.ledgerPath ?? i.join(t.bundleDir, ".import..ledger.json"), m = yield* mt(f);
|
|
@@ -935,40 +942,60 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
935
942
|
reason: `replace refuses a partial bundle (scope='${s.scope.kind}') — truncating would delete rows not in the bundle. Use --mode upsert, or re-export with full scope.`
|
|
936
943
|
}));
|
|
937
944
|
if (t.dryRun === !0) return s;
|
|
938
|
-
let h =
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
945
|
+
let h = /* @__PURE__ */ new Map();
|
|
946
|
+
for (let e of t.targetSnapshot?.tables ?? []) {
|
|
947
|
+
let t = e.columns.filter((e) => e.generatedAs !== void 0).map((e) => e.name);
|
|
948
|
+
t.length > 0 && h.set(e.name, t);
|
|
949
|
+
}
|
|
950
|
+
let g = (e, t) => {
|
|
951
|
+
let n = h.get(e);
|
|
952
|
+
if (n === void 0) return t;
|
|
953
|
+
let r;
|
|
954
|
+
for (let e of n) e in t && (r ??= { ...t }, delete r[e]);
|
|
955
|
+
return r ?? t;
|
|
956
|
+
}, _ = (e, t, n) => {
|
|
957
|
+
let r = t.name, i = t.primaryKey, a = g(r, n);
|
|
958
|
+
return u === "append" ? d === "fail" ? e.insert(r, a) : e.insertIgnore(r, a, { conflictColumns: [i] }) : u === "replace" ? e.insert(r, a) : e.upsert(r, a, { conflictColumns: [i] });
|
|
959
|
+
}, v = (e, t, r = !0) => n.tryPromise({
|
|
942
960
|
try: e,
|
|
943
|
-
catch: (e) =>
|
|
944
|
-
}).pipe(n.map(() => !0), n.catchAll((e) => n.sync(() => (r && (t.reason = e), !1)))),
|
|
961
|
+
catch: (e) => Yt(e)
|
|
962
|
+
}).pipe(n.map(() => !0), n.catchAll((e) => n.sync(() => (r && (t.reason = e), !1)))), y = (e) => {
|
|
945
963
|
let t = Object.entries(e.entry.columnTypes).filter(([t, n]) => n === "reference" && e.row[t] !== null && e.row[t] !== void 0).map(([e]) => e);
|
|
946
964
|
if (t.length !== 0) return {
|
|
947
965
|
...e.row,
|
|
948
966
|
...Object.fromEntries(t.map((e) => [e, null]))
|
|
949
967
|
};
|
|
950
|
-
},
|
|
968
|
+
}, b = (e) => {
|
|
969
|
+
let t = new Set(e.map((e) => String(e.row[e.entry.primaryKey]))), n = (e) => Object.entries(e.entry.columnTypes).some(([n, r]) => {
|
|
970
|
+
if (r !== "reference") return !1;
|
|
971
|
+
let i = e.row[n];
|
|
972
|
+
return i != null && t.has(String(i));
|
|
973
|
+
}), r = e.map((e) => ({
|
|
974
|
+
table: e.entry.name,
|
|
975
|
+
id: String(e.row[e.entry.primaryKey]),
|
|
976
|
+
reason: e.reason,
|
|
977
|
+
derived: n(e)
|
|
978
|
+
}));
|
|
979
|
+
return new Ie({
|
|
980
|
+
rows: [...r.filter((e) => !e.derived), ...r.filter((e) => e.derived)].slice(0, 20),
|
|
981
|
+
primaryCount: r.filter((e) => !e.derived).length,
|
|
982
|
+
totalCount: e.length
|
|
983
|
+
});
|
|
984
|
+
}, x = (e, t) => n.gen(function* () {
|
|
951
985
|
let r = t, i = [], a = !0;
|
|
952
986
|
for (; r.length > 0 && a;) {
|
|
953
987
|
a = !1;
|
|
954
988
|
let t = [];
|
|
955
|
-
for (let n of r) (yield*
|
|
989
|
+
for (let n of r) (yield* v(() => _(e, n.entry, n.row), n)) ? a = !0 : t.push(n);
|
|
956
990
|
if (!a && t.length > 0) for (let n = t.length - 1; n >= 0; n--) {
|
|
957
|
-
let r = t[n], o =
|
|
958
|
-
o !== void 0 && (yield*
|
|
991
|
+
let r = t[n], o = y(r);
|
|
992
|
+
o !== void 0 && (yield* v(() => _(e, r.entry, o), r, !1)) && (i.push(r), t.splice(n, 1), a = !0);
|
|
959
993
|
}
|
|
960
994
|
r = t;
|
|
961
995
|
}
|
|
962
|
-
for (let t of i) (yield*
|
|
963
|
-
if (r.length > 0) return yield* n.fail(
|
|
964
|
-
|
|
965
|
-
table: e.entry.name,
|
|
966
|
-
id: String(e.row[e.entry.primaryKey]),
|
|
967
|
-
reason: e.reason
|
|
968
|
-
})),
|
|
969
|
-
totalCount: r.length
|
|
970
|
-
}));
|
|
971
|
-
}), y = (e, r) => n.gen(function* () {
|
|
996
|
+
for (let t of i) (yield* v(() => e.upsert(t.entry.name, t.row, { conflictColumns: [t.entry.primaryKey] }), t)) || (r = [...r, t]);
|
|
997
|
+
if (r.length > 0) return yield* n.fail(b(r));
|
|
998
|
+
}), S = (e, r) => n.gen(function* () {
|
|
972
999
|
if (u === "replace" && !(r && m.truncated)) {
|
|
973
1000
|
for (let t of [...s.tables].reverse()) yield* n.tryPromise({
|
|
974
1001
|
try: () => e.deleteMany(t.name, { where: p(t.primaryKey) }),
|
|
@@ -976,42 +1003,42 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
976
1003
|
});
|
|
977
1004
|
r && (m.truncated = !0, yield* q(f, m));
|
|
978
1005
|
}
|
|
979
|
-
let a = [], o = [], d = [],
|
|
1006
|
+
let a = [], o = [], d = [], h = s.tables.length;
|
|
980
1007
|
for (let p = 0; p < s.tables.length; p++) {
|
|
981
|
-
let
|
|
982
|
-
if (r &&
|
|
983
|
-
d.push(
|
|
1008
|
+
let g = s.tables[p];
|
|
1009
|
+
if (r && g.name in m.tables) {
|
|
1010
|
+
d.push(g.name), K(t.onProgress, {
|
|
984
1011
|
phase: "import",
|
|
985
|
-
table:
|
|
1012
|
+
table: g.name,
|
|
986
1013
|
index: p,
|
|
987
|
-
tableCount:
|
|
1014
|
+
tableCount: h,
|
|
988
1015
|
event: "done",
|
|
989
|
-
rowsDone: m.tables[
|
|
990
|
-
total:
|
|
1016
|
+
rowsDone: m.tables[g.name].rowCount,
|
|
1017
|
+
total: g.rowCount
|
|
991
1018
|
});
|
|
992
1019
|
continue;
|
|
993
1020
|
}
|
|
994
|
-
let v = i.join(t.bundleDir,
|
|
1021
|
+
let v = i.join(t.bundleDir, g.file);
|
|
995
1022
|
K(t.onProgress, {
|
|
996
1023
|
phase: "import",
|
|
997
|
-
table:
|
|
1024
|
+
table: g.name,
|
|
998
1025
|
index: p,
|
|
999
|
-
tableCount:
|
|
1026
|
+
tableCount: h,
|
|
1000
1027
|
event: "start",
|
|
1001
1028
|
rowsDone: 0,
|
|
1002
|
-
total:
|
|
1029
|
+
total: g.rowCount
|
|
1003
1030
|
});
|
|
1004
|
-
let y = a.length,
|
|
1005
|
-
let { createHash: r } = yield* n.promise(() => import("node:crypto")), i = r("sha256"), o = 0, l =
|
|
1031
|
+
let y = a.length, b = n.gen(function* () {
|
|
1032
|
+
let { createHash: r } = yield* n.promise(() => import("node:crypto")), i = r("sha256"), o = 0, l = w("bundle", () => E(v).pipe(Ze(s.compression))).pipe(c.tap((e) => n.sync(() => i.update(e)))), d = async (t) => {
|
|
1006
1033
|
let n = {
|
|
1007
|
-
entry:
|
|
1034
|
+
entry: g,
|
|
1008
1035
|
row: t,
|
|
1009
1036
|
reason: ""
|
|
1010
1037
|
};
|
|
1011
1038
|
try {
|
|
1012
|
-
await
|
|
1039
|
+
await _(e, g, t);
|
|
1013
1040
|
} catch (e) {
|
|
1014
|
-
n.reason =
|
|
1041
|
+
n.reason = Yt(e), a.push(n);
|
|
1015
1042
|
}
|
|
1016
1043
|
}, f = yield* n.promise(async () => {
|
|
1017
1044
|
let n = t.copyLoader;
|
|
@@ -1020,7 +1047,7 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1020
1047
|
if (u !== "upsert") return !1;
|
|
1021
1048
|
try {
|
|
1022
1049
|
return (await e.query({
|
|
1023
|
-
table:
|
|
1050
|
+
table: g.name,
|
|
1024
1051
|
predicate: void 0,
|
|
1025
1052
|
order: [],
|
|
1026
1053
|
take: 1,
|
|
@@ -1030,25 +1057,25 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1030
1057
|
} catch {
|
|
1031
1058
|
return !1;
|
|
1032
1059
|
}
|
|
1033
|
-
}), p = Object.keys(
|
|
1034
|
-
if (
|
|
1035
|
-
let e =
|
|
1036
|
-
|
|
1060
|
+
}), p = Object.keys(g.columnTypes), m = Math.max(1, t.copyBatchSize ?? 5e3), h = [], y = async () => {
|
|
1061
|
+
if (h.length === 0) return;
|
|
1062
|
+
let e = h;
|
|
1063
|
+
h = [];
|
|
1037
1064
|
try {
|
|
1038
1065
|
await t.copyLoader.copyInto({
|
|
1039
|
-
table:
|
|
1066
|
+
table: g.name,
|
|
1040
1067
|
columns: p,
|
|
1041
|
-
columnTypes:
|
|
1068
|
+
columnTypes: g.columnTypes,
|
|
1042
1069
|
rows: e
|
|
1043
1070
|
});
|
|
1044
1071
|
} catch (n) {
|
|
1045
|
-
f = !1, t.onWarn?.(`bulk COPY into ${
|
|
1072
|
+
f = !1, t.onWarn?.(`bulk COPY into ${g.name} failed (${String(n?.message ?? n)}); falling back to per-row writes for this table`);
|
|
1046
1073
|
for (let t of e) await d(t);
|
|
1047
1074
|
}
|
|
1048
1075
|
};
|
|
1049
|
-
return yield* c.runForEach(kt(l,
|
|
1076
|
+
return yield* c.runForEach(kt(l, g.name, g.columnTypes), (e) => n.promise(async () => {
|
|
1050
1077
|
if (o++, f) {
|
|
1051
|
-
|
|
1078
|
+
h.push(e), h.length >= m && await y();
|
|
1052
1079
|
return;
|
|
1053
1080
|
}
|
|
1054
1081
|
await d(e);
|
|
@@ -1056,36 +1083,36 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1056
1083
|
rowCount: o,
|
|
1057
1084
|
checksum: i.digest("hex")
|
|
1058
1085
|
};
|
|
1059
|
-
}), { rowCount:
|
|
1086
|
+
}), { rowCount: x, checksum: S } = yield* ft("import", g.name, p, h, (e) => e.rowCount, b);
|
|
1060
1087
|
if (l) {
|
|
1061
|
-
if (
|
|
1062
|
-
what: `table ${
|
|
1063
|
-
expected:
|
|
1064
|
-
actual:
|
|
1088
|
+
if (S !== g.checksum) return yield* n.fail(new F({
|
|
1089
|
+
what: `table ${g.name} checksum`,
|
|
1090
|
+
expected: g.checksum,
|
|
1091
|
+
actual: S
|
|
1065
1092
|
}));
|
|
1066
|
-
if (
|
|
1067
|
-
what: `table ${
|
|
1068
|
-
expected: String(
|
|
1069
|
-
actual: String(
|
|
1093
|
+
if (x !== g.rowCount) return yield* n.fail(new F({
|
|
1094
|
+
what: `table ${g.name} rowCount`,
|
|
1095
|
+
expected: String(g.rowCount),
|
|
1096
|
+
actual: String(x)
|
|
1070
1097
|
}));
|
|
1071
1098
|
}
|
|
1072
1099
|
K(t.onProgress, {
|
|
1073
1100
|
phase: "import",
|
|
1074
|
-
table:
|
|
1101
|
+
table: g.name,
|
|
1075
1102
|
index: p,
|
|
1076
|
-
tableCount:
|
|
1103
|
+
tableCount: h,
|
|
1077
1104
|
event: "done",
|
|
1078
|
-
rowsDone:
|
|
1079
|
-
total:
|
|
1105
|
+
rowsDone: x,
|
|
1106
|
+
total: g.rowCount
|
|
1080
1107
|
}), r && (a.length > y ? o.push({
|
|
1081
|
-
name:
|
|
1082
|
-
rowCount:
|
|
1083
|
-
}) : (m.tables[
|
|
1084
|
-
rowCount:
|
|
1085
|
-
checksum:
|
|
1108
|
+
name: g.name,
|
|
1109
|
+
rowCount: x
|
|
1110
|
+
}) : (m.tables[g.name] = {
|
|
1111
|
+
rowCount: x,
|
|
1112
|
+
checksum: g.checksum
|
|
1086
1113
|
}, yield* q(f, m)));
|
|
1087
1114
|
}
|
|
1088
|
-
if (a.length > 0 && (yield*
|
|
1115
|
+
if (a.length > 0 && (yield* x(e, a)), r && o.length > 0) {
|
|
1089
1116
|
for (let e of o) {
|
|
1090
1117
|
let t = s.tables.find((t) => t.name === e.name);
|
|
1091
1118
|
m.tables[e.name] = {
|
|
@@ -1102,29 +1129,29 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1102
1129
|
});
|
|
1103
1130
|
if (t.atomic ? yield* n.tryPromise({
|
|
1104
1131
|
try: () => t.store.transactional(async (t) => {
|
|
1105
|
-
let i = await n.runPromiseExit(
|
|
1132
|
+
let i = await n.runPromiseExit(S(t, !1));
|
|
1106
1133
|
if (r.isFailure(i)) throw Error(e.pretty(i.cause));
|
|
1107
1134
|
}),
|
|
1108
1135
|
catch: (e) => new P({ reason: `atomic import failed (rolled back): ${String(e?.message ?? e)}` })
|
|
1109
|
-
}) : yield*
|
|
1110
|
-
let e = t.assets, r = i.join(t.bundleDir, W), a = i.join(t.bundleDir, s.assets.index ?? "assets/index.ndjson"), o =
|
|
1136
|
+
}) : yield* S(t.store, !0), t.assets && s.assets.index && !t.assetsAlreadyRestored) {
|
|
1137
|
+
let e = t.assets, r = i.join(t.bundleDir, W), a = i.join(t.bundleDir, s.assets.index ?? "assets/index.ndjson"), o = w("bundle", () => E(a)).pipe(c.decodeText(), c.splitLines, c.filter((e) => e.trim().length > 0), c.map((e) => JSON.parse(e)));
|
|
1111
1138
|
yield* c.runForEach(o, (t) => t.key in m.assets ? n.void : Ke(e, r, t).pipe(n.andThen(n.sync(() => {
|
|
1112
1139
|
m.assets[t.key] = !0;
|
|
1113
1140
|
})), n.andThen(q(f, m))));
|
|
1114
1141
|
}
|
|
1115
1142
|
return s;
|
|
1116
|
-
}),
|
|
1143
|
+
}), nn = (e) => e, rn = (e) => {
|
|
1117
1144
|
if (e.allowLive || e.liveInstance === null || e.sameTarget === "different") return { refuse: !1 };
|
|
1118
1145
|
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.";
|
|
1119
1146
|
return {
|
|
1120
1147
|
refuse: !0,
|
|
1121
1148
|
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).`
|
|
1122
1149
|
};
|
|
1123
|
-
}, Y = Buffer.from("VBUNDLE2"),
|
|
1150
|
+
}, Y = Buffer.from("VBUNDLE2"), an = 0, on = 1, sn = 2, cn = 32, ln = async (e) => {
|
|
1124
1151
|
let t = [], n = async (r) => {
|
|
1125
1152
|
let i;
|
|
1126
1153
|
try {
|
|
1127
|
-
i = await
|
|
1154
|
+
i = await ce(k(e, r), { withFileTypes: !0 });
|
|
1128
1155
|
} catch {
|
|
1129
1156
|
return;
|
|
1130
1157
|
}
|
|
@@ -1134,21 +1161,21 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
1134
1161
|
}
|
|
1135
1162
|
};
|
|
1136
1163
|
return await n(""), t.sort();
|
|
1137
|
-
},
|
|
1164
|
+
}, un = (e, t) => {
|
|
1138
1165
|
let n = Buffer.from(e, "utf8"), r = Buffer.alloc(5 + n.length + 8);
|
|
1139
|
-
return r.writeUInt8(
|
|
1140
|
-
},
|
|
1166
|
+
return r.writeUInt8(on, 0), r.writeUInt32BE(n.length, 1), n.copy(r, 5), r.writeBigUInt64BE(BigInt(t), 5 + n.length), r;
|
|
1167
|
+
}, dn = (e, t, n) => {
|
|
1141
1168
|
let r = Buffer.from(e, "utf8"), i = Buffer.from(t, "utf8"), a = Buffer.alloc(5 + r.length + 2 + i.length + 8), o = 0;
|
|
1142
|
-
return a.writeUInt8(
|
|
1169
|
+
return a.writeUInt8(sn, 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;
|
|
1143
1170
|
};
|
|
1144
|
-
async function*
|
|
1171
|
+
async function* fn(e) {
|
|
1145
1172
|
yield new Uint8Array(Y);
|
|
1146
|
-
for (let t of await
|
|
1147
|
-
let n =
|
|
1148
|
-
if (yield new Uint8Array(
|
|
1173
|
+
for (let t of await ln(e.dir)) {
|
|
1174
|
+
let n = k(e.dir, t), r = await le(n);
|
|
1175
|
+
if (yield new Uint8Array(un(t, r.size)), r.size > 0) for await (let e of E(n)) yield new Uint8Array(e);
|
|
1149
1176
|
}
|
|
1150
1177
|
if (e.blobs) for await (let t of e.blobs.list()) {
|
|
1151
|
-
yield new Uint8Array(
|
|
1178
|
+
yield new Uint8Array(dn(t.key, t.contentType, t.size));
|
|
1152
1179
|
let n = y("sha256"), r = 0;
|
|
1153
1180
|
for await (let i of e.blobs.open(t.key)) {
|
|
1154
1181
|
let e = Buffer.from(i);
|
|
@@ -1157,11 +1184,11 @@ async function* un(e) {
|
|
|
1157
1184
|
if (r !== t.size) throw Error(`blob '${t.key}' size mismatch: header ${t.size}, streamed ${r}`);
|
|
1158
1185
|
yield new Uint8Array(n.digest());
|
|
1159
1186
|
}
|
|
1160
|
-
yield new Uint8Array(Buffer.from([
|
|
1187
|
+
yield new Uint8Array(Buffer.from([an]));
|
|
1161
1188
|
}
|
|
1162
|
-
var
|
|
1163
|
-
let n =
|
|
1164
|
-
await
|
|
1189
|
+
var pn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), mn = (e) => new Promise((t) => e.end(t)), hn = async (e, t) => {
|
|
1190
|
+
let n = pe(t.dir);
|
|
1191
|
+
await O(n, { recursive: !0 });
|
|
1165
1192
|
let r = Buffer.alloc(0), i = e[Symbol.asyncIterator](), a = !1, o = async () => {
|
|
1166
1193
|
let { value: e, done: t } = await i.next();
|
|
1167
1194
|
return t ? (a = !0, !1) : (r = r.length === 0 ? Buffer.from(e) : Buffer.concat([r, Buffer.from(e)]), !0);
|
|
@@ -1176,24 +1203,24 @@ var dn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), fn
|
|
|
1176
1203
|
for (;;) {
|
|
1177
1204
|
await s(1);
|
|
1178
1205
|
let e = c(1).readUInt8(0);
|
|
1179
|
-
if (e ===
|
|
1180
|
-
if (e ===
|
|
1206
|
+
if (e === an) return;
|
|
1207
|
+
if (e === on) {
|
|
1181
1208
|
await s(4);
|
|
1182
1209
|
let e = c(4).readUInt32BE(0);
|
|
1183
1210
|
await s(e);
|
|
1184
1211
|
let t = c(e).toString("utf8");
|
|
1185
1212
|
await s(8);
|
|
1186
|
-
let i = c(8).readBigUInt64BE(0), a =
|
|
1187
|
-
if (a !== n && !a.startsWith(n +
|
|
1188
|
-
await
|
|
1189
|
-
let o =
|
|
1213
|
+
let i = c(8).readBigUInt64BE(0), a = pe(n, t);
|
|
1214
|
+
if (a !== n && !a.startsWith(n + me)) throw Error(`archive path '${t}' escapes the destination`);
|
|
1215
|
+
await O(fe(a), { recursive: !0 });
|
|
1216
|
+
let o = D(a);
|
|
1190
1217
|
for (; i > 0n;) {
|
|
1191
1218
|
r.length === 0 && await s(1);
|
|
1192
1219
|
let e = i < BigInt(r.length) ? Number(i) : r.length;
|
|
1193
|
-
await
|
|
1220
|
+
await pn(o, c(e)), i -= BigInt(e);
|
|
1194
1221
|
}
|
|
1195
|
-
await
|
|
1196
|
-
} else if (e ===
|
|
1222
|
+
await mn(o);
|
|
1223
|
+
} else if (e === sn) {
|
|
1197
1224
|
await s(4);
|
|
1198
1225
|
let e = c(4).readUInt32BE(0);
|
|
1199
1226
|
await s(e);
|
|
@@ -1203,24 +1230,24 @@ var dn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), fn
|
|
|
1203
1230
|
await s(i);
|
|
1204
1231
|
let a = c(i).toString("utf8");
|
|
1205
1232
|
await s(8);
|
|
1206
|
-
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = y("sha256"), d = new
|
|
1233
|
+
let o = c(8).readBigUInt64BE(0), l = await t.blobs.has(n), u = y("sha256"), d = new re(), f = l ? Promise.resolve() : t.blobs.write(n, d, {
|
|
1207
1234
|
contentType: a,
|
|
1208
1235
|
size: Number(o)
|
|
1209
1236
|
}), p = o;
|
|
1210
1237
|
for (; p > 0n;) {
|
|
1211
1238
|
r.length === 0 && await s(1);
|
|
1212
1239
|
let e = p < BigInt(r.length) ? Number(p) : r.length, t = c(e);
|
|
1213
|
-
u.update(t), l || await
|
|
1240
|
+
u.update(t), l || await pn(d, t), p -= BigInt(e);
|
|
1214
1241
|
}
|
|
1215
|
-
l ? d.destroy() : await
|
|
1216
|
-
let m = c(
|
|
1242
|
+
l ? d.destroy() : await mn(d), await f, await s(cn);
|
|
1243
|
+
let m = c(cn);
|
|
1217
1244
|
if (!u.digest().equals(m)) throw Error(`blob '${n}' failed integrity (sha mismatch)`);
|
|
1218
1245
|
} else throw Error(`unknown bundle entry kind ${e}`);
|
|
1219
1246
|
}
|
|
1220
1247
|
} finally {
|
|
1221
1248
|
a || await Promise.resolve(i.return?.()).catch(() => void 0);
|
|
1222
1249
|
}
|
|
1223
|
-
},
|
|
1250
|
+
}, gn = async (e, t) => {
|
|
1224
1251
|
let n = new Set(t), r = /* @__PURE__ */ new Map(), i = Buffer.alloc(0), a = e[Symbol.asyncIterator](), o = async () => {
|
|
1225
1252
|
let { value: e, done: t } = await a.next();
|
|
1226
1253
|
return !t && (i = i.length === 0 ? Buffer.from(e) : Buffer.concat([i, Buffer.from(e)]), !0);
|
|
@@ -1242,8 +1269,8 @@ var dn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), fn
|
|
|
1242
1269
|
if (!await s(Y.length) || !c(Y.length).equals(Y)) throw Error("not a bundle archive (bad magic)");
|
|
1243
1270
|
for (; await s(1);) {
|
|
1244
1271
|
let e = c(1).readUInt8(0);
|
|
1245
|
-
if (e ===
|
|
1246
|
-
if (e !==
|
|
1272
|
+
if (e === an || e === sn) break;
|
|
1273
|
+
if (e !== on) throw Error(`unknown bundle entry kind ${e}`);
|
|
1247
1274
|
if (!await s(4)) break;
|
|
1248
1275
|
let t = c(4).readUInt32BE(0);
|
|
1249
1276
|
if (!await s(t)) break;
|
|
@@ -1253,22 +1280,22 @@ var dn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), fn
|
|
|
1253
1280
|
if (a === null || n.has(i) && (r.set(i, a), n.delete(i), n.size === 0)) break;
|
|
1254
1281
|
}
|
|
1255
1282
|
return r;
|
|
1256
|
-
},
|
|
1283
|
+
}, _n = (e, t) => hn(e, {
|
|
1257
1284
|
dir: t,
|
|
1258
|
-
blobs:
|
|
1259
|
-
}),
|
|
1285
|
+
blobs: vn(t)
|
|
1286
|
+
}), vn = (e) => {
|
|
1260
1287
|
let t = /* @__PURE__ */ new Set();
|
|
1261
1288
|
return {
|
|
1262
1289
|
has: async (e) => t.has(e),
|
|
1263
1290
|
write: async (n, r, i) => {
|
|
1264
|
-
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c =
|
|
1265
|
-
await
|
|
1291
|
+
let a = await import("node:fs/promises"), { pipeline: o } = await import("node:stream/promises"), { Transform: s } = await import("node:stream"), c = k(e, "assets");
|
|
1292
|
+
await O(c, { recursive: !0 });
|
|
1266
1293
|
let l = y("sha256"), u = 0, d = new s({ transform(e, t, n) {
|
|
1267
1294
|
l.update(e), u += e.length, n(null, e);
|
|
1268
|
-
} }), f =
|
|
1269
|
-
await o(r, d,
|
|
1295
|
+
} }), f = k(c, `.tmp-${Date.now()}-${t.size}`);
|
|
1296
|
+
await o(r, d, D(f));
|
|
1270
1297
|
let p = l.digest("hex");
|
|
1271
|
-
await a.rename(f,
|
|
1298
|
+
await a.rename(f, k(c, p)), await a.appendFile(k(c, "index.ndjson"), `${JSON.stringify({
|
|
1272
1299
|
key: n,
|
|
1273
1300
|
sha256: p,
|
|
1274
1301
|
size: u,
|
|
@@ -1276,33 +1303,33 @@ var dn = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), fn
|
|
|
1276
1303
|
})}\n`), t.add(n);
|
|
1277
1304
|
}
|
|
1278
1305
|
};
|
|
1279
|
-
},
|
|
1306
|
+
}, yn = he(S), bn = Buffer.from("VENC1\0\0\0"), xn = 32, Sn = 16, Cn = 7, X = 16, wn = 262144, Z = {
|
|
1280
1307
|
N: 32768,
|
|
1281
1308
|
r: 8,
|
|
1282
1309
|
p: 1
|
|
1283
|
-
},
|
|
1310
|
+
}, Tn = 134217728, Q = 43, En = (e, t, n) => {
|
|
1284
1311
|
let r = Buffer.alloc(12);
|
|
1285
|
-
return e.copy(r, 0, 0,
|
|
1312
|
+
return e.copy(r, 0, 0, Cn), r.writeUInt32BE(t >>> 0, Cn), r.writeUInt8(+!!n, 11), r;
|
|
1286
1313
|
};
|
|
1287
|
-
async function*
|
|
1314
|
+
async function* Dn(e, t) {
|
|
1288
1315
|
if (!t) throw Error("encryptStream: a non-empty passphrase is required");
|
|
1289
|
-
let n =
|
|
1316
|
+
let n = x(Sn), r = x(Cn), i = await yn(t, n, xn, {
|
|
1290
1317
|
...Z,
|
|
1291
|
-
maxmem:
|
|
1318
|
+
maxmem: Tn
|
|
1292
1319
|
}), a = Buffer.alloc(Q);
|
|
1293
|
-
|
|
1320
|
+
bn.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);
|
|
1294
1321
|
let o = 0, s = (e, t) => {
|
|
1295
|
-
let n = _("aes-256-gcm", i,
|
|
1322
|
+
let n = _("aes-256-gcm", i, En(r, o, t));
|
|
1296
1323
|
o === 0 && n.setAAD(a);
|
|
1297
1324
|
let s = Buffer.concat([n.update(e), n.final()]), c = n.getAuthTag();
|
|
1298
1325
|
o++;
|
|
1299
1326
|
let l = Buffer.alloc(5 + s.length + X);
|
|
1300
1327
|
return l.writeUInt8(+!!t, 0), l.writeUInt32BE(s.length + X, 1), s.copy(l, 5), c.copy(l, 5 + s.length), new Uint8Array(l);
|
|
1301
1328
|
}, c = Buffer.alloc(0);
|
|
1302
|
-
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length >
|
|
1329
|
+
for await (let t of e) for (c = c.length === 0 ? Buffer.from(t) : Buffer.concat([c, Buffer.from(t)]); c.length > wn;) yield s(c.subarray(0, wn), !1), c = c.subarray(wn);
|
|
1303
1330
|
yield s(c, !0);
|
|
1304
1331
|
}
|
|
1305
|
-
async function*
|
|
1332
|
+
async function* On(e, t) {
|
|
1306
1333
|
if (!t) throw Error("decryptStream: a non-empty passphrase is required");
|
|
1307
1334
|
let n = e[Symbol.asyncIterator](), r = Buffer.alloc(0), i = !1, a = async () => {
|
|
1308
1335
|
let { value: e, done: t } = await n.next();
|
|
@@ -1313,12 +1340,12 @@ async function* En(e, t) {
|
|
|
1313
1340
|
};
|
|
1314
1341
|
if (!await o(Q)) throw Error("encrypted bundle truncated (no header)");
|
|
1315
1342
|
let s = r.subarray(0, Q);
|
|
1316
|
-
if (!s.subarray(0, 8).equals(
|
|
1317
|
-
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
|
|
1343
|
+
if (!s.subarray(0, 8).equals(bn)) throw Error("not an encrypted bundle (bad magic / wrong passphrase target)");
|
|
1344
|
+
let c = s.readUInt32BE(8), l = s.readUInt32BE(12), u = s.readUInt32BE(16), d = Buffer.from(s.subarray(20, 36)), f = Buffer.from(s.subarray(36, Q)), p = await yn(t, d, xn, {
|
|
1318
1345
|
N: c,
|
|
1319
1346
|
r: l,
|
|
1320
1347
|
p: u,
|
|
1321
|
-
maxmem:
|
|
1348
|
+
maxmem: Tn
|
|
1322
1349
|
});
|
|
1323
1350
|
r = r.subarray(Q);
|
|
1324
1351
|
let m = 0, h = !1;
|
|
@@ -1333,7 +1360,7 @@ async function* En(e, t) {
|
|
|
1333
1360
|
if (!await o(5 + t)) throw Error("encrypted bundle truncated (frame body)");
|
|
1334
1361
|
let n = r.subarray(5, 5 + t - X), i = r.subarray(5 + t - X, 5 + t);
|
|
1335
1362
|
r = r.subarray(5 + t);
|
|
1336
|
-
let a = v("aes-256-gcm", p,
|
|
1363
|
+
let a = v("aes-256-gcm", p, En(f, m, e));
|
|
1337
1364
|
m === 0 && a.setAAD(s), a.setAuthTag(i);
|
|
1338
1365
|
let c = Buffer.concat([a.update(n), a.final()]);
|
|
1339
1366
|
m++, e && (h = !0), c.length > 0 && (yield new Uint8Array(c));
|
|
@@ -1341,7 +1368,7 @@ async function* En(e, t) {
|
|
|
1341
1368
|
}
|
|
1342
1369
|
//#endregion
|
|
1343
1370
|
//#region src/blobStorage.ts
|
|
1344
|
-
var
|
|
1371
|
+
var kn = (e, t) => ({
|
|
1345
1372
|
list: () => {
|
|
1346
1373
|
let e = t();
|
|
1347
1374
|
return { async *[Symbol.asyncIterator]() {
|
|
@@ -1354,29 +1381,29 @@ var Dn = (e, t) => ({
|
|
|
1354
1381
|
} };
|
|
1355
1382
|
},
|
|
1356
1383
|
open: (t) => ({ async *[Symbol.asyncIterator]() {
|
|
1357
|
-
let r = await n.runPromise(
|
|
1384
|
+
let r = await n.runPromise(ee(e, t)), i = await ne(r.stream);
|
|
1358
1385
|
for await (let e of i) yield e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
1359
1386
|
} })
|
|
1360
|
-
}),
|
|
1361
|
-
table:
|
|
1387
|
+
}), An = (e, t) => kn(e, () => h(t, {
|
|
1388
|
+
table: C,
|
|
1362
1389
|
chunkSize: 500
|
|
1363
1390
|
}).pipe(c.map((e) => ({
|
|
1364
1391
|
key: String(e.key),
|
|
1365
1392
|
contentType: String(e.contentType ?? "application/octet-stream"),
|
|
1366
1393
|
size: Number(e.size ?? 0)
|
|
1367
|
-
})))),
|
|
1394
|
+
})))), jn = (e) => ({
|
|
1368
1395
|
has: (t) => n.runPromise(e.head(t).pipe(n.map((e) => e !== null))),
|
|
1369
1396
|
write: async (t, r, i) => {
|
|
1370
|
-
let a =
|
|
1371
|
-
await n.runPromise(
|
|
1397
|
+
let a = w("storage", () => ie.from(r));
|
|
1398
|
+
await n.runPromise(te(e, t, a, {
|
|
1372
1399
|
contentType: i.contentType,
|
|
1373
1400
|
totalSize: i.size
|
|
1374
1401
|
}));
|
|
1375
1402
|
}
|
|
1376
|
-
}),
|
|
1403
|
+
}), Mn = (e, t) => {
|
|
1377
1404
|
let n = t === "dump" ? "mariadb-dump" : "mariadb", r = t === "dump" ? "mysqldump" : "mysql";
|
|
1378
|
-
return e === "mariadb" &&
|
|
1379
|
-
},
|
|
1405
|
+
return e === "mariadb" && Nn(n) ? n : r;
|
|
1406
|
+
}, Nn = (e) => (process.env.PATH ?? "").split(de).filter((e) => e !== "").some((t) => oe(k(t, e))), Pn = (e) => {
|
|
1380
1407
|
switch (e) {
|
|
1381
1408
|
case "postgres": return "db.dump";
|
|
1382
1409
|
case "mysql":
|
|
@@ -1386,7 +1413,7 @@ var Dn = (e, t) => ({
|
|
|
1386
1413
|
case "mssql": return "db.bacpac";
|
|
1387
1414
|
default: return "db.dump";
|
|
1388
1415
|
}
|
|
1389
|
-
},
|
|
1416
|
+
}, Fn = (e) => e.filename ?? e.database ?? ((e.url ?? "").replace(/^file:/, "") || "app.sqlite"), $ = (e) => {
|
|
1390
1417
|
if (e.host || e.database) return {
|
|
1391
1418
|
host: e.host ?? "localhost",
|
|
1392
1419
|
port: e.port ?? 3306,
|
|
@@ -1402,7 +1429,7 @@ var Dn = (e, t) => ({
|
|
|
1402
1429
|
password: decodeURIComponent(t.password) || "",
|
|
1403
1430
|
database: t.pathname.replace(/^\//, "") || ""
|
|
1404
1431
|
};
|
|
1405
|
-
},
|
|
1432
|
+
}, In = (e) => `Server=${e.host},${e.port};Database=${e.database};User ID=${e.username};Password=${e.password};TrustServerCertificate=True`, Ln = (e, t, n) => {
|
|
1406
1433
|
switch (e) {
|
|
1407
1434
|
case "postgres": {
|
|
1408
1435
|
if (t.url) return {
|
|
@@ -1449,7 +1476,7 @@ var Dn = (e, t) => ({
|
|
|
1449
1476
|
let r = $(t);
|
|
1450
1477
|
return {
|
|
1451
1478
|
kind: "spawn",
|
|
1452
|
-
tool:
|
|
1479
|
+
tool: Mn(e, "dump"),
|
|
1453
1480
|
args: [
|
|
1454
1481
|
"--single-transaction",
|
|
1455
1482
|
"--routines",
|
|
@@ -1471,7 +1498,7 @@ var Dn = (e, t) => ({
|
|
|
1471
1498
|
case "sqlite":
|
|
1472
1499
|
case "turso": return {
|
|
1473
1500
|
kind: "copy",
|
|
1474
|
-
from:
|
|
1501
|
+
from: Fn(t),
|
|
1475
1502
|
to: n
|
|
1476
1503
|
};
|
|
1477
1504
|
case "mssql": return {
|
|
@@ -1479,7 +1506,7 @@ var Dn = (e, t) => ({
|
|
|
1479
1506
|
tool: "sqlpackage",
|
|
1480
1507
|
args: [
|
|
1481
1508
|
"/Action:Export",
|
|
1482
|
-
`/SourceConnectionString:${
|
|
1509
|
+
`/SourceConnectionString:${In($({
|
|
1483
1510
|
...t,
|
|
1484
1511
|
port: t.port ?? 1433
|
|
1485
1512
|
}))}`,
|
|
@@ -1492,7 +1519,7 @@ var Dn = (e, t) => ({
|
|
|
1492
1519
|
reason: `no native backup for dialect '${e}'`
|
|
1493
1520
|
});
|
|
1494
1521
|
}
|
|
1495
|
-
},
|
|
1522
|
+
}, Rn = (e, t, n) => {
|
|
1496
1523
|
switch (e) {
|
|
1497
1524
|
case "postgres": {
|
|
1498
1525
|
if (t.url) return {
|
|
@@ -1537,7 +1564,7 @@ var Dn = (e, t) => ({
|
|
|
1537
1564
|
let r = $(t);
|
|
1538
1565
|
return {
|
|
1539
1566
|
kind: "spawn",
|
|
1540
|
-
tool:
|
|
1567
|
+
tool: Mn(e, "client"),
|
|
1541
1568
|
args: [
|
|
1542
1569
|
"--protocol=TCP",
|
|
1543
1570
|
"-h",
|
|
@@ -1556,14 +1583,14 @@ var Dn = (e, t) => ({
|
|
|
1556
1583
|
case "turso": return {
|
|
1557
1584
|
kind: "copy",
|
|
1558
1585
|
from: n,
|
|
1559
|
-
to:
|
|
1586
|
+
to: Fn(t)
|
|
1560
1587
|
};
|
|
1561
1588
|
case "mssql": return {
|
|
1562
1589
|
kind: "spawn",
|
|
1563
1590
|
tool: "sqlpackage",
|
|
1564
1591
|
args: [
|
|
1565
1592
|
"/Action:Import",
|
|
1566
|
-
`/TargetConnectionString:${
|
|
1593
|
+
`/TargetConnectionString:${In($({
|
|
1567
1594
|
...t,
|
|
1568
1595
|
port: t.port ?? 1433
|
|
1569
1596
|
}))}`,
|
|
@@ -1576,13 +1603,13 @@ var Dn = (e, t) => ({
|
|
|
1576
1603
|
reason: `no native restore for dialect '${e}'`
|
|
1577
1604
|
});
|
|
1578
1605
|
}
|
|
1579
|
-
},
|
|
1580
|
-
|
|
1606
|
+
}, zn = (e) => e.kind === "copy" ? n.async((t) => {
|
|
1607
|
+
ae(e.from, e.to, (r) => t(r ? n.fail(new L({
|
|
1581
1608
|
tool: "copy",
|
|
1582
1609
|
reason: `copy ${e.from} → ${e.to}: ${r.message}`
|
|
1583
1610
|
})) : n.void));
|
|
1584
1611
|
}) : n.async((t) => {
|
|
1585
|
-
let r =
|
|
1612
|
+
let r = ge(e.tool, [...e.args], {
|
|
1586
1613
|
env: {
|
|
1587
1614
|
...process.env,
|
|
1588
1615
|
...e.env
|
|
@@ -1595,10 +1622,10 @@ var Dn = (e, t) => ({
|
|
|
1595
1622
|
}), i = "";
|
|
1596
1623
|
r.stderr?.on("data", (e) => {
|
|
1597
1624
|
i += String(e);
|
|
1598
|
-
}), e.stdoutFile && r.stdout && r.stdout.pipe(
|
|
1625
|
+
}), e.stdoutFile && r.stdout && r.stdout.pipe(D(e.stdoutFile)), e.stdinFile && r.stdin && E(e.stdinFile).pipe(r.stdin);
|
|
1599
1626
|
let a = () => {
|
|
1600
1627
|
if (e.stdoutFile !== void 0) try {
|
|
1601
|
-
|
|
1628
|
+
se(e.stdoutFile);
|
|
1602
1629
|
} catch {}
|
|
1603
1630
|
};
|
|
1604
1631
|
r.on("error", (r) => {
|
|
@@ -1613,15 +1640,15 @@ var Dn = (e, t) => ({
|
|
|
1613
1640
|
}
|
|
1614
1641
|
a(), t(n.fail(new L({
|
|
1615
1642
|
tool: e.tool,
|
|
1616
|
-
reason: `exited with code ${r}` + (e.stdoutFile === void 0 ? "" : ` — the partial ${
|
|
1643
|
+
reason: `exited with code ${r}` + (e.stdoutFile === void 0 ? "" : ` — the partial ${ue(e.stdoutFile)} was removed, so it cannot be mistaken for a backup`),
|
|
1617
1644
|
stderr: i.slice(-2e3)
|
|
1618
1645
|
})));
|
|
1619
1646
|
});
|
|
1620
|
-
}),
|
|
1647
|
+
}), Bn = (e) => typeof e == "object" && e ? "fake" in e ? `fake:${e.fake}` : "custom" : String(e), Vn = (e) => n.gen(function* () {
|
|
1621
1648
|
let t = yield* V(e.scope ?? { kind: "all" }, e.snapshot, {
|
|
1622
1649
|
store: e.store,
|
|
1623
1650
|
...e.tenantTables ? { tenantTables: e.tenantTables } : {}
|
|
1624
|
-
}), r = At(t.tables, e.snapshot), i = e.classification ??
|
|
1651
|
+
}), r = At(t.tables, e.snapshot), i = e.classification ?? A(e.snapshot), a = e.sampleSize ?? 20, o = Ae(r.map((t) => ({
|
|
1625
1652
|
name: t,
|
|
1626
1653
|
columns: (e.snapshot.tables.find((e) => e.name === t)?.columns ?? []).map((e) => ({
|
|
1627
1654
|
name: e.name,
|
|
@@ -1641,7 +1668,7 @@ var Dn = (e, t) => ({
|
|
|
1641
1668
|
let n = e.slice(i.length + 1);
|
|
1642
1669
|
m.push({
|
|
1643
1670
|
column: n,
|
|
1644
|
-
action:
|
|
1671
|
+
action: Bn(t),
|
|
1645
1672
|
before: f[n],
|
|
1646
1673
|
after: p[n]
|
|
1647
1674
|
});
|
|
@@ -1656,7 +1683,7 @@ var Dn = (e, t) => ({
|
|
|
1656
1683
|
leaks: l,
|
|
1657
1684
|
unclassified: o.unclassified
|
|
1658
1685
|
};
|
|
1659
|
-
}),
|
|
1686
|
+
}), Hn = (e, t) => {
|
|
1660
1687
|
let n = new Map(t.map((e) => [e.name, e])), r = [], i = {};
|
|
1661
1688
|
for (let t of e) {
|
|
1662
1689
|
let e = n.get(t.name);
|
|
@@ -1711,7 +1738,7 @@ var Dn = (e, t) => ({
|
|
|
1711
1738
|
skipColumns: i,
|
|
1712
1739
|
refuse: r.some((e) => e.verdict === "refuse")
|
|
1713
1740
|
};
|
|
1714
|
-
},
|
|
1741
|
+
}, Un = (e) => {
|
|
1715
1742
|
if (e.findings.length === 0) return [" schema matches the bundle"];
|
|
1716
1743
|
let t = {
|
|
1717
1744
|
safe: "✓",
|
|
@@ -1722,4 +1749,4 @@ var Dn = (e, t) => ({
|
|
|
1722
1749
|
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;
|
|
1723
1750
|
};
|
|
1724
1751
|
//#endregion
|
|
1725
|
-
export { W as ASSETS_DIR, G as ASSET_INDEX_FILE, P as BundleError, Pe as CodecError, Fe as CompressionError, Be as CrossDialectError, U as DATA_DIR,
|
|
1752
|
+
export { W as ASSETS_DIR, G as ASSET_INDEX_FILE, P as BundleError, Pe as CodecError, Fe as CompressionError, Be as CrossDialectError, U as DATA_DIR, ve as DEFAULT_CLASS_ACTIONS, Qe as FORMAT_VERSION, ze as ImportModeError, F as IntegrityError, ot as LEDGER_FILE, H as MANIFEST_FILE, Re as MaskingError, L as NativeToolError, Ie as RowsRefusedError, Le as SchemaDriftError, I as ScopeError, Oe as applyAction, rn as assessLiveImport, gt as assetDone, Pn as backupArtifactName, Ln as backupCommand, Ht as canonicalType, Gt as checkPortability, $t as checkSchemaDrift, A as classificationFromSnapshot, Hn as classifyImportDrift, Ye as compressionExt, z as computeSubsetIds, it as decodeManifest, Et as decodeRow, wt as decodeValue, On as decryptStream, nn as defineDataProfile, Qt as diffSnapshots, vn as dirBlobSink, pt as emptyLedger, rt as encodeManifest, Tt as encodeRow, St as encodeValue, Dn as encryptStream, Un as formatImportDrift, Kt as formatIssue, qe as hasZstd, Xe as makeCompressor, Ze as makeDecompressor, Ne as maskRow, kt as ndjsonToRows, fn as packBundle, gn as peekBundle, Je as pickCompression, Ae as planMasking, Vn as previewMasking, mt as readLedger, ye as resolveAction, V as resolveScope, Ke as restoreAssetFromCas, Rn as restoreCommand, Ot as rowsToNdjson, Vt as runExport, tn as runImport, zn as runNativeStep, Me as scanForLeaks, We as storageAssetSink, Ue as storageAssetSource, jn as storageBlobSink, kn as storageBlobSource, An as storageRefsBlobSource, He as subsetToScope, ht as tableDone, At as topoSortTables, hn as unpackBundle, _n as unpackBundleToDir, Ge as writeAssetToCas, q as writeLedger };
|