resourcexjs 2.5.5 → 2.5.7
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/README.md +57 -50
- package/dist/arp.d.ts +2 -71
- package/dist/arp.js +3 -2628
- package/dist/arp.js.map +4 -9
- package/dist/index.d.ts +35 -91
- package/dist/index.js +14942 -16360
- package/dist/index.js.map +7 -10
- package/package.json +3 -7
package/dist/arp.js
CHANGED
|
@@ -10,1194 +10,6 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
|
-
// ../core/dist/index.js
|
|
14
|
-
var exports_dist = {};
|
|
15
|
-
__export(exports_dist, {
|
|
16
|
-
wrap: () => wrap,
|
|
17
|
-
resource: () => resource,
|
|
18
|
-
parse: () => parse,
|
|
19
|
-
manifest: () => manifest,
|
|
20
|
-
locate: () => locate,
|
|
21
|
-
format: () => format,
|
|
22
|
-
extract: () => extract,
|
|
23
|
-
define: () => define,
|
|
24
|
-
archive: () => archive,
|
|
25
|
-
ResourceXError: () => ResourceXError,
|
|
26
|
-
ManifestError: () => ManifestError,
|
|
27
|
-
LocatorError: () => LocatorError,
|
|
28
|
-
DefinitionError: () => DefinitionError,
|
|
29
|
-
ContentError: () => ContentError
|
|
30
|
-
});
|
|
31
|
-
import { gzip } from "node:zlib";
|
|
32
|
-
import { promisify } from "node:util";
|
|
33
|
-
import { gunzip } from "node:zlib";
|
|
34
|
-
import { promisify as promisify2 } from "node:util";
|
|
35
|
-
function define(input) {
|
|
36
|
-
if (input === null || typeof input !== "object") {
|
|
37
|
-
throw new DefinitionError("definition must be an object");
|
|
38
|
-
}
|
|
39
|
-
const obj = input;
|
|
40
|
-
if (!obj.name || typeof obj.name !== "string") {
|
|
41
|
-
throw new DefinitionError("name is required");
|
|
42
|
-
}
|
|
43
|
-
if (!obj.type || typeof obj.type !== "string") {
|
|
44
|
-
throw new DefinitionError("type is required");
|
|
45
|
-
}
|
|
46
|
-
const tagValue = obj.tag ?? obj.version;
|
|
47
|
-
if (tagValue !== undefined && typeof tagValue !== "string") {
|
|
48
|
-
throw new DefinitionError("tag must be a string");
|
|
49
|
-
}
|
|
50
|
-
const rxd = {
|
|
51
|
-
...obj,
|
|
52
|
-
name: obj.name,
|
|
53
|
-
type: obj.type,
|
|
54
|
-
tag: typeof tagValue === "string" ? tagValue : undefined,
|
|
55
|
-
registry: typeof obj.registry === "string" ? obj.registry : undefined,
|
|
56
|
-
path: typeof obj.path === "string" ? obj.path : undefined,
|
|
57
|
-
description: typeof obj.description === "string" ? obj.description : undefined,
|
|
58
|
-
author: typeof obj.author === "string" ? obj.author : undefined,
|
|
59
|
-
license: typeof obj.license === "string" ? obj.license : undefined,
|
|
60
|
-
keywords: Array.isArray(obj.keywords) ? obj.keywords : undefined,
|
|
61
|
-
repository: typeof obj.repository === "string" ? obj.repository : undefined
|
|
62
|
-
};
|
|
63
|
-
return rxd;
|
|
64
|
-
}
|
|
65
|
-
function manifest(rxd) {
|
|
66
|
-
return {
|
|
67
|
-
registry: rxd.registry,
|
|
68
|
-
path: rxd.path,
|
|
69
|
-
name: rxd.name,
|
|
70
|
-
type: rxd.type,
|
|
71
|
-
tag: rxd.tag ?? "latest"
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
function writeString(view, offset, size, value) {
|
|
75
|
-
if (value)
|
|
76
|
-
encoder.encodeInto(value, view.subarray(offset, offset + size));
|
|
77
|
-
}
|
|
78
|
-
function writeOctal(view, offset, size, value) {
|
|
79
|
-
if (value === undefined)
|
|
80
|
-
return;
|
|
81
|
-
const octalString = value.toString(8).padStart(size - 1, "0");
|
|
82
|
-
encoder.encodeInto(octalString, view.subarray(offset, offset + size - 1));
|
|
83
|
-
}
|
|
84
|
-
function readString(view, offset, size) {
|
|
85
|
-
const end = view.indexOf(0, offset);
|
|
86
|
-
const sliceEnd = end === -1 || end > offset + size ? offset + size : end;
|
|
87
|
-
return decoder.decode(view.subarray(offset, sliceEnd));
|
|
88
|
-
}
|
|
89
|
-
function readOctal(view, offset, size) {
|
|
90
|
-
let value = 0;
|
|
91
|
-
const end = offset + size;
|
|
92
|
-
for (let i = offset;i < end; i++) {
|
|
93
|
-
const charCode = view[i];
|
|
94
|
-
if (charCode === 0)
|
|
95
|
-
break;
|
|
96
|
-
if (charCode === 32)
|
|
97
|
-
continue;
|
|
98
|
-
value = value * 8 + (charCode - 48);
|
|
99
|
-
}
|
|
100
|
-
return value;
|
|
101
|
-
}
|
|
102
|
-
function readNumeric(view, offset, size) {
|
|
103
|
-
if (view[offset] & 128) {
|
|
104
|
-
let result = 0;
|
|
105
|
-
result = view[offset] & 127;
|
|
106
|
-
for (let i = 1;i < size; i++)
|
|
107
|
-
result = result * 256 + view[offset + i];
|
|
108
|
-
if (!Number.isSafeInteger(result))
|
|
109
|
-
throw new Error("TAR number too large");
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
return readOctal(view, offset, size);
|
|
113
|
-
}
|
|
114
|
-
async function normalizeBody(body) {
|
|
115
|
-
if (body === null || body === undefined)
|
|
116
|
-
return EMPTY;
|
|
117
|
-
if (body instanceof Uint8Array)
|
|
118
|
-
return body;
|
|
119
|
-
if (typeof body === "string")
|
|
120
|
-
return encoder.encode(body);
|
|
121
|
-
if (body instanceof ArrayBuffer)
|
|
122
|
-
return new Uint8Array(body);
|
|
123
|
-
if (body instanceof Blob)
|
|
124
|
-
return new Uint8Array(await body.arrayBuffer());
|
|
125
|
-
throw new TypeError("Unsupported content type for entry body.");
|
|
126
|
-
}
|
|
127
|
-
function transformHeader(header, options) {
|
|
128
|
-
const { strip, filter, map } = options;
|
|
129
|
-
if (!strip && !filter && !map)
|
|
130
|
-
return header;
|
|
131
|
-
const h = { ...header };
|
|
132
|
-
if (strip && strip > 0) {
|
|
133
|
-
const components = h.name.split("/").filter(Boolean);
|
|
134
|
-
if (strip >= components.length)
|
|
135
|
-
return null;
|
|
136
|
-
const newName = components.slice(strip).join("/");
|
|
137
|
-
h.name = h.type === DIRECTORY && !newName.endsWith("/") ? `${newName}/` : newName;
|
|
138
|
-
if (h.linkname?.startsWith("/")) {
|
|
139
|
-
const linkComponents = h.linkname.split("/").filter(Boolean);
|
|
140
|
-
h.linkname = strip >= linkComponents.length ? "/" : `/${linkComponents.slice(strip).join("/")}`;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (filter?.(h) === false)
|
|
144
|
-
return null;
|
|
145
|
-
const result = map ? map(h) : h;
|
|
146
|
-
if (result && (!result.name || !result.name.trim() || result.name === "." || result.name === "/"))
|
|
147
|
-
return null;
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
function validateChecksum(block) {
|
|
151
|
-
const stored = readOctal(block, USTAR_CHECKSUM_OFFSET, USTAR_CHECKSUM_SIZE);
|
|
152
|
-
let sum = 0;
|
|
153
|
-
for (let i = 0;i < block.length; i++)
|
|
154
|
-
if (i >= USTAR_CHECKSUM_OFFSET && i < USTAR_CHECKSUM_OFFSET + USTAR_CHECKSUM_SIZE)
|
|
155
|
-
sum += CHECKSUM_SPACE;
|
|
156
|
-
else
|
|
157
|
-
sum += block[i];
|
|
158
|
-
return stored === sum;
|
|
159
|
-
}
|
|
160
|
-
function writeChecksum(block) {
|
|
161
|
-
block.fill(CHECKSUM_SPACE, USTAR_CHECKSUM_OFFSET, USTAR_CHECKSUM_OFFSET + USTAR_CHECKSUM_SIZE);
|
|
162
|
-
let checksum = 0;
|
|
163
|
-
for (const byte of block)
|
|
164
|
-
checksum += byte;
|
|
165
|
-
for (let i = USTAR_CHECKSUM_OFFSET + 6 - 1;i >= USTAR_CHECKSUM_OFFSET; i--) {
|
|
166
|
-
block[i] = (checksum & 7) + ASCII_ZERO;
|
|
167
|
-
checksum >>= 3;
|
|
168
|
-
}
|
|
169
|
-
block[USTAR_CHECKSUM_OFFSET + 6] = 0;
|
|
170
|
-
block[USTAR_CHECKSUM_OFFSET + 7] = CHECKSUM_SPACE;
|
|
171
|
-
}
|
|
172
|
-
function generatePax(header) {
|
|
173
|
-
const paxRecords = {};
|
|
174
|
-
if (header.name.length > USTAR_NAME_SIZE) {
|
|
175
|
-
if (findUstarSplit(header.name) === null)
|
|
176
|
-
paxRecords.path = header.name;
|
|
177
|
-
}
|
|
178
|
-
if (header.linkname && header.linkname.length > USTAR_NAME_SIZE)
|
|
179
|
-
paxRecords.linkpath = header.linkname;
|
|
180
|
-
if (header.uname && header.uname.length > USTAR_UNAME_SIZE)
|
|
181
|
-
paxRecords.uname = header.uname;
|
|
182
|
-
if (header.gname && header.gname.length > USTAR_GNAME_SIZE)
|
|
183
|
-
paxRecords.gname = header.gname;
|
|
184
|
-
if (header.uid != null && header.uid > USTAR_MAX_UID_GID)
|
|
185
|
-
paxRecords.uid = String(header.uid);
|
|
186
|
-
if (header.gid != null && header.gid > USTAR_MAX_UID_GID)
|
|
187
|
-
paxRecords.gid = String(header.gid);
|
|
188
|
-
if (header.size != null && header.size > USTAR_MAX_SIZE)
|
|
189
|
-
paxRecords.size = String(header.size);
|
|
190
|
-
if (header.pax)
|
|
191
|
-
Object.assign(paxRecords, header.pax);
|
|
192
|
-
const paxEntries = Object.entries(paxRecords);
|
|
193
|
-
if (paxEntries.length === 0)
|
|
194
|
-
return null;
|
|
195
|
-
const paxBody = encoder.encode(paxEntries.map(([key, value]) => {
|
|
196
|
-
const record = `${key}=${value}
|
|
197
|
-
`;
|
|
198
|
-
const partLength = encoder.encode(record).length + 1;
|
|
199
|
-
let totalLength = partLength + String(partLength).length;
|
|
200
|
-
totalLength = partLength + String(totalLength).length;
|
|
201
|
-
return `${totalLength} ${record}`;
|
|
202
|
-
}).join(""));
|
|
203
|
-
return {
|
|
204
|
-
paxHeader: createTarHeader({
|
|
205
|
-
name: decoder.decode(encoder.encode(`PaxHeader/${header.name}`).slice(0, 100)),
|
|
206
|
-
size: paxBody.length,
|
|
207
|
-
type: "pax-header",
|
|
208
|
-
mode: 420,
|
|
209
|
-
mtime: header.mtime,
|
|
210
|
-
uname: header.uname,
|
|
211
|
-
gname: header.gname,
|
|
212
|
-
uid: header.uid,
|
|
213
|
-
gid: header.gid
|
|
214
|
-
}),
|
|
215
|
-
paxBody
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
function findUstarSplit(path) {
|
|
219
|
-
if (path.length <= USTAR_NAME_SIZE)
|
|
220
|
-
return null;
|
|
221
|
-
const minSlashIndex = path.length - USTAR_NAME_SIZE - 1;
|
|
222
|
-
const slashIndex = path.lastIndexOf("/", USTAR_PREFIX_SIZE);
|
|
223
|
-
if (slashIndex > 0 && slashIndex >= minSlashIndex)
|
|
224
|
-
return {
|
|
225
|
-
prefix: path.slice(0, slashIndex),
|
|
226
|
-
name: path.slice(slashIndex + 1)
|
|
227
|
-
};
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
function createTarHeader(header) {
|
|
231
|
-
const view = new Uint8Array(BLOCK_SIZE);
|
|
232
|
-
const size = isBodyless(header) ? 0 : header.size ?? 0;
|
|
233
|
-
let name = header.name;
|
|
234
|
-
let prefix = "";
|
|
235
|
-
if (!header.pax?.path) {
|
|
236
|
-
const split = findUstarSplit(name);
|
|
237
|
-
if (split) {
|
|
238
|
-
name = split.name;
|
|
239
|
-
prefix = split.prefix;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
writeString(view, USTAR_NAME_OFFSET, USTAR_NAME_SIZE, name);
|
|
243
|
-
writeOctal(view, USTAR_MODE_OFFSET, USTAR_MODE_SIZE, header.mode ?? (header.type === DIRECTORY ? DEFAULT_DIR_MODE : DEFAULT_FILE_MODE));
|
|
244
|
-
writeOctal(view, USTAR_UID_OFFSET, USTAR_UID_SIZE, header.uid ?? 0);
|
|
245
|
-
writeOctal(view, USTAR_GID_OFFSET, USTAR_GID_SIZE, header.gid ?? 0);
|
|
246
|
-
writeOctal(view, USTAR_SIZE_OFFSET, USTAR_SIZE_SIZE, size);
|
|
247
|
-
writeOctal(view, USTAR_MTIME_OFFSET, USTAR_MTIME_SIZE, Math.floor((header.mtime?.getTime() ?? Date.now()) / 1000));
|
|
248
|
-
writeString(view, USTAR_TYPEFLAG_OFFSET, USTAR_TYPEFLAG_SIZE, TYPEFLAG[header.type ?? FILE]);
|
|
249
|
-
writeString(view, USTAR_LINKNAME_OFFSET, USTAR_LINKNAME_SIZE, header.linkname);
|
|
250
|
-
writeString(view, USTAR_MAGIC_OFFSET, USTAR_MAGIC_SIZE, "ustar\x00");
|
|
251
|
-
writeString(view, USTAR_VERSION_OFFSET, USTAR_VERSION_SIZE, USTAR_VERSION);
|
|
252
|
-
writeString(view, USTAR_UNAME_OFFSET, USTAR_UNAME_SIZE, header.uname);
|
|
253
|
-
writeString(view, USTAR_GNAME_OFFSET, USTAR_GNAME_SIZE, header.gname);
|
|
254
|
-
writeString(view, USTAR_PREFIX_OFFSET, USTAR_PREFIX_SIZE, prefix);
|
|
255
|
-
writeChecksum(view);
|
|
256
|
-
return view;
|
|
257
|
-
}
|
|
258
|
-
function parseUstarHeader(block, strict) {
|
|
259
|
-
if (strict && !validateChecksum(block))
|
|
260
|
-
throw new Error("Invalid tar header checksum.");
|
|
261
|
-
const typeflag = readString(block, USTAR_TYPEFLAG_OFFSET, USTAR_TYPEFLAG_SIZE);
|
|
262
|
-
const header = {
|
|
263
|
-
name: readString(block, USTAR_NAME_OFFSET, USTAR_NAME_SIZE),
|
|
264
|
-
mode: readOctal(block, USTAR_MODE_OFFSET, USTAR_MODE_SIZE),
|
|
265
|
-
uid: readNumeric(block, USTAR_UID_OFFSET, USTAR_UID_SIZE),
|
|
266
|
-
gid: readNumeric(block, USTAR_GID_OFFSET, USTAR_GID_SIZE),
|
|
267
|
-
size: readNumeric(block, USTAR_SIZE_OFFSET, USTAR_SIZE_SIZE),
|
|
268
|
-
mtime: /* @__PURE__ */ new Date(readNumeric(block, USTAR_MTIME_OFFSET, USTAR_MTIME_SIZE) * 1000),
|
|
269
|
-
type: FLAGTYPE[typeflag] || FILE,
|
|
270
|
-
linkname: readString(block, USTAR_LINKNAME_OFFSET, USTAR_LINKNAME_SIZE)
|
|
271
|
-
};
|
|
272
|
-
const magic = readString(block, USTAR_MAGIC_OFFSET, USTAR_MAGIC_SIZE);
|
|
273
|
-
if (magic.trim() === "ustar") {
|
|
274
|
-
header.uname = readString(block, USTAR_UNAME_OFFSET, USTAR_UNAME_SIZE);
|
|
275
|
-
header.gname = readString(block, USTAR_GNAME_OFFSET, USTAR_GNAME_SIZE);
|
|
276
|
-
}
|
|
277
|
-
if (magic === "ustar")
|
|
278
|
-
header.prefix = readString(block, USTAR_PREFIX_OFFSET, USTAR_PREFIX_SIZE);
|
|
279
|
-
return header;
|
|
280
|
-
}
|
|
281
|
-
function parsePax(buffer) {
|
|
282
|
-
const decoder$1 = new TextDecoder("utf-8");
|
|
283
|
-
const overrides = {};
|
|
284
|
-
const pax = {};
|
|
285
|
-
let offset = 0;
|
|
286
|
-
while (offset < buffer.length) {
|
|
287
|
-
const spaceIndex = buffer.indexOf(32, offset);
|
|
288
|
-
if (spaceIndex === -1)
|
|
289
|
-
break;
|
|
290
|
-
const length = parseInt(decoder$1.decode(buffer.subarray(offset, spaceIndex)), 10);
|
|
291
|
-
if (Number.isNaN(length) || length === 0)
|
|
292
|
-
break;
|
|
293
|
-
const recordEnd = offset + length;
|
|
294
|
-
const [key, value] = decoder$1.decode(buffer.subarray(spaceIndex + 1, recordEnd - 1)).split("=", 2);
|
|
295
|
-
if (key && value !== undefined) {
|
|
296
|
-
pax[key] = value;
|
|
297
|
-
const mapping = PAX_MAPPING[key];
|
|
298
|
-
if (mapping) {
|
|
299
|
-
const [targetKey, parser] = mapping;
|
|
300
|
-
const parsedValue = parser(value);
|
|
301
|
-
if (typeof parsedValue === "string" || !Number.isNaN(parsedValue))
|
|
302
|
-
overrides[targetKey] = parsedValue;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
offset = recordEnd;
|
|
306
|
-
}
|
|
307
|
-
if (Object.keys(pax).length > 0)
|
|
308
|
-
overrides.pax = pax;
|
|
309
|
-
return overrides;
|
|
310
|
-
}
|
|
311
|
-
function applyOverrides(header, overrides) {
|
|
312
|
-
if (overrides.name !== undefined)
|
|
313
|
-
header.name = overrides.name;
|
|
314
|
-
if (overrides.linkname !== undefined)
|
|
315
|
-
header.linkname = overrides.linkname;
|
|
316
|
-
if (overrides.size !== undefined)
|
|
317
|
-
header.size = overrides.size;
|
|
318
|
-
if (overrides.mtime !== undefined)
|
|
319
|
-
header.mtime = /* @__PURE__ */ new Date(overrides.mtime * 1000);
|
|
320
|
-
if (overrides.uid !== undefined)
|
|
321
|
-
header.uid = overrides.uid;
|
|
322
|
-
if (overrides.gid !== undefined)
|
|
323
|
-
header.gid = overrides.gid;
|
|
324
|
-
if (overrides.uname !== undefined)
|
|
325
|
-
header.uname = overrides.uname;
|
|
326
|
-
if (overrides.gname !== undefined)
|
|
327
|
-
header.gname = overrides.gname;
|
|
328
|
-
if (overrides.pax)
|
|
329
|
-
header.pax = Object.assign({}, header.pax ?? {}, overrides.pax);
|
|
330
|
-
}
|
|
331
|
-
function getMetaParser(type) {
|
|
332
|
-
switch (type) {
|
|
333
|
-
case "pax-global-header":
|
|
334
|
-
case "pax-header":
|
|
335
|
-
return parsePax;
|
|
336
|
-
case "gnu-long-name":
|
|
337
|
-
return (data) => ({ name: readString(data, 0, data.length) });
|
|
338
|
-
case "gnu-long-link-name":
|
|
339
|
-
return (data) => ({ linkname: readString(data, 0, data.length) });
|
|
340
|
-
default:
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
function getHeaderBlocks(header) {
|
|
345
|
-
const base = createTarHeader(header);
|
|
346
|
-
const pax = generatePax(header);
|
|
347
|
-
if (!pax)
|
|
348
|
-
return [base];
|
|
349
|
-
const paxPadding = -pax.paxBody.length & BLOCK_SIZE_MASK;
|
|
350
|
-
const paddingBlocks = paxPadding > 0 ? [ZERO_BLOCK.subarray(0, paxPadding)] : [];
|
|
351
|
-
return [
|
|
352
|
-
pax.paxHeader,
|
|
353
|
-
pax.paxBody,
|
|
354
|
-
...paddingBlocks,
|
|
355
|
-
base
|
|
356
|
-
];
|
|
357
|
-
}
|
|
358
|
-
function createTarPacker(onData, onError, onFinalize) {
|
|
359
|
-
let currentHeader = null;
|
|
360
|
-
let bytesWritten = 0;
|
|
361
|
-
let finalized = false;
|
|
362
|
-
return {
|
|
363
|
-
add(header) {
|
|
364
|
-
if (finalized) {
|
|
365
|
-
const error = /* @__PURE__ */ new Error("No new tar entries after finalize.");
|
|
366
|
-
onError(error);
|
|
367
|
-
throw error;
|
|
368
|
-
}
|
|
369
|
-
if (currentHeader !== null) {
|
|
370
|
-
const error = /* @__PURE__ */ new Error("Previous entry must be completed before adding a new one");
|
|
371
|
-
onError(error);
|
|
372
|
-
throw error;
|
|
373
|
-
}
|
|
374
|
-
try {
|
|
375
|
-
const size = isBodyless(header) ? 0 : header.size ?? 0;
|
|
376
|
-
const headerBlocks = getHeaderBlocks({
|
|
377
|
-
...header,
|
|
378
|
-
size
|
|
379
|
-
});
|
|
380
|
-
for (const block of headerBlocks)
|
|
381
|
-
onData(block);
|
|
382
|
-
currentHeader = {
|
|
383
|
-
...header,
|
|
384
|
-
size
|
|
385
|
-
};
|
|
386
|
-
bytesWritten = 0;
|
|
387
|
-
} catch (error) {
|
|
388
|
-
onError(error);
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
|
-
write(chunk) {
|
|
392
|
-
if (!currentHeader) {
|
|
393
|
-
const error = /* @__PURE__ */ new Error("No active tar entry.");
|
|
394
|
-
onError(error);
|
|
395
|
-
throw error;
|
|
396
|
-
}
|
|
397
|
-
if (finalized) {
|
|
398
|
-
const error = /* @__PURE__ */ new Error("Cannot write data after finalize.");
|
|
399
|
-
onError(error);
|
|
400
|
-
throw error;
|
|
401
|
-
}
|
|
402
|
-
const newTotal = bytesWritten + chunk.length;
|
|
403
|
-
if (newTotal > currentHeader.size) {
|
|
404
|
-
const error = /* @__PURE__ */ new Error(`"${currentHeader.name}" exceeds given size of ${currentHeader.size} bytes.`);
|
|
405
|
-
onError(error);
|
|
406
|
-
throw error;
|
|
407
|
-
}
|
|
408
|
-
try {
|
|
409
|
-
bytesWritten = newTotal;
|
|
410
|
-
onData(chunk);
|
|
411
|
-
} catch (error) {
|
|
412
|
-
onError(error);
|
|
413
|
-
}
|
|
414
|
-
},
|
|
415
|
-
endEntry() {
|
|
416
|
-
if (!currentHeader) {
|
|
417
|
-
const error = /* @__PURE__ */ new Error("No active entry to end.");
|
|
418
|
-
onError(error);
|
|
419
|
-
throw error;
|
|
420
|
-
}
|
|
421
|
-
if (finalized) {
|
|
422
|
-
const error = /* @__PURE__ */ new Error("Cannot end entry after finalize.");
|
|
423
|
-
onError(error);
|
|
424
|
-
throw error;
|
|
425
|
-
}
|
|
426
|
-
try {
|
|
427
|
-
if (bytesWritten !== currentHeader.size) {
|
|
428
|
-
const error = /* @__PURE__ */ new Error(`Size mismatch for "${currentHeader.name}".`);
|
|
429
|
-
onError(error);
|
|
430
|
-
throw error;
|
|
431
|
-
}
|
|
432
|
-
const paddingSize = -currentHeader.size & BLOCK_SIZE_MASK;
|
|
433
|
-
if (paddingSize > 0)
|
|
434
|
-
onData(new Uint8Array(paddingSize));
|
|
435
|
-
currentHeader = null;
|
|
436
|
-
bytesWritten = 0;
|
|
437
|
-
} catch (error) {
|
|
438
|
-
onError(error);
|
|
439
|
-
throw error;
|
|
440
|
-
}
|
|
441
|
-
},
|
|
442
|
-
finalize() {
|
|
443
|
-
if (finalized) {
|
|
444
|
-
const error = /* @__PURE__ */ new Error("Archive has already been finalized");
|
|
445
|
-
onError(error);
|
|
446
|
-
throw error;
|
|
447
|
-
}
|
|
448
|
-
if (currentHeader !== null) {
|
|
449
|
-
const error = /* @__PURE__ */ new Error("Cannot finalize while an entry is still active");
|
|
450
|
-
onError(error);
|
|
451
|
-
throw error;
|
|
452
|
-
}
|
|
453
|
-
try {
|
|
454
|
-
onData(EOF_BUFFER);
|
|
455
|
-
finalized = true;
|
|
456
|
-
if (onFinalize)
|
|
457
|
-
onFinalize();
|
|
458
|
-
} catch (error) {
|
|
459
|
-
onError(error);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
function createChunkQueue() {
|
|
465
|
-
let chunks = new Array(INITIAL_CAPACITY);
|
|
466
|
-
let capacityMask = chunks.length - 1;
|
|
467
|
-
let head = 0;
|
|
468
|
-
let tail = 0;
|
|
469
|
-
let totalAvailable = 0;
|
|
470
|
-
const consumeFromHead = (count) => {
|
|
471
|
-
const chunk = chunks[head];
|
|
472
|
-
if (count === chunk.length) {
|
|
473
|
-
chunks[head] = EMPTY;
|
|
474
|
-
head = head + 1 & capacityMask;
|
|
475
|
-
} else
|
|
476
|
-
chunks[head] = chunk.subarray(count);
|
|
477
|
-
totalAvailable -= count;
|
|
478
|
-
if (totalAvailable === 0 && chunks.length > INITIAL_CAPACITY) {
|
|
479
|
-
chunks = new Array(INITIAL_CAPACITY);
|
|
480
|
-
capacityMask = INITIAL_CAPACITY - 1;
|
|
481
|
-
head = 0;
|
|
482
|
-
tail = 0;
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
function pull(bytes, callback) {
|
|
486
|
-
if (callback) {
|
|
487
|
-
let fed = 0;
|
|
488
|
-
let remaining$1 = Math.min(bytes, totalAvailable);
|
|
489
|
-
while (remaining$1 > 0) {
|
|
490
|
-
const chunk = chunks[head];
|
|
491
|
-
const toFeed = Math.min(remaining$1, chunk.length);
|
|
492
|
-
const segment = toFeed === chunk.length ? chunk : chunk.subarray(0, toFeed);
|
|
493
|
-
consumeFromHead(toFeed);
|
|
494
|
-
remaining$1 -= toFeed;
|
|
495
|
-
fed += toFeed;
|
|
496
|
-
if (!callback(segment))
|
|
497
|
-
break;
|
|
498
|
-
}
|
|
499
|
-
return fed;
|
|
500
|
-
}
|
|
501
|
-
if (totalAvailable < bytes)
|
|
502
|
-
return null;
|
|
503
|
-
if (bytes === 0)
|
|
504
|
-
return EMPTY;
|
|
505
|
-
const firstChunk = chunks[head];
|
|
506
|
-
if (firstChunk.length >= bytes) {
|
|
507
|
-
const view = firstChunk.length === bytes ? firstChunk : firstChunk.subarray(0, bytes);
|
|
508
|
-
consumeFromHead(bytes);
|
|
509
|
-
return view;
|
|
510
|
-
}
|
|
511
|
-
const result = new Uint8Array(bytes);
|
|
512
|
-
let copied = 0;
|
|
513
|
-
let remaining = bytes;
|
|
514
|
-
while (remaining > 0) {
|
|
515
|
-
const chunk = chunks[head];
|
|
516
|
-
const toCopy = Math.min(remaining, chunk.length);
|
|
517
|
-
result.set(toCopy === chunk.length ? chunk : chunk.subarray(0, toCopy), copied);
|
|
518
|
-
copied += toCopy;
|
|
519
|
-
remaining -= toCopy;
|
|
520
|
-
consumeFromHead(toCopy);
|
|
521
|
-
}
|
|
522
|
-
return result;
|
|
523
|
-
}
|
|
524
|
-
return {
|
|
525
|
-
push: (chunk) => {
|
|
526
|
-
if (chunk.length === 0)
|
|
527
|
-
return;
|
|
528
|
-
let nextTail = tail + 1 & capacityMask;
|
|
529
|
-
if (nextTail === head) {
|
|
530
|
-
const oldLen = chunks.length;
|
|
531
|
-
const newLen = oldLen * 2;
|
|
532
|
-
const newChunks = new Array(newLen);
|
|
533
|
-
const count = tail - head + oldLen & oldLen - 1;
|
|
534
|
-
if (head < tail)
|
|
535
|
-
for (let i = 0;i < count; i++)
|
|
536
|
-
newChunks[i] = chunks[head + i];
|
|
537
|
-
else if (count > 0) {
|
|
538
|
-
const firstPart = oldLen - head;
|
|
539
|
-
for (let i = 0;i < firstPart; i++)
|
|
540
|
-
newChunks[i] = chunks[head + i];
|
|
541
|
-
for (let i = 0;i < tail; i++)
|
|
542
|
-
newChunks[firstPart + i] = chunks[i];
|
|
543
|
-
}
|
|
544
|
-
chunks = newChunks;
|
|
545
|
-
capacityMask = newLen - 1;
|
|
546
|
-
head = 0;
|
|
547
|
-
tail = count;
|
|
548
|
-
nextTail = tail + 1 & capacityMask;
|
|
549
|
-
}
|
|
550
|
-
chunks[tail] = chunk;
|
|
551
|
-
tail = nextTail;
|
|
552
|
-
totalAvailable += chunk.length;
|
|
553
|
-
},
|
|
554
|
-
available: () => totalAvailable,
|
|
555
|
-
peek: (bytes) => {
|
|
556
|
-
if (totalAvailable < bytes)
|
|
557
|
-
return null;
|
|
558
|
-
if (bytes === 0)
|
|
559
|
-
return EMPTY;
|
|
560
|
-
const firstChunk = chunks[head];
|
|
561
|
-
if (firstChunk.length >= bytes)
|
|
562
|
-
return firstChunk.length === bytes ? firstChunk : firstChunk.subarray(0, bytes);
|
|
563
|
-
const result = new Uint8Array(bytes);
|
|
564
|
-
let copied = 0;
|
|
565
|
-
let index = head;
|
|
566
|
-
while (copied < bytes) {
|
|
567
|
-
const chunk = chunks[index];
|
|
568
|
-
const toCopy = Math.min(bytes - copied, chunk.length);
|
|
569
|
-
if (toCopy === chunk.length)
|
|
570
|
-
result.set(chunk, copied);
|
|
571
|
-
else
|
|
572
|
-
result.set(chunk.subarray(0, toCopy), copied);
|
|
573
|
-
copied += toCopy;
|
|
574
|
-
index = index + 1 & capacityMask;
|
|
575
|
-
}
|
|
576
|
-
return result;
|
|
577
|
-
},
|
|
578
|
-
discard: (bytes) => {
|
|
579
|
-
if (bytes > totalAvailable)
|
|
580
|
-
throw new Error("Too many bytes consumed");
|
|
581
|
-
if (bytes === 0)
|
|
582
|
-
return;
|
|
583
|
-
let remaining = bytes;
|
|
584
|
-
while (remaining > 0) {
|
|
585
|
-
const chunk = chunks[head];
|
|
586
|
-
const toConsume = Math.min(remaining, chunk.length);
|
|
587
|
-
consumeFromHead(toConsume);
|
|
588
|
-
remaining -= toConsume;
|
|
589
|
-
}
|
|
590
|
-
},
|
|
591
|
-
pull
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
function createUnpacker(options = {}) {
|
|
595
|
-
const strict = options.strict ?? false;
|
|
596
|
-
const { available, peek, push, discard, pull } = createChunkQueue();
|
|
597
|
-
let state = STATE_HEADER;
|
|
598
|
-
let ended = false;
|
|
599
|
-
let done = false;
|
|
600
|
-
let eof = false;
|
|
601
|
-
let currentEntry = null;
|
|
602
|
-
const paxGlobals = {};
|
|
603
|
-
let nextEntryOverrides = {};
|
|
604
|
-
const unpacker = {
|
|
605
|
-
isEntryActive: () => state === STATE_BODY,
|
|
606
|
-
isBodyComplete: () => !currentEntry || currentEntry.remaining === 0,
|
|
607
|
-
write(chunk) {
|
|
608
|
-
if (ended)
|
|
609
|
-
throw new Error("Archive already ended.");
|
|
610
|
-
push(chunk);
|
|
611
|
-
},
|
|
612
|
-
end() {
|
|
613
|
-
ended = true;
|
|
614
|
-
},
|
|
615
|
-
readHeader() {
|
|
616
|
-
if (state !== STATE_HEADER)
|
|
617
|
-
throw new Error("Cannot read header while an entry is active");
|
|
618
|
-
if (done)
|
|
619
|
-
return;
|
|
620
|
-
while (!done) {
|
|
621
|
-
if (available() < BLOCK_SIZE) {
|
|
622
|
-
if (ended) {
|
|
623
|
-
if (available() > 0 && strict)
|
|
624
|
-
throw truncateErr;
|
|
625
|
-
done = true;
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
return null;
|
|
629
|
-
}
|
|
630
|
-
const headerBlock = peek(BLOCK_SIZE);
|
|
631
|
-
if (isZeroBlock(headerBlock)) {
|
|
632
|
-
if (available() < BLOCK_SIZE * 2) {
|
|
633
|
-
if (ended) {
|
|
634
|
-
if (strict)
|
|
635
|
-
throw truncateErr;
|
|
636
|
-
done = true;
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
return null;
|
|
640
|
-
}
|
|
641
|
-
if (isZeroBlock(peek(BLOCK_SIZE * 2).subarray(BLOCK_SIZE))) {
|
|
642
|
-
discard(BLOCK_SIZE * 2);
|
|
643
|
-
done = true;
|
|
644
|
-
eof = true;
|
|
645
|
-
return;
|
|
646
|
-
}
|
|
647
|
-
if (strict)
|
|
648
|
-
throw new Error("Invalid tar header.");
|
|
649
|
-
discard(BLOCK_SIZE);
|
|
650
|
-
continue;
|
|
651
|
-
}
|
|
652
|
-
let internalHeader;
|
|
653
|
-
try {
|
|
654
|
-
internalHeader = parseUstarHeader(headerBlock, strict);
|
|
655
|
-
} catch (err) {
|
|
656
|
-
if (strict)
|
|
657
|
-
throw err;
|
|
658
|
-
discard(BLOCK_SIZE);
|
|
659
|
-
continue;
|
|
660
|
-
}
|
|
661
|
-
const metaParser = getMetaParser(internalHeader.type);
|
|
662
|
-
if (metaParser) {
|
|
663
|
-
const paddedSize = internalHeader.size + BLOCK_SIZE_MASK & ~BLOCK_SIZE_MASK;
|
|
664
|
-
if (available() < BLOCK_SIZE + paddedSize) {
|
|
665
|
-
if (ended && strict)
|
|
666
|
-
throw truncateErr;
|
|
667
|
-
return null;
|
|
668
|
-
}
|
|
669
|
-
discard(BLOCK_SIZE);
|
|
670
|
-
const overrides = metaParser(pull(paddedSize).subarray(0, internalHeader.size));
|
|
671
|
-
const target = internalHeader.type === "pax-global-header" ? paxGlobals : nextEntryOverrides;
|
|
672
|
-
for (const key in overrides)
|
|
673
|
-
target[key] = overrides[key];
|
|
674
|
-
continue;
|
|
675
|
-
}
|
|
676
|
-
discard(BLOCK_SIZE);
|
|
677
|
-
const header = internalHeader;
|
|
678
|
-
if (internalHeader.prefix)
|
|
679
|
-
header.name = `${internalHeader.prefix}/${header.name}`;
|
|
680
|
-
applyOverrides(header, paxGlobals);
|
|
681
|
-
applyOverrides(header, nextEntryOverrides);
|
|
682
|
-
nextEntryOverrides = {};
|
|
683
|
-
currentEntry = {
|
|
684
|
-
header,
|
|
685
|
-
remaining: header.size,
|
|
686
|
-
padding: -header.size & BLOCK_SIZE_MASK
|
|
687
|
-
};
|
|
688
|
-
state = STATE_BODY;
|
|
689
|
-
return header;
|
|
690
|
-
}
|
|
691
|
-
},
|
|
692
|
-
streamBody(callback) {
|
|
693
|
-
if (state !== STATE_BODY || !currentEntry || currentEntry.remaining === 0)
|
|
694
|
-
return 0;
|
|
695
|
-
const bytesToFeed = Math.min(currentEntry.remaining, available());
|
|
696
|
-
if (bytesToFeed === 0)
|
|
697
|
-
return 0;
|
|
698
|
-
const fed = pull(bytesToFeed, callback);
|
|
699
|
-
currentEntry.remaining -= fed;
|
|
700
|
-
return fed;
|
|
701
|
-
},
|
|
702
|
-
skipPadding() {
|
|
703
|
-
if (state !== STATE_BODY || !currentEntry)
|
|
704
|
-
return true;
|
|
705
|
-
if (currentEntry.remaining > 0)
|
|
706
|
-
throw new Error("Body not fully consumed");
|
|
707
|
-
if (available() < currentEntry.padding)
|
|
708
|
-
return false;
|
|
709
|
-
discard(currentEntry.padding);
|
|
710
|
-
currentEntry = null;
|
|
711
|
-
state = STATE_HEADER;
|
|
712
|
-
return true;
|
|
713
|
-
},
|
|
714
|
-
skipEntry() {
|
|
715
|
-
if (state !== STATE_BODY || !currentEntry)
|
|
716
|
-
return true;
|
|
717
|
-
const toDiscard = Math.min(currentEntry.remaining, available());
|
|
718
|
-
if (toDiscard > 0) {
|
|
719
|
-
discard(toDiscard);
|
|
720
|
-
currentEntry.remaining -= toDiscard;
|
|
721
|
-
}
|
|
722
|
-
if (currentEntry.remaining > 0)
|
|
723
|
-
return false;
|
|
724
|
-
return unpacker.skipPadding();
|
|
725
|
-
},
|
|
726
|
-
validateEOF() {
|
|
727
|
-
if (strict) {
|
|
728
|
-
if (!eof)
|
|
729
|
-
throw truncateErr;
|
|
730
|
-
if (available() > 0) {
|
|
731
|
-
if (pull(available()).some((byte) => byte !== 0))
|
|
732
|
-
throw new Error("Invalid EOF.");
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
return unpacker;
|
|
738
|
-
}
|
|
739
|
-
function isZeroBlock(block) {
|
|
740
|
-
if (block.byteOffset % 8 === 0) {
|
|
741
|
-
const view = new BigUint64Array(block.buffer, block.byteOffset, block.length / 8);
|
|
742
|
-
for (let i = 0;i < view.length; i++)
|
|
743
|
-
if (view[i] !== 0n)
|
|
744
|
-
return false;
|
|
745
|
-
return true;
|
|
746
|
-
}
|
|
747
|
-
for (let i = 0;i < block.length; i++)
|
|
748
|
-
if (block[i] !== 0)
|
|
749
|
-
return false;
|
|
750
|
-
return true;
|
|
751
|
-
}
|
|
752
|
-
function createTarPacker2() {
|
|
753
|
-
let streamController;
|
|
754
|
-
let packer;
|
|
755
|
-
return {
|
|
756
|
-
readable: new ReadableStream({ start(controller) {
|
|
757
|
-
streamController = controller;
|
|
758
|
-
packer = createTarPacker(controller.enqueue.bind(controller), controller.error.bind(controller), controller.close.bind(controller));
|
|
759
|
-
} }),
|
|
760
|
-
controller: {
|
|
761
|
-
add(header) {
|
|
762
|
-
const bodyless = isBodyless(header);
|
|
763
|
-
const h = { ...header };
|
|
764
|
-
if (bodyless)
|
|
765
|
-
h.size = 0;
|
|
766
|
-
packer.add(h);
|
|
767
|
-
if (bodyless)
|
|
768
|
-
packer.endEntry();
|
|
769
|
-
return new WritableStream({
|
|
770
|
-
write(chunk) {
|
|
771
|
-
packer.write(chunk);
|
|
772
|
-
},
|
|
773
|
-
close() {
|
|
774
|
-
if (!bodyless)
|
|
775
|
-
packer.endEntry();
|
|
776
|
-
},
|
|
777
|
-
abort(reason) {
|
|
778
|
-
streamController.error(reason);
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
|
-
},
|
|
782
|
-
finalize() {
|
|
783
|
-
packer.finalize();
|
|
784
|
-
},
|
|
785
|
-
error(err) {
|
|
786
|
-
streamController.error(err);
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
}
|
|
791
|
-
async function streamToBuffer(stream) {
|
|
792
|
-
const chunks = [];
|
|
793
|
-
const reader = stream.getReader();
|
|
794
|
-
let totalLength = 0;
|
|
795
|
-
try {
|
|
796
|
-
while (true) {
|
|
797
|
-
const { done, value } = await reader.read();
|
|
798
|
-
if (done)
|
|
799
|
-
break;
|
|
800
|
-
chunks.push(value);
|
|
801
|
-
totalLength += value.length;
|
|
802
|
-
}
|
|
803
|
-
const result = new Uint8Array(totalLength);
|
|
804
|
-
let offset = 0;
|
|
805
|
-
for (const chunk of chunks) {
|
|
806
|
-
result.set(chunk, offset);
|
|
807
|
-
offset += chunk.length;
|
|
808
|
-
}
|
|
809
|
-
return result;
|
|
810
|
-
} finally {
|
|
811
|
-
reader.releaseLock();
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
function createTarDecoder(options = {}) {
|
|
815
|
-
const unpacker = createUnpacker(options);
|
|
816
|
-
let bodyController = null;
|
|
817
|
-
let pumping = false;
|
|
818
|
-
const pump = (controller) => {
|
|
819
|
-
if (pumping)
|
|
820
|
-
return;
|
|
821
|
-
pumping = true;
|
|
822
|
-
try {
|
|
823
|
-
while (true)
|
|
824
|
-
if (unpacker.isEntryActive()) {
|
|
825
|
-
if (bodyController) {
|
|
826
|
-
if (unpacker.streamBody((c) => (bodyController.enqueue(c), true)) === 0 && !unpacker.isBodyComplete())
|
|
827
|
-
break;
|
|
828
|
-
} else if (!unpacker.skipEntry())
|
|
829
|
-
break;
|
|
830
|
-
if (unpacker.isBodyComplete()) {
|
|
831
|
-
try {
|
|
832
|
-
bodyController?.close();
|
|
833
|
-
} catch {}
|
|
834
|
-
bodyController = null;
|
|
835
|
-
if (!unpacker.skipPadding())
|
|
836
|
-
break;
|
|
837
|
-
}
|
|
838
|
-
} else {
|
|
839
|
-
const header = unpacker.readHeader();
|
|
840
|
-
if (header === null || header === undefined)
|
|
841
|
-
break;
|
|
842
|
-
controller.enqueue({
|
|
843
|
-
header,
|
|
844
|
-
body: new ReadableStream({
|
|
845
|
-
start(c) {
|
|
846
|
-
if (header.size === 0)
|
|
847
|
-
c.close();
|
|
848
|
-
else
|
|
849
|
-
bodyController = c;
|
|
850
|
-
},
|
|
851
|
-
pull: () => pump(controller),
|
|
852
|
-
cancel() {
|
|
853
|
-
bodyController = null;
|
|
854
|
-
pump(controller);
|
|
855
|
-
}
|
|
856
|
-
})
|
|
857
|
-
});
|
|
858
|
-
}
|
|
859
|
-
} catch (error) {
|
|
860
|
-
try {
|
|
861
|
-
bodyController?.error(error);
|
|
862
|
-
} catch {}
|
|
863
|
-
bodyController = null;
|
|
864
|
-
throw error;
|
|
865
|
-
} finally {
|
|
866
|
-
pumping = false;
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
return new TransformStream({
|
|
870
|
-
transform(chunk, controller) {
|
|
871
|
-
try {
|
|
872
|
-
unpacker.write(chunk);
|
|
873
|
-
pump(controller);
|
|
874
|
-
} catch (error) {
|
|
875
|
-
try {
|
|
876
|
-
bodyController?.error(error);
|
|
877
|
-
} catch {}
|
|
878
|
-
throw error;
|
|
879
|
-
}
|
|
880
|
-
},
|
|
881
|
-
flush(controller) {
|
|
882
|
-
try {
|
|
883
|
-
unpacker.end();
|
|
884
|
-
pump(controller);
|
|
885
|
-
unpacker.validateEOF();
|
|
886
|
-
if (unpacker.isEntryActive() && !unpacker.isBodyComplete())
|
|
887
|
-
try {
|
|
888
|
-
bodyController?.close();
|
|
889
|
-
} catch {}
|
|
890
|
-
} catch (error) {
|
|
891
|
-
try {
|
|
892
|
-
bodyController?.error(error);
|
|
893
|
-
} catch {}
|
|
894
|
-
throw error;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
}, undefined, { highWaterMark: 1 });
|
|
898
|
-
}
|
|
899
|
-
async function packTar(entries) {
|
|
900
|
-
const { readable, controller } = createTarPacker2();
|
|
901
|
-
await (async () => {
|
|
902
|
-
for (const entry of entries) {
|
|
903
|
-
const entryStream = controller.add(entry.header);
|
|
904
|
-
const body = "body" in entry ? entry.body : entry.data;
|
|
905
|
-
if (!body) {
|
|
906
|
-
await entryStream.close();
|
|
907
|
-
continue;
|
|
908
|
-
}
|
|
909
|
-
if (body instanceof ReadableStream)
|
|
910
|
-
await body.pipeTo(entryStream);
|
|
911
|
-
else if (body instanceof Blob)
|
|
912
|
-
await body.stream().pipeTo(entryStream);
|
|
913
|
-
else
|
|
914
|
-
try {
|
|
915
|
-
const chunk = await normalizeBody(body);
|
|
916
|
-
if (chunk.length > 0) {
|
|
917
|
-
const writer = entryStream.getWriter();
|
|
918
|
-
await writer.write(chunk);
|
|
919
|
-
await writer.close();
|
|
920
|
-
} else
|
|
921
|
-
await entryStream.close();
|
|
922
|
-
} catch {
|
|
923
|
-
throw new TypeError(`Unsupported content type for entry "${entry.header.name}".`);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
})().then(() => controller.finalize()).catch((err) => controller.error(err));
|
|
927
|
-
return new Uint8Array(await streamToBuffer(readable));
|
|
928
|
-
}
|
|
929
|
-
async function unpackTar(archive, options = {}) {
|
|
930
|
-
const sourceStream = archive instanceof ReadableStream ? archive : new ReadableStream({ start(controller) {
|
|
931
|
-
controller.enqueue(archive instanceof Uint8Array ? archive : new Uint8Array(archive));
|
|
932
|
-
controller.close();
|
|
933
|
-
} });
|
|
934
|
-
const results = [];
|
|
935
|
-
const entryStream = sourceStream.pipeThrough(createTarDecoder(options));
|
|
936
|
-
for await (const entry of entryStream) {
|
|
937
|
-
let processedHeader;
|
|
938
|
-
try {
|
|
939
|
-
processedHeader = transformHeader(entry.header, options);
|
|
940
|
-
} catch (error) {
|
|
941
|
-
await entry.body.cancel();
|
|
942
|
-
throw error;
|
|
943
|
-
}
|
|
944
|
-
if (processedHeader === null) {
|
|
945
|
-
await drain(entry.body);
|
|
946
|
-
continue;
|
|
947
|
-
}
|
|
948
|
-
if (isBodyless(processedHeader)) {
|
|
949
|
-
await drain(entry.body);
|
|
950
|
-
results.push({ header: processedHeader });
|
|
951
|
-
} else
|
|
952
|
-
results.push({
|
|
953
|
-
header: processedHeader,
|
|
954
|
-
data: await streamToBuffer(entry.body)
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
return results;
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
class RXAImpl {
|
|
961
|
-
_buffer;
|
|
962
|
-
constructor(buffer) {
|
|
963
|
-
this._buffer = buffer;
|
|
964
|
-
}
|
|
965
|
-
get stream() {
|
|
966
|
-
const buffer = this._buffer;
|
|
967
|
-
return new ReadableStream({
|
|
968
|
-
start(controller) {
|
|
969
|
-
controller.enqueue(new Uint8Array(buffer));
|
|
970
|
-
controller.close();
|
|
971
|
-
}
|
|
972
|
-
});
|
|
973
|
-
}
|
|
974
|
-
async buffer() {
|
|
975
|
-
return this._buffer;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
async function archive(files) {
|
|
979
|
-
const entries = Object.entries(files).map(([name, content]) => {
|
|
980
|
-
return {
|
|
981
|
-
header: { name, size: content.length, type: "file" },
|
|
982
|
-
body: new Uint8Array(content)
|
|
983
|
-
};
|
|
984
|
-
});
|
|
985
|
-
const tarBuffer = await packTar(entries);
|
|
986
|
-
const gzipBuffer = await gzipAsync(Buffer.from(tarBuffer));
|
|
987
|
-
return new RXAImpl(gzipBuffer);
|
|
988
|
-
}
|
|
989
|
-
function locate(rxm) {
|
|
990
|
-
return {
|
|
991
|
-
registry: rxm.registry,
|
|
992
|
-
path: rxm.path,
|
|
993
|
-
name: rxm.name,
|
|
994
|
-
tag: rxm.tag
|
|
995
|
-
};
|
|
996
|
-
}
|
|
997
|
-
function resource(rxm, rxa) {
|
|
998
|
-
const rxl = locate(rxm);
|
|
999
|
-
return {
|
|
1000
|
-
locator: rxl,
|
|
1001
|
-
manifest: rxm,
|
|
1002
|
-
archive: rxa
|
|
1003
|
-
};
|
|
1004
|
-
}
|
|
1005
|
-
async function extract(rxa) {
|
|
1006
|
-
const buffer = await rxa.buffer();
|
|
1007
|
-
const tarBuffer = await gunzipAsync(buffer);
|
|
1008
|
-
const entries = await unpackTar(tarBuffer);
|
|
1009
|
-
const files = {};
|
|
1010
|
-
for (const entry of entries) {
|
|
1011
|
-
if ((entry.header.type === "file" || entry.header.type === undefined) && entry.data) {
|
|
1012
|
-
files[entry.header.name] = Buffer.from(entry.data);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
return files;
|
|
1016
|
-
}
|
|
1017
|
-
function format(rxl) {
|
|
1018
|
-
let result = "";
|
|
1019
|
-
if (rxl.registry) {
|
|
1020
|
-
result += rxl.registry + "/";
|
|
1021
|
-
}
|
|
1022
|
-
if (rxl.path) {
|
|
1023
|
-
result += rxl.path + "/";
|
|
1024
|
-
}
|
|
1025
|
-
result += rxl.name;
|
|
1026
|
-
if (rxl.tag && rxl.tag !== "latest") {
|
|
1027
|
-
result += ":" + rxl.tag;
|
|
1028
|
-
}
|
|
1029
|
-
return result;
|
|
1030
|
-
}
|
|
1031
|
-
function looksLikeRegistry(str) {
|
|
1032
|
-
if (str.includes(":") && !str.includes("/")) {
|
|
1033
|
-
return true;
|
|
1034
|
-
}
|
|
1035
|
-
if (str.includes(".")) {
|
|
1036
|
-
return true;
|
|
1037
|
-
}
|
|
1038
|
-
if (str === "localhost") {
|
|
1039
|
-
return true;
|
|
1040
|
-
}
|
|
1041
|
-
return false;
|
|
1042
|
-
}
|
|
1043
|
-
function parse(locator) {
|
|
1044
|
-
if (!locator || typeof locator !== "string") {
|
|
1045
|
-
throw new LocatorError("Locator must be a non-empty string", locator);
|
|
1046
|
-
}
|
|
1047
|
-
if (locator.includes("@")) {
|
|
1048
|
-
throw new LocatorError("Invalid locator format. Use name:tag instead of name@version", locator);
|
|
1049
|
-
}
|
|
1050
|
-
const lastSlashIndex = locator.lastIndexOf("/");
|
|
1051
|
-
let beforeSlash = "";
|
|
1052
|
-
let afterSlash = locator;
|
|
1053
|
-
if (lastSlashIndex !== -1) {
|
|
1054
|
-
beforeSlash = locator.substring(0, lastSlashIndex);
|
|
1055
|
-
afterSlash = locator.substring(lastSlashIndex + 1);
|
|
1056
|
-
}
|
|
1057
|
-
const colonIndex = afterSlash.lastIndexOf(":");
|
|
1058
|
-
let name;
|
|
1059
|
-
let tag;
|
|
1060
|
-
if (colonIndex === -1) {
|
|
1061
|
-
name = afterSlash;
|
|
1062
|
-
tag = "latest";
|
|
1063
|
-
} else {
|
|
1064
|
-
name = afterSlash.substring(0, colonIndex);
|
|
1065
|
-
tag = afterSlash.substring(colonIndex + 1);
|
|
1066
|
-
}
|
|
1067
|
-
if (!name) {
|
|
1068
|
-
throw new LocatorError("Name is required", locator);
|
|
1069
|
-
}
|
|
1070
|
-
if (!tag) {
|
|
1071
|
-
throw new LocatorError("Tag cannot be empty. Use name:tag format or omit tag for :latest", locator);
|
|
1072
|
-
}
|
|
1073
|
-
if (lastSlashIndex === -1) {
|
|
1074
|
-
return {
|
|
1075
|
-
registry: undefined,
|
|
1076
|
-
path: undefined,
|
|
1077
|
-
name,
|
|
1078
|
-
tag
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
const parts = beforeSlash.split("/");
|
|
1082
|
-
if (looksLikeRegistry(parts[0])) {
|
|
1083
|
-
const registry = parts[0];
|
|
1084
|
-
const path = parts.length > 1 ? parts.slice(1).join("/") : undefined;
|
|
1085
|
-
return {
|
|
1086
|
-
registry,
|
|
1087
|
-
path,
|
|
1088
|
-
name,
|
|
1089
|
-
tag
|
|
1090
|
-
};
|
|
1091
|
-
}
|
|
1092
|
-
return {
|
|
1093
|
-
registry: undefined,
|
|
1094
|
-
path: beforeSlash,
|
|
1095
|
-
name,
|
|
1096
|
-
tag
|
|
1097
|
-
};
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
class RXAImpl2 {
|
|
1101
|
-
_buffer;
|
|
1102
|
-
constructor(buffer) {
|
|
1103
|
-
this._buffer = buffer;
|
|
1104
|
-
}
|
|
1105
|
-
get stream() {
|
|
1106
|
-
const buffer = this._buffer;
|
|
1107
|
-
return new ReadableStream({
|
|
1108
|
-
start(controller) {
|
|
1109
|
-
controller.enqueue(new Uint8Array(buffer));
|
|
1110
|
-
controller.close();
|
|
1111
|
-
}
|
|
1112
|
-
});
|
|
1113
|
-
}
|
|
1114
|
-
async buffer() {
|
|
1115
|
-
return this._buffer;
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
function wrap(buffer) {
|
|
1119
|
-
return new RXAImpl2(buffer);
|
|
1120
|
-
}
|
|
1121
|
-
var ResourceXError, LocatorError, ManifestError, ContentError, DefinitionError, BLOCK_SIZE = 512, BLOCK_SIZE_MASK = 511, DEFAULT_FILE_MODE = 420, DEFAULT_DIR_MODE = 493, USTAR_NAME_OFFSET = 0, USTAR_NAME_SIZE = 100, USTAR_MODE_OFFSET = 100, USTAR_MODE_SIZE = 8, USTAR_UID_OFFSET = 108, USTAR_UID_SIZE = 8, USTAR_GID_OFFSET = 116, USTAR_GID_SIZE = 8, USTAR_SIZE_OFFSET = 124, USTAR_SIZE_SIZE = 12, USTAR_MTIME_OFFSET = 136, USTAR_MTIME_SIZE = 12, USTAR_CHECKSUM_OFFSET = 148, USTAR_CHECKSUM_SIZE = 8, USTAR_TYPEFLAG_OFFSET = 156, USTAR_TYPEFLAG_SIZE = 1, USTAR_LINKNAME_OFFSET = 157, USTAR_LINKNAME_SIZE = 100, USTAR_MAGIC_OFFSET = 257, USTAR_MAGIC_SIZE = 6, USTAR_VERSION_OFFSET = 263, USTAR_VERSION_SIZE = 2, USTAR_UNAME_OFFSET = 265, USTAR_UNAME_SIZE = 32, USTAR_GNAME_OFFSET = 297, USTAR_GNAME_SIZE = 32, USTAR_PREFIX_OFFSET = 345, USTAR_PREFIX_SIZE = 155, USTAR_VERSION = "00", USTAR_MAX_UID_GID = 2097151, USTAR_MAX_SIZE = 8589934591, FILE = "file", LINK = "link", SYMLINK = "symlink", DIRECTORY = "directory", TYPEFLAG, FLAGTYPE, ZERO_BLOCK, EMPTY, encoder, decoder, isBodyless = (header) => header.type === DIRECTORY || header.type === SYMLINK || header.type === LINK, CHECKSUM_SPACE = 32, ASCII_ZERO = 48, PAX_MAPPING, EOF_BUFFER, INITIAL_CAPACITY = 256, STATE_HEADER = 0, STATE_BODY = 1, truncateErr, drain = (stream) => stream.pipeTo(new WritableStream), gzipAsync, gunzipAsync;
|
|
1122
|
-
var init_dist = __esm(() => {
|
|
1123
|
-
ResourceXError = class ResourceXError extends Error {
|
|
1124
|
-
constructor(message, options) {
|
|
1125
|
-
super(message, options);
|
|
1126
|
-
this.name = "ResourceXError";
|
|
1127
|
-
}
|
|
1128
|
-
};
|
|
1129
|
-
LocatorError = class LocatorError extends ResourceXError {
|
|
1130
|
-
locator;
|
|
1131
|
-
constructor(message, locator) {
|
|
1132
|
-
super(message);
|
|
1133
|
-
this.locator = locator;
|
|
1134
|
-
this.name = "LocatorError";
|
|
1135
|
-
}
|
|
1136
|
-
};
|
|
1137
|
-
ManifestError = class ManifestError extends ResourceXError {
|
|
1138
|
-
constructor(message) {
|
|
1139
|
-
super(message);
|
|
1140
|
-
this.name = "ManifestError";
|
|
1141
|
-
}
|
|
1142
|
-
};
|
|
1143
|
-
ContentError = class ContentError extends ResourceXError {
|
|
1144
|
-
constructor(message) {
|
|
1145
|
-
super(message);
|
|
1146
|
-
this.name = "ContentError";
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
DefinitionError = class DefinitionError extends ResourceXError {
|
|
1150
|
-
constructor(message) {
|
|
1151
|
-
super(message);
|
|
1152
|
-
this.name = "DefinitionError";
|
|
1153
|
-
}
|
|
1154
|
-
};
|
|
1155
|
-
TYPEFLAG = {
|
|
1156
|
-
file: "0",
|
|
1157
|
-
link: "1",
|
|
1158
|
-
symlink: "2",
|
|
1159
|
-
"character-device": "3",
|
|
1160
|
-
"block-device": "4",
|
|
1161
|
-
directory: "5",
|
|
1162
|
-
fifo: "6",
|
|
1163
|
-
"pax-header": "x",
|
|
1164
|
-
"pax-global-header": "g",
|
|
1165
|
-
"gnu-long-name": "L",
|
|
1166
|
-
"gnu-long-link-name": "K"
|
|
1167
|
-
};
|
|
1168
|
-
FLAGTYPE = {
|
|
1169
|
-
"0": FILE,
|
|
1170
|
-
"1": LINK,
|
|
1171
|
-
"2": SYMLINK,
|
|
1172
|
-
"3": "character-device",
|
|
1173
|
-
"4": "block-device",
|
|
1174
|
-
"5": DIRECTORY,
|
|
1175
|
-
"6": "fifo",
|
|
1176
|
-
x: "pax-header",
|
|
1177
|
-
g: "pax-global-header",
|
|
1178
|
-
L: "gnu-long-name",
|
|
1179
|
-
K: "gnu-long-link-name"
|
|
1180
|
-
};
|
|
1181
|
-
ZERO_BLOCK = new Uint8Array(BLOCK_SIZE);
|
|
1182
|
-
EMPTY = new Uint8Array(0);
|
|
1183
|
-
encoder = new TextEncoder;
|
|
1184
|
-
decoder = new TextDecoder;
|
|
1185
|
-
PAX_MAPPING = {
|
|
1186
|
-
path: ["name", (v) => v],
|
|
1187
|
-
linkpath: ["linkname", (v) => v],
|
|
1188
|
-
size: ["size", (v) => parseInt(v, 10)],
|
|
1189
|
-
mtime: ["mtime", parseFloat],
|
|
1190
|
-
uid: ["uid", (v) => parseInt(v, 10)],
|
|
1191
|
-
gid: ["gid", (v) => parseInt(v, 10)],
|
|
1192
|
-
uname: ["uname", (v) => v],
|
|
1193
|
-
gname: ["gname", (v) => v]
|
|
1194
|
-
};
|
|
1195
|
-
EOF_BUFFER = new Uint8Array(BLOCK_SIZE * 2);
|
|
1196
|
-
truncateErr = /* @__PURE__ */ new Error("Tar archive is truncated.");
|
|
1197
|
-
gzipAsync = promisify(gzip);
|
|
1198
|
-
gunzipAsync = promisify2(gunzip);
|
|
1199
|
-
});
|
|
1200
|
-
|
|
1201
13
|
// ../arp/dist/index.js
|
|
1202
14
|
import { readFile, writeFile, readdir, mkdir, rm, access, stat } from "node:fs/promises";
|
|
1203
15
|
import { resolve, dirname, join } from "node:path";
|
|
@@ -1714,1455 +526,18 @@ class ARP {
|
|
|
1714
526
|
function createARP(config) {
|
|
1715
527
|
return new ARP(config);
|
|
1716
528
|
}
|
|
1717
|
-
var VERSION = "2.5.
|
|
1718
|
-
|
|
1719
|
-
// src/transport/rxr.ts
|
|
1720
|
-
import { homedir } from "node:os";
|
|
1721
|
-
import { join as join4 } from "node:path";
|
|
1722
|
-
init_dist();
|
|
1723
|
-
|
|
1724
|
-
// ../storage/dist/index.js
|
|
1725
|
-
import { join as join2, dirname as dirname2 } from "node:path";
|
|
1726
|
-
import { readFile as readFile2, writeFile as writeFile2, rm as rm2, access as access2, readdir as readdir2, mkdir as mkdir2 } from "node:fs/promises";
|
|
1727
|
-
|
|
1728
|
-
class StorageError extends Error {
|
|
1729
|
-
code;
|
|
1730
|
-
constructor(message, code) {
|
|
1731
|
-
super(message);
|
|
1732
|
-
this.code = code;
|
|
1733
|
-
this.name = "StorageError";
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
class FileSystemStorage {
|
|
1738
|
-
basePath;
|
|
1739
|
-
constructor(basePath) {
|
|
1740
|
-
this.basePath = basePath;
|
|
1741
|
-
}
|
|
1742
|
-
async get(key) {
|
|
1743
|
-
const filePath = join2(this.basePath, key);
|
|
1744
|
-
try {
|
|
1745
|
-
return await readFile2(filePath);
|
|
1746
|
-
} catch (error) {
|
|
1747
|
-
if (error.code === "ENOENT") {
|
|
1748
|
-
throw new StorageError(`Key not found: ${key}`, "NOT_FOUND");
|
|
1749
|
-
}
|
|
1750
|
-
throw new StorageError(`Failed to read: ${key}`, "READ_ERROR");
|
|
1751
|
-
}
|
|
1752
|
-
}
|
|
1753
|
-
async put(key, data) {
|
|
1754
|
-
const filePath = join2(this.basePath, key);
|
|
1755
|
-
try {
|
|
1756
|
-
await mkdir2(dirname2(filePath), { recursive: true });
|
|
1757
|
-
await writeFile2(filePath, data);
|
|
1758
|
-
} catch {
|
|
1759
|
-
throw new StorageError(`Failed to write: ${key}`, "WRITE_ERROR");
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
async delete(key) {
|
|
1763
|
-
const filePath = join2(this.basePath, key);
|
|
1764
|
-
try {
|
|
1765
|
-
await rm2(filePath, { recursive: true, force: true });
|
|
1766
|
-
} catch {
|
|
1767
|
-
throw new StorageError(`Failed to delete: ${key}`, "DELETE_ERROR");
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
async exists(key) {
|
|
1771
|
-
const filePath = join2(this.basePath, key);
|
|
1772
|
-
try {
|
|
1773
|
-
await access2(filePath);
|
|
1774
|
-
return true;
|
|
1775
|
-
} catch {
|
|
1776
|
-
return false;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
async list(prefix) {
|
|
1780
|
-
const searchPath = prefix ? join2(this.basePath, prefix) : this.basePath;
|
|
1781
|
-
const results = [];
|
|
1782
|
-
try {
|
|
1783
|
-
await this.listRecursive(searchPath, prefix ?? "", results);
|
|
1784
|
-
} catch {
|
|
1785
|
-
return [];
|
|
1786
|
-
}
|
|
1787
|
-
return results;
|
|
1788
|
-
}
|
|
1789
|
-
async listRecursive(dirPath, prefix, results) {
|
|
1790
|
-
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
1791
|
-
for (const entry of entries) {
|
|
1792
|
-
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
1793
|
-
if (entry.isDirectory()) {
|
|
1794
|
-
await this.listRecursive(join2(dirPath, entry.name), relativePath, results);
|
|
1795
|
-
} else {
|
|
1796
|
-
results.push(relativePath);
|
|
1797
|
-
}
|
|
1798
|
-
}
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
class MemoryStorage {
|
|
1803
|
-
data = new Map;
|
|
1804
|
-
async get(key) {
|
|
1805
|
-
const value = this.data.get(key);
|
|
1806
|
-
if (!value) {
|
|
1807
|
-
throw new StorageError(`Key not found: ${key}`, "NOT_FOUND");
|
|
1808
|
-
}
|
|
1809
|
-
return value;
|
|
1810
|
-
}
|
|
1811
|
-
async put(key, data) {
|
|
1812
|
-
this.data.set(key, data);
|
|
1813
|
-
}
|
|
1814
|
-
async delete(key) {
|
|
1815
|
-
for (const k of this.data.keys()) {
|
|
1816
|
-
if (k === key || k.startsWith(`${key}/`)) {
|
|
1817
|
-
this.data.delete(k);
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1821
|
-
async exists(key) {
|
|
1822
|
-
return this.data.has(key);
|
|
1823
|
-
}
|
|
1824
|
-
async list(prefix) {
|
|
1825
|
-
const results = [];
|
|
1826
|
-
for (const key of this.data.keys()) {
|
|
1827
|
-
if (!prefix || key.startsWith(prefix)) {
|
|
1828
|
-
results.push(key);
|
|
1829
|
-
}
|
|
1830
|
-
}
|
|
1831
|
-
return results;
|
|
1832
|
-
}
|
|
1833
|
-
clear() {
|
|
1834
|
-
this.data.clear();
|
|
1835
|
-
}
|
|
1836
|
-
size() {
|
|
1837
|
-
return this.data.size;
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
// ../registry/dist/index.js
|
|
1842
|
-
import { gzip as gzip2 } from "node:zlib";
|
|
1843
|
-
import { promisify as promisify3 } from "node:util";
|
|
1844
|
-
import { gunzip as gunzip2 } from "node:zlib";
|
|
1845
|
-
import { promisify as promisify22 } from "node:util";
|
|
1846
|
-
import { join as join22, resolve as resolvePath } from "node:path";
|
|
1847
|
-
import { symlink, lstat, readlink, rm as rm3, mkdir as mkdir3, readdir as readdir22 } from "node:fs/promises";
|
|
1848
|
-
import { join as join3, relative } from "node:path";
|
|
1849
|
-
import { stat as stat2, readFile as readFile3, readdir as readdir3 } from "node:fs/promises";
|
|
1850
|
-
import { gzip as gzip22 } from "node:zlib";
|
|
1851
|
-
import { promisify as promisify32 } from "node:util";
|
|
1852
|
-
import { gunzip as gunzip22 } from "node:zlib";
|
|
1853
|
-
import { promisify as promisify222 } from "node:util";
|
|
1854
|
-
|
|
1855
|
-
class ResourceXError2 extends Error {
|
|
1856
|
-
constructor(message, options) {
|
|
1857
|
-
super(message, options);
|
|
1858
|
-
this.name = "ResourceXError";
|
|
1859
|
-
}
|
|
1860
|
-
}
|
|
1861
|
-
|
|
1862
|
-
class LocatorError2 extends ResourceXError2 {
|
|
1863
|
-
locator;
|
|
1864
|
-
constructor(message, locator) {
|
|
1865
|
-
super(message);
|
|
1866
|
-
this.locator = locator;
|
|
1867
|
-
this.name = "LocatorError";
|
|
1868
|
-
}
|
|
1869
|
-
}
|
|
1870
|
-
var BLOCK_SIZE2 = 512;
|
|
1871
|
-
var ZERO_BLOCK2 = new Uint8Array(BLOCK_SIZE2);
|
|
1872
|
-
var EMPTY2 = new Uint8Array(0);
|
|
1873
|
-
var encoder2 = new TextEncoder;
|
|
1874
|
-
var decoder2 = new TextDecoder;
|
|
1875
|
-
var EOF_BUFFER2 = new Uint8Array(BLOCK_SIZE2 * 2);
|
|
1876
|
-
var gzipAsync2 = promisify3(gzip2);
|
|
1877
|
-
function locate2(rxm) {
|
|
1878
|
-
return {
|
|
1879
|
-
registry: rxm.registry,
|
|
1880
|
-
path: rxm.path,
|
|
1881
|
-
name: rxm.name,
|
|
1882
|
-
tag: rxm.tag
|
|
1883
|
-
};
|
|
1884
|
-
}
|
|
1885
|
-
function resource2(rxm, rxa) {
|
|
1886
|
-
const rxl = locate2(rxm);
|
|
1887
|
-
return {
|
|
1888
|
-
locator: rxl,
|
|
1889
|
-
manifest: rxm,
|
|
1890
|
-
archive: rxa
|
|
1891
|
-
};
|
|
1892
|
-
}
|
|
1893
|
-
var gunzipAsync2 = promisify22(gunzip2);
|
|
1894
|
-
function format2(rxl) {
|
|
1895
|
-
let result = "";
|
|
1896
|
-
if (rxl.registry) {
|
|
1897
|
-
result += rxl.registry + "/";
|
|
1898
|
-
}
|
|
1899
|
-
if (rxl.path) {
|
|
1900
|
-
result += rxl.path + "/";
|
|
1901
|
-
}
|
|
1902
|
-
result += rxl.name;
|
|
1903
|
-
if (rxl.tag && rxl.tag !== "latest") {
|
|
1904
|
-
result += ":" + rxl.tag;
|
|
1905
|
-
}
|
|
1906
|
-
return result;
|
|
1907
|
-
}
|
|
1908
|
-
function looksLikeRegistry2(str) {
|
|
1909
|
-
if (str.includes(":") && !str.includes("/")) {
|
|
1910
|
-
return true;
|
|
1911
|
-
}
|
|
1912
|
-
if (str.includes(".")) {
|
|
1913
|
-
return true;
|
|
1914
|
-
}
|
|
1915
|
-
if (str === "localhost") {
|
|
1916
|
-
return true;
|
|
1917
|
-
}
|
|
1918
|
-
return false;
|
|
1919
|
-
}
|
|
1920
|
-
function parse2(locator) {
|
|
1921
|
-
if (!locator || typeof locator !== "string") {
|
|
1922
|
-
throw new LocatorError2("Locator must be a non-empty string", locator);
|
|
1923
|
-
}
|
|
1924
|
-
if (locator.includes("@")) {
|
|
1925
|
-
throw new LocatorError2("Invalid locator format. Use name:tag instead of name@version", locator);
|
|
1926
|
-
}
|
|
1927
|
-
const lastSlashIndex = locator.lastIndexOf("/");
|
|
1928
|
-
let beforeSlash = "";
|
|
1929
|
-
let afterSlash = locator;
|
|
1930
|
-
if (lastSlashIndex !== -1) {
|
|
1931
|
-
beforeSlash = locator.substring(0, lastSlashIndex);
|
|
1932
|
-
afterSlash = locator.substring(lastSlashIndex + 1);
|
|
1933
|
-
}
|
|
1934
|
-
const colonIndex = afterSlash.lastIndexOf(":");
|
|
1935
|
-
let name;
|
|
1936
|
-
let tag;
|
|
1937
|
-
if (colonIndex === -1) {
|
|
1938
|
-
name = afterSlash;
|
|
1939
|
-
tag = "latest";
|
|
1940
|
-
} else {
|
|
1941
|
-
name = afterSlash.substring(0, colonIndex);
|
|
1942
|
-
tag = afterSlash.substring(colonIndex + 1);
|
|
1943
|
-
}
|
|
1944
|
-
if (!name) {
|
|
1945
|
-
throw new LocatorError2("Name is required", locator);
|
|
1946
|
-
}
|
|
1947
|
-
if (!tag) {
|
|
1948
|
-
throw new LocatorError2("Tag cannot be empty. Use name:tag format or omit tag for :latest", locator);
|
|
1949
|
-
}
|
|
1950
|
-
if (lastSlashIndex === -1) {
|
|
1951
|
-
return {
|
|
1952
|
-
registry: undefined,
|
|
1953
|
-
path: undefined,
|
|
1954
|
-
name,
|
|
1955
|
-
tag
|
|
1956
|
-
};
|
|
1957
|
-
}
|
|
1958
|
-
const parts = beforeSlash.split("/");
|
|
1959
|
-
if (looksLikeRegistry2(parts[0])) {
|
|
1960
|
-
const registry = parts[0];
|
|
1961
|
-
const path = parts.length > 1 ? parts.slice(1).join("/") : undefined;
|
|
1962
|
-
return {
|
|
1963
|
-
registry,
|
|
1964
|
-
path,
|
|
1965
|
-
name,
|
|
1966
|
-
tag
|
|
1967
|
-
};
|
|
1968
|
-
}
|
|
1969
|
-
return {
|
|
1970
|
-
registry: undefined,
|
|
1971
|
-
path: beforeSlash,
|
|
1972
|
-
name,
|
|
1973
|
-
tag
|
|
1974
|
-
};
|
|
1975
|
-
}
|
|
1976
|
-
|
|
1977
|
-
class RXAImpl22 {
|
|
1978
|
-
_buffer;
|
|
1979
|
-
constructor(buffer) {
|
|
1980
|
-
this._buffer = buffer;
|
|
1981
|
-
}
|
|
1982
|
-
get stream() {
|
|
1983
|
-
const buffer = this._buffer;
|
|
1984
|
-
return new ReadableStream({
|
|
1985
|
-
start(controller) {
|
|
1986
|
-
controller.enqueue(new Uint8Array(buffer));
|
|
1987
|
-
controller.close();
|
|
1988
|
-
}
|
|
1989
|
-
});
|
|
1990
|
-
}
|
|
1991
|
-
async buffer() {
|
|
1992
|
-
return this._buffer;
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
function wrap2(buffer) {
|
|
1996
|
-
return new RXAImpl22(buffer);
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
class RegistryError extends ResourceXError2 {
|
|
2000
|
-
constructor(message, options) {
|
|
2001
|
-
super(message, options);
|
|
2002
|
-
this.name = "RegistryError";
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
|
|
2006
|
-
class LocalRegistry {
|
|
2007
|
-
storage;
|
|
2008
|
-
constructor(storage) {
|
|
2009
|
-
this.storage = storage;
|
|
2010
|
-
}
|
|
2011
|
-
buildKeyPrefix(rxl) {
|
|
2012
|
-
const tag = rxl.tag ?? "latest";
|
|
2013
|
-
let key = rxl.name;
|
|
2014
|
-
if (rxl.path) {
|
|
2015
|
-
key = `${rxl.path}/${key}`;
|
|
2016
|
-
}
|
|
2017
|
-
key += `/${tag}`;
|
|
2018
|
-
return key;
|
|
2019
|
-
}
|
|
2020
|
-
async get(rxl) {
|
|
2021
|
-
const prefix = this.buildKeyPrefix(rxl);
|
|
2022
|
-
const manifestKey = `${prefix}/manifest.json`;
|
|
2023
|
-
const archiveKey = `${prefix}/archive.tar.gz`;
|
|
2024
|
-
let manifestData;
|
|
2025
|
-
try {
|
|
2026
|
-
manifestData = await this.storage.get(manifestKey);
|
|
2027
|
-
} catch {
|
|
2028
|
-
throw new RegistryError(`Resource not found: ${format2(rxl)}`);
|
|
2029
|
-
}
|
|
2030
|
-
const manifestJson = JSON.parse(manifestData.toString("utf-8"));
|
|
2031
|
-
const rxm = {
|
|
2032
|
-
registry: manifestJson.registry,
|
|
2033
|
-
path: manifestJson.path,
|
|
2034
|
-
name: manifestJson.name,
|
|
2035
|
-
type: manifestJson.type,
|
|
2036
|
-
tag: manifestJson.tag,
|
|
2037
|
-
files: manifestJson.files
|
|
2038
|
-
};
|
|
2039
|
-
const archiveData = await this.storage.get(archiveKey);
|
|
2040
|
-
const rxa = wrap2(archiveData);
|
|
2041
|
-
return resource2(rxm, rxa);
|
|
2042
|
-
}
|
|
2043
|
-
async put(rxr) {
|
|
2044
|
-
const prefix = this.buildKeyPrefix(rxr.locator);
|
|
2045
|
-
const manifestKey = `${prefix}/manifest.json`;
|
|
2046
|
-
const archiveKey = `${prefix}/archive.tar.gz`;
|
|
2047
|
-
const manifestJson = {
|
|
2048
|
-
registry: rxr.manifest.registry,
|
|
2049
|
-
path: rxr.manifest.path,
|
|
2050
|
-
name: rxr.manifest.name,
|
|
2051
|
-
type: rxr.manifest.type,
|
|
2052
|
-
tag: rxr.manifest.tag,
|
|
2053
|
-
files: rxr.manifest.files
|
|
2054
|
-
};
|
|
2055
|
-
const manifestData = Buffer.from(JSON.stringify(manifestJson, null, 2), "utf-8");
|
|
2056
|
-
await this.storage.put(manifestKey, manifestData);
|
|
2057
|
-
const archiveData = await rxr.archive.buffer();
|
|
2058
|
-
await this.storage.put(archiveKey, archiveData);
|
|
2059
|
-
}
|
|
2060
|
-
async has(rxl) {
|
|
2061
|
-
const prefix = this.buildKeyPrefix(rxl);
|
|
2062
|
-
const manifestKey = `${prefix}/manifest.json`;
|
|
2063
|
-
return this.storage.exists(manifestKey);
|
|
2064
|
-
}
|
|
2065
|
-
async remove(rxl) {
|
|
2066
|
-
const prefix = this.buildKeyPrefix(rxl);
|
|
2067
|
-
await this.storage.delete(prefix);
|
|
2068
|
-
}
|
|
2069
|
-
async list(options) {
|
|
2070
|
-
const { query, limit, offset = 0 } = options ?? {};
|
|
2071
|
-
const allKeys = await this.storage.list();
|
|
2072
|
-
const locators = [];
|
|
2073
|
-
for (const key of allKeys) {
|
|
2074
|
-
if (!key.endsWith("manifest.json"))
|
|
2075
|
-
continue;
|
|
2076
|
-
const rxl = this.parseKeyToRXL(key);
|
|
2077
|
-
if (rxl) {
|
|
2078
|
-
locators.push(rxl);
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
let filtered = locators;
|
|
2082
|
-
if (query) {
|
|
2083
|
-
const lowerQuery = query.toLowerCase();
|
|
2084
|
-
filtered = locators.filter((rxl) => {
|
|
2085
|
-
const searchText = `${rxl.path ?? ""} ${rxl.name}`.toLowerCase();
|
|
2086
|
-
return searchText.includes(lowerQuery);
|
|
2087
|
-
});
|
|
2088
|
-
}
|
|
2089
|
-
let result = filtered.slice(offset);
|
|
2090
|
-
if (limit !== undefined) {
|
|
2091
|
-
result = result.slice(0, limit);
|
|
2092
|
-
}
|
|
2093
|
-
return result;
|
|
2094
|
-
}
|
|
2095
|
-
parseKeyToRXL(key) {
|
|
2096
|
-
const dirPath = key.replace(/\/manifest\.json$/, "");
|
|
2097
|
-
const parts = dirPath.split("/");
|
|
2098
|
-
if (parts.length < 2) {
|
|
2099
|
-
return null;
|
|
2100
|
-
}
|
|
2101
|
-
const tag = parts.pop();
|
|
2102
|
-
const name = parts.pop();
|
|
2103
|
-
const path = parts.length > 0 ? parts.join("/") : undefined;
|
|
2104
|
-
let locatorStr = "";
|
|
2105
|
-
if (path)
|
|
2106
|
-
locatorStr += `${path}/`;
|
|
2107
|
-
locatorStr += name;
|
|
2108
|
-
if (tag !== "latest")
|
|
2109
|
-
locatorStr += `:${tag}`;
|
|
2110
|
-
try {
|
|
2111
|
-
return parse2(locatorStr);
|
|
2112
|
-
} catch {
|
|
2113
|
-
return null;
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
|
-
class MirrorRegistry {
|
|
2119
|
-
storage;
|
|
2120
|
-
constructor(storage) {
|
|
2121
|
-
this.storage = storage;
|
|
2122
|
-
}
|
|
2123
|
-
buildKeyPrefix(rxl) {
|
|
2124
|
-
const registry = rxl.registry ?? "localhost";
|
|
2125
|
-
const tag = rxl.tag ?? "latest";
|
|
2126
|
-
let key = registry;
|
|
2127
|
-
if (rxl.path) {
|
|
2128
|
-
key += `/${rxl.path}`;
|
|
2129
|
-
}
|
|
2130
|
-
key += `/${rxl.name}/${tag}`;
|
|
2131
|
-
return key;
|
|
2132
|
-
}
|
|
2133
|
-
async get(rxl) {
|
|
2134
|
-
const prefix = this.buildKeyPrefix(rxl);
|
|
2135
|
-
const manifestKey = `${prefix}/manifest.json`;
|
|
2136
|
-
const archiveKey = `${prefix}/archive.tar.gz`;
|
|
2137
|
-
let manifestData;
|
|
2138
|
-
try {
|
|
2139
|
-
manifestData = await this.storage.get(manifestKey);
|
|
2140
|
-
} catch {
|
|
2141
|
-
throw new RegistryError(`Resource not found in cache: ${format2(rxl)}`);
|
|
2142
|
-
}
|
|
2143
|
-
const manifestJson = JSON.parse(manifestData.toString("utf-8"));
|
|
2144
|
-
const rxm = {
|
|
2145
|
-
registry: manifestJson.registry,
|
|
2146
|
-
path: manifestJson.path,
|
|
2147
|
-
name: manifestJson.name,
|
|
2148
|
-
type: manifestJson.type,
|
|
2149
|
-
tag: manifestJson.tag,
|
|
2150
|
-
files: manifestJson.files
|
|
2151
|
-
};
|
|
2152
|
-
const archiveData = await this.storage.get(archiveKey);
|
|
2153
|
-
const rxa = wrap2(archiveData);
|
|
2154
|
-
return resource2(rxm, rxa);
|
|
2155
|
-
}
|
|
2156
|
-
async put(rxr) {
|
|
2157
|
-
const prefix = this.buildKeyPrefix(rxr.locator);
|
|
2158
|
-
const manifestKey = `${prefix}/manifest.json`;
|
|
2159
|
-
const archiveKey = `${prefix}/archive.tar.gz`;
|
|
2160
|
-
const manifestJson = {
|
|
2161
|
-
registry: rxr.manifest.registry,
|
|
2162
|
-
path: rxr.manifest.path,
|
|
2163
|
-
name: rxr.manifest.name,
|
|
2164
|
-
type: rxr.manifest.type,
|
|
2165
|
-
tag: rxr.manifest.tag,
|
|
2166
|
-
files: rxr.manifest.files
|
|
2167
|
-
};
|
|
2168
|
-
const manifestData = Buffer.from(JSON.stringify(manifestJson, null, 2), "utf-8");
|
|
2169
|
-
await this.storage.put(manifestKey, manifestData);
|
|
2170
|
-
const archiveData = await rxr.archive.buffer();
|
|
2171
|
-
await this.storage.put(archiveKey, archiveData);
|
|
2172
|
-
}
|
|
2173
|
-
async has(rxl) {
|
|
2174
|
-
const prefix = this.buildKeyPrefix(rxl);
|
|
2175
|
-
const manifestKey = `${prefix}/manifest.json`;
|
|
2176
|
-
return this.storage.exists(manifestKey);
|
|
2177
|
-
}
|
|
2178
|
-
async remove(rxl) {
|
|
2179
|
-
const prefix = this.buildKeyPrefix(rxl);
|
|
2180
|
-
await this.storage.delete(prefix);
|
|
2181
|
-
}
|
|
2182
|
-
async list(options) {
|
|
2183
|
-
const { query, limit, offset = 0 } = options ?? {};
|
|
2184
|
-
const allKeys = await this.storage.list();
|
|
2185
|
-
const locators = [];
|
|
2186
|
-
for (const key of allKeys) {
|
|
2187
|
-
if (!key.endsWith("manifest.json"))
|
|
2188
|
-
continue;
|
|
2189
|
-
const rxl = this.parseKeyToRXL(key);
|
|
2190
|
-
if (rxl) {
|
|
2191
|
-
locators.push(rxl);
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
let filtered = locators;
|
|
2195
|
-
if (query) {
|
|
2196
|
-
const lowerQuery = query.toLowerCase();
|
|
2197
|
-
filtered = locators.filter((rxl) => {
|
|
2198
|
-
const searchText = `${rxl.registry ?? ""} ${rxl.path ?? ""} ${rxl.name}`.toLowerCase();
|
|
2199
|
-
return searchText.includes(lowerQuery);
|
|
2200
|
-
});
|
|
2201
|
-
}
|
|
2202
|
-
let result = filtered.slice(offset);
|
|
2203
|
-
if (limit !== undefined) {
|
|
2204
|
-
result = result.slice(0, limit);
|
|
2205
|
-
}
|
|
2206
|
-
return result;
|
|
2207
|
-
}
|
|
2208
|
-
async clear(registry) {
|
|
2209
|
-
if (registry) {
|
|
2210
|
-
await this.storage.delete(registry);
|
|
2211
|
-
} else {
|
|
2212
|
-
const allKeys = await this.storage.list();
|
|
2213
|
-
const registries = new Set;
|
|
2214
|
-
for (const key of allKeys) {
|
|
2215
|
-
const firstSlash = key.indexOf("/");
|
|
2216
|
-
if (firstSlash !== -1) {
|
|
2217
|
-
registries.add(key.substring(0, firstSlash));
|
|
2218
|
-
} else {
|
|
2219
|
-
registries.add(key);
|
|
2220
|
-
}
|
|
2221
|
-
}
|
|
2222
|
-
for (const r of registries) {
|
|
2223
|
-
await this.storage.delete(r);
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
}
|
|
2227
|
-
parseKeyToRXL(key) {
|
|
2228
|
-
const dirPath = key.replace(/\/manifest\.json$/, "");
|
|
2229
|
-
const parts = dirPath.split("/");
|
|
2230
|
-
if (parts.length < 3) {
|
|
2231
|
-
return null;
|
|
2232
|
-
}
|
|
2233
|
-
const tag = parts.pop();
|
|
2234
|
-
const name = parts.pop();
|
|
2235
|
-
const registry = parts.shift();
|
|
2236
|
-
const path = parts.length > 0 ? parts.join("/") : undefined;
|
|
2237
|
-
let locatorStr = registry;
|
|
2238
|
-
if (path)
|
|
2239
|
-
locatorStr += `/${path}`;
|
|
2240
|
-
locatorStr += `/${name}`;
|
|
2241
|
-
if (tag !== "latest")
|
|
2242
|
-
locatorStr += `:${tag}`;
|
|
2243
|
-
try {
|
|
2244
|
-
return parse2(locatorStr);
|
|
2245
|
-
} catch {
|
|
2246
|
-
return null;
|
|
2247
|
-
}
|
|
2248
|
-
}
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
class ResourceXError22 extends Error {
|
|
2252
|
-
constructor(message, options) {
|
|
2253
|
-
super(message, options);
|
|
2254
|
-
this.name = "ResourceXError";
|
|
2255
|
-
}
|
|
2256
|
-
}
|
|
2257
|
-
|
|
2258
|
-
class DefinitionError2 extends ResourceXError22 {
|
|
2259
|
-
constructor(message) {
|
|
2260
|
-
super(message);
|
|
2261
|
-
this.name = "DefinitionError";
|
|
2262
|
-
}
|
|
2263
|
-
}
|
|
2264
|
-
function define2(input) {
|
|
2265
|
-
if (input === null || typeof input !== "object") {
|
|
2266
|
-
throw new DefinitionError2("definition must be an object");
|
|
2267
|
-
}
|
|
2268
|
-
const obj = input;
|
|
2269
|
-
if (!obj.name || typeof obj.name !== "string") {
|
|
2270
|
-
throw new DefinitionError2("name is required");
|
|
2271
|
-
}
|
|
2272
|
-
if (!obj.type || typeof obj.type !== "string") {
|
|
2273
|
-
throw new DefinitionError2("type is required");
|
|
2274
|
-
}
|
|
2275
|
-
const tagValue = obj.tag ?? obj.version;
|
|
2276
|
-
if (tagValue !== undefined && typeof tagValue !== "string") {
|
|
2277
|
-
throw new DefinitionError2("tag must be a string");
|
|
2278
|
-
}
|
|
2279
|
-
const rxd = {
|
|
2280
|
-
...obj,
|
|
2281
|
-
name: obj.name,
|
|
2282
|
-
type: obj.type,
|
|
2283
|
-
tag: typeof tagValue === "string" ? tagValue : undefined,
|
|
2284
|
-
registry: typeof obj.registry === "string" ? obj.registry : undefined,
|
|
2285
|
-
path: typeof obj.path === "string" ? obj.path : undefined,
|
|
2286
|
-
description: typeof obj.description === "string" ? obj.description : undefined,
|
|
2287
|
-
author: typeof obj.author === "string" ? obj.author : undefined,
|
|
2288
|
-
license: typeof obj.license === "string" ? obj.license : undefined,
|
|
2289
|
-
keywords: Array.isArray(obj.keywords) ? obj.keywords : undefined,
|
|
2290
|
-
repository: typeof obj.repository === "string" ? obj.repository : undefined
|
|
2291
|
-
};
|
|
2292
|
-
return rxd;
|
|
2293
|
-
}
|
|
2294
|
-
function manifest2(rxd) {
|
|
2295
|
-
return {
|
|
2296
|
-
registry: rxd.registry,
|
|
2297
|
-
path: rxd.path,
|
|
2298
|
-
name: rxd.name,
|
|
2299
|
-
type: rxd.type,
|
|
2300
|
-
tag: rxd.tag ?? "latest"
|
|
2301
|
-
};
|
|
2302
|
-
}
|
|
2303
|
-
var BLOCK_SIZE22 = 512;
|
|
2304
|
-
var BLOCK_SIZE_MASK2 = 511;
|
|
2305
|
-
var DEFAULT_FILE_MODE2 = 420;
|
|
2306
|
-
var DEFAULT_DIR_MODE2 = 493;
|
|
2307
|
-
var USTAR_NAME_OFFSET2 = 0;
|
|
2308
|
-
var USTAR_NAME_SIZE2 = 100;
|
|
2309
|
-
var USTAR_MODE_OFFSET2 = 100;
|
|
2310
|
-
var USTAR_MODE_SIZE2 = 8;
|
|
2311
|
-
var USTAR_UID_OFFSET2 = 108;
|
|
2312
|
-
var USTAR_UID_SIZE2 = 8;
|
|
2313
|
-
var USTAR_GID_OFFSET2 = 116;
|
|
2314
|
-
var USTAR_GID_SIZE2 = 8;
|
|
2315
|
-
var USTAR_SIZE_OFFSET2 = 124;
|
|
2316
|
-
var USTAR_SIZE_SIZE2 = 12;
|
|
2317
|
-
var USTAR_MTIME_OFFSET2 = 136;
|
|
2318
|
-
var USTAR_MTIME_SIZE2 = 12;
|
|
2319
|
-
var USTAR_CHECKSUM_OFFSET2 = 148;
|
|
2320
|
-
var USTAR_CHECKSUM_SIZE2 = 8;
|
|
2321
|
-
var USTAR_TYPEFLAG_OFFSET2 = 156;
|
|
2322
|
-
var USTAR_TYPEFLAG_SIZE2 = 1;
|
|
2323
|
-
var USTAR_LINKNAME_OFFSET2 = 157;
|
|
2324
|
-
var USTAR_LINKNAME_SIZE2 = 100;
|
|
2325
|
-
var USTAR_MAGIC_OFFSET2 = 257;
|
|
2326
|
-
var USTAR_MAGIC_SIZE2 = 6;
|
|
2327
|
-
var USTAR_VERSION_OFFSET2 = 263;
|
|
2328
|
-
var USTAR_VERSION_SIZE2 = 2;
|
|
2329
|
-
var USTAR_UNAME_OFFSET2 = 265;
|
|
2330
|
-
var USTAR_UNAME_SIZE2 = 32;
|
|
2331
|
-
var USTAR_GNAME_OFFSET2 = 297;
|
|
2332
|
-
var USTAR_GNAME_SIZE2 = 32;
|
|
2333
|
-
var USTAR_PREFIX_OFFSET2 = 345;
|
|
2334
|
-
var USTAR_PREFIX_SIZE2 = 155;
|
|
2335
|
-
var USTAR_VERSION2 = "00";
|
|
2336
|
-
var USTAR_MAX_UID_GID2 = 2097151;
|
|
2337
|
-
var USTAR_MAX_SIZE2 = 8589934591;
|
|
2338
|
-
var FILE2 = "file";
|
|
2339
|
-
var LINK2 = "link";
|
|
2340
|
-
var SYMLINK2 = "symlink";
|
|
2341
|
-
var DIRECTORY2 = "directory";
|
|
2342
|
-
var TYPEFLAG2 = {
|
|
2343
|
-
file: "0",
|
|
2344
|
-
link: "1",
|
|
2345
|
-
symlink: "2",
|
|
2346
|
-
"character-device": "3",
|
|
2347
|
-
"block-device": "4",
|
|
2348
|
-
directory: "5",
|
|
2349
|
-
fifo: "6",
|
|
2350
|
-
"pax-header": "x",
|
|
2351
|
-
"pax-global-header": "g",
|
|
2352
|
-
"gnu-long-name": "L",
|
|
2353
|
-
"gnu-long-link-name": "K"
|
|
2354
|
-
};
|
|
2355
|
-
var ZERO_BLOCK22 = new Uint8Array(BLOCK_SIZE22);
|
|
2356
|
-
var EMPTY22 = new Uint8Array(0);
|
|
2357
|
-
var encoder22 = new TextEncoder;
|
|
2358
|
-
var decoder22 = new TextDecoder;
|
|
2359
|
-
function writeString2(view, offset, size, value) {
|
|
2360
|
-
if (value)
|
|
2361
|
-
encoder22.encodeInto(value, view.subarray(offset, offset + size));
|
|
2362
|
-
}
|
|
2363
|
-
function writeOctal2(view, offset, size, value) {
|
|
2364
|
-
if (value === undefined)
|
|
2365
|
-
return;
|
|
2366
|
-
const octalString = value.toString(8).padStart(size - 1, "0");
|
|
2367
|
-
encoder22.encodeInto(octalString, view.subarray(offset, offset + size - 1));
|
|
2368
|
-
}
|
|
2369
|
-
var isBodyless2 = (header) => header.type === DIRECTORY2 || header.type === SYMLINK2 || header.type === LINK2;
|
|
2370
|
-
async function normalizeBody2(body) {
|
|
2371
|
-
if (body === null || body === undefined)
|
|
2372
|
-
return EMPTY22;
|
|
2373
|
-
if (body instanceof Uint8Array)
|
|
2374
|
-
return body;
|
|
2375
|
-
if (typeof body === "string")
|
|
2376
|
-
return encoder22.encode(body);
|
|
2377
|
-
if (body instanceof ArrayBuffer)
|
|
2378
|
-
return new Uint8Array(body);
|
|
2379
|
-
if (body instanceof Blob)
|
|
2380
|
-
return new Uint8Array(await body.arrayBuffer());
|
|
2381
|
-
throw new TypeError("Unsupported content type for entry body.");
|
|
2382
|
-
}
|
|
2383
|
-
var CHECKSUM_SPACE2 = 32;
|
|
2384
|
-
var ASCII_ZERO2 = 48;
|
|
2385
|
-
function writeChecksum2(block) {
|
|
2386
|
-
block.fill(CHECKSUM_SPACE2, USTAR_CHECKSUM_OFFSET2, USTAR_CHECKSUM_OFFSET2 + USTAR_CHECKSUM_SIZE2);
|
|
2387
|
-
let checksum = 0;
|
|
2388
|
-
for (const byte of block)
|
|
2389
|
-
checksum += byte;
|
|
2390
|
-
for (let i = USTAR_CHECKSUM_OFFSET2 + 6 - 1;i >= USTAR_CHECKSUM_OFFSET2; i--) {
|
|
2391
|
-
block[i] = (checksum & 7) + ASCII_ZERO2;
|
|
2392
|
-
checksum >>= 3;
|
|
2393
|
-
}
|
|
2394
|
-
block[USTAR_CHECKSUM_OFFSET2 + 6] = 0;
|
|
2395
|
-
block[USTAR_CHECKSUM_OFFSET2 + 7] = CHECKSUM_SPACE2;
|
|
2396
|
-
}
|
|
2397
|
-
function generatePax2(header) {
|
|
2398
|
-
const paxRecords = {};
|
|
2399
|
-
if (header.name.length > USTAR_NAME_SIZE2) {
|
|
2400
|
-
if (findUstarSplit2(header.name) === null)
|
|
2401
|
-
paxRecords.path = header.name;
|
|
2402
|
-
}
|
|
2403
|
-
if (header.linkname && header.linkname.length > USTAR_NAME_SIZE2)
|
|
2404
|
-
paxRecords.linkpath = header.linkname;
|
|
2405
|
-
if (header.uname && header.uname.length > USTAR_UNAME_SIZE2)
|
|
2406
|
-
paxRecords.uname = header.uname;
|
|
2407
|
-
if (header.gname && header.gname.length > USTAR_GNAME_SIZE2)
|
|
2408
|
-
paxRecords.gname = header.gname;
|
|
2409
|
-
if (header.uid != null && header.uid > USTAR_MAX_UID_GID2)
|
|
2410
|
-
paxRecords.uid = String(header.uid);
|
|
2411
|
-
if (header.gid != null && header.gid > USTAR_MAX_UID_GID2)
|
|
2412
|
-
paxRecords.gid = String(header.gid);
|
|
2413
|
-
if (header.size != null && header.size > USTAR_MAX_SIZE2)
|
|
2414
|
-
paxRecords.size = String(header.size);
|
|
2415
|
-
if (header.pax)
|
|
2416
|
-
Object.assign(paxRecords, header.pax);
|
|
2417
|
-
const paxEntries = Object.entries(paxRecords);
|
|
2418
|
-
if (paxEntries.length === 0)
|
|
2419
|
-
return null;
|
|
2420
|
-
const paxBody = encoder22.encode(paxEntries.map(([key, value]) => {
|
|
2421
|
-
const record = `${key}=${value}
|
|
2422
|
-
`;
|
|
2423
|
-
const partLength = encoder22.encode(record).length + 1;
|
|
2424
|
-
let totalLength = partLength + String(partLength).length;
|
|
2425
|
-
totalLength = partLength + String(totalLength).length;
|
|
2426
|
-
return `${totalLength} ${record}`;
|
|
2427
|
-
}).join(""));
|
|
2428
|
-
return {
|
|
2429
|
-
paxHeader: createTarHeader2({
|
|
2430
|
-
name: decoder22.decode(encoder22.encode(`PaxHeader/${header.name}`).slice(0, 100)),
|
|
2431
|
-
size: paxBody.length,
|
|
2432
|
-
type: "pax-header",
|
|
2433
|
-
mode: 420,
|
|
2434
|
-
mtime: header.mtime,
|
|
2435
|
-
uname: header.uname,
|
|
2436
|
-
gname: header.gname,
|
|
2437
|
-
uid: header.uid,
|
|
2438
|
-
gid: header.gid
|
|
2439
|
-
}),
|
|
2440
|
-
paxBody
|
|
2441
|
-
};
|
|
2442
|
-
}
|
|
2443
|
-
function findUstarSplit2(path) {
|
|
2444
|
-
if (path.length <= USTAR_NAME_SIZE2)
|
|
2445
|
-
return null;
|
|
2446
|
-
const minSlashIndex = path.length - USTAR_NAME_SIZE2 - 1;
|
|
2447
|
-
const slashIndex = path.lastIndexOf("/", USTAR_PREFIX_SIZE2);
|
|
2448
|
-
if (slashIndex > 0 && slashIndex >= minSlashIndex)
|
|
2449
|
-
return {
|
|
2450
|
-
prefix: path.slice(0, slashIndex),
|
|
2451
|
-
name: path.slice(slashIndex + 1)
|
|
2452
|
-
};
|
|
2453
|
-
return null;
|
|
2454
|
-
}
|
|
2455
|
-
function createTarHeader2(header) {
|
|
2456
|
-
const view = new Uint8Array(BLOCK_SIZE22);
|
|
2457
|
-
const size = isBodyless2(header) ? 0 : header.size ?? 0;
|
|
2458
|
-
let name = header.name;
|
|
2459
|
-
let prefix = "";
|
|
2460
|
-
if (!header.pax?.path) {
|
|
2461
|
-
const split = findUstarSplit2(name);
|
|
2462
|
-
if (split) {
|
|
2463
|
-
name = split.name;
|
|
2464
|
-
prefix = split.prefix;
|
|
2465
|
-
}
|
|
2466
|
-
}
|
|
2467
|
-
writeString2(view, USTAR_NAME_OFFSET2, USTAR_NAME_SIZE2, name);
|
|
2468
|
-
writeOctal2(view, USTAR_MODE_OFFSET2, USTAR_MODE_SIZE2, header.mode ?? (header.type === DIRECTORY2 ? DEFAULT_DIR_MODE2 : DEFAULT_FILE_MODE2));
|
|
2469
|
-
writeOctal2(view, USTAR_UID_OFFSET2, USTAR_UID_SIZE2, header.uid ?? 0);
|
|
2470
|
-
writeOctal2(view, USTAR_GID_OFFSET2, USTAR_GID_SIZE2, header.gid ?? 0);
|
|
2471
|
-
writeOctal2(view, USTAR_SIZE_OFFSET2, USTAR_SIZE_SIZE2, size);
|
|
2472
|
-
writeOctal2(view, USTAR_MTIME_OFFSET2, USTAR_MTIME_SIZE2, Math.floor((header.mtime?.getTime() ?? Date.now()) / 1000));
|
|
2473
|
-
writeString2(view, USTAR_TYPEFLAG_OFFSET2, USTAR_TYPEFLAG_SIZE2, TYPEFLAG2[header.type ?? FILE2]);
|
|
2474
|
-
writeString2(view, USTAR_LINKNAME_OFFSET2, USTAR_LINKNAME_SIZE2, header.linkname);
|
|
2475
|
-
writeString2(view, USTAR_MAGIC_OFFSET2, USTAR_MAGIC_SIZE2, "ustar\x00");
|
|
2476
|
-
writeString2(view, USTAR_VERSION_OFFSET2, USTAR_VERSION_SIZE2, USTAR_VERSION2);
|
|
2477
|
-
writeString2(view, USTAR_UNAME_OFFSET2, USTAR_UNAME_SIZE2, header.uname);
|
|
2478
|
-
writeString2(view, USTAR_GNAME_OFFSET2, USTAR_GNAME_SIZE2, header.gname);
|
|
2479
|
-
writeString2(view, USTAR_PREFIX_OFFSET2, USTAR_PREFIX_SIZE2, prefix);
|
|
2480
|
-
writeChecksum2(view);
|
|
2481
|
-
return view;
|
|
2482
|
-
}
|
|
2483
|
-
function getHeaderBlocks2(header) {
|
|
2484
|
-
const base = createTarHeader2(header);
|
|
2485
|
-
const pax = generatePax2(header);
|
|
2486
|
-
if (!pax)
|
|
2487
|
-
return [base];
|
|
2488
|
-
const paxPadding = -pax.paxBody.length & BLOCK_SIZE_MASK2;
|
|
2489
|
-
const paddingBlocks = paxPadding > 0 ? [ZERO_BLOCK22.subarray(0, paxPadding)] : [];
|
|
2490
|
-
return [
|
|
2491
|
-
pax.paxHeader,
|
|
2492
|
-
pax.paxBody,
|
|
2493
|
-
...paddingBlocks,
|
|
2494
|
-
base
|
|
2495
|
-
];
|
|
2496
|
-
}
|
|
2497
|
-
var EOF_BUFFER22 = new Uint8Array(BLOCK_SIZE22 * 2);
|
|
2498
|
-
function createTarPacker3(onData, onError, onFinalize) {
|
|
2499
|
-
let currentHeader = null;
|
|
2500
|
-
let bytesWritten = 0;
|
|
2501
|
-
let finalized = false;
|
|
2502
|
-
return {
|
|
2503
|
-
add(header) {
|
|
2504
|
-
if (finalized) {
|
|
2505
|
-
const error = /* @__PURE__ */ new Error("No new tar entries after finalize.");
|
|
2506
|
-
onError(error);
|
|
2507
|
-
throw error;
|
|
2508
|
-
}
|
|
2509
|
-
if (currentHeader !== null) {
|
|
2510
|
-
const error = /* @__PURE__ */ new Error("Previous entry must be completed before adding a new one");
|
|
2511
|
-
onError(error);
|
|
2512
|
-
throw error;
|
|
2513
|
-
}
|
|
2514
|
-
try {
|
|
2515
|
-
const size = isBodyless2(header) ? 0 : header.size ?? 0;
|
|
2516
|
-
const headerBlocks = getHeaderBlocks2({
|
|
2517
|
-
...header,
|
|
2518
|
-
size
|
|
2519
|
-
});
|
|
2520
|
-
for (const block of headerBlocks)
|
|
2521
|
-
onData(block);
|
|
2522
|
-
currentHeader = {
|
|
2523
|
-
...header,
|
|
2524
|
-
size
|
|
2525
|
-
};
|
|
2526
|
-
bytesWritten = 0;
|
|
2527
|
-
} catch (error) {
|
|
2528
|
-
onError(error);
|
|
2529
|
-
}
|
|
2530
|
-
},
|
|
2531
|
-
write(chunk) {
|
|
2532
|
-
if (!currentHeader) {
|
|
2533
|
-
const error = /* @__PURE__ */ new Error("No active tar entry.");
|
|
2534
|
-
onError(error);
|
|
2535
|
-
throw error;
|
|
2536
|
-
}
|
|
2537
|
-
if (finalized) {
|
|
2538
|
-
const error = /* @__PURE__ */ new Error("Cannot write data after finalize.");
|
|
2539
|
-
onError(error);
|
|
2540
|
-
throw error;
|
|
2541
|
-
}
|
|
2542
|
-
const newTotal = bytesWritten + chunk.length;
|
|
2543
|
-
if (newTotal > currentHeader.size) {
|
|
2544
|
-
const error = /* @__PURE__ */ new Error(`"${currentHeader.name}" exceeds given size of ${currentHeader.size} bytes.`);
|
|
2545
|
-
onError(error);
|
|
2546
|
-
throw error;
|
|
2547
|
-
}
|
|
2548
|
-
try {
|
|
2549
|
-
bytesWritten = newTotal;
|
|
2550
|
-
onData(chunk);
|
|
2551
|
-
} catch (error) {
|
|
2552
|
-
onError(error);
|
|
2553
|
-
}
|
|
2554
|
-
},
|
|
2555
|
-
endEntry() {
|
|
2556
|
-
if (!currentHeader) {
|
|
2557
|
-
const error = /* @__PURE__ */ new Error("No active entry to end.");
|
|
2558
|
-
onError(error);
|
|
2559
|
-
throw error;
|
|
2560
|
-
}
|
|
2561
|
-
if (finalized) {
|
|
2562
|
-
const error = /* @__PURE__ */ new Error("Cannot end entry after finalize.");
|
|
2563
|
-
onError(error);
|
|
2564
|
-
throw error;
|
|
2565
|
-
}
|
|
2566
|
-
try {
|
|
2567
|
-
if (bytesWritten !== currentHeader.size) {
|
|
2568
|
-
const error = /* @__PURE__ */ new Error(`Size mismatch for "${currentHeader.name}".`);
|
|
2569
|
-
onError(error);
|
|
2570
|
-
throw error;
|
|
2571
|
-
}
|
|
2572
|
-
const paddingSize = -currentHeader.size & BLOCK_SIZE_MASK2;
|
|
2573
|
-
if (paddingSize > 0)
|
|
2574
|
-
onData(new Uint8Array(paddingSize));
|
|
2575
|
-
currentHeader = null;
|
|
2576
|
-
bytesWritten = 0;
|
|
2577
|
-
} catch (error) {
|
|
2578
|
-
onError(error);
|
|
2579
|
-
throw error;
|
|
2580
|
-
}
|
|
2581
|
-
},
|
|
2582
|
-
finalize() {
|
|
2583
|
-
if (finalized) {
|
|
2584
|
-
const error = /* @__PURE__ */ new Error("Archive has already been finalized");
|
|
2585
|
-
onError(error);
|
|
2586
|
-
throw error;
|
|
2587
|
-
}
|
|
2588
|
-
if (currentHeader !== null) {
|
|
2589
|
-
const error = /* @__PURE__ */ new Error("Cannot finalize while an entry is still active");
|
|
2590
|
-
onError(error);
|
|
2591
|
-
throw error;
|
|
2592
|
-
}
|
|
2593
|
-
try {
|
|
2594
|
-
onData(EOF_BUFFER22);
|
|
2595
|
-
finalized = true;
|
|
2596
|
-
if (onFinalize)
|
|
2597
|
-
onFinalize();
|
|
2598
|
-
} catch (error) {
|
|
2599
|
-
onError(error);
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
};
|
|
2603
|
-
}
|
|
2604
|
-
function createTarPacker22() {
|
|
2605
|
-
let streamController;
|
|
2606
|
-
let packer;
|
|
2607
|
-
return {
|
|
2608
|
-
readable: new ReadableStream({ start(controller) {
|
|
2609
|
-
streamController = controller;
|
|
2610
|
-
packer = createTarPacker3(controller.enqueue.bind(controller), controller.error.bind(controller), controller.close.bind(controller));
|
|
2611
|
-
} }),
|
|
2612
|
-
controller: {
|
|
2613
|
-
add(header) {
|
|
2614
|
-
const bodyless = isBodyless2(header);
|
|
2615
|
-
const h = { ...header };
|
|
2616
|
-
if (bodyless)
|
|
2617
|
-
h.size = 0;
|
|
2618
|
-
packer.add(h);
|
|
2619
|
-
if (bodyless)
|
|
2620
|
-
packer.endEntry();
|
|
2621
|
-
return new WritableStream({
|
|
2622
|
-
write(chunk) {
|
|
2623
|
-
packer.write(chunk);
|
|
2624
|
-
},
|
|
2625
|
-
close() {
|
|
2626
|
-
if (!bodyless)
|
|
2627
|
-
packer.endEntry();
|
|
2628
|
-
},
|
|
2629
|
-
abort(reason) {
|
|
2630
|
-
streamController.error(reason);
|
|
2631
|
-
}
|
|
2632
|
-
});
|
|
2633
|
-
},
|
|
2634
|
-
finalize() {
|
|
2635
|
-
packer.finalize();
|
|
2636
|
-
},
|
|
2637
|
-
error(err) {
|
|
2638
|
-
streamController.error(err);
|
|
2639
|
-
}
|
|
2640
|
-
}
|
|
2641
|
-
};
|
|
2642
|
-
}
|
|
2643
|
-
async function streamToBuffer2(stream) {
|
|
2644
|
-
const chunks = [];
|
|
2645
|
-
const reader = stream.getReader();
|
|
2646
|
-
let totalLength = 0;
|
|
2647
|
-
try {
|
|
2648
|
-
while (true) {
|
|
2649
|
-
const { done, value } = await reader.read();
|
|
2650
|
-
if (done)
|
|
2651
|
-
break;
|
|
2652
|
-
chunks.push(value);
|
|
2653
|
-
totalLength += value.length;
|
|
2654
|
-
}
|
|
2655
|
-
const result = new Uint8Array(totalLength);
|
|
2656
|
-
let offset = 0;
|
|
2657
|
-
for (const chunk of chunks) {
|
|
2658
|
-
result.set(chunk, offset);
|
|
2659
|
-
offset += chunk.length;
|
|
2660
|
-
}
|
|
2661
|
-
return result;
|
|
2662
|
-
} finally {
|
|
2663
|
-
reader.releaseLock();
|
|
2664
|
-
}
|
|
2665
|
-
}
|
|
2666
|
-
async function packTar2(entries) {
|
|
2667
|
-
const { readable, controller } = createTarPacker22();
|
|
2668
|
-
await (async () => {
|
|
2669
|
-
for (const entry of entries) {
|
|
2670
|
-
const entryStream = controller.add(entry.header);
|
|
2671
|
-
const body = "body" in entry ? entry.body : entry.data;
|
|
2672
|
-
if (!body) {
|
|
2673
|
-
await entryStream.close();
|
|
2674
|
-
continue;
|
|
2675
|
-
}
|
|
2676
|
-
if (body instanceof ReadableStream)
|
|
2677
|
-
await body.pipeTo(entryStream);
|
|
2678
|
-
else if (body instanceof Blob)
|
|
2679
|
-
await body.stream().pipeTo(entryStream);
|
|
2680
|
-
else
|
|
2681
|
-
try {
|
|
2682
|
-
const chunk = await normalizeBody2(body);
|
|
2683
|
-
if (chunk.length > 0) {
|
|
2684
|
-
const writer = entryStream.getWriter();
|
|
2685
|
-
await writer.write(chunk);
|
|
2686
|
-
await writer.close();
|
|
2687
|
-
} else
|
|
2688
|
-
await entryStream.close();
|
|
2689
|
-
} catch {
|
|
2690
|
-
throw new TypeError(`Unsupported content type for entry "${entry.header.name}".`);
|
|
2691
|
-
}
|
|
2692
|
-
}
|
|
2693
|
-
})().then(() => controller.finalize()).catch((err) => controller.error(err));
|
|
2694
|
-
return new Uint8Array(await streamToBuffer2(readable));
|
|
2695
|
-
}
|
|
2696
|
-
var gzipAsync22 = promisify32(gzip22);
|
|
2697
|
-
|
|
2698
|
-
class RXAImpl3 {
|
|
2699
|
-
_buffer;
|
|
2700
|
-
constructor(buffer) {
|
|
2701
|
-
this._buffer = buffer;
|
|
2702
|
-
}
|
|
2703
|
-
get stream() {
|
|
2704
|
-
const buffer = this._buffer;
|
|
2705
|
-
return new ReadableStream({
|
|
2706
|
-
start(controller) {
|
|
2707
|
-
controller.enqueue(new Uint8Array(buffer));
|
|
2708
|
-
controller.close();
|
|
2709
|
-
}
|
|
2710
|
-
});
|
|
2711
|
-
}
|
|
2712
|
-
async buffer() {
|
|
2713
|
-
return this._buffer;
|
|
2714
|
-
}
|
|
2715
|
-
}
|
|
2716
|
-
async function archive2(files) {
|
|
2717
|
-
const entries = Object.entries(files).map(([name, content]) => {
|
|
2718
|
-
return {
|
|
2719
|
-
header: { name, size: content.length, type: "file" },
|
|
2720
|
-
body: new Uint8Array(content)
|
|
2721
|
-
};
|
|
2722
|
-
});
|
|
2723
|
-
const tarBuffer = await packTar2(entries);
|
|
2724
|
-
const gzipBuffer = await gzipAsync22(Buffer.from(tarBuffer));
|
|
2725
|
-
return new RXAImpl3(gzipBuffer);
|
|
2726
|
-
}
|
|
2727
|
-
function locate22(rxm) {
|
|
2728
|
-
return {
|
|
2729
|
-
registry: rxm.registry,
|
|
2730
|
-
path: rxm.path,
|
|
2731
|
-
name: rxm.name,
|
|
2732
|
-
tag: rxm.tag
|
|
2733
|
-
};
|
|
2734
|
-
}
|
|
2735
|
-
function resource22(rxm, rxa) {
|
|
2736
|
-
const rxl = locate22(rxm);
|
|
2737
|
-
return {
|
|
2738
|
-
locator: rxl,
|
|
2739
|
-
manifest: rxm,
|
|
2740
|
-
archive: rxa
|
|
2741
|
-
};
|
|
2742
|
-
}
|
|
2743
|
-
var gunzipAsync22 = promisify222(gunzip22);
|
|
2744
|
-
|
|
2745
|
-
class FolderLoader {
|
|
2746
|
-
async canLoad(source) {
|
|
2747
|
-
try {
|
|
2748
|
-
const stats = await stat2(source);
|
|
2749
|
-
if (!stats.isDirectory()) {
|
|
2750
|
-
return false;
|
|
2751
|
-
}
|
|
2752
|
-
const manifestPath = join3(source, "resource.json");
|
|
2753
|
-
const manifestStats = await stat2(manifestPath);
|
|
2754
|
-
return manifestStats.isFile();
|
|
2755
|
-
} catch {
|
|
2756
|
-
return false;
|
|
2757
|
-
}
|
|
2758
|
-
}
|
|
2759
|
-
async load(folderPath) {
|
|
2760
|
-
const resourceJsonPath = join3(folderPath, "resource.json");
|
|
2761
|
-
let resourceJson;
|
|
2762
|
-
try {
|
|
2763
|
-
resourceJson = await readFile3(resourceJsonPath, "utf-8");
|
|
2764
|
-
} catch (error) {
|
|
2765
|
-
throw new ResourceXError22(`Failed to read resource.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
2766
|
-
}
|
|
2767
|
-
let json;
|
|
2768
|
-
try {
|
|
2769
|
-
json = JSON.parse(resourceJson);
|
|
2770
|
-
} catch (error) {
|
|
2771
|
-
throw new ResourceXError22(`Invalid JSON in resource.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
2772
|
-
}
|
|
2773
|
-
const rxd = define2(json);
|
|
2774
|
-
const files = await this.readFolderFiles(folderPath);
|
|
2775
|
-
if (Object.keys(files).length === 0) {
|
|
2776
|
-
throw new ResourceXError22("No content files found in resource folder");
|
|
2777
|
-
}
|
|
2778
|
-
const rxm = manifest2(rxd);
|
|
2779
|
-
const rxa = await archive2(files);
|
|
2780
|
-
return resource22(rxm, rxa);
|
|
2781
|
-
}
|
|
2782
|
-
async readFolderFiles(folderPath, basePath = folderPath) {
|
|
2783
|
-
const files = {};
|
|
2784
|
-
const entries = await readdir3(folderPath, { withFileTypes: true });
|
|
2785
|
-
for (const entry of entries) {
|
|
2786
|
-
const fullPath = join3(folderPath, entry.name);
|
|
2787
|
-
const relativePath = relative(basePath, fullPath);
|
|
2788
|
-
if (relativePath === "resource.json") {
|
|
2789
|
-
continue;
|
|
2790
|
-
}
|
|
2791
|
-
if (entry.isFile()) {
|
|
2792
|
-
files[relativePath] = await readFile3(fullPath);
|
|
2793
|
-
} else if (entry.isDirectory()) {
|
|
2794
|
-
const subFiles = await this.readFolderFiles(fullPath, basePath);
|
|
2795
|
-
Object.assign(files, subFiles);
|
|
2796
|
-
}
|
|
2797
|
-
}
|
|
2798
|
-
return files;
|
|
2799
|
-
}
|
|
2800
|
-
}
|
|
2801
|
-
async function loadResource(source, config) {
|
|
2802
|
-
const loader = config?.loader ?? new FolderLoader;
|
|
2803
|
-
const canLoad = await loader.canLoad(source);
|
|
2804
|
-
if (!canLoad) {
|
|
2805
|
-
throw new ResourceXError22(`Cannot load resource from: ${source}`);
|
|
2806
|
-
}
|
|
2807
|
-
return loader.load(source);
|
|
2808
|
-
}
|
|
2809
|
-
|
|
2810
|
-
class LinkedRegistry {
|
|
2811
|
-
basePath;
|
|
2812
|
-
constructor(basePath) {
|
|
2813
|
-
this.basePath = basePath;
|
|
2814
|
-
}
|
|
2815
|
-
buildLinkPath(rxl) {
|
|
2816
|
-
const registry = rxl.registry ?? "localhost";
|
|
2817
|
-
const tag = rxl.tag ?? "latest";
|
|
2818
|
-
let linkPath = join22(this.basePath, registry);
|
|
2819
|
-
if (rxl.path) {
|
|
2820
|
-
linkPath = join22(linkPath, rxl.path);
|
|
2821
|
-
}
|
|
2822
|
-
return join22(linkPath, rxl.name, tag);
|
|
2823
|
-
}
|
|
2824
|
-
async isSymlink(path) {
|
|
2825
|
-
try {
|
|
2826
|
-
const stats = await lstat(path);
|
|
2827
|
-
return stats.isSymbolicLink();
|
|
2828
|
-
} catch {
|
|
2829
|
-
return false;
|
|
2830
|
-
}
|
|
2831
|
-
}
|
|
2832
|
-
async get(rxl) {
|
|
2833
|
-
const linkPath = this.buildLinkPath(rxl);
|
|
2834
|
-
if (!await this.isSymlink(linkPath)) {
|
|
2835
|
-
throw new RegistryError(`Linked resource not found: ${format2(rxl)}`);
|
|
2836
|
-
}
|
|
2837
|
-
const targetPath = await readlink(linkPath);
|
|
2838
|
-
return loadResource(targetPath);
|
|
2839
|
-
}
|
|
2840
|
-
async put(_rxr) {
|
|
2841
|
-
throw new RegistryError("LinkedRegistry does not support put(). Use link() instead.");
|
|
2842
|
-
}
|
|
2843
|
-
async has(rxl) {
|
|
2844
|
-
const linkPath = this.buildLinkPath(rxl);
|
|
2845
|
-
return this.isSymlink(linkPath);
|
|
2846
|
-
}
|
|
2847
|
-
async remove(rxl) {
|
|
2848
|
-
const linkPath = this.buildLinkPath(rxl);
|
|
2849
|
-
if (await this.isSymlink(linkPath)) {
|
|
2850
|
-
await rm3(linkPath);
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
async list(options) {
|
|
2854
|
-
const { query, limit, offset = 0 } = options ?? {};
|
|
2855
|
-
const locators = [];
|
|
2856
|
-
try {
|
|
2857
|
-
await this.scanSymlinks(this.basePath, "", locators);
|
|
2858
|
-
} catch {
|
|
2859
|
-
return [];
|
|
2860
|
-
}
|
|
2861
|
-
let filtered = locators;
|
|
2862
|
-
if (query) {
|
|
2863
|
-
const lowerQuery = query.toLowerCase();
|
|
2864
|
-
filtered = locators.filter((rxl) => {
|
|
2865
|
-
const searchText = `${rxl.registry ?? ""} ${rxl.path ?? ""} ${rxl.name}`.toLowerCase();
|
|
2866
|
-
return searchText.includes(lowerQuery);
|
|
2867
|
-
});
|
|
2868
|
-
}
|
|
2869
|
-
let result = filtered.slice(offset);
|
|
2870
|
-
if (limit !== undefined) {
|
|
2871
|
-
result = result.slice(0, limit);
|
|
2872
|
-
}
|
|
2873
|
-
return result;
|
|
2874
|
-
}
|
|
2875
|
-
async link(devPath) {
|
|
2876
|
-
const rxr = await loadResource(devPath);
|
|
2877
|
-
const linkPath = this.buildLinkPath(rxr.locator);
|
|
2878
|
-
try {
|
|
2879
|
-
const stats = await lstat(linkPath);
|
|
2880
|
-
if (stats.isSymbolicLink() || stats.isDirectory()) {
|
|
2881
|
-
await rm3(linkPath, { recursive: true });
|
|
2882
|
-
}
|
|
2883
|
-
} catch {}
|
|
2884
|
-
const parentPath = join22(linkPath, "..");
|
|
2885
|
-
await mkdir3(parentPath, { recursive: true });
|
|
2886
|
-
const absolutePath = resolvePath(devPath);
|
|
2887
|
-
await symlink(absolutePath, linkPath);
|
|
2888
|
-
return rxr.locator;
|
|
2889
|
-
}
|
|
2890
|
-
async unlink(rxl) {
|
|
2891
|
-
return this.remove(rxl);
|
|
2892
|
-
}
|
|
2893
|
-
async scanSymlinks(dirPath, relativePath, locators) {
|
|
2894
|
-
let entries;
|
|
2895
|
-
try {
|
|
2896
|
-
entries = await readdir22(dirPath);
|
|
2897
|
-
} catch {
|
|
2898
|
-
return;
|
|
2899
|
-
}
|
|
2900
|
-
for (const entry of entries) {
|
|
2901
|
-
const fullPath = join22(dirPath, entry);
|
|
2902
|
-
const relPath = relativePath ? `${relativePath}/${entry}` : entry;
|
|
2903
|
-
try {
|
|
2904
|
-
const stats = await lstat(fullPath);
|
|
2905
|
-
if (stats.isSymbolicLink()) {
|
|
2906
|
-
const rxl = this.parsePathToRXL(relPath);
|
|
2907
|
-
if (rxl) {
|
|
2908
|
-
locators.push(rxl);
|
|
2909
|
-
}
|
|
2910
|
-
} else if (stats.isDirectory()) {
|
|
2911
|
-
await this.scanSymlinks(fullPath, relPath, locators);
|
|
2912
|
-
}
|
|
2913
|
-
} catch {}
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
parsePathToRXL(relPath) {
|
|
2917
|
-
const parts = relPath.split("/");
|
|
2918
|
-
if (parts.length < 3) {
|
|
2919
|
-
return null;
|
|
2920
|
-
}
|
|
2921
|
-
const tag = parts.pop();
|
|
2922
|
-
const name = parts.pop();
|
|
2923
|
-
const registry = parts.shift();
|
|
2924
|
-
const path = parts.length > 0 ? parts.join("/") : undefined;
|
|
2925
|
-
let locatorStr = registry;
|
|
2926
|
-
if (path)
|
|
2927
|
-
locatorStr += `/${path}`;
|
|
2928
|
-
locatorStr += `/${name}`;
|
|
2929
|
-
if (tag !== "latest")
|
|
2930
|
-
locatorStr += `:${tag}`;
|
|
2931
|
-
try {
|
|
2932
|
-
return parse2(locatorStr);
|
|
2933
|
-
} catch {
|
|
2934
|
-
return null;
|
|
2935
|
-
}
|
|
2936
|
-
}
|
|
2937
|
-
}
|
|
2938
|
-
|
|
2939
|
-
class RegistryAccessChain {
|
|
2940
|
-
accessors;
|
|
2941
|
-
memCache = new Map;
|
|
2942
|
-
useMemCache;
|
|
2943
|
-
constructor(accessors, options) {
|
|
2944
|
-
this.accessors = accessors;
|
|
2945
|
-
this.useMemCache = options?.memCache ?? false;
|
|
2946
|
-
}
|
|
2947
|
-
async get(rxl) {
|
|
2948
|
-
const key = format2(rxl);
|
|
2949
|
-
if (this.useMemCache && this.memCache.has(key)) {
|
|
2950
|
-
return this.memCache.get(key);
|
|
2951
|
-
}
|
|
2952
|
-
for (const accessor of this.accessors) {
|
|
2953
|
-
if (await accessor.canHandle(rxl)) {
|
|
2954
|
-
const rxr = await accessor.get(rxl);
|
|
2955
|
-
if (this.useMemCache && accessor.name !== "linked") {
|
|
2956
|
-
this.memCache.set(key, rxr);
|
|
2957
|
-
}
|
|
2958
|
-
return rxr;
|
|
2959
|
-
}
|
|
2960
|
-
}
|
|
2961
|
-
throw new RegistryError(`Resource not found: ${key}`);
|
|
2962
|
-
}
|
|
2963
|
-
async has(rxl) {
|
|
2964
|
-
const key = format2(rxl);
|
|
2965
|
-
if (this.useMemCache && this.memCache.has(key)) {
|
|
2966
|
-
return true;
|
|
2967
|
-
}
|
|
2968
|
-
for (const accessor of this.accessors) {
|
|
2969
|
-
if (await accessor.canHandle(rxl)) {
|
|
2970
|
-
return true;
|
|
2971
|
-
}
|
|
2972
|
-
}
|
|
2973
|
-
return false;
|
|
2974
|
-
}
|
|
2975
|
-
clearCache() {
|
|
2976
|
-
this.memCache.clear();
|
|
2977
|
-
}
|
|
2978
|
-
invalidate(rxl) {
|
|
2979
|
-
this.memCache.delete(format2(rxl));
|
|
2980
|
-
}
|
|
2981
|
-
}
|
|
2982
|
-
|
|
2983
|
-
class LinkedAccessor {
|
|
2984
|
-
registry;
|
|
2985
|
-
name = "linked";
|
|
2986
|
-
constructor(registry) {
|
|
2987
|
-
this.registry = registry;
|
|
2988
|
-
}
|
|
2989
|
-
async canHandle(rxl) {
|
|
2990
|
-
return this.registry.has(rxl);
|
|
2991
|
-
}
|
|
2992
|
-
async get(rxl) {
|
|
2993
|
-
return this.registry.get(rxl);
|
|
2994
|
-
}
|
|
2995
|
-
}
|
|
2996
|
-
|
|
2997
|
-
class LocalAccessor {
|
|
2998
|
-
registry;
|
|
2999
|
-
name = "local";
|
|
3000
|
-
constructor(registry) {
|
|
3001
|
-
this.registry = registry;
|
|
3002
|
-
}
|
|
3003
|
-
async canHandle(rxl) {
|
|
3004
|
-
if (rxl.registry) {
|
|
3005
|
-
return false;
|
|
3006
|
-
}
|
|
3007
|
-
return this.registry.has(rxl);
|
|
3008
|
-
}
|
|
3009
|
-
async get(rxl) {
|
|
3010
|
-
return this.registry.get(rxl);
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
|
|
3014
|
-
class CacheAccessor {
|
|
3015
|
-
registry;
|
|
3016
|
-
name = "cache";
|
|
3017
|
-
constructor(registry) {
|
|
3018
|
-
this.registry = registry;
|
|
3019
|
-
}
|
|
3020
|
-
async canHandle(rxl) {
|
|
3021
|
-
if (!rxl.registry) {
|
|
3022
|
-
return false;
|
|
3023
|
-
}
|
|
3024
|
-
return this.registry.has(rxl);
|
|
3025
|
-
}
|
|
3026
|
-
async get(rxl) {
|
|
3027
|
-
return this.registry.get(rxl);
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3030
|
-
|
|
3031
|
-
class RemoteAccessor {
|
|
3032
|
-
fetcher;
|
|
3033
|
-
cache;
|
|
3034
|
-
name = "remote";
|
|
3035
|
-
constructor(fetcher, cache) {
|
|
3036
|
-
this.fetcher = fetcher;
|
|
3037
|
-
this.cache = cache;
|
|
3038
|
-
}
|
|
3039
|
-
async canHandle(rxl) {
|
|
3040
|
-
return !!rxl.registry;
|
|
3041
|
-
}
|
|
3042
|
-
async get(rxl) {
|
|
3043
|
-
const rxr = await this.fetcher.fetch(rxl);
|
|
3044
|
-
await this.cache.put(rxr);
|
|
3045
|
-
return rxr;
|
|
3046
|
-
}
|
|
3047
|
-
}
|
|
3048
|
-
|
|
3049
|
-
// src/transport/rxr.ts
|
|
3050
|
-
var DEFAULT_BASE_PATH = `${homedir()}/.resourcex`;
|
|
3051
|
-
|
|
3052
|
-
class InternalRegistryAccess {
|
|
3053
|
-
local;
|
|
3054
|
-
cache;
|
|
3055
|
-
linked;
|
|
3056
|
-
constructor(basePath = DEFAULT_BASE_PATH) {
|
|
3057
|
-
const localStorage = new FileSystemStorage(join4(basePath, "local"));
|
|
3058
|
-
const cacheStorage = new FileSystemStorage(join4(basePath, "cache"));
|
|
3059
|
-
this.local = new LocalRegistry(localStorage);
|
|
3060
|
-
this.cache = new MirrorRegistry(cacheStorage);
|
|
3061
|
-
this.linked = new LinkedRegistry(join4(basePath, "linked"));
|
|
3062
|
-
}
|
|
3063
|
-
async get(locator) {
|
|
3064
|
-
const rxl = parse(locator);
|
|
3065
|
-
if (await this.linked.has(rxl)) {
|
|
3066
|
-
return this.linked.get(rxl);
|
|
3067
|
-
}
|
|
3068
|
-
if (!rxl.registry && await this.local.has(rxl)) {
|
|
3069
|
-
return this.local.get(rxl);
|
|
3070
|
-
}
|
|
3071
|
-
if (rxl.registry && await this.cache.has(rxl)) {
|
|
3072
|
-
return this.cache.get(rxl);
|
|
3073
|
-
}
|
|
3074
|
-
throw new Error(`Resource not found: ${locator}`);
|
|
3075
|
-
}
|
|
3076
|
-
}
|
|
3077
|
-
var defaultRegistry = null;
|
|
3078
|
-
|
|
3079
|
-
class RxrTransport {
|
|
3080
|
-
basePath;
|
|
3081
|
-
name = "rxr";
|
|
3082
|
-
constructor(basePath) {
|
|
3083
|
-
this.basePath = basePath;
|
|
3084
|
-
}
|
|
3085
|
-
async get(location, _params) {
|
|
3086
|
-
const { rxl, internalPath } = this.parseLocation(location);
|
|
3087
|
-
const registry = this.getRegistry();
|
|
3088
|
-
const rxr = await registry.get(rxl);
|
|
3089
|
-
const files = await extract(rxr.archive);
|
|
3090
|
-
const file = files[internalPath];
|
|
3091
|
-
if (!file) {
|
|
3092
|
-
throw new TransportError(`File not found in resource: ${internalPath}`, this.name);
|
|
3093
|
-
}
|
|
3094
|
-
return {
|
|
3095
|
-
content: file,
|
|
3096
|
-
metadata: { type: "file", size: file.length }
|
|
3097
|
-
};
|
|
3098
|
-
}
|
|
3099
|
-
async set(_location, _content, _params) {
|
|
3100
|
-
throw new TransportError("RXR transport is read-only", this.name);
|
|
3101
|
-
}
|
|
3102
|
-
async exists(location) {
|
|
3103
|
-
try {
|
|
3104
|
-
const { rxl, internalPath } = this.parseLocation(location);
|
|
3105
|
-
const registry = this.getRegistry();
|
|
3106
|
-
const rxr = await registry.get(rxl);
|
|
3107
|
-
const files = await extract(rxr.archive);
|
|
3108
|
-
return internalPath in files;
|
|
3109
|
-
} catch {
|
|
3110
|
-
return false;
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
async delete(_location) {
|
|
3114
|
-
throw new TransportError("RXR transport is read-only", this.name);
|
|
3115
|
-
}
|
|
3116
|
-
getRegistry() {
|
|
3117
|
-
if (this.basePath) {
|
|
3118
|
-
return new InternalRegistryAccess(this.basePath);
|
|
3119
|
-
}
|
|
3120
|
-
if (!defaultRegistry) {
|
|
3121
|
-
defaultRegistry = new InternalRegistryAccess;
|
|
3122
|
-
}
|
|
3123
|
-
return defaultRegistry;
|
|
3124
|
-
}
|
|
3125
|
-
parseLocation(location) {
|
|
3126
|
-
const atIndex = location.indexOf("@");
|
|
3127
|
-
if (atIndex === -1) {
|
|
3128
|
-
throw new TransportError(`Invalid RXR location (missing @version): ${location}`, this.name);
|
|
3129
|
-
}
|
|
3130
|
-
const slashAfterVersion = location.indexOf("/", atIndex);
|
|
3131
|
-
if (slashAfterVersion === -1) {
|
|
3132
|
-
throw new TransportError(`Invalid RXR location (missing internal path): ${location}`, this.name);
|
|
3133
|
-
}
|
|
3134
|
-
return {
|
|
3135
|
-
rxl: location.slice(0, slashAfterVersion),
|
|
3136
|
-
internalPath: location.slice(slashAfterVersion + 1)
|
|
3137
|
-
};
|
|
3138
|
-
}
|
|
3139
|
-
}
|
|
3140
|
-
function clearRegistryCache() {
|
|
3141
|
-
defaultRegistry = null;
|
|
3142
|
-
}
|
|
3143
|
-
|
|
3144
|
-
// src/arp.ts
|
|
3145
|
-
function createARP2(config) {
|
|
3146
|
-
const arp = createARP(config);
|
|
3147
|
-
const hasRxrTransport = config?.transports?.some((t) => t.name === "rxr");
|
|
3148
|
-
if (!hasRxrTransport) {
|
|
3149
|
-
arp.registerTransport(new RxrTransport);
|
|
3150
|
-
}
|
|
3151
|
-
return arp;
|
|
3152
|
-
}
|
|
529
|
+
var VERSION = "2.5.7";
|
|
3153
530
|
export {
|
|
3154
531
|
textSemantic,
|
|
3155
532
|
httpsTransport,
|
|
3156
533
|
httpTransport,
|
|
3157
534
|
fileTransport,
|
|
3158
|
-
|
|
3159
|
-
clearRegistryCache,
|
|
535
|
+
createARP,
|
|
3160
536
|
binarySemantic,
|
|
3161
537
|
VERSION,
|
|
3162
538
|
TransportError,
|
|
3163
539
|
TextSemanticHandler,
|
|
3164
540
|
SemanticError,
|
|
3165
|
-
RxrTransport,
|
|
3166
541
|
ParseError,
|
|
3167
542
|
HttpTransportHandler,
|
|
3168
543
|
FileTransportHandler,
|
|
@@ -3171,4 +546,4 @@ export {
|
|
|
3171
546
|
ARP
|
|
3172
547
|
};
|
|
3173
548
|
|
|
3174
|
-
//# debugId=
|
|
549
|
+
//# debugId=962C017218F1C6E664756E2164756E21
|