@voltro/data-transfer 0.86.0 → 0.88.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 +5484 -0
- package/THIRD-PARTY-NOTICES.md +2503 -690
- package/dist/assetAdmission.js +91 -0
- package/dist/assets.js +62 -42
- package/dist/blobStorage.js +55 -32
- package/dist/bundleArchive.js +249 -105
- package/dist/bundleCrypto.js +1 -2
- package/dist/bundlePaths.js +3 -0
- package/dist/casAssetPhase.js +78 -35
- package/dist/compress.js +4 -5
- package/dist/consistency.js +1 -2
- package/dist/crossDialect.js +1 -2
- package/dist/driftClassification.js +1 -2
- package/dist/environmentLocal.js +267 -4
- package/dist/errors.js +13 -7
- package/dist/exporter.js +146 -133
- package/dist/filesystemAdmission.js +32 -0
- package/dist/importer.js +326 -287
- package/dist/index.d.ts +200 -46
- package/dist/index.js +28 -26
- package/dist/ledger.js +1 -2
- package/dist/liveGuard.js +1 -2
- package/dist/manifest.js +45 -42
- package/dist/masking.js +1 -2
- package/dist/maskingPreview.js +1 -2
- package/dist/nativeDump.js +134 -86
- package/dist/ndjson.js +1 -2
- package/dist/physicalRequest.js +9 -0
- package/dist/profile.js +1 -2
- package/dist/progress.js +1 -2
- package/dist/readme.js +1 -2
- package/dist/replacePreflight.js +1 -2
- package/dist/rollbackCapture.js +1 -2
- package/dist/rowFailureReason.js +1 -2
- package/dist/schemaDrift.js +1 -2
- package/dist/scope.js +1 -2
- package/dist/sealedKeys.js +39 -0
- package/dist/stagedSwap.js +1 -2
- package/dist/storageAssetMetadata.js +46 -0
- package/dist/subset.js +1 -2
- package/dist/topo.js +1 -2
- package/dist/typedCodec.js +1 -2
- package/package.json +4 -4
package/dist/manifest.js
CHANGED
|
@@ -1,52 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { isSafeBundlePath as e } from "./bundlePaths.js";
|
|
2
|
+
import { Schema as t } from "effect";
|
|
3
|
+
import { StorageAddress as n } from "@voltro/plugin-storage/errors";
|
|
4
|
+
// src/manifest.ts
|
|
5
|
+
var r = 2, i = t.Struct({
|
|
6
|
+
name: t.String,
|
|
7
|
+
file: t.String,
|
|
8
|
+
rowCount: t.Number,
|
|
9
|
+
checksum: t.String,
|
|
10
|
+
columnTypes: t.Record(t.String, t.String),
|
|
11
|
+
primaryKey: t.String
|
|
12
|
+
}), a = t.Struct({
|
|
13
|
+
kind: t.Literals([
|
|
12
14
|
"all",
|
|
13
15
|
"tenant",
|
|
14
16
|
"tables"
|
|
15
17
|
]),
|
|
16
|
-
tenantId:
|
|
17
|
-
tables:
|
|
18
|
-
exclude:
|
|
19
|
-
}),
|
|
20
|
-
count:
|
|
21
|
-
totalBytes:
|
|
22
|
-
index:
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
dialect: e.String,
|
|
35
|
-
schemaFingerprint: e.String
|
|
18
|
+
tenantId: t.optional(t.String),
|
|
19
|
+
tables: t.optional(t.Array(t.String)),
|
|
20
|
+
exclude: t.optional(t.Array(t.String))
|
|
21
|
+
}), o = t.Struct({
|
|
22
|
+
count: t.Number,
|
|
23
|
+
totalBytes: t.Number,
|
|
24
|
+
index: t.optional(t.String.pipe(t.check(t.makeFilter(e))))
|
|
25
|
+
}), s = n, c = t.Struct({
|
|
26
|
+
...s.fields,
|
|
27
|
+
sha256: t.String.pipe(t.check(t.isPattern(/^[a-f0-9]{64}$/))),
|
|
28
|
+
size: t.Number.pipe(t.check(t.isInt()), t.check(t.isGreaterThanOrEqualTo(0)), t.check(t.isLessThanOrEqualTo(2 ** 53 - 1))),
|
|
29
|
+
contentType: t.String.pipe(t.check(t.isMinLength(1)), t.check(t.makeFilter((e) => !/[\uD800-\uDFFF]/u.test(e))))
|
|
30
|
+
}), l = t.Struct({
|
|
31
|
+
formatVersion: t.Number,
|
|
32
|
+
createdAt: t.String,
|
|
33
|
+
source: t.Struct({
|
|
34
|
+
dialect: t.String,
|
|
35
|
+
schemaFingerprint: t.String
|
|
36
36
|
}),
|
|
37
|
-
scope:
|
|
38
|
-
consistency:
|
|
39
|
-
compression:
|
|
37
|
+
scope: a,
|
|
38
|
+
consistency: t.Literals(["live", "snapshot"]),
|
|
39
|
+
compression: t.Literals([
|
|
40
40
|
"zstd",
|
|
41
41
|
"gzip",
|
|
42
42
|
"none"
|
|
43
43
|
]),
|
|
44
|
-
tables:
|
|
45
|
-
assets:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
tables: t.Array(i),
|
|
45
|
+
assets: o,
|
|
46
|
+
fieldKeys: t.optional(t.Struct({
|
|
47
|
+
keyIds: t.Array(t.String),
|
|
48
|
+
unnamed: t.Number
|
|
49
|
+
})),
|
|
50
|
+
masking: t.optional(t.Struct({
|
|
51
|
+
policyId: t.optional(t.String),
|
|
52
|
+
transformed: t.Array(t.String)
|
|
49
53
|
}))
|
|
50
|
-
}),
|
|
51
|
-
|
|
52
|
-
export { d as ASSETS_DIR, f as ASSET_INDEX_FILE, i as AssetSummary, u as DATA_DIR, r as ExportScope, t as FORMAT_VERSION, p as LEDGER_FILE, c as MANIFEST_FILE, a as Manifest, l as README_FILE, n as TableEntry, s as decodeManifest, o as encodeManifest };
|
|
54
|
+
}), u = t.encodeSync(t.fromJsonString(l)), d = t.decodeUnknownSync(t.fromJsonString(l)), f = "manifest.json", p = "README.md", m = "data", h = "assets", g = "assets/index.ndjson", _ = ".ledger.json";
|
|
55
|
+
export { h as ASSETS_DIR, g as ASSET_INDEX_FILE, s as AssetAddress, c as AssetEntry, o as AssetSummary, m as DATA_DIR, a as ExportScope, r as FORMAT_VERSION, _ as LEDGER_FILE, f as MANIFEST_FILE, l as Manifest, p as README_FILE, i as TableEntry, d as decodeManifest, u as encodeManifest };
|
package/dist/masking.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHmac as e } from "node:crypto";
|
|
2
|
-
|
|
2
|
+
// src/masking.ts
|
|
3
3
|
var t = {
|
|
4
4
|
email: { fake: "email" },
|
|
5
5
|
fullName: { fake: "fullName" },
|
|
@@ -242,5 +242,4 @@ var t = {
|
|
|
242
242
|
});
|
|
243
243
|
return a;
|
|
244
244
|
};
|
|
245
|
-
//#endregion
|
|
246
245
|
export { t as DEFAULT_CLASS_ACTIONS, h as applyAction, n as classificationFromSnapshot, v as isMaskAction, S as maskRow, y as planMasking, r as resolveAction, x as scanForLeaks };
|
package/dist/maskingPreview.js
CHANGED
|
@@ -3,7 +3,7 @@ import { resolveScope as i } from "./scope.js";
|
|
|
3
3
|
import { topoSortTables as a } from "./topo.js";
|
|
4
4
|
import { Effect as o, Stream as s } from "effect";
|
|
5
5
|
import { streamTable as c } from "@voltro/database";
|
|
6
|
-
|
|
6
|
+
// src/maskingPreview.ts
|
|
7
7
|
var l = (e) => typeof e == "object" && e ? "fake" in e ? `fake:${e.fake}` : "custom" : String(e), u = (u) => o.gen(function* () {
|
|
8
8
|
let d = u.scope ?? { kind: "all" }, f = yield* i(d, u.snapshot, {
|
|
9
9
|
store: u.store,
|
|
@@ -44,5 +44,4 @@ var l = (e) => typeof e == "object" && e ? "fake" in e ? `fake:${e.fake}` : "cus
|
|
|
44
44
|
unclassified: _.unclassified
|
|
45
45
|
};
|
|
46
46
|
});
|
|
47
|
-
//#endregion
|
|
48
47
|
export { u as previewMasking };
|
package/dist/nativeDump.js
CHANGED
|
@@ -5,7 +5,7 @@ import { randomUUID as i } from "node:crypto";
|
|
|
5
5
|
import { copyFile as a, createReadStream as o, createWriteStream as s, existsSync as c, rename as l, statSync as u, unlinkSync as d } from "node:fs";
|
|
6
6
|
import { basename as f, delimiter as p, join as m } from "node:path";
|
|
7
7
|
import { spawn as h } from "node:child_process";
|
|
8
|
-
|
|
8
|
+
// src/nativeDump.ts
|
|
9
9
|
var g = (e, t) => {
|
|
10
10
|
let n = t === "dump" ? "mariadb-dump" : "mariadb", r = t === "dump" ? "mysqldump" : "mysql";
|
|
11
11
|
return e === "mariadb" ? _(n) ? { tool: n } : {
|
|
@@ -104,12 +104,16 @@ var g = (e, t) => {
|
|
|
104
104
|
stdoutFile: r
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
|
-
case "sqlite":
|
|
108
|
-
|
|
109
|
-
kind: "copy",
|
|
107
|
+
case "sqlite": return {
|
|
108
|
+
kind: "sqlite-backup",
|
|
110
109
|
from: y(n),
|
|
111
110
|
to: r
|
|
112
111
|
};
|
|
112
|
+
case "turso": return {
|
|
113
|
+
kind: "vacuum-into",
|
|
114
|
+
conn: n,
|
|
115
|
+
to: r
|
|
116
|
+
};
|
|
113
117
|
case "mssql": return {
|
|
114
118
|
kind: "spawn",
|
|
115
119
|
tool: "sqlpackage",
|
|
@@ -273,97 +277,141 @@ END`;
|
|
|
273
277
|
return t.gen(function* () {
|
|
274
278
|
yield* a(`preparing ${n.scratch}`, i.prepare), yield* L(n.load).pipe(t.tapError(() => o)), yield* a(`carrying ${n.carry.join(", ")} into the imported copy`, i.carry).pipe(t.tapError(() => o)), yield* a(`swapping ${n.scratch} in as ${n.live}`, i.swap).pipe(t.tapError(() => a("putting the original database back", i.undoSwap).pipe(t.ignore)));
|
|
275
279
|
});
|
|
276
|
-
}, L = (n, r) =>
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
})))
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
for (let e of [
|
|
290
|
-
`${n.to}-wal`,
|
|
291
|
-
`${n.to}-shm`,
|
|
292
|
-
`${n.to}-journal`
|
|
293
|
-
]) try {
|
|
294
|
-
d(e);
|
|
280
|
+
}, L = (n, r) => {
|
|
281
|
+
if (n.kind === "mssql-replace") return I(n, r);
|
|
282
|
+
if (n.kind === "vacuum-into") {
|
|
283
|
+
if (r === void 0) return t.fail(new e({
|
|
284
|
+
tool: "vacuum-into",
|
|
285
|
+
reason: "a VACUUM INTO backup needs a SQL connection to the database"
|
|
286
|
+
}));
|
|
287
|
+
let a = `${n.to}.backing-up-${i()}`;
|
|
288
|
+
return r(n.conn, [`VACUUM INTO '${a.replaceAll("'", "''")}'`]).pipe(t.flatMap(() => t.callback((e) => {
|
|
289
|
+
l(a, n.to, (n) => e(n ? t.fail(n) : t.void));
|
|
290
|
+
})), t.mapError((t) => {
|
|
291
|
+
try {
|
|
292
|
+
d(a);
|
|
295
293
|
} catch {}
|
|
296
|
-
|
|
297
|
-
|
|
294
|
+
return new e({
|
|
295
|
+
tool: "vacuum-into",
|
|
296
|
+
reason: `VACUUM INTO ${n.to}: ${t instanceof Error ? t.message : String(t)}`
|
|
298
297
|
});
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
}) : t.callback((r) => {
|
|
302
|
-
let i = h(n.tool, [...n.args], {
|
|
303
|
-
env: {
|
|
304
|
-
...process.env,
|
|
305
|
-
...n.env
|
|
306
|
-
},
|
|
307
|
-
stdio: [
|
|
308
|
-
"pipe",
|
|
309
|
-
n.stdoutFile ? "pipe" : "inherit",
|
|
310
|
-
"pipe"
|
|
311
|
-
]
|
|
312
|
-
}), a = "";
|
|
313
|
-
i.stderr?.on("data", (e) => {
|
|
314
|
-
a += String(e);
|
|
315
|
-
});
|
|
316
|
-
let c = !1, l = (e) => {
|
|
317
|
-
c || (c = !0, r(e));
|
|
318
|
-
}, u, p = (e) => {
|
|
319
|
-
u ??= e;
|
|
320
|
-
};
|
|
321
|
-
if (n.stdoutFile && i.stdout) {
|
|
322
|
-
let e = s(n.stdoutFile);
|
|
323
|
-
e.on("error", (e) => p(`writing ${f(n.stdoutFile)}: ${e.message}`)), i.stdout.on("error", (e) => p(`reading the tool's output: ${e.message}`)), i.stdout.pipe(e);
|
|
324
|
-
}
|
|
325
|
-
let m = 0;
|
|
326
|
-
if (n.stdinFile && i.stdin) {
|
|
327
|
-
let e = o(n.stdinFile);
|
|
328
|
-
e.on("data", (e) => {
|
|
329
|
-
m += e.length;
|
|
330
|
-
}), e.on("error", (e) => {
|
|
331
|
-
p(`reading ${f(n.stdinFile)}: ${e.message}`), i.stdin?.end();
|
|
332
|
-
}), i.stdin.on("error", (e) => {
|
|
333
|
-
e.code !== "EPIPE" && p(`feeding ${f(n.stdinFile)} to ${n.tool}: ${e.message}`);
|
|
334
|
-
}), e.pipe(i.stdin);
|
|
298
|
+
}));
|
|
335
299
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
300
|
+
return n.kind === "sqlite-backup" ? t.tryPromise({
|
|
301
|
+
try: async () => {
|
|
302
|
+
let { backup: e, DatabaseSync: t } = await import("node:sqlite"), r = `${n.to}.backing-up-${i()}`, a = new t(n.from, { readOnly: !0 });
|
|
303
|
+
try {
|
|
304
|
+
await e(a, r);
|
|
305
|
+
} catch (e) {
|
|
306
|
+
try {
|
|
307
|
+
d(r);
|
|
308
|
+
} catch {}
|
|
309
|
+
throw e;
|
|
310
|
+
} finally {
|
|
311
|
+
a.close();
|
|
312
|
+
}
|
|
313
|
+
await new Promise((e, t) => {
|
|
314
|
+
l(r, n.to, (n) => {
|
|
315
|
+
n ? t(n) : e();
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
},
|
|
319
|
+
catch: (t) => new e({
|
|
320
|
+
tool: "sqlite-backup",
|
|
321
|
+
reason: `backup ${n.from} → ${n.to}: ${t instanceof Error ? t.message : String(t)}`
|
|
322
|
+
})
|
|
323
|
+
}) : n.kind === "copy" ? t.callback((r) => {
|
|
324
|
+
let o = `${n.to}.restoring-${i()}`, s = (n) => {
|
|
325
|
+
try {
|
|
326
|
+
d(o);
|
|
327
|
+
} catch {}
|
|
328
|
+
r(t.fail(new e({
|
|
329
|
+
tool: "copy",
|
|
330
|
+
reason: n
|
|
331
|
+
})));
|
|
332
|
+
};
|
|
333
|
+
a(n.from, o, (e) => {
|
|
334
|
+
if (e) s(`copy ${n.from} → ${n.to}: ${e.message}`);
|
|
335
|
+
else {
|
|
336
|
+
for (let e of [
|
|
337
|
+
`${n.to}-wal`,
|
|
338
|
+
`${n.to}-shm`,
|
|
339
|
+
`${n.to}-journal`,
|
|
340
|
+
`${n.to}-log`
|
|
341
|
+
]) try {
|
|
342
|
+
d(e);
|
|
343
|
+
} catch {}
|
|
344
|
+
l(o, n.to, (e) => {
|
|
345
|
+
e ? s(`copy ${n.from} → ${n.to}: ${e.message}`) : r(t.void);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}) : t.callback((r) => {
|
|
350
|
+
let i = h(n.tool, [...n.args], {
|
|
351
|
+
env: {
|
|
352
|
+
...process.env,
|
|
353
|
+
...n.env
|
|
354
|
+
},
|
|
355
|
+
stdio: [
|
|
356
|
+
"pipe",
|
|
357
|
+
n.stdoutFile ? "pipe" : "inherit",
|
|
358
|
+
"pipe"
|
|
359
|
+
]
|
|
360
|
+
}), a = "";
|
|
361
|
+
i.stderr?.on("data", (e) => {
|
|
362
|
+
a += String(e);
|
|
363
|
+
});
|
|
364
|
+
let c = !1, l = (e) => {
|
|
365
|
+
c || (c = !0, r(e));
|
|
366
|
+
}, u, p = (e) => {
|
|
367
|
+
u ??= e;
|
|
368
|
+
};
|
|
369
|
+
if (n.stdoutFile && i.stdout) {
|
|
370
|
+
let e = s(n.stdoutFile);
|
|
371
|
+
e.on("error", (e) => p(`writing ${f(n.stdoutFile)}: ${e.message}`)), i.stdout.on("error", (e) => p(`reading the tool's output: ${e.message}`)), i.stdout.pipe(e);
|
|
372
|
+
}
|
|
373
|
+
let m = 0;
|
|
374
|
+
if (n.stdinFile && i.stdin) {
|
|
375
|
+
let e = o(n.stdinFile);
|
|
376
|
+
e.on("data", (e) => {
|
|
377
|
+
m += e.length;
|
|
378
|
+
}), e.on("error", (e) => {
|
|
379
|
+
p(`reading ${f(n.stdinFile)}: ${e.message}`), i.stdin?.end();
|
|
380
|
+
}), i.stdin.on("error", (e) => {
|
|
381
|
+
e.code !== "EPIPE" && p(`feeding ${f(n.stdinFile)} to ${n.tool}: ${e.message}`);
|
|
382
|
+
}), e.pipe(i.stdin);
|
|
351
383
|
}
|
|
352
|
-
g()
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
384
|
+
let g = () => {
|
|
385
|
+
if (n.stdoutFile !== void 0) try {
|
|
386
|
+
d(n.stdoutFile);
|
|
387
|
+
} catch {}
|
|
388
|
+
};
|
|
389
|
+
i.on("error", (r) => {
|
|
390
|
+
g(), l(t.fail(new e({
|
|
391
|
+
tool: n.tool,
|
|
392
|
+
reason: `failed to launch (is '${n.tool}' installed + on PATH?): ${r.message}`,
|
|
393
|
+
...n.hint === void 0 ? {} : { hint: n.hint }
|
|
394
|
+
})));
|
|
395
|
+
}), i.on("close", (r) => {
|
|
396
|
+
if (r === 0 && u === void 0) {
|
|
397
|
+
l(t.void);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
g();
|
|
401
|
+
let i = n.stdinFile === void 0 ? "" : ` — ${m} of ${R(n.stdinFile)} byte(s) of ${f(n.stdinFile)} had been fed to it`;
|
|
402
|
+
l(t.fail(new e({
|
|
403
|
+
tool: n.tool,
|
|
404
|
+
reason: (r === 0 ? `exited cleanly, but ${u}` : `exited with code ${r}${u === void 0 ? "" : ` (${u})`}`) + i + (n.stdoutFile === void 0 ? "" : ` — the partial ${f(n.stdoutFile)} was removed, so it cannot be mistaken for a backup`),
|
|
405
|
+
stderr: a.trim() === "" ? `(${n.tool} printed nothing to stderr)` : a.slice(-2e3),
|
|
406
|
+
...n.hint === void 0 ? {} : { hint: n.hint }
|
|
407
|
+
})));
|
|
408
|
+
});
|
|
360
409
|
});
|
|
361
|
-
}
|
|
410
|
+
}, R = (e) => {
|
|
362
411
|
try {
|
|
363
412
|
return String(u(e).size);
|
|
364
413
|
} catch {
|
|
365
414
|
return "?";
|
|
366
415
|
}
|
|
367
416
|
};
|
|
368
|
-
//#endregion
|
|
369
417
|
export { C as EXCLUDED_FROM_DUMP, v as backupArtifactName, S as backupCommand, T as dumpExcludedTables, P as mssqlReplaceStatements, A as mssqlScratchName, E as restoreCommand, L as runNativeStep };
|
package/dist/ndjson.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CodecError as e } from "./errors.js";
|
|
2
2
|
import { decodeRow as t, encodeRow as n } from "./typedCodec.js";
|
|
3
3
|
import { Effect as r, Stream as i } from "effect";
|
|
4
|
-
|
|
4
|
+
// src/ndjson.ts
|
|
5
5
|
var a = new TextEncoder(), o = (e, t) => e.pipe(i.map((e) => a.encode(`${JSON.stringify(n(e, t))}\n`))), s = (n, a, o) => n.pipe(i.decodeText(), i.splitLines, i.filter((e) => e.trim().length > 0), i.mapEffect((n) => r.try({
|
|
6
6
|
try: () => t(JSON.parse(n), o),
|
|
7
7
|
catch: (t) => new e({
|
|
@@ -9,5 +9,4 @@ var a = new TextEncoder(), o = (e, t) => e.pipe(i.map((e) => a.encode(`${JSON.st
|
|
|
9
9
|
reason: String(t?.message ?? t)
|
|
10
10
|
})
|
|
11
11
|
})));
|
|
12
|
-
//#endregion
|
|
13
12
|
export { s as ndjsonToRows, o as rowsToNdjson };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Effect as e } from "effect";
|
|
2
|
+
// src/physicalRequest.ts
|
|
3
|
+
var t = (t, n) => e.callback((r) => {
|
|
4
|
+
let i = new AbortController(), a = Promise.resolve().then(() => t(i.signal));
|
|
5
|
+
return a.then((t) => r(e.succeed(t)), (t) => r(e.fail(n(t)))), e.sync(() => {
|
|
6
|
+
i.abort();
|
|
7
|
+
}).pipe(e.andThen(e.promise(() => a.then(() => void 0, () => void 0))));
|
|
8
|
+
});
|
|
9
|
+
export { t as physicalRequest };
|
package/dist/profile.js
CHANGED
package/dist/progress.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect as e, Metric as t } from "effect";
|
|
2
|
-
|
|
2
|
+
// src/progress.ts
|
|
3
3
|
var n = t.counter("voltro_data_transfer_rows", { description: "Rows exported/imported by @voltro/data-transfer, tagged by phase + table." }), r = Array.from({ length: 16 }, (e, t) => .01 * 2 ** t), i = t.histogram("voltro_data_transfer_table_seconds", {
|
|
4
4
|
boundaries: r,
|
|
5
5
|
description: "Per-table export/import duration in seconds, tagged by phase."
|
|
@@ -13,5 +13,4 @@ var n = t.counter("voltro_data_transfer_rows", { description: "Rows exported/imp
|
|
|
13
13
|
tableCount: s,
|
|
14
14
|
phase: r
|
|
15
15
|
} }));
|
|
16
|
-
//#endregion
|
|
17
16
|
export { a as reportProgress, o as withTableSpan };
|
package/dist/readme.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/readme.ts
|
|
2
2
|
var e = (e) => e.kind === "tenant" ? `tenant \`${e.tenantId}\`` : e.kind === "tables" ? `tables \`${(e.tables ?? []).join(", ")}\`` : "all tables", t = (t, n) => {
|
|
3
3
|
let r = t.tables.reduce((e, t) => e + t.rowCount, 0), i = t.masking ? `✅ **Masked at the source** — ${t.masking.transformed.length} column(s) transformed${t.masking.policyId ? ` (policy \`${t.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`).", a = t.masking && t.masking.transformed.length > 0 ? `\n\nMasked columns: ${t.masking.transformed.map((e) => `\`${e}\``).join(", ")}.` : "", o = t.assets.count > 0 ? `${t.assets.count} object(s), ${t.assets.totalBytes} bytes` : "none", s = t.tables.map((e) => `| \`${e.name}\` | ${e.rowCount} |`).join("\n");
|
|
4
4
|
return `# Voltro data export
|
|
@@ -39,5 +39,4 @@ voltro data import <this-directory> --target api --api-url <url> --token <secret
|
|
|
39
39
|
\`\`\`
|
|
40
40
|
`;
|
|
41
41
|
};
|
|
42
|
-
//#endregion
|
|
43
42
|
export { t as buildReadme };
|
package/dist/replacePreflight.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/replacePreflight.ts
|
|
2
2
|
var e = (e, t) => {
|
|
3
3
|
let n = new Set(t), r = [];
|
|
4
4
|
for (let t of e.tables) if (!n.has(t.name)) for (let e of t.columns) {
|
|
@@ -19,5 +19,4 @@ var e = (e, t) => {
|
|
|
19
19
|
});
|
|
20
20
|
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.`;
|
|
21
21
|
};
|
|
22
|
-
//#endregion
|
|
23
22
|
export { t as outsideReferenceRefusal, e as outsideReferencesInto };
|
package/dist/rollbackCapture.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BundleError as e } from "./errors.js";
|
|
2
2
|
import { runExport as t } from "./exporter.js";
|
|
3
3
|
import { Effect as n } from "effect";
|
|
4
|
-
|
|
4
|
+
// src/rollbackCapture.ts
|
|
5
5
|
var r = (r) => n.gen(function* () {
|
|
6
6
|
if (r.mode !== "replace" || r.dir === void 0 || r.tables.length === 0) return;
|
|
7
7
|
if (r.snapshot === void 0) return yield* n.fail(new e({
|
|
@@ -32,5 +32,4 @@ var r = (r) => n.gen(function* () {
|
|
|
32
32
|
tables: a.tables.length
|
|
33
33
|
};
|
|
34
34
|
}), i = (e) => `rollback capture: ${e.rows} row(s) across ${e.tables} table(s) → ${e.dir}\n If this run does not finish, restore with: voltro data import ${e.dir} --mode replace`;
|
|
35
|
-
//#endregion
|
|
36
35
|
export { r as captureRollback, i as rollbackNotice };
|
package/dist/rowFailureReason.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { classifyConstraintViolation as e, extractDbCause as t } from "@voltro/database";
|
|
2
|
-
|
|
2
|
+
// src/rowFailureReason.ts
|
|
3
3
|
var n = (e) => {
|
|
4
4
|
let t = e.constraint ?? e.column, n = t === void 0 ? "" : ` ${t}`;
|
|
5
5
|
switch (e.kind) {
|
|
@@ -32,5 +32,4 @@ var n = (e) => {
|
|
|
32
32
|
}
|
|
33
33
|
return s(n);
|
|
34
34
|
};
|
|
35
|
-
//#endregion
|
|
36
35
|
export { o as rowFailureDiagnosis, s as rowFailureReason, c as tableFailureReason };
|
package/dist/schemaDrift.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fingerprintSchema as e } from "@voltro/database/sql";
|
|
2
|
-
|
|
2
|
+
// src/schemaDrift.ts
|
|
3
3
|
var t = /__dropped_\d+$/, n = (e, n) => {
|
|
4
4
|
let r = [], i = /* @__PURE__ */ new Map();
|
|
5
5
|
for (let e of n.tables) {
|
|
@@ -36,5 +36,4 @@ var t = /__dropped_\d+$/, n = (e, n) => {
|
|
|
36
36
|
diff: o
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
|
-
//#endregion
|
|
40
39
|
export { r as checkSchemaDrift, n as diffSnapshots };
|
package/dist/scope.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ScopeError as t } from "./errors.js";
|
|
|
3
3
|
import { computeSubsetIds as n, pkOf as r } from "./subset.js";
|
|
4
4
|
import { Effect as i } from "effect";
|
|
5
5
|
import { eq as a, inSet as o } from "@voltro/database";
|
|
6
|
-
|
|
6
|
+
// src/scope.ts
|
|
7
7
|
var s = "tenantId", c = (c, l, u) => i.gen(function* () {
|
|
8
8
|
let d = l.tables.map((e) => e.name), f = new Map(l.tables.map((e) => [e.name, e]));
|
|
9
9
|
if (c.kind === "all") {
|
|
@@ -36,5 +36,4 @@ var s = "tenantId", c = (c, l, u) => i.gen(function* () {
|
|
|
36
36
|
predicateFor: (e) => _.has(e) ? a(s, p) : h.has(e) ? o(r(l, e), [...h.get(e)]) : void 0
|
|
37
37
|
};
|
|
38
38
|
});
|
|
39
|
-
//#endregion
|
|
40
39
|
export { c as resolveScope };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ciphertextKeyId as e } from "@voltro/database";
|
|
2
|
+
// src/sealedKeys.ts
|
|
3
|
+
var t = /enc:v[12]:[A-Za-z0-9+/=:_-]+/g, n = () => ({
|
|
4
|
+
byKey: {},
|
|
5
|
+
unnamed: 0
|
|
6
|
+
}), r = (e) => typeof e == "string" ? e : typeof e == "object" && e && !(e instanceof Uint8Array) && !(e instanceof Date) ? JSON.stringify(e) : void 0, i = (n, i) => {
|
|
7
|
+
for (let a of Object.values(n)) {
|
|
8
|
+
let n = r(a);
|
|
9
|
+
if (n !== void 0 && n.includes("enc:v")) for (let r of n.match(t) ?? []) {
|
|
10
|
+
let t = e(r);
|
|
11
|
+
t === void 0 ? i.unnamed += 1 : i.byKey[t] = (i.byKey[t] ?? 0) + 1;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}, a = (e, t) => {
|
|
15
|
+
for (let [n, r] of Object.entries(t.byKey)) e.byKey[n] = (e.byKey[n] ?? 0) + r;
|
|
16
|
+
e.unnamed += t.unnamed;
|
|
17
|
+
}, o = (e) => {
|
|
18
|
+
let n = e.match(t);
|
|
19
|
+
return n !== null && n.length === 1 && n[0] === e;
|
|
20
|
+
}, s = (n, i, a, s) => {
|
|
21
|
+
let c = new Set(a.held), l = (t, r) => {
|
|
22
|
+
let o = e(t);
|
|
23
|
+
return o === void 0 ? a.opens?.(t, {
|
|
24
|
+
table: n,
|
|
25
|
+
column: r,
|
|
26
|
+
row: i
|
|
27
|
+
}) ?? !0 : c.has(o);
|
|
28
|
+
}, u = { ...i };
|
|
29
|
+
for (let [e, n] of Object.entries(i)) {
|
|
30
|
+
if (typeof n == "string" && o(n)) {
|
|
31
|
+
l(n, e) || (u[e] = null, s.nulled.set(e, (s.nulled.get(e) ?? 0) + 1));
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
let i = r(n);
|
|
35
|
+
if (i !== void 0 && i.includes("enc:v")) for (let n of i.match(t) ?? []) l(n, e) || s.unreadable.set(e, (s.unreadable.get(e) ?? 0) + 1);
|
|
36
|
+
}
|
|
37
|
+
return u;
|
|
38
|
+
};
|
|
39
|
+
export { n as emptyTally, a as mergeTally, s as nullUnreadableSealed, i as tallyRow };
|
package/dist/stagedSwap.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect as e } from "effect";
|
|
2
2
|
import { STAGING_TABLE_PREFIX as t } from "@voltro/database";
|
|
3
3
|
import { SqlClient as n } from "effect/sql";
|
|
4
|
-
|
|
4
|
+
// src/stagedSwap.ts
|
|
5
5
|
var r = t, i = (e) => `${r}${e}`, a = (e) => typeof e.run == "function", o = (e) => `staging is not available for this run — loading directly into the target instead: ${e}\n The load therefore holds the destructive transaction open for its whole duration, so a
|
|
6
6
|
process that dies mid-load depends on the database rolling it back. The rollback capture
|
|
7
7
|
written before the first delete is what covers that case.`, s = /^[a-zA-Z_][a-zA-Z0-9_]*$/, c = (e, t) => {
|
|
@@ -160,5 +160,4 @@ var r = t, i = (e) => `${r}${e}`, a = (e) => typeof e.run == "function", o = (e)
|
|
|
160
160
|
tables: o
|
|
161
161
|
};
|
|
162
162
|
};
|
|
163
|
-
//#endregion
|
|
164
163
|
export { r as STAGING_PREFIX, a as canStage, l as createStagingSql, m as danglingProbeSql, h as danglingReport, x as decideStaging, u as dropStagingSql, g as execStatements, v as findDangling, y as forwardReferences, c as quoteIdent, f as registerStagingClones, _ as runSwap, p as stagedReferences, i as stagingNameFor, o as stagingUnavailable, b as suspendsIntegrity, d as swapStatements };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { BundleError as e } from "./errors.js";
|
|
2
|
+
import { admitFilesystemPath as t } from "./filesystemAdmission.js";
|
|
3
|
+
import { isSafeBundlePath as n } from "./bundlePaths.js";
|
|
4
|
+
import { MANIFEST_FILE as r, decodeManifest as i } from "./manifest.js";
|
|
5
|
+
import { AssetSourceInfo as a } from "./assetAdmission.js";
|
|
6
|
+
import { makeDecompressor as o } from "./compress.js";
|
|
7
|
+
import { ndjsonToRows as s } from "./ndjson.js";
|
|
8
|
+
import { Effect as c, Schema as l, Stream as u } from "effect";
|
|
9
|
+
import { createReadStream as d } from "node:fs";
|
|
10
|
+
import { readFile as f } from "node:fs/promises";
|
|
11
|
+
import { join as p } from "node:path";
|
|
12
|
+
import { STORAGE_REFS_TABLE as m, fromNodeReadable as h } from "@voltro/plugin-storage";
|
|
13
|
+
import { compose as g } from "node:stream";
|
|
14
|
+
// src/storageAssetMetadata.ts
|
|
15
|
+
var _ = (t) => c.tryPromise({
|
|
16
|
+
try: async () => {
|
|
17
|
+
let e = i(await f(p(t, r), "utf8"));
|
|
18
|
+
return {
|
|
19
|
+
dir: t,
|
|
20
|
+
tables: e.tables,
|
|
21
|
+
compression: e.compression
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
catch: () => new e({ reason: "exported asset manifest unavailable" })
|
|
25
|
+
}), v = (e) => l.decodeUnknownSync(a)({
|
|
26
|
+
destination: e.bucket,
|
|
27
|
+
tenantId: e.tenantId,
|
|
28
|
+
key: e.key,
|
|
29
|
+
...typeof e.checksum == "string" && /^[a-f0-9]{64}$/.test(e.checksum) ? { sha256: e.checksum } : {},
|
|
30
|
+
contentType: e.contentType,
|
|
31
|
+
size: typeof e.size == "bigint" || typeof e.size == "string" && /^(0|[1-9]\d*)$/.test(e.size) ? Number(e.size) : e.size
|
|
32
|
+
}), y = (r) => {
|
|
33
|
+
let i = r.tables.find((e) => e.name === m);
|
|
34
|
+
return i === void 0 ? u.empty : u.unwrap(c.gen(function* () {
|
|
35
|
+
if (!n(i.file)) return yield* c.fail(new e({ reason: "invalid asset metadata table path" }));
|
|
36
|
+
let a = p(r.dir, i.file);
|
|
37
|
+
return yield* c.tryPromise({
|
|
38
|
+
try: () => t(a, "file"),
|
|
39
|
+
catch: () => new e({ reason: "asset metadata path unavailable" })
|
|
40
|
+
}), s(h("bundle", () => g(d(a), o(r.compression))), i.name, i.columnTypes).pipe(u.mapEffect((t) => c.try({
|
|
41
|
+
try: () => v(t),
|
|
42
|
+
catch: () => new e({ reason: "invalid storage ownership in exported rows" })
|
|
43
|
+
})));
|
|
44
|
+
}));
|
|
45
|
+
};
|
|
46
|
+
export { _ as assetBundleContext, y as bundleAssetInfoStream, v as storageAssetInfo };
|
package/dist/subset.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect as e, Stream as t } from "effect";
|
|
2
2
|
import { inSet as n, or as r, streamTable as i } from "@voltro/database";
|
|
3
|
-
|
|
3
|
+
// src/subset.ts
|
|
4
4
|
var a = (e, t) => e.tables.find((e) => e.name === t)?.columns.find((e) => e.type === "id")?.name ?? "id", o = (a, o, s) => e.gen(function* () {
|
|
5
5
|
let c = s.maxDepth ?? 12, l = new Set(s.pinned ?? []), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map();
|
|
6
6
|
for (let e of o.tables) p.has(e.name) || p.set(e.name, e);
|
|
@@ -86,5 +86,4 @@ var a = (e, t) => e.tables.find((e) => e.name === t)?.columns.find((e) => e.type
|
|
|
86
86
|
return i ? n(a(t, r), [...i]) : void 0;
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
|
-
//#endregion
|
|
90
89
|
export { o as computeSubsetIds, a as pkOf, s as subsetToScope };
|
package/dist/topo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/topo.ts
|
|
2
2
|
var e = (e, t) => {
|
|
3
3
|
let n = new Set(e), r = /* @__PURE__ */ new Map();
|
|
4
4
|
for (let e of t.tables) {
|
|
@@ -20,5 +20,4 @@ var e = (e, t) => {
|
|
|
20
20
|
for (let t of e) n.has(t) && s(t);
|
|
21
21
|
return i;
|
|
22
22
|
};
|
|
23
|
-
//#endregion
|
|
24
23
|
export { e as topoSortTables };
|
package/dist/typedCodec.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/typedCodec.ts
|
|
2
2
|
var e = /* @__PURE__ */ new Set([
|
|
3
3
|
"json",
|
|
4
4
|
"array",
|
|
@@ -32,5 +32,4 @@ var e = /* @__PURE__ */ new Set([
|
|
|
32
32
|
for (let [r, i] of Object.entries(e)) n[r] = s(i, t[r]);
|
|
33
33
|
return n;
|
|
34
34
|
};
|
|
35
|
-
//#endregion
|
|
36
35
|
export { l as decodeRow, s as decodeValue, c as encodeRow, a as encodeValue };
|