@voltro/data-transfer 0.86.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.
- package/CHANGELOG.md +5321 -0
- package/THIRD-PARTY-NOTICES.md +856 -217
- package/dist/assetAdmission.js +92 -0
- package/dist/assets.js +61 -40
- package/dist/blobStorage.js +54 -30
- package/dist/bundleArchive.js +248 -103
- package/dist/bundlePaths.js +4 -0
- package/dist/casAssetPhase.js +77 -33
- package/dist/compress.js +3 -3
- package/dist/environmentLocal.js +266 -2
- package/dist/errors.js +12 -5
- package/dist/exporter.js +145 -131
- package/dist/filesystemAdmission.js +33 -0
- package/dist/importer.js +325 -285
- package/dist/index.d.ts +200 -46
- package/dist/index.js +28 -26
- package/dist/manifest.js +44 -40
- package/dist/nativeDump.js +133 -84
- package/dist/physicalRequest.js +10 -0
- package/dist/sealedKeys.js +40 -0
- package/dist/storageAssetMetadata.js +47 -0
- package/package.json +3 -3
package/dist/bundleArchive.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { admitFilesystemPath as e, publishBundleFile as t } from "./filesystemAdmission.js";
|
|
2
|
+
import { isSafeBundlePath as n } from "./bundlePaths.js";
|
|
3
|
+
import { AssetAddress as r, MANIFEST_FILE as i, decodeManifest as a, encodeManifest as o } from "./manifest.js";
|
|
4
|
+
import { decodeAssetSourceInfo as s, prepareAssetEntries as c } from "./assetAdmission.js";
|
|
5
|
+
import { readAssetIndex as l } from "./casAssetPhase.js";
|
|
6
|
+
import { Effect as u, Schema as d, Stream as f } from "effect";
|
|
7
|
+
import { createHash as p } from "node:crypto";
|
|
8
|
+
import { createReadStream as m, createWriteStream as h } from "node:fs";
|
|
9
|
+
import { lstat as g, mkdir as _, mkdtemp as v, readdir as y, rm as b, stat as x } from "node:fs/promises";
|
|
10
|
+
import { dirname as S, join as C, resolve as w, sep as T } from "node:path";
|
|
11
|
+
import { tmpdir as E } from "node:os";
|
|
12
|
+
import { PassThrough as D } from "node:stream";
|
|
13
|
+
import { storageAddressIdentity as O } from "@voltro/plugin-storage/errors";
|
|
6
14
|
//#region src/bundleArchive.ts
|
|
7
|
-
var
|
|
15
|
+
var k = Buffer.from("VBUNDLE3"), A = 0, j = 1, M = 2, N = 32, P = async (e) => {
|
|
8
16
|
let t = [], n = async (r) => {
|
|
9
17
|
let i;
|
|
10
18
|
try {
|
|
11
|
-
i = await
|
|
19
|
+
i = await y(C(e, r), { withFileTypes: !0 });
|
|
12
20
|
} catch {
|
|
13
21
|
return;
|
|
14
22
|
}
|
|
@@ -18,93 +26,166 @@ var d = Buffer.from("VBUNDLE2"), f = 0, p = 1, m = 2, h = 32, g = async (e) => {
|
|
|
18
26
|
}
|
|
19
27
|
};
|
|
20
28
|
return await n(""), t.sort();
|
|
21
|
-
},
|
|
29
|
+
}, F = (e, t) => {
|
|
22
30
|
let n = Buffer.from(e, "utf8"), r = Buffer.alloc(5 + n.length + 8);
|
|
23
|
-
return r.writeUInt8(
|
|
24
|
-
},
|
|
25
|
-
let
|
|
26
|
-
return
|
|
31
|
+
return r.writeUInt8(j, 0), r.writeUInt32BE(n.length, 1), n.copy(r, 5), r.writeBigUInt64BE(BigInt(t), 5 + n.length), r;
|
|
32
|
+
}, I = (e, t, n) => {
|
|
33
|
+
let i = Buffer.from(JSON.stringify(d.decodeUnknownSync(r)(e)), "utf8"), a = Buffer.from(t, "utf8"), o = Buffer.alloc(5 + i.length + 2 + a.length + 8), s = 0;
|
|
34
|
+
return o.writeUInt8(M, s), s += 1, o.writeUInt32BE(i.length, s), s += 4, i.copy(o, s), s += i.length, o.writeUInt16BE(a.length, s), s += 2, a.copy(o, s), s += a.length, o.writeBigUInt64BE(BigInt(n), s), o;
|
|
27
35
|
};
|
|
28
|
-
async function*
|
|
29
|
-
yield new Uint8Array(
|
|
30
|
-
for (let
|
|
31
|
-
let
|
|
32
|
-
if (yield new Uint8Array(
|
|
36
|
+
async function* L(e) {
|
|
37
|
+
yield new Uint8Array(k);
|
|
38
|
+
for (let t of await P(e.dir)) {
|
|
39
|
+
let n = C(e.dir, t), r = await x(n);
|
|
40
|
+
if (yield new Uint8Array(F(t, r.size)), r.size > 0) for await (let e of m(n)) yield new Uint8Array(e);
|
|
33
41
|
}
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
if (e.blobs) for await (let t of e.blobs.list(e.dir)) {
|
|
43
|
+
let n = await u.runPromise(s(t));
|
|
44
|
+
yield new Uint8Array(I(n, n.contentType, n.size));
|
|
45
|
+
let r = p("sha256"), i = 0;
|
|
46
|
+
for await (let t of e.blobs.open(n)) {
|
|
47
|
+
let e = Buffer.from(t);
|
|
48
|
+
r.update(e), i += e.length, yield new Uint8Array(e);
|
|
40
49
|
}
|
|
41
|
-
if (i !==
|
|
42
|
-
|
|
50
|
+
if (i !== n.size) throw Error(`blob '${n.key}' size mismatch: header ${n.size}, streamed ${i}`);
|
|
51
|
+
let a = r.digest();
|
|
52
|
+
if (n.sha256 !== void 0 && a.toString("hex") !== n.sha256) throw Error("archive blob contradicts SQL checksum");
|
|
53
|
+
yield new Uint8Array(a);
|
|
43
54
|
}
|
|
44
|
-
yield new Uint8Array(Buffer.from([
|
|
55
|
+
yield new Uint8Array(Buffer.from([A]));
|
|
45
56
|
}
|
|
46
|
-
var
|
|
47
|
-
let
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
var R = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), z = (e) => new Promise((t) => e.end(t)), B = async (n, r) => {
|
|
58
|
+
let i = await v(C(E(), "voltro-admitted-archive-")), a = C(i, "files"), o = C(i, "objects");
|
|
59
|
+
try {
|
|
60
|
+
await V(n, {
|
|
61
|
+
dir: a,
|
|
62
|
+
blobs: {
|
|
63
|
+
...W(o),
|
|
64
|
+
has: async () => !1
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
let i = C(o, "assets", "index.ndjson"), s = await x(i).then(() => !0, () => !1) ? Array.from(await u.runPromise(f.runCollect(l(i)))) : [], c = await P(a);
|
|
68
|
+
await e(r.dir, "directory");
|
|
69
|
+
for (let t of c) await e(C(w(r.dir), t), "file");
|
|
70
|
+
let d = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Set();
|
|
71
|
+
for (let e of s) {
|
|
72
|
+
let t = O(e), n = d.get(t);
|
|
73
|
+
if (n !== void 0 && (n.sha256 !== e.sha256 || n.size !== e.size || n.contentType !== e.contentType)) throw Error("archive contains conflicting blob entries");
|
|
74
|
+
d.set(t, e), await r.blobs.has(e), await r.blobs.matches(e) && p.add(t);
|
|
75
|
+
}
|
|
76
|
+
for (let e of c) {
|
|
77
|
+
let n = C(w(r.dir), e);
|
|
78
|
+
await t(C(a, e), n);
|
|
79
|
+
}
|
|
80
|
+
for (let [e, t] of d) {
|
|
81
|
+
if (p.has(e)) continue;
|
|
82
|
+
let n = m(C(o, "assets", t.sha256));
|
|
83
|
+
try {
|
|
84
|
+
await r.blobs.write(t, n, {
|
|
85
|
+
contentType: t.contentType,
|
|
86
|
+
size: t.size
|
|
87
|
+
});
|
|
88
|
+
} finally {
|
|
89
|
+
n.destroy();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} finally {
|
|
93
|
+
await b(i, {
|
|
94
|
+
recursive: !0,
|
|
95
|
+
force: !0
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}, V = async (e, t) => {
|
|
99
|
+
let i = w(t.dir);
|
|
100
|
+
await _(i, { recursive: !0 });
|
|
101
|
+
let a = Buffer.alloc(0), o = e[Symbol.asyncIterator](), s = !1, c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map(), u = async () => {
|
|
102
|
+
let { value: e, done: t } = await o.next();
|
|
103
|
+
return t ? (s = !0, !1) : (a = a.length === 0 ? Buffer.from(e) : Buffer.concat([a, Buffer.from(e)]), !0);
|
|
104
|
+
}, f = async (e) => {
|
|
105
|
+
for (; a.length < e;) if (!await u()) throw Error("truncated bundle archive");
|
|
106
|
+
}, m = (e) => {
|
|
107
|
+
let t = a.subarray(0, e);
|
|
108
|
+
return a = a.subarray(e), t;
|
|
57
109
|
};
|
|
58
110
|
try {
|
|
59
|
-
if (await
|
|
111
|
+
if (await f(k.length), !m(k.length).equals(k)) throw Error("not a bundle archive (bad magic)");
|
|
60
112
|
for (;;) {
|
|
61
|
-
await
|
|
62
|
-
let
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
await
|
|
70
|
-
let
|
|
71
|
-
if (
|
|
72
|
-
await
|
|
73
|
-
let
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
113
|
+
await f(1);
|
|
114
|
+
let e = m(1).readUInt8(0);
|
|
115
|
+
if (e === A) {
|
|
116
|
+
if (a.length > 0) throw Error("trailing bytes after bundle end marker");
|
|
117
|
+
for (; await u();) if (a.length > 0) throw Error("trailing bytes after bundle end marker");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (e === j) {
|
|
121
|
+
await f(4);
|
|
122
|
+
let e = m(4).readUInt32BE(0);
|
|
123
|
+
if (e === 0 || e > 65536) throw Error("invalid archive path length");
|
|
124
|
+
await f(e);
|
|
125
|
+
let t = m(e).toString("utf8");
|
|
126
|
+
await f(8);
|
|
127
|
+
let r = m(8).readBigUInt64BE(0), o = w(i, t);
|
|
128
|
+
if (o === i || !o.startsWith(i + T) || !n(t)) throw Error(`archive path '${t}' escapes the destination`);
|
|
129
|
+
if (c.has(o)) throw Error("duplicate plain archive path");
|
|
130
|
+
c.add(o), await _(S(o), { recursive: !0 });
|
|
131
|
+
let s = h(o);
|
|
132
|
+
try {
|
|
133
|
+
for (; r > 0n;) {
|
|
134
|
+
a.length === 0 && await f(1);
|
|
135
|
+
let e = r < BigInt(a.length) ? Number(r) : a.length;
|
|
136
|
+
await R(s, m(e)), r -= BigInt(e);
|
|
137
|
+
}
|
|
138
|
+
await z(s);
|
|
139
|
+
} finally {
|
|
140
|
+
s.destroy();
|
|
78
141
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
await
|
|
84
|
-
let n =
|
|
85
|
-
await
|
|
86
|
-
let
|
|
87
|
-
await
|
|
88
|
-
let
|
|
89
|
-
await
|
|
90
|
-
let
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
142
|
+
} else if (e === M) {
|
|
143
|
+
await f(4);
|
|
144
|
+
let e = m(4).readUInt32BE(0);
|
|
145
|
+
if (e === 0 || e > 65536) throw Error("invalid archive key length");
|
|
146
|
+
await f(e);
|
|
147
|
+
let n = d.decodeUnknownSync(r)(JSON.parse(m(e).toString("utf8"))), i = O(n);
|
|
148
|
+
await f(2);
|
|
149
|
+
let o = m(2).readUInt16BE(0);
|
|
150
|
+
await f(o);
|
|
151
|
+
let s = m(o).toString("utf8");
|
|
152
|
+
await f(8);
|
|
153
|
+
let c = m(8).readBigUInt64BE(0);
|
|
154
|
+
if (c > BigInt(2 ** 53 - 1)) throw Error("archive blob size exceeds exact integer range");
|
|
155
|
+
let u = p("sha256"), h = new D(), g = t.blobs.write(n, h, {
|
|
156
|
+
contentType: s,
|
|
157
|
+
size: Number(c)
|
|
158
|
+
});
|
|
159
|
+
g.catch((e) => {
|
|
160
|
+
h.destroy(e instanceof Error ? e : /* @__PURE__ */ Error("archive staging failed"));
|
|
161
|
+
});
|
|
162
|
+
let _ = c;
|
|
163
|
+
try {
|
|
164
|
+
for (; _ > 0n;) {
|
|
165
|
+
a.length === 0 && await f(1);
|
|
166
|
+
let e = _ < BigInt(a.length) ? Number(_) : a.length, t = m(e);
|
|
167
|
+
u.update(t), await R(h, t), _ -= BigInt(e);
|
|
168
|
+
}
|
|
169
|
+
await z(h), await g, await f(N);
|
|
170
|
+
let e = m(N), t = u.digest();
|
|
171
|
+
if (!t.equals(e)) throw Error(`blob '${i}' failed integrity (sha mismatch)`);
|
|
172
|
+
let r = {
|
|
173
|
+
...n,
|
|
174
|
+
sha256: t.toString("hex"),
|
|
175
|
+
size: Number(c),
|
|
176
|
+
contentType: s
|
|
177
|
+
}, o = l.get(i);
|
|
178
|
+
if (o !== void 0 && (o.sha256 !== r.sha256 || o.size !== r.size || o.contentType !== r.contentType)) throw Error("archive contains conflicting blob addresses");
|
|
179
|
+
l.set(i, r);
|
|
180
|
+
} finally {
|
|
181
|
+
h.destroy(), await g.catch(() => void 0);
|
|
98
182
|
}
|
|
99
|
-
|
|
100
|
-
let m = S(h);
|
|
101
|
-
if (!u.digest().equals(m)) throw Error(`blob '${n}' failed integrity (sha mismatch)`);
|
|
102
|
-
} else throw Error(`unknown bundle entry kind ${t}`);
|
|
183
|
+
} else throw Error(`unknown bundle entry kind ${e}`);
|
|
103
184
|
}
|
|
104
185
|
} finally {
|
|
105
|
-
|
|
186
|
+
s || await Promise.resolve(o.return?.()).catch(() => void 0);
|
|
106
187
|
}
|
|
107
|
-
},
|
|
188
|
+
}, H = async (e, t) => {
|
|
108
189
|
let n = new Set(t), r = /* @__PURE__ */ new Map(), i = Buffer.alloc(0), a = e[Symbol.asyncIterator](), o = async () => {
|
|
109
190
|
let { value: e, done: t } = await a.next();
|
|
110
191
|
return !t && (i = i.length === 0 ? Buffer.from(e) : Buffer.concat([i, Buffer.from(e)]), !0);
|
|
@@ -123,11 +204,11 @@ var b = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), x =
|
|
|
123
204
|
}
|
|
124
205
|
return Buffer.concat(t);
|
|
125
206
|
};
|
|
126
|
-
if (!await s(
|
|
207
|
+
if (!await s(k.length) || !c(k.length).equals(k)) throw Error("not a bundle archive (bad magic)");
|
|
127
208
|
for (; await s(1);) {
|
|
128
209
|
let e = c(1).readUInt8(0);
|
|
129
|
-
if (e ===
|
|
130
|
-
if (e !==
|
|
210
|
+
if (e === A || e === M) break;
|
|
211
|
+
if (e !== j) throw Error(`unknown bundle entry kind ${e}`);
|
|
131
212
|
if (!await s(4)) break;
|
|
132
213
|
let t = c(4).readUInt32BE(0);
|
|
133
214
|
if (!await s(t)) break;
|
|
@@ -137,29 +218,93 @@ var b = (e, t) => new Promise((n, r) => e.write(t, (e) => e ? r(e) : n())), x =
|
|
|
137
218
|
if (a === null || n.has(i) && (r.set(i, a), n.delete(i), n.size === 0)) break;
|
|
138
219
|
}
|
|
139
220
|
return r;
|
|
140
|
-
},
|
|
221
|
+
}, U = (e, t) => B(e, {
|
|
141
222
|
dir: t,
|
|
142
|
-
blobs:
|
|
143
|
-
})
|
|
144
|
-
let
|
|
223
|
+
blobs: W(t)
|
|
224
|
+
}).then(async () => {
|
|
225
|
+
let e = await import("node:fs/promises"), n = C(t, "assets", "index.ndjson");
|
|
226
|
+
if (!await x(n).then(() => !0, () => !1)) return;
|
|
227
|
+
let r = await e.readFile(C(t, i), "utf8").catch(() => void 0);
|
|
228
|
+
if (r === void 0) return;
|
|
229
|
+
let s;
|
|
230
|
+
try {
|
|
231
|
+
s = a(r);
|
|
232
|
+
} catch {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
let c = Array.from(await u.runPromise(f.runCollect(l(n)))), d = new Map(c.map((e) => [O(e), e]));
|
|
236
|
+
await e.writeFile(C(t, i), o({
|
|
237
|
+
...s,
|
|
238
|
+
assets: {
|
|
239
|
+
count: d.size,
|
|
240
|
+
totalBytes: [...d.values()].reduce((e, t) => e + t.size, 0),
|
|
241
|
+
index: "assets/index.ndjson"
|
|
242
|
+
}
|
|
243
|
+
}));
|
|
244
|
+
}), W = (t) => {
|
|
245
|
+
let n = /* @__PURE__ */ new Set();
|
|
145
246
|
return {
|
|
146
|
-
has: async (
|
|
147
|
-
|
|
148
|
-
let
|
|
149
|
-
await
|
|
150
|
-
let
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
await
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
247
|
+
has: async (r) => (await e(C(t, "assets"), "directory"), await e(C(t, "assets", "index.ndjson"), "file"), n.has(O(r))),
|
|
248
|
+
matches: async (n) => {
|
|
249
|
+
let r = C(t, "assets", "index.ndjson");
|
|
250
|
+
if (await e(r, "file"), !await x(r).then(() => !0, () => !1)) return !1;
|
|
251
|
+
let i = Array.from(await u.runPromise(f.runCollect(l(r)))).filter((e) => O(e) === O(n));
|
|
252
|
+
if (i.length === 0 || i.some((e) => e.sha256 !== n.sha256 || e.size !== n.size || e.contentType !== n.contentType)) return !1;
|
|
253
|
+
let a = C(t, "assets", n.sha256);
|
|
254
|
+
await e(a, "file");
|
|
255
|
+
try {
|
|
256
|
+
await g(a);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
if (typeof e == "object" && e && "code" in e && e.code === "ENOENT") return !1;
|
|
259
|
+
throw e;
|
|
260
|
+
}
|
|
261
|
+
return u.runPromise(u.scoped(c({
|
|
262
|
+
entries: [n],
|
|
263
|
+
assetsDir: C(t, "assets"),
|
|
264
|
+
sink: {
|
|
265
|
+
has: () => u.succeed(!1),
|
|
266
|
+
matches: () => u.succeed(!1),
|
|
267
|
+
write: () => u.void
|
|
268
|
+
}
|
|
269
|
+
}).pipe(u.as(!0), u.catchTag("IntegrityError", () => u.succeed(!1)))));
|
|
270
|
+
},
|
|
271
|
+
write: async (r, i, a) => {
|
|
272
|
+
let o = await import("node:fs/promises"), { pipeline: s } = await import("node:stream/promises"), { Transform: c } = await import("node:stream"), d = C(t, "assets");
|
|
273
|
+
await e(d, "directory"), await _(d, { recursive: !0 });
|
|
274
|
+
let m = p("sha256"), g = 0, y = new c({ transform(e, t, n) {
|
|
275
|
+
m.update(e), g += e.length, n(null, e);
|
|
276
|
+
} });
|
|
277
|
+
await e(d, "directory"), await e(C(d, "index.ndjson"), "file");
|
|
278
|
+
let S = await v(C(d, ".voltro-blob-"));
|
|
279
|
+
try {
|
|
280
|
+
let t = C(S, "body");
|
|
281
|
+
if (await s(i, y, h(t, {
|
|
282
|
+
flags: "wx",
|
|
283
|
+
mode: 384
|
|
284
|
+
})), g !== a.size) throw Error("blob body size does not match its metadata");
|
|
285
|
+
let n = m.digest("hex"), c = C(d, n);
|
|
286
|
+
await e(c, "file"), await e(C(d, "index.ndjson"), "file"), await o.rename(t, c);
|
|
287
|
+
let p = C(d, "index.ndjson"), _ = (await x(p).then(() => !0, () => !1) ? Array.from(await u.runPromise(f.runCollect(l(p)))) : []).filter((e) => O(e) !== O(r));
|
|
288
|
+
_.push({
|
|
289
|
+
...r,
|
|
290
|
+
sha256: n,
|
|
291
|
+
size: g,
|
|
292
|
+
contentType: a.contentType
|
|
293
|
+
});
|
|
294
|
+
let v = C(S, "index");
|
|
295
|
+
await o.writeFile(v, _.map((e) => JSON.stringify(e)).join("\n") + "\n", {
|
|
296
|
+
flag: "wx",
|
|
297
|
+
mode: 384
|
|
298
|
+
}), await e(p, "file"), await o.rename(v, p);
|
|
299
|
+
} finally {
|
|
300
|
+
await b(S, {
|
|
301
|
+
recursive: !0,
|
|
302
|
+
force: !0
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
n.add(O(r));
|
|
161
306
|
}
|
|
162
307
|
};
|
|
163
308
|
};
|
|
164
309
|
//#endregion
|
|
165
|
-
export {
|
|
310
|
+
export { W as dirBlobSink, L as packBundle, H as peekBundle, B as unpackBundle, U as unpackBundleToDir };
|
package/dist/casAssetPhase.js
CHANGED
|
@@ -1,43 +1,87 @@
|
|
|
1
1
|
import { BundleError as e } from "./errors.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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";
|
|
6
10
|
//#region src/casAssetPhase.ts
|
|
7
|
-
var
|
|
11
|
+
var m = {
|
|
8
12
|
done: () => !1,
|
|
9
|
-
mark: () =>
|
|
10
|
-
},
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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,
|
|
17
26
|
sha256: t.sha256,
|
|
18
27
|
size: t.size,
|
|
19
28
|
contentType: t.contentType
|
|
20
29
|
};
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
29
42
|
};
|
|
30
|
-
}),
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
40
81
|
};
|
|
41
|
-
})
|
|
82
|
+
})), y = (e) => l.runCollect(_(e.indexPath)).pipe(c.flatMap((t) => a({
|
|
83
|
+
...e,
|
|
84
|
+
entries: Array.from(t)
|
|
85
|
+
})));
|
|
42
86
|
//#endregion
|
|
43
|
-
export {
|
|
87
|
+
export { g as captureAssetsToCas, m as noAssetProgress, y as prepareAssetsFromCas, _ as readAssetIndex, v as restoreAssetsFromCas };
|
package/dist/compress.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { PassThrough as e } from "node:stream";
|
|
2
|
+
import * as t from "node:zlib";
|
|
3
3
|
//#region src/compress.ts
|
|
4
|
-
var n = () => typeof
|
|
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
5
|
//#endregion
|
|
6
6
|
export { i as compressionExt, n as hasZstd, a as makeCompressor, o as makeDecompressor, r as pickCompression };
|