@voltro/data-transfer 0.85.0 → 0.87.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +5987 -0
  2. package/THIRD-PARTY-NOTICES.md +860 -249
  3. package/dist/assetAdmission.js +92 -0
  4. package/dist/assets.js +68 -0
  5. package/dist/blobStorage.js +64 -0
  6. package/dist/bundleArchive.js +310 -0
  7. package/dist/bundleCrypto.js +106 -0
  8. package/dist/bundlePaths.js +4 -0
  9. package/dist/casAssetPhase.js +87 -0
  10. package/dist/compress.js +6 -0
  11. package/dist/consistency.js +14 -0
  12. package/dist/crossDialect.js +58 -0
  13. package/dist/driftClassification.js +58 -0
  14. package/dist/environmentLocal.js +386 -0
  15. package/dist/errors.js +89 -0
  16. package/dist/exporter.js +271 -0
  17. package/dist/filesystemAdmission.js +33 -0
  18. package/dist/importer.js +576 -0
  19. package/dist/index.d.ts +202 -46
  20. package/dist/index.js +30 -2673
  21. package/dist/ledger.js +21 -0
  22. package/dist/liveGuard.js +11 -0
  23. package/dist/manifest.js +56 -0
  24. package/dist/masking.js +246 -0
  25. package/dist/maskingPreview.js +48 -0
  26. package/dist/nativeDump.js +418 -0
  27. package/dist/ndjson.js +13 -0
  28. package/dist/physicalRequest.js +10 -0
  29. package/dist/profile.js +4 -0
  30. package/dist/progress.js +17 -0
  31. package/dist/readme.js +43 -0
  32. package/dist/replacePreflight.js +23 -0
  33. package/dist/rollbackCapture.js +36 -0
  34. package/dist/rowFailureReason.js +36 -0
  35. package/dist/schemaDrift.js +40 -0
  36. package/dist/scope.js +40 -0
  37. package/dist/sealedKeys.js +40 -0
  38. package/dist/stagedSwap.js +164 -0
  39. package/dist/storageAssetMetadata.js +47 -0
  40. package/dist/subset.js +90 -0
  41. package/dist/topo.js +24 -0
  42. package/dist/typedCodec.js +36 -0
  43. package/package.json +3 -3
@@ -0,0 +1,87 @@
1
+ import { BundleError as e } from "./errors.js";
2
+ import { admitFilesystemPath as t } from "./filesystemAdmission.js";
3
+ import { assertPreparedAssets as n, decodeAssetEntry as r, decodeAssetSourceInfo as i, prepareAssetEntries as a } from "./assetAdmission.js";
4
+ import { applyAdmittedAsset as o, writeAssetToCas as s } from "./assets.js";
5
+ import { Effect as c, Stream as l } from "effect";
6
+ import { constants as u } from "node:fs";
7
+ import { open as d } from "node:fs/promises";
8
+ import { fromNodeReadable as f } from "@voltro/plugin-storage";
9
+ import { storageAddressIdentity as p } from "@voltro/plugin-storage/errors";
10
+ //#region src/casAssetPhase.ts
11
+ var m = {
12
+ done: () => !1,
13
+ mark: () => c.void
14
+ }, h = (e) => typeof e == "object" && !!e && e.status === 404, g = (t) => c.gen(function* () {
15
+ let n = t.progress ?? m, r = 0, a = 0, o = 0, u = 0, d = /* @__PURE__ */ new Set(), f = /* @__PURE__ */ new Map(), g = [], _ = (t) => {
16
+ o++;
17
+ let r = p(t), i = f.get(r);
18
+ return i === void 0 ? (f.set(r, t), n.done(r) ? c.logDebug("Revalidating previously recorded source asset").pipe(c.andThen(v(t, r))) : v(t, r)) : i.size !== t.size || i.contentType !== t.contentType || i.sha256 !== void 0 && t.sha256 !== void 0 && i.sha256 !== t.sha256 ? c.fail(new e({ reason: "duplicate asset address has contradictory source metadata" })) : i.sha256 === void 0 && t.sha256 !== void 0 ? v(t, r) : c.void;
19
+ }, v = (i, o) => t.source.open(i).pipe(c.map((e) => e), c.catchIf(h, () => c.sync(() => {
20
+ g.push(o);
21
+ })), c.flatMap((l) => l === void 0 ? c.void : s(l, t.assetsDir).pipe(c.flatMap((t) => {
22
+ let s = {
23
+ destination: i.destination,
24
+ tenantId: i.tenantId,
25
+ key: i.key,
26
+ sha256: t.sha256,
27
+ size: t.size,
28
+ contentType: t.contentType
29
+ };
30
+ return t.size !== i.size || t.contentType !== i.contentType || i.sha256 !== void 0 && t.sha256 !== i.sha256 ? c.fail(new e({ reason: "asset bytes contradict their source metadata" })) : (f.set(o, {
31
+ ...i,
32
+ sha256: t.sha256
33
+ }), r++, a += t.size, d.has(t.sha256) || (d.add(t.sha256), u += t.size), n.mark(o, s));
34
+ }))));
35
+ return yield* l.runForEach(t.source.list().pipe(l.mapEffect(i)), _).pipe(c.mapError((t) => t instanceof e ? t : new e({ reason: `asset export failed: ${String(t)}` }))), {
36
+ count: r,
37
+ totalBytes: a,
38
+ references: o,
39
+ objects: d.size,
40
+ objectBytes: u,
41
+ missing: g
42
+ };
43
+ }), _ = (n) => l.unwrap(c.gen(function* () {
44
+ let r = yield* c.acquireRelease(c.tryPromise({
45
+ try: async () => {
46
+ await t(n, "file");
47
+ let e = await d(n, u.O_RDONLY | u.O_NOFOLLOW | u.O_NONBLOCK);
48
+ try {
49
+ if (!(await e.stat()).isFile()) throw Error("asset index must be a regular file");
50
+ return e;
51
+ } catch (t) {
52
+ throw await e.close(), t;
53
+ }
54
+ },
55
+ catch: () => new e({
56
+ reason: "asset index could not be admitted",
57
+ path: n
58
+ })
59
+ }), (e) => c.promise(() => e.close()));
60
+ return f("bundle", () => r.createReadStream({ autoClose: !1 }));
61
+ })).pipe(l.decodeText(), l.splitLines, l.filter((e) => e.trim().length > 0), l.mapEffect((t) => c.try({
62
+ try: () => JSON.parse(t),
63
+ catch: () => new e({
64
+ reason: "asset index contains invalid JSON",
65
+ path: n
66
+ })
67
+ }).pipe(c.flatMap(r))), l.mapError((t) => t instanceof e ? t : new e({
68
+ reason: `asset index unreadable: ${String(t)}`,
69
+ path: n
70
+ }))), v = (e) => c.scoped(c.gen(function* () {
71
+ let t = e.prepared ?? (yield* y(e));
72
+ yield* n(t, e.sink);
73
+ let r = e.progress ?? m, i = 0, a = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Set();
74
+ for (let n of t.entries) {
75
+ let l = p(n);
76
+ s.has(l) || (s.add(l), r.done(l) && (yield* c.logDebug("Revalidating previously recorded destination asset")), (yield* e.sink.matches(n)) || (yield* o(e.sink, t, n), i++, a.add(n.sha256)), yield* r.mark(l, n));
77
+ }
78
+ return {
79
+ count: i,
80
+ objects: a.size
81
+ };
82
+ })), y = (e) => l.runCollect(_(e.indexPath)).pipe(c.flatMap((t) => a({
83
+ ...e,
84
+ entries: Array.from(t)
85
+ })));
86
+ //#endregion
87
+ export { g as captureAssetsToCas, m as noAssetProgress, y as prepareAssetsFromCas, _ as readAssetIndex, v as restoreAssetsFromCas };
@@ -0,0 +1,6 @@
1
+ import { PassThrough as e } from "node:stream";
2
+ import * as t from "node:zlib";
3
+ //#region src/compress.ts
4
+ var n = () => typeof t.createZstdCompress == "function", r = (e) => e === "none" ? "none" : e === "gzip" ? "gzip" : n() ? "zstd" : "gzip", i = (e) => e === "zstd" ? ".zst" : e === "gzip" ? ".gz" : "", a = (n) => n === "zstd" ? t.createZstdCompress() : n === "gzip" ? t.createGzip() : new e(), o = (n) => n === "zstd" ? t.createZstdDecompress() : n === "gzip" ? t.createGunzip() : new e();
5
+ //#endregion
6
+ export { i as compressionExt, n as hasZstd, a as makeCompressor, o as makeDecompressor, r as pickCompression };
@@ -0,0 +1,14 @@
1
+ //#region src/consistency.ts
2
+ var e = (e) => {
3
+ switch (e) {
4
+ case "postgres": return ["SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"];
5
+ case "mysql":
6
+ case "mariadb": return ["SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"];
7
+ case "mssql": return ["SET TRANSACTION ISOLATION LEVEL SNAPSHOT"];
8
+ case "sqlite":
9
+ case "turso": return [];
10
+ default: return [];
11
+ }
12
+ };
13
+ //#endregion
14
+ export { e as snapshotPrelude };
@@ -0,0 +1,58 @@
1
+ //#region src/crossDialect.ts
2
+ var e = (e) => {
3
+ switch (e) {
4
+ case "id":
5
+ case "text":
6
+ case "enum": return e === "enum" ? "enum" : "string";
7
+ case "integer": return "integer";
8
+ case "real": return "float";
9
+ case "boolean": return "boolean";
10
+ case "timestamp": return "datetime";
11
+ case "date": return "date";
12
+ case "json": return "json";
13
+ case "bytes": return "binary";
14
+ case "reference": return "reference";
15
+ case "vector": return "vector";
16
+ case "array": return "array";
17
+ case "interval": return "interval";
18
+ case "raw": return "raw";
19
+ default: return "string";
20
+ }
21
+ }, t = {
22
+ vector: /* @__PURE__ */ new Set(["postgres"]),
23
+ array: /* @__PURE__ */ new Set(["postgres"]),
24
+ interval: /* @__PURE__ */ new Set(["postgres"])
25
+ }, n = (n, r, i, a) => {
26
+ let o = e(i);
27
+ if (o === "raw") return {
28
+ table: n,
29
+ column: r,
30
+ type: i,
31
+ severity: "block",
32
+ reason: `raw() is verbatim source-dialect SQL — it cannot be assumed valid on ${a}`
33
+ };
34
+ let s = t[o];
35
+ return !s || s.has(a) ? null : o === "array" || o === "interval" ? {
36
+ table: n,
37
+ column: r,
38
+ type: i,
39
+ severity: "warn",
40
+ reason: `${o} is native to postgres; ${a} will represent it as json/text — verify downstream reads`
41
+ } : {
42
+ table: n,
43
+ column: r,
44
+ type: i,
45
+ severity: "block",
46
+ reason: `${o} columns require a ${[...s].join("/")} target; ${a} has no compatible column type`
47
+ };
48
+ }, r = (e, t, r) => {
49
+ if (t === r) return [];
50
+ let i = [];
51
+ for (let t of e) for (let [e, a] of Object.entries(t.columnTypes)) {
52
+ let o = n(t.name, e, a, r);
53
+ o && i.push(o);
54
+ }
55
+ return i;
56
+ }, i = (e) => `[${e.severity}] ${e.table}.${e.column} (${e.type}): ${e.reason}`;
57
+ //#endregion
58
+ export { e as canonicalType, r as checkPortability, i as formatIssue };
@@ -0,0 +1,58 @@
1
+ //#region src/driftClassification.ts
2
+ var e = (e, t) => {
3
+ let n = new Map(t.map((e) => [e.name, e])), r = [], i = {};
4
+ for (let t of e) {
5
+ let e = n.get(t.name);
6
+ if (e === void 0) {
7
+ r.push({
8
+ verdict: "refuse",
9
+ table: t.name,
10
+ detail: `the bundle carries '${t.name}' and the target schema has no such table — nowhere to put ${t.name}'s rows`
11
+ });
12
+ continue;
13
+ }
14
+ let a = new Map(e.columns.map((e) => [e.name, e])), o = new Map(t.columns.map((e) => [e.name, e])), s = [];
15
+ for (let e of t.columns) {
16
+ let n = a.get(e.name);
17
+ n === void 0 ? (s.push(e.name), r.push({
18
+ verdict: "value-dropped",
19
+ table: t.name,
20
+ column: e.name,
21
+ detail: `'${t.name}.${e.name}' is in the bundle and not in the schema — its values are DISCARDED`
22
+ })) : n.type !== e.type && r.push({
23
+ verdict: "refuse",
24
+ table: t.name,
25
+ column: e.name,
26
+ detail: `'${t.name}.${e.name}' changed type (${e.type} → ${n.type}) — the bundle's values would be written through a codec that no longer matches them`
27
+ });
28
+ }
29
+ for (let n of e.columns) o.has(n.name) || (n.nullable || n.hasDefault ? r.push({
30
+ verdict: "filled-by-default",
31
+ table: t.name,
32
+ column: n.name,
33
+ detail: `'${t.name}.${n.name}' is in the schema and not in the bundle — every imported row gets ${n.hasDefault ? "its default" : "NULL"}`
34
+ }) : r.push({
35
+ verdict: "refuse",
36
+ table: t.name,
37
+ column: n.name,
38
+ detail: `'${t.name}.${n.name}' is NOT NULL with no default and the bundle has no value for it`
39
+ }));
40
+ s.length > 0 && (i[t.name] = s);
41
+ }
42
+ return {
43
+ findings: r,
44
+ skipColumns: i,
45
+ refuse: r.some((e) => e.verdict === "refuse")
46
+ };
47
+ }, t = (e) => {
48
+ if (e.findings.length === 0) return [" schema matches the bundle"];
49
+ let t = {
50
+ safe: "✓",
51
+ "value-dropped": "⊖",
52
+ "filled-by-default": "⊕",
53
+ refuse: "✗"
54
+ }, n = e.findings.map((e) => ` ${t[e.verdict]} ${e.detail}`), r = (t) => e.findings.filter((e) => e.verdict === t).length;
55
+ 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;
56
+ };
57
+ //#endregion
58
+ export { e as classifyImportDrift, t as formatImportDrift };