@modeloslab/modelcode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +73 -0
  2. package/SPEC.md +127 -0
  3. package/agents/code-reviewer.md +49 -0
  4. package/agents/debugger.md +25 -0
  5. package/agents/explore.md +22 -0
  6. package/agents/general-purpose.md +25 -0
  7. package/agents/plan.md +28 -0
  8. package/agents/researcher.md +26 -0
  9. package/agents/security-auditor.md +44 -0
  10. package/dist/BrowserWebSocketTransport-e6g854ra.mjs +8 -0
  11. package/dist/LaunchOptions-d24f2e73.mjs +8 -0
  12. package/dist/NodeWebSocketTransport-s3fsfh3j.mjs +9 -0
  13. package/dist/bidi-fwqajnyx.mjs +17261 -0
  14. package/dist/cli.mjs +1669 -0
  15. package/dist/devtools-fkz8mzpk.mjs +83 -0
  16. package/dist/fileFromPath-s8scncrt.mjs +128 -0
  17. package/dist/helpers-667kxskd.mjs +17 -0
  18. package/dist/index-4706p1xh.mjs +3238 -0
  19. package/dist/index-gp8nzd9n.mjs +1561 -0
  20. package/dist/main-0r35eyef.mjs +16229 -0
  21. package/dist/main-2aqyq9g6.mjs +24239 -0
  22. package/dist/main-5vqwebnv.mjs +54 -0
  23. package/dist/main-7f2pnmhh.mjs +2901 -0
  24. package/dist/main-7jta7ark.mjs +57 -0
  25. package/dist/main-8y3fe7c3.mjs +48 -0
  26. package/dist/main-9w13grbs.mjs +41 -0
  27. package/dist/main-d71btkt1.mjs +2478 -0
  28. package/dist/main-h8e68gyt.mjs +2819 -0
  29. package/dist/main-p2xnn95s.mjs +2240 -0
  30. package/dist/main-qfprs50h.mjs +1629 -0
  31. package/dist/main-tqg5vhra.mjs +19 -0
  32. package/dist/puppeteer-core-qdv3v3fq.mjs +1486 -0
  33. package/dist/tui-0r2q70wm.mjs +23768 -0
  34. package/package.json +66 -0
  35. package/skills/commit/SKILL.md +34 -0
  36. package/skills/debug/SKILL.md +44 -0
  37. package/skills/docker/SKILL.md +18 -0
  38. package/skills/init/SKILL.md +36 -0
  39. package/skills/nextjs-app-router/SKILL.md +16 -0
  40. package/skills/nextjs-data-fetching/SKILL.md +16 -0
  41. package/skills/nextjs-env-config/SKILL.md +18 -0
  42. package/skills/nextjs-metadata-seo/SKILL.md +17 -0
  43. package/skills/nextjs-middleware/SKILL.md +18 -0
  44. package/skills/nextjs-performance/SKILL.md +17 -0
  45. package/skills/nextjs-route-handler/SKILL.md +18 -0
  46. package/skills/nextjs-server-actions/SKILL.md +17 -0
  47. package/skills/nextjs-server-components/SKILL.md +18 -0
  48. package/skills/power-ui/SKILL.md +40 -0
  49. package/skills/pr/SKILL.md +38 -0
  50. package/skills/refactor/SKILL.md +40 -0
  51. package/skills/remember/SKILL.md +39 -0
  52. package/skills/review/SKILL.md +22 -0
  53. package/skills/security-review/SKILL.md +21 -0
  54. package/skills/simplify/SKILL.md +47 -0
  55. package/skills/skill-create/SKILL.md +37 -0
  56. package/skills/test/SKILL.md +34 -0
  57. package/skills/vercel-deploy/SKILL.md +16 -0
@@ -0,0 +1,1561 @@
1
+ import"./main-8y3fe7c3.mjs";
2
+
3
+ // node_modules/modern-tar/dist/unpacker-CPCEF5CT.js
4
+ var FILE = "file";
5
+ var LINK = "link";
6
+ var SYMLINK = "symlink";
7
+ var DIRECTORY = "directory";
8
+ var TYPEFLAG = {
9
+ file: "0",
10
+ link: "1",
11
+ symlink: "2",
12
+ "character-device": "3",
13
+ "block-device": "4",
14
+ directory: "5",
15
+ fifo: "6",
16
+ "pax-header": "x",
17
+ "pax-global-header": "g",
18
+ "gnu-long-name": "L",
19
+ "gnu-long-link-name": "K"
20
+ };
21
+ var FLAGTYPE = {
22
+ "0": FILE,
23
+ "1": LINK,
24
+ "2": SYMLINK,
25
+ "3": "character-device",
26
+ "4": "block-device",
27
+ "5": DIRECTORY,
28
+ "6": "fifo",
29
+ x: "pax-header",
30
+ g: "pax-global-header",
31
+ L: "gnu-long-name",
32
+ K: "gnu-long-link-name"
33
+ };
34
+ var ZERO_BLOCK = new Uint8Array(512);
35
+ var EMPTY = new Uint8Array(0);
36
+ var encoder = new TextEncoder;
37
+ var decoder = new TextDecoder;
38
+ function writeString(view, offset, size, value) {
39
+ if (value)
40
+ encoder.encodeInto(value, view.subarray(offset, offset + size));
41
+ }
42
+ function writeOctal(view, offset, size, value) {
43
+ if (value === undefined)
44
+ return;
45
+ const octalString = value.toString(8).padStart(size - 1, "0");
46
+ encoder.encodeInto(octalString, view.subarray(offset, offset + size - 1));
47
+ }
48
+ function readString(view, offset, size) {
49
+ const end = view.indexOf(0, offset);
50
+ const sliceEnd = end === -1 || end > offset + size ? offset + size : end;
51
+ return decoder.decode(view.subarray(offset, sliceEnd));
52
+ }
53
+ function readOctal(view, offset, size) {
54
+ let value = 0;
55
+ const end = offset + size;
56
+ for (let i = offset;i < end; i++) {
57
+ const charCode = view[i];
58
+ if (charCode === 0)
59
+ break;
60
+ if (charCode === 32)
61
+ continue;
62
+ value = value * 8 + (charCode - 48);
63
+ }
64
+ return value;
65
+ }
66
+ function readNumeric(view, offset, size) {
67
+ if (view[offset] & 128) {
68
+ let result = 0;
69
+ result = view[offset] & 127;
70
+ for (let i = 1;i < size; i++)
71
+ result = result * 256 + view[offset + i];
72
+ if (!Number.isSafeInteger(result))
73
+ throw new Error("TAR number too large");
74
+ return result;
75
+ }
76
+ return readOctal(view, offset, size);
77
+ }
78
+ var isBodyless = (header) => header.type === "directory" || header.type === "symlink" || header.type === "link" || header.type === "character-device" || header.type === "block-device" || header.type === "fifo";
79
+ async function normalizeBody(body) {
80
+ if (body === null || body === undefined)
81
+ return EMPTY;
82
+ if (body instanceof Uint8Array)
83
+ return body;
84
+ if (typeof body === "string")
85
+ return encoder.encode(body);
86
+ if (body instanceof ArrayBuffer)
87
+ return new Uint8Array(body);
88
+ if (body instanceof Blob)
89
+ return new Uint8Array(await body.arrayBuffer());
90
+ throw new TypeError("Unsupported content type for entry body.");
91
+ }
92
+ var stripPath = (p, n) => {
93
+ const parts = p.split("/").filter(Boolean);
94
+ return n >= parts.length ? "" : parts.slice(n).join("/");
95
+ };
96
+ function transformHeader(header, options) {
97
+ const { strip, filter, map } = options;
98
+ if (!strip && !filter && !map)
99
+ return header;
100
+ const h = { ...header };
101
+ if (strip && strip > 0) {
102
+ const newName = stripPath(h.name, strip);
103
+ if (!newName)
104
+ return null;
105
+ h.name = h.type === "directory" && !newName.endsWith("/") ? `${newName}/` : newName;
106
+ if (h.linkname) {
107
+ const isAbsolute = h.linkname.startsWith("/");
108
+ if (isAbsolute || h.type === "link") {
109
+ const stripped = stripPath(h.linkname, strip);
110
+ h.linkname = isAbsolute ? `/${stripped}` || "/" : stripped;
111
+ }
112
+ }
113
+ }
114
+ if (filter?.(h) === false)
115
+ return null;
116
+ const result = map ? map(h) : h;
117
+ if (result && (!result.name || !result.name.trim() || result.name === "." || result.name === "/"))
118
+ return null;
119
+ return result;
120
+ }
121
+ var CHECKSUM_SPACE = 32;
122
+ var ASCII_ZERO = 48;
123
+ function validateChecksum(block) {
124
+ const stored = readOctal(block, 148, 8);
125
+ let sum = 0;
126
+ for (let i = 0;i < block.length; i++)
127
+ if (i >= 148 && i < 156)
128
+ sum += CHECKSUM_SPACE;
129
+ else
130
+ sum += block[i];
131
+ return stored === sum;
132
+ }
133
+ function writeChecksum(block) {
134
+ block.fill(CHECKSUM_SPACE, 148, 156);
135
+ let checksum = 0;
136
+ for (const byte of block)
137
+ checksum += byte;
138
+ for (let i = 153;i >= 148; i--) {
139
+ block[i] = (checksum & 7) + ASCII_ZERO;
140
+ checksum >>= 3;
141
+ }
142
+ block[154] = 0;
143
+ block[155] = CHECKSUM_SPACE;
144
+ }
145
+ var USTAR_SPLIT_MAX_SIZE = 256;
146
+ function generatePax(header) {
147
+ const paxRecords = {};
148
+ if (encoder.encode(header.name).length > 100) {
149
+ if (findUstarSplit(header.name) === null)
150
+ paxRecords.path = header.name;
151
+ }
152
+ if (header.linkname && encoder.encode(header.linkname).length > 100)
153
+ paxRecords.linkpath = header.linkname;
154
+ if (header.uname && encoder.encode(header.uname).length > 32)
155
+ paxRecords.uname = header.uname;
156
+ if (header.gname && encoder.encode(header.gname).length > 32)
157
+ paxRecords.gname = header.gname;
158
+ if (header.uid != null && header.uid > 2097151)
159
+ paxRecords.uid = String(header.uid);
160
+ if (header.gid != null && header.gid > 2097151)
161
+ paxRecords.gid = String(header.gid);
162
+ if (header.size != null && header.size > 8589934591)
163
+ paxRecords.size = String(header.size);
164
+ if (header.pax)
165
+ Object.assign(paxRecords, header.pax);
166
+ const paxEntries = Object.entries(paxRecords);
167
+ if (paxEntries.length === 0)
168
+ return null;
169
+ const paxBody = encoder.encode(paxEntries.map(([key, value]) => {
170
+ const record = `${key}=${value}
171
+ `;
172
+ const partLength = encoder.encode(record).length + 1;
173
+ let totalLength = partLength + String(partLength).length;
174
+ totalLength = partLength + String(totalLength).length;
175
+ return `${totalLength} ${record}`;
176
+ }).join(""));
177
+ return {
178
+ paxHeader: createTarHeader({
179
+ name: decoder.decode(encoder.encode(`PaxHeader/${header.name}`).slice(0, 100)),
180
+ size: paxBody.length,
181
+ type: "pax-header",
182
+ mode: 420,
183
+ mtime: header.mtime,
184
+ uname: header.uname,
185
+ gname: header.gname,
186
+ uid: header.uid,
187
+ gid: header.gid
188
+ }),
189
+ paxBody
190
+ };
191
+ }
192
+ function findUstarSplit(path) {
193
+ const totalPathBytes = encoder.encode(path).length;
194
+ if (totalPathBytes <= 100 || totalPathBytes > USTAR_SPLIT_MAX_SIZE)
195
+ return null;
196
+ for (let i = path.length - 1;i > 0; i--) {
197
+ if (path[i] !== "/")
198
+ continue;
199
+ const prefix = path.slice(0, i);
200
+ const name = path.slice(i + 1);
201
+ if (encoder.encode(prefix).length <= 155 && encoder.encode(name).length <= 100)
202
+ return {
203
+ prefix,
204
+ name
205
+ };
206
+ }
207
+ return null;
208
+ }
209
+ function createTarHeader(header) {
210
+ const view = new Uint8Array(512);
211
+ const size = isBodyless(header) ? 0 : header.size ?? 0;
212
+ let name = header.name;
213
+ let prefix = "";
214
+ if (!header.pax?.path) {
215
+ const split = findUstarSplit(name);
216
+ if (split) {
217
+ name = split.name;
218
+ prefix = split.prefix;
219
+ }
220
+ }
221
+ writeString(view, 0, 100, name);
222
+ writeOctal(view, 100, 8, header.mode ?? (header.type === "directory" ? 493 : 420));
223
+ writeOctal(view, 108, 8, header.uid ?? 0);
224
+ writeOctal(view, 116, 8, header.gid ?? 0);
225
+ writeOctal(view, 124, 12, size);
226
+ writeOctal(view, 136, 12, Math.floor((header.mtime?.getTime() ?? Date.now()) / 1000));
227
+ writeString(view, 156, 1, TYPEFLAG[header.type ?? "file"]);
228
+ writeString(view, 157, 100, header.linkname);
229
+ writeString(view, 257, 6, "ustar\x00");
230
+ writeString(view, 263, 2, "00");
231
+ writeString(view, 265, 32, header.uname);
232
+ writeString(view, 297, 32, header.gname);
233
+ writeString(view, 345, 155, prefix);
234
+ writeChecksum(view);
235
+ return view;
236
+ }
237
+ function parseUstarHeader(block, strict) {
238
+ if (strict && !validateChecksum(block))
239
+ throw new Error("Invalid tar header checksum.");
240
+ const typeflag = readString(block, 156, 1);
241
+ const header = {
242
+ name: readString(block, 0, 100),
243
+ mode: readOctal(block, 100, 8),
244
+ uid: readNumeric(block, 108, 8),
245
+ gid: readNumeric(block, 116, 8),
246
+ size: readNumeric(block, 124, 12),
247
+ mtime: /* @__PURE__ */ new Date(readNumeric(block, 136, 12) * 1000),
248
+ type: FLAGTYPE[typeflag] || "file",
249
+ linkname: readString(block, 157, 100)
250
+ };
251
+ const magic = readString(block, 257, 6);
252
+ if (isBodyless(header))
253
+ header.size = 0;
254
+ if (magic.trim() === "ustar") {
255
+ header.uname = readString(block, 265, 32);
256
+ header.gname = readString(block, 297, 32);
257
+ }
258
+ if (magic === "ustar")
259
+ header.prefix = readString(block, 345, 155);
260
+ return header;
261
+ }
262
+ var PAX_MAPPING = {
263
+ path: ["name", (v) => v],
264
+ linkpath: ["linkname", (v) => v],
265
+ size: ["size", (v) => parseInt(v, 10)],
266
+ mtime: ["mtime", parseFloat],
267
+ uid: ["uid", (v) => parseInt(v, 10)],
268
+ gid: ["gid", (v) => parseInt(v, 10)],
269
+ uname: ["uname", (v) => v],
270
+ gname: ["gname", (v) => v]
271
+ };
272
+ function parsePax(buffer) {
273
+ const decoder2 = new TextDecoder("utf-8");
274
+ const overrides = Object.create(null);
275
+ const pax = Object.create(null);
276
+ let offset = 0;
277
+ while (offset < buffer.length) {
278
+ const spaceIndex = buffer.indexOf(32, offset);
279
+ if (spaceIndex === -1)
280
+ break;
281
+ const length = parseInt(decoder2.decode(buffer.subarray(offset, spaceIndex)), 10);
282
+ if (Number.isNaN(length) || length === 0)
283
+ break;
284
+ const recordEnd = offset + length;
285
+ const [key, value] = decoder2.decode(buffer.subarray(spaceIndex + 1, recordEnd - 1)).split("=", 2);
286
+ if (key && value !== undefined) {
287
+ pax[key] = value;
288
+ if (Object.hasOwn(PAX_MAPPING, key)) {
289
+ const [targetKey, parser] = PAX_MAPPING[key];
290
+ const parsedValue = parser(value);
291
+ if (typeof parsedValue === "string" || !Number.isNaN(parsedValue))
292
+ overrides[targetKey] = parsedValue;
293
+ }
294
+ }
295
+ offset = recordEnd;
296
+ }
297
+ if (Object.keys(pax).length > 0)
298
+ overrides.pax = pax;
299
+ return overrides;
300
+ }
301
+ function applyOverrides(header, overrides) {
302
+ if (overrides.name !== undefined)
303
+ header.name = overrides.name;
304
+ if (overrides.linkname !== undefined)
305
+ header.linkname = overrides.linkname;
306
+ if (overrides.size !== undefined)
307
+ header.size = overrides.size;
308
+ if (overrides.mtime !== undefined)
309
+ header.mtime = /* @__PURE__ */ new Date(overrides.mtime * 1000);
310
+ if (overrides.uid !== undefined)
311
+ header.uid = overrides.uid;
312
+ if (overrides.gid !== undefined)
313
+ header.gid = overrides.gid;
314
+ if (overrides.uname !== undefined)
315
+ header.uname = overrides.uname;
316
+ if (overrides.gname !== undefined)
317
+ header.gname = overrides.gname;
318
+ if (overrides.pax)
319
+ header.pax = Object.assign({}, header.pax ?? {}, overrides.pax);
320
+ }
321
+ function getMetaParser(type) {
322
+ switch (type) {
323
+ case "pax-global-header":
324
+ case "pax-header":
325
+ return parsePax;
326
+ case "gnu-long-name":
327
+ return (data) => ({ name: readString(data, 0, data.length) });
328
+ case "gnu-long-link-name":
329
+ return (data) => ({ linkname: readString(data, 0, data.length) });
330
+ default:
331
+ return;
332
+ }
333
+ }
334
+ function getHeaderBlocks(header) {
335
+ const base = createTarHeader(header);
336
+ const pax = generatePax(header);
337
+ if (!pax)
338
+ return [base];
339
+ const paxPadding = -pax.paxBody.length & 511;
340
+ const paddingBlocks = paxPadding > 0 ? [ZERO_BLOCK.subarray(0, paxPadding)] : [];
341
+ return [
342
+ pax.paxHeader,
343
+ pax.paxBody,
344
+ ...paddingBlocks,
345
+ base
346
+ ];
347
+ }
348
+ var EOF_BUFFER = new Uint8Array(512 * 2);
349
+ function createTarPacker(onData, onError, onFinalize) {
350
+ let currentHeader = null;
351
+ let bytesWritten = 0;
352
+ let finalized = false;
353
+ const fail = (message) => {
354
+ const error = new Error(message);
355
+ onError(error);
356
+ throw error;
357
+ };
358
+ return {
359
+ add(header) {
360
+ if (finalized)
361
+ fail("No new tar entries after finalize.");
362
+ if (currentHeader !== null)
363
+ fail("Previous entry must be completed before adding a new one");
364
+ const size = isBodyless(header) ? 0 : header.size;
365
+ if (!Number.isSafeInteger(size) || size < 0)
366
+ fail("Invalid tar entry size.");
367
+ try {
368
+ const headerBlocks = getHeaderBlocks({
369
+ ...header,
370
+ size
371
+ });
372
+ for (const block of headerBlocks)
373
+ onData(block);
374
+ currentHeader = {
375
+ ...header,
376
+ size
377
+ };
378
+ bytesWritten = 0;
379
+ } catch (error) {
380
+ onError(error);
381
+ }
382
+ },
383
+ write(chunk) {
384
+ if (!currentHeader)
385
+ fail("No active tar entry.");
386
+ if (finalized)
387
+ fail("Cannot write data after finalize.");
388
+ const newTotal = bytesWritten + chunk.length;
389
+ if (newTotal > currentHeader.size)
390
+ fail(`"${currentHeader.name}" exceeds given size of ${currentHeader.size} bytes.`);
391
+ try {
392
+ bytesWritten = newTotal;
393
+ onData(chunk);
394
+ } catch (error) {
395
+ onError(error);
396
+ }
397
+ },
398
+ endEntry() {
399
+ if (!currentHeader)
400
+ fail("No active entry to end.");
401
+ if (finalized)
402
+ fail("Cannot end entry after finalize.");
403
+ try {
404
+ if (bytesWritten !== currentHeader.size)
405
+ fail(`Size mismatch for "${currentHeader.name}".`);
406
+ const paddingSize = -currentHeader.size & 511;
407
+ if (paddingSize > 0)
408
+ onData(new Uint8Array(paddingSize));
409
+ currentHeader = null;
410
+ bytesWritten = 0;
411
+ } catch (error) {
412
+ onError(error);
413
+ throw error;
414
+ }
415
+ },
416
+ finalize() {
417
+ if (finalized)
418
+ fail("Archive has already been finalized");
419
+ if (currentHeader !== null)
420
+ fail("Cannot finalize while an entry is still active");
421
+ try {
422
+ onData(EOF_BUFFER);
423
+ finalized = true;
424
+ if (onFinalize)
425
+ onFinalize();
426
+ } catch (error) {
427
+ onError(error);
428
+ }
429
+ }
430
+ };
431
+ }
432
+ var INITIAL_CAPACITY = 256;
433
+ function createChunkQueue() {
434
+ let chunks = new Array(INITIAL_CAPACITY);
435
+ let capacityMask = chunks.length - 1;
436
+ let head = 0;
437
+ let tail = 0;
438
+ let totalAvailable = 0;
439
+ const consumeFromHead = (count) => {
440
+ const chunk = chunks[head];
441
+ if (count === chunk.length) {
442
+ chunks[head] = EMPTY;
443
+ head = head + 1 & capacityMask;
444
+ } else
445
+ chunks[head] = chunk.subarray(count);
446
+ totalAvailable -= count;
447
+ if (totalAvailable === 0 && chunks.length > INITIAL_CAPACITY) {
448
+ chunks = new Array(INITIAL_CAPACITY);
449
+ capacityMask = INITIAL_CAPACITY - 1;
450
+ head = 0;
451
+ tail = 0;
452
+ }
453
+ };
454
+ function pull(bytes, callback) {
455
+ if (callback) {
456
+ let fed = 0;
457
+ let remaining2 = Math.min(bytes, totalAvailable);
458
+ while (remaining2 > 0) {
459
+ const chunk = chunks[head];
460
+ const toFeed = Math.min(remaining2, chunk.length);
461
+ const segment = toFeed === chunk.length ? chunk : chunk.subarray(0, toFeed);
462
+ consumeFromHead(toFeed);
463
+ remaining2 -= toFeed;
464
+ fed += toFeed;
465
+ if (!callback(segment))
466
+ break;
467
+ }
468
+ return fed;
469
+ }
470
+ if (totalAvailable < bytes)
471
+ return null;
472
+ if (bytes === 0)
473
+ return EMPTY;
474
+ const firstChunk = chunks[head];
475
+ if (firstChunk.length >= bytes) {
476
+ const view = firstChunk.length === bytes ? firstChunk : firstChunk.subarray(0, bytes);
477
+ consumeFromHead(bytes);
478
+ return view;
479
+ }
480
+ const result = new Uint8Array(bytes);
481
+ let copied = 0;
482
+ let remaining = bytes;
483
+ while (remaining > 0) {
484
+ const chunk = chunks[head];
485
+ const toCopy = Math.min(remaining, chunk.length);
486
+ result.set(toCopy === chunk.length ? chunk : chunk.subarray(0, toCopy), copied);
487
+ copied += toCopy;
488
+ remaining -= toCopy;
489
+ consumeFromHead(toCopy);
490
+ }
491
+ return result;
492
+ }
493
+ return {
494
+ push: (chunk) => {
495
+ if (chunk.length === 0)
496
+ return;
497
+ let nextTail = tail + 1 & capacityMask;
498
+ if (nextTail === head) {
499
+ const oldLen = chunks.length;
500
+ const newLen = oldLen * 2;
501
+ const newChunks = new Array(newLen);
502
+ const count = tail - head + oldLen & oldLen - 1;
503
+ if (head < tail)
504
+ for (let i = 0;i < count; i++)
505
+ newChunks[i] = chunks[head + i];
506
+ else if (count > 0) {
507
+ const firstPart = oldLen - head;
508
+ for (let i = 0;i < firstPart; i++)
509
+ newChunks[i] = chunks[head + i];
510
+ for (let i = 0;i < tail; i++)
511
+ newChunks[firstPart + i] = chunks[i];
512
+ }
513
+ chunks = newChunks;
514
+ capacityMask = newLen - 1;
515
+ head = 0;
516
+ tail = count;
517
+ nextTail = tail + 1 & capacityMask;
518
+ }
519
+ chunks[tail] = chunk;
520
+ tail = nextTail;
521
+ totalAvailable += chunk.length;
522
+ },
523
+ available: () => totalAvailable,
524
+ peek: (bytes) => {
525
+ if (totalAvailable < bytes)
526
+ return null;
527
+ if (bytes === 0)
528
+ return EMPTY;
529
+ const firstChunk = chunks[head];
530
+ if (firstChunk.length >= bytes)
531
+ return firstChunk.length === bytes ? firstChunk : firstChunk.subarray(0, bytes);
532
+ const result = new Uint8Array(bytes);
533
+ let copied = 0;
534
+ let index = head;
535
+ while (copied < bytes) {
536
+ const chunk = chunks[index];
537
+ const toCopy = Math.min(bytes - copied, chunk.length);
538
+ if (toCopy === chunk.length)
539
+ result.set(chunk, copied);
540
+ else
541
+ result.set(chunk.subarray(0, toCopy), copied);
542
+ copied += toCopy;
543
+ index = index + 1 & capacityMask;
544
+ }
545
+ return result;
546
+ },
547
+ discard: (bytes) => {
548
+ if (bytes > totalAvailable)
549
+ throw new Error("Too many bytes consumed");
550
+ if (bytes === 0)
551
+ return;
552
+ let remaining = bytes;
553
+ while (remaining > 0) {
554
+ const chunk = chunks[head];
555
+ const toConsume = Math.min(remaining, chunk.length);
556
+ consumeFromHead(toConsume);
557
+ remaining -= toConsume;
558
+ }
559
+ },
560
+ pull
561
+ };
562
+ }
563
+ var STATE_HEADER = 0;
564
+ var STATE_BODY = 1;
565
+ var truncateErr = /* @__PURE__ */ new Error("Tar archive is truncated.");
566
+ function createUnpacker(options = {}) {
567
+ const strict = options.strict ?? false;
568
+ const { available, peek, push, discard, pull } = createChunkQueue();
569
+ let state = STATE_HEADER;
570
+ let ended = false;
571
+ let done = false;
572
+ let eof = false;
573
+ let currentEntry = null;
574
+ const paxGlobals = {};
575
+ let nextEntryOverrides = {};
576
+ const unpacker = {
577
+ isEntryActive: () => state === STATE_BODY,
578
+ isBodyComplete: () => !currentEntry || currentEntry.remaining === 0,
579
+ canFinish: () => !currentEntry || available() >= currentEntry.remaining + currentEntry.padding,
580
+ write(chunk) {
581
+ if (ended)
582
+ throw new Error("Archive already ended.");
583
+ push(chunk);
584
+ },
585
+ end() {
586
+ ended = true;
587
+ },
588
+ readHeader() {
589
+ if (state !== STATE_HEADER)
590
+ throw new Error("Cannot read header while an entry is active");
591
+ if (done)
592
+ return;
593
+ while (!done) {
594
+ if (available() < 512) {
595
+ if (ended) {
596
+ if (available() > 0 && strict)
597
+ throw truncateErr;
598
+ done = true;
599
+ return;
600
+ }
601
+ return null;
602
+ }
603
+ const headerBlock = peek(512);
604
+ if (isZeroBlock(headerBlock)) {
605
+ if (available() < 512 * 2) {
606
+ if (ended) {
607
+ if (strict)
608
+ throw truncateErr;
609
+ done = true;
610
+ return;
611
+ }
612
+ return null;
613
+ }
614
+ if (isZeroBlock(peek(512 * 2).subarray(512))) {
615
+ discard(512 * 2);
616
+ done = true;
617
+ eof = true;
618
+ return;
619
+ }
620
+ if (strict)
621
+ throw new Error("Invalid tar header.");
622
+ discard(512);
623
+ continue;
624
+ }
625
+ let internalHeader;
626
+ try {
627
+ internalHeader = parseUstarHeader(headerBlock, strict);
628
+ } catch (err) {
629
+ if (strict)
630
+ throw err;
631
+ discard(512);
632
+ continue;
633
+ }
634
+ const metaParser = getMetaParser(internalHeader.type);
635
+ if (metaParser) {
636
+ const paddedSize = internalHeader.size + (-internalHeader.size & 511);
637
+ if (available() < 512 + paddedSize) {
638
+ if (ended && strict)
639
+ throw truncateErr;
640
+ return null;
641
+ }
642
+ discard(512);
643
+ const overrides = metaParser(pull(paddedSize).subarray(0, internalHeader.size));
644
+ const target = internalHeader.type === "pax-global-header" ? paxGlobals : nextEntryOverrides;
645
+ for (const key in overrides)
646
+ target[key] = overrides[key];
647
+ continue;
648
+ }
649
+ discard(512);
650
+ const header = internalHeader;
651
+ if (internalHeader.prefix)
652
+ header.name = `${internalHeader.prefix}/${header.name}`;
653
+ applyOverrides(header, paxGlobals);
654
+ applyOverrides(header, nextEntryOverrides);
655
+ if (header.name.endsWith("/") && header.type === "file")
656
+ header.type = DIRECTORY;
657
+ nextEntryOverrides = {};
658
+ currentEntry = {
659
+ header,
660
+ remaining: header.size,
661
+ padding: -header.size & 511
662
+ };
663
+ state = STATE_BODY;
664
+ return header;
665
+ }
666
+ },
667
+ streamBody(callback) {
668
+ if (state !== STATE_BODY || !currentEntry || currentEntry.remaining === 0)
669
+ return 0;
670
+ const bytesToFeed = Math.min(currentEntry.remaining, available());
671
+ if (bytesToFeed === 0)
672
+ return 0;
673
+ const fed = pull(bytesToFeed, callback);
674
+ currentEntry.remaining -= fed;
675
+ return fed;
676
+ },
677
+ skipPadding() {
678
+ if (state !== STATE_BODY || !currentEntry)
679
+ return true;
680
+ if (currentEntry.remaining > 0)
681
+ throw new Error("Body not fully consumed");
682
+ if (available() < currentEntry.padding)
683
+ return false;
684
+ discard(currentEntry.padding);
685
+ currentEntry = null;
686
+ state = STATE_HEADER;
687
+ return true;
688
+ },
689
+ skipEntry() {
690
+ if (state !== STATE_BODY || !currentEntry)
691
+ return true;
692
+ const toDiscard = Math.min(currentEntry.remaining, available());
693
+ if (toDiscard > 0) {
694
+ discard(toDiscard);
695
+ currentEntry.remaining -= toDiscard;
696
+ }
697
+ if (currentEntry.remaining > 0)
698
+ return false;
699
+ return unpacker.skipPadding();
700
+ },
701
+ validateEOF() {
702
+ if (strict) {
703
+ if (!eof)
704
+ throw truncateErr;
705
+ if (available() > 0) {
706
+ if (pull(available()).some((byte) => byte !== 0))
707
+ throw new Error("Invalid EOF.");
708
+ }
709
+ }
710
+ }
711
+ };
712
+ return unpacker;
713
+ }
714
+ function isZeroBlock(block) {
715
+ if (block.byteOffset % 8 === 0) {
716
+ const view = new BigUint64Array(block.buffer, block.byteOffset, block.length / 8);
717
+ for (let i = 0;i < view.length; i++)
718
+ if (view[i] !== 0n)
719
+ return false;
720
+ return true;
721
+ }
722
+ for (let i = 0;i < block.length; i++)
723
+ if (block[i] !== 0)
724
+ return false;
725
+ return true;
726
+ }
727
+
728
+ // node_modules/modern-tar/dist/fs/index.js
729
+ import * as fs$1 from "node:fs/promises";
730
+ import { cpus } from "node:os";
731
+ import * as path from "node:path";
732
+ import { Readable, Writable } from "node:stream";
733
+ import * as fs from "node:fs";
734
+ var createCache = () => {
735
+ const m = /* @__PURE__ */ new Map;
736
+ return {
737
+ get(k) {
738
+ const v = m.get(k);
739
+ if (m.delete(k))
740
+ m.set(k, v);
741
+ return v;
742
+ },
743
+ set(k, v) {
744
+ if (m.set(k, v).size > 1e4)
745
+ m.delete(m.keys().next().value);
746
+ }
747
+ };
748
+ };
749
+ var unicodeCache = createCache();
750
+ var normalizeUnicode = (s) => {
751
+ for (let i = 0;i < s.length; i++)
752
+ if (s.charCodeAt(i) >= 128) {
753
+ const cached = unicodeCache.get(s);
754
+ if (cached !== undefined)
755
+ return cached;
756
+ const normalized = s.normalize("NFD");
757
+ unicodeCache.set(s, normalized);
758
+ return normalized;
759
+ }
760
+ return s;
761
+ };
762
+ function validateBounds(targetPath, destDir, errorMessage) {
763
+ const target = normalizeUnicode(path.resolve(targetPath));
764
+ const dest = path.resolve(destDir);
765
+ if (target !== dest && !target.startsWith(dest + path.sep))
766
+ throw new Error(errorMessage);
767
+ }
768
+ var win32Reserved = {
769
+ ":": "",
770
+ "<": "",
771
+ ">": "",
772
+ "|": "",
773
+ "?": "",
774
+ "*": "",
775
+ '"': ""
776
+ };
777
+ function normalizeName(name) {
778
+ const path2 = name.replace(/\\/g, "/");
779
+ if (path2.split("/").includes("..") || /^[a-zA-Z]:\.\./.test(path2))
780
+ throw new Error(`${name} points outside extraction directory`);
781
+ let relative = path2;
782
+ if (/^[a-zA-Z]:/.test(relative))
783
+ relative = relative.replace(/^[a-zA-Z]:[/\\]?/, "");
784
+ else if (relative.startsWith("/"))
785
+ relative = relative.replace(/^\/+/, "");
786
+ if (process.platform === "win32")
787
+ return relative.replace(/[<>:"|?*]/g, (char) => win32Reserved[char]);
788
+ return relative;
789
+ }
790
+ var normalizeHeaderName = (s) => normalizeUnicode(normalizeName(s.replace(/\/+$/, "")));
791
+ var packTarSources = packTar;
792
+ function packTar(sources, options = {}) {
793
+ const stream = new Readable({ read() {} });
794
+ (async () => {
795
+ const packer = createTarPacker((chunk) => stream.push(Buffer.from(chunk)), stream.destroy.bind(stream), () => stream.push(null));
796
+ const { dereference = false, filter, map, baseDir, concurrency = cpus().length || 8 } = options;
797
+ const isDir = typeof sources === "string";
798
+ const directoryPath = isDir ? path.resolve(sources) : null;
799
+ const jobs = isDir ? (await fs$1.readdir(directoryPath, { withFileTypes: true })).map((entry) => ({
800
+ type: entry.isDirectory() ? DIRECTORY : FILE,
801
+ source: path.join(directoryPath, entry.name),
802
+ target: entry.name
803
+ })) : sources;
804
+ const results = /* @__PURE__ */ new Map;
805
+ const resolvers = /* @__PURE__ */ new Map;
806
+ const seenInodes = /* @__PURE__ */ new Map;
807
+ let jobIndex = 0;
808
+ let writeIndex = 0;
809
+ let activeWorkers = 0;
810
+ let allJobsQueued = false;
811
+ const writer = async () => {
812
+ const readBufferSmall = Buffer.alloc(64 * 1024);
813
+ let readBufferLarge = null;
814
+ while (true) {
815
+ if (stream.destroyed)
816
+ return;
817
+ if (allJobsQueued && writeIndex >= jobs.length)
818
+ break;
819
+ if (!results.has(writeIndex)) {
820
+ await new Promise((resolve2) => resolvers.set(writeIndex, resolve2));
821
+ continue;
822
+ }
823
+ const result = results.get(writeIndex);
824
+ results.delete(writeIndex);
825
+ resolvers.delete(writeIndex);
826
+ if (!result) {
827
+ writeIndex++;
828
+ continue;
829
+ }
830
+ packer.add(result.header);
831
+ if (result.body)
832
+ if (result.body instanceof Uint8Array) {
833
+ if (result.body.length > 0)
834
+ packer.write(result.body);
835
+ } else if (result.body instanceof Readable || result.body instanceof ReadableStream)
836
+ try {
837
+ for await (const chunk of result.body) {
838
+ if (stream.destroyed)
839
+ break;
840
+ packer.write(chunk instanceof Uint8Array ? chunk : Buffer.from(chunk));
841
+ }
842
+ } catch (error) {
843
+ stream.destroy(error);
844
+ return;
845
+ }
846
+ else {
847
+ const { handle, size } = result.body;
848
+ const readBuffer = size > 1048576 ? readBufferLarge ??= Buffer.alloc(512 * 1024) : readBufferSmall;
849
+ try {
850
+ let bytesLeft = size;
851
+ while (bytesLeft > 0 && !stream.destroyed) {
852
+ const toRead = Math.min(bytesLeft, readBuffer.length);
853
+ const { bytesRead } = await handle.read(readBuffer, 0, toRead, null);
854
+ if (bytesRead === 0)
855
+ break;
856
+ packer.write(readBuffer.subarray(0, bytesRead));
857
+ bytesLeft -= bytesRead;
858
+ }
859
+ } catch (error) {
860
+ stream.destroy(error);
861
+ return;
862
+ } finally {
863
+ await handle.close();
864
+ }
865
+ }
866
+ packer.endEntry();
867
+ writeIndex++;
868
+ }
869
+ };
870
+ const controller = () => {
871
+ if (stream.destroyed || allJobsQueued)
872
+ return;
873
+ while (activeWorkers < concurrency && jobIndex < jobs.length) {
874
+ activeWorkers++;
875
+ const currentIndex = jobIndex++;
876
+ processJob(jobs[currentIndex], currentIndex).catch(stream.destroy.bind(stream)).finally(() => {
877
+ activeWorkers--;
878
+ controller();
879
+ });
880
+ }
881
+ if (activeWorkers === 0 && jobIndex >= jobs.length) {
882
+ allJobsQueued = true;
883
+ resolvers.get(writeIndex)?.();
884
+ }
885
+ };
886
+ const processJob = async (job, index) => {
887
+ let jobResult = null;
888
+ const target = normalizeName(job.target);
889
+ try {
890
+ if (job.type === "content" || job.type === "stream") {
891
+ let body2;
892
+ let size;
893
+ const isDir2 = target.endsWith("/");
894
+ if (job.type === "stream") {
895
+ if (!isDir2 && job.size <= 0 || isDir2 && job.size !== 0)
896
+ throw new Error(isDir2 ? "Streams for directories must have size 0." : "Streams require a positive size.");
897
+ size = job.size;
898
+ body2 = job.content;
899
+ } else {
900
+ const content = await normalizeBody(job.content);
901
+ size = content.length;
902
+ body2 = content;
903
+ }
904
+ const stat3 = {
905
+ size: isDir2 ? 0 : size,
906
+ isFile: () => !isDir2,
907
+ isDirectory: () => isDir2,
908
+ isSymbolicLink: () => false,
909
+ mode: job.mode,
910
+ mtime: job.mtime ?? /* @__PURE__ */ new Date,
911
+ uid: job.uid ?? 0,
912
+ gid: job.gid ?? 0
913
+ };
914
+ if (filter && !filter(target, stat3))
915
+ return;
916
+ let header2 = {
917
+ name: target,
918
+ type: isDir2 ? DIRECTORY : FILE,
919
+ size: isDir2 ? 0 : size,
920
+ mode: stat3.mode,
921
+ mtime: stat3.mtime,
922
+ uid: stat3.uid,
923
+ gid: stat3.gid,
924
+ uname: job.uname,
925
+ gname: job.gname
926
+ };
927
+ if (map)
928
+ header2 = map(header2);
929
+ jobResult = {
930
+ header: header2,
931
+ body: isDir2 ? undefined : body2
932
+ };
933
+ return;
934
+ }
935
+ let stat2 = await fs$1.lstat(job.source, { bigint: true });
936
+ if (dereference && stat2.isSymbolicLink()) {
937
+ const linkTarget = await fs$1.readlink(job.source);
938
+ const resolved = path.resolve(path.dirname(job.source), linkTarget);
939
+ const resolvedBase = baseDir ?? directoryPath ?? process.cwd();
940
+ if (!resolved.startsWith(resolvedBase + path.sep) && resolved !== resolvedBase)
941
+ return;
942
+ stat2 = await fs$1.stat(job.source, { bigint: true });
943
+ }
944
+ if (filter && !filter(job.source, stat2))
945
+ return;
946
+ let header = {
947
+ name: target,
948
+ size: 0,
949
+ mode: job.mode ?? Number(stat2.mode),
950
+ mtime: job.mtime ?? stat2.mtime,
951
+ uid: job.uid ?? Number(stat2.uid),
952
+ gid: job.gid ?? Number(stat2.gid),
953
+ uname: job.uname,
954
+ gname: job.gname,
955
+ type: FILE
956
+ };
957
+ let body;
958
+ if (stat2.isDirectory()) {
959
+ header.type = DIRECTORY;
960
+ header.name = target.endsWith("/") ? target : `${target}/`;
961
+ try {
962
+ for (const d of await fs$1.readdir(job.source, { withFileTypes: true }))
963
+ jobs.push({
964
+ type: d.isDirectory() ? DIRECTORY : FILE,
965
+ source: path.join(job.source, d.name),
966
+ target: `${header.name}${d.name}`
967
+ });
968
+ } catch {}
969
+ } else if (stat2.isSymbolicLink()) {
970
+ header.type = SYMLINK;
971
+ header.linkname = await fs$1.readlink(job.source);
972
+ } else if (stat2.isFile()) {
973
+ header.size = Number(stat2.size);
974
+ if (stat2.nlink > 1 && seenInodes.has(stat2.ino)) {
975
+ header.type = LINK;
976
+ header.linkname = seenInodes.get(stat2.ino);
977
+ header.size = 0;
978
+ } else {
979
+ if (stat2.nlink > 1)
980
+ seenInodes.set(stat2.ino, target);
981
+ if (header.size > 0)
982
+ if (header.size < 32 * 1024)
983
+ body = await fs$1.readFile(job.source);
984
+ else
985
+ body = {
986
+ handle: await fs$1.open(job.source, "r"),
987
+ size: header.size
988
+ };
989
+ }
990
+ } else
991
+ return;
992
+ if (map)
993
+ header = map(header);
994
+ jobResult = {
995
+ header,
996
+ body
997
+ };
998
+ } finally {
999
+ results.set(index, jobResult);
1000
+ resolvers.get(index)?.();
1001
+ }
1002
+ };
1003
+ controller();
1004
+ await writer();
1005
+ if (!stream.destroyed)
1006
+ packer.finalize();
1007
+ })().catch((error) => stream.destroy(error));
1008
+ return stream;
1009
+ }
1010
+ var createOperationQueue = (concurrency) => {
1011
+ let active = 0;
1012
+ const tasks = [];
1013
+ let head = 0;
1014
+ let idle = null;
1015
+ let resolveIdle = null;
1016
+ const ensureIdle = () => idle ??= new Promise((resolve2) => resolveIdle = resolve2);
1017
+ const flush = () => {
1018
+ while (active < concurrency && head < tasks.length) {
1019
+ const task = tasks[head++];
1020
+ active++;
1021
+ task().finally(() => {
1022
+ active--;
1023
+ flush();
1024
+ });
1025
+ }
1026
+ if (head === tasks.length) {
1027
+ tasks.length = 0;
1028
+ head = 0;
1029
+ if (active === 0 && resolveIdle) {
1030
+ resolveIdle();
1031
+ idle = null;
1032
+ resolveIdle = null;
1033
+ }
1034
+ }
1035
+ };
1036
+ return {
1037
+ add(op) {
1038
+ const wasIdle = active === 0 && head === tasks.length;
1039
+ return new Promise((resolve2, reject) => {
1040
+ tasks.push(() => Promise.resolve().then(op).then(resolve2, reject));
1041
+ if (wasIdle)
1042
+ ensureIdle();
1043
+ flush();
1044
+ });
1045
+ },
1046
+ onIdle() {
1047
+ return active === 0 && head === tasks.length ? Promise.resolve() : ensureIdle();
1048
+ }
1049
+ };
1050
+ };
1051
+ var BATCH_BYTES = 256 * 1024;
1052
+ var OPEN_FLAGS = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_TRUNC | (fs.constants.O_NOFOLLOW ?? 0);
1053
+ var STATE_UNOPENED = 0;
1054
+ var STATE_OPENING = 1;
1055
+ var STATE_OPEN = 2;
1056
+ var STATE_CLOSED = 3;
1057
+ var STATE_FAILED = 4;
1058
+ var DRAINED_PROMISE = Promise.resolve();
1059
+ function createFileSink(path2, { mode = 438, mtime } = {}) {
1060
+ let state = STATE_UNOPENED;
1061
+ let flushing = false;
1062
+ let fd = null;
1063
+ let queue = [];
1064
+ let spare = [];
1065
+ let bytes = 0;
1066
+ let storedError = null;
1067
+ let endPromise = null;
1068
+ let endResolve = null;
1069
+ let endReject = null;
1070
+ const waitResolves = [];
1071
+ const waitRejects = [];
1072
+ const settleWaiters = () => {
1073
+ if (waitResolves.length === 0)
1074
+ return;
1075
+ for (let i = 0;i < waitResolves.length; i++)
1076
+ waitResolves[i]();
1077
+ waitResolves.length = 0;
1078
+ waitRejects.length = 0;
1079
+ };
1080
+ const failWaiters = (error) => {
1081
+ if (waitRejects.length === 0)
1082
+ return;
1083
+ for (let i = 0;i < waitRejects.length; i++)
1084
+ waitRejects[i](error);
1085
+ waitRejects.length = 0;
1086
+ waitResolves.length = 0;
1087
+ };
1088
+ const resetBuffers = () => {
1089
+ bytes = 0;
1090
+ queue.length = 0;
1091
+ spare.length = 0;
1092
+ };
1093
+ const finish = () => {
1094
+ state = STATE_CLOSED;
1095
+ endResolve?.();
1096
+ settleWaiters();
1097
+ };
1098
+ const swapQueues = () => {
1099
+ const current = queue;
1100
+ queue = spare;
1101
+ spare = current;
1102
+ queue.length = 0;
1103
+ return current;
1104
+ };
1105
+ const fail = (error) => {
1106
+ if (storedError)
1107
+ return;
1108
+ storedError = error;
1109
+ state = STATE_FAILED;
1110
+ resetBuffers();
1111
+ flushing = false;
1112
+ const fdToClose = fd;
1113
+ fd = null;
1114
+ if (fdToClose !== null)
1115
+ fs.ftruncate(fdToClose, 0, () => fs.close(fdToClose));
1116
+ endReject?.(error);
1117
+ failWaiters(error);
1118
+ };
1119
+ const close2 = () => {
1120
+ if (fd === null) {
1121
+ finish();
1122
+ return;
1123
+ }
1124
+ const fdToClose = fd;
1125
+ fd = null;
1126
+ if (mtime)
1127
+ fs.futimes(fdToClose, mtime, mtime, (err) => {
1128
+ if (err)
1129
+ return fail(err);
1130
+ fs.close(fdToClose, (closeErr) => {
1131
+ if (closeErr)
1132
+ fail(closeErr);
1133
+ else
1134
+ finish();
1135
+ });
1136
+ });
1137
+ else
1138
+ fs.close(fdToClose, (err) => {
1139
+ if (err)
1140
+ fail(err);
1141
+ else
1142
+ finish();
1143
+ });
1144
+ };
1145
+ const flush = () => {
1146
+ if (flushing || queue.length === 0 || state !== STATE_OPEN)
1147
+ return;
1148
+ flushing = true;
1149
+ const bufs = swapQueues();
1150
+ const onDone = (err, written = 0) => {
1151
+ if (err)
1152
+ return fail(err);
1153
+ flushing = false;
1154
+ bytes -= written;
1155
+ spare.length = 0;
1156
+ if (bytes < BATCH_BYTES)
1157
+ settleWaiters();
1158
+ if (queue.length > 0)
1159
+ flush();
1160
+ else if (endResolve)
1161
+ close2();
1162
+ };
1163
+ if (bufs.length === 1) {
1164
+ const buf = bufs[0];
1165
+ fs.write(fd, buf, 0, buf.length, null, onDone);
1166
+ } else
1167
+ fs.writev(fd, bufs, onDone);
1168
+ };
1169
+ const open3 = () => {
1170
+ if (state !== STATE_UNOPENED)
1171
+ return;
1172
+ state = STATE_OPENING;
1173
+ fs.open(path2, OPEN_FLAGS, mode, (err, openFd) => {
1174
+ if (err)
1175
+ return fail(err);
1176
+ if (state === STATE_CLOSED || state === STATE_FAILED) {
1177
+ fs.close(openFd);
1178
+ return;
1179
+ }
1180
+ fd = openFd;
1181
+ state = STATE_OPEN;
1182
+ if (endResolve)
1183
+ if (queue.length > 0)
1184
+ flush();
1185
+ else
1186
+ close2();
1187
+ else if (bytes >= BATCH_BYTES && !flushing)
1188
+ flush();
1189
+ else
1190
+ settleWaiters();
1191
+ });
1192
+ };
1193
+ const write2 = (chunk) => {
1194
+ if (storedError || state >= STATE_CLOSED || endResolve)
1195
+ return false;
1196
+ if (state !== STATE_OPEN && state !== STATE_OPENING)
1197
+ open3();
1198
+ const buf = Buffer.isBuffer(chunk) ? chunk : chunk instanceof Uint8Array ? Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength) : Buffer.from(chunk);
1199
+ if (buf.length === 0)
1200
+ return bytes < BATCH_BYTES;
1201
+ queue.push(buf);
1202
+ bytes += buf.length;
1203
+ if (state === STATE_OPEN && !flushing && bytes >= BATCH_BYTES)
1204
+ flush();
1205
+ return bytes < BATCH_BYTES;
1206
+ };
1207
+ const waitDrain = () => {
1208
+ if (bytes < BATCH_BYTES || state !== STATE_OPEN)
1209
+ return DRAINED_PROMISE;
1210
+ return new Promise((resolve2, reject) => {
1211
+ waitResolves.push(resolve2);
1212
+ waitRejects.push(reject);
1213
+ });
1214
+ };
1215
+ const end = () => {
1216
+ if (state >= STATE_CLOSED)
1217
+ return DRAINED_PROMISE;
1218
+ if (storedError)
1219
+ return Promise.reject(storedError);
1220
+ if (endPromise)
1221
+ return endPromise;
1222
+ endPromise = new Promise((resolve2, reject) => {
1223
+ endResolve = resolve2;
1224
+ endReject = reject;
1225
+ if (state !== STATE_OPEN && state !== STATE_OPENING)
1226
+ open3();
1227
+ else if (state === STATE_OPEN && !flushing)
1228
+ if (queue.length > 0)
1229
+ flush();
1230
+ else
1231
+ close2();
1232
+ });
1233
+ return endPromise;
1234
+ };
1235
+ const destroy = (error) => {
1236
+ if (error) {
1237
+ fail(error);
1238
+ return;
1239
+ }
1240
+ if (state >= STATE_CLOSED || storedError)
1241
+ return;
1242
+ resetBuffers();
1243
+ flushing = false;
1244
+ if (fd !== null) {
1245
+ const fdToClose = fd;
1246
+ fd = null;
1247
+ fs.close(fdToClose);
1248
+ }
1249
+ finish();
1250
+ };
1251
+ return {
1252
+ write: write2,
1253
+ end,
1254
+ destroy,
1255
+ waitDrain
1256
+ };
1257
+ }
1258
+ var ENOENT = "ENOENT";
1259
+ var createPathCache = (destDirPath, options) => {
1260
+ const { maxDepth = 1024, dmode } = options;
1261
+ const dirPromises = createCache();
1262
+ const pathConflicts = /* @__PURE__ */ new Map;
1263
+ const deferredLinks = [];
1264
+ const realDirCache = createCache();
1265
+ const initializeDestDir = async (destDirPath2) => {
1266
+ const symbolic = normalizeUnicode(path.resolve(destDirPath2));
1267
+ try {
1268
+ await fs$1.mkdir(symbolic, { recursive: true });
1269
+ } catch (err) {
1270
+ if (err.code === ENOENT) {
1271
+ const parentDir = path.dirname(symbolic);
1272
+ if (parentDir === symbolic)
1273
+ throw err;
1274
+ await fs$1.mkdir(parentDir, { recursive: true });
1275
+ await fs$1.mkdir(symbolic, { recursive: true });
1276
+ } else
1277
+ throw err;
1278
+ }
1279
+ try {
1280
+ return {
1281
+ symbolic,
1282
+ real: await fs$1.realpath(symbolic)
1283
+ };
1284
+ } catch (err) {
1285
+ if (err.code === ENOENT)
1286
+ return {
1287
+ symbolic,
1288
+ real: symbolic
1289
+ };
1290
+ throw err;
1291
+ }
1292
+ };
1293
+ const destDirPromise = initializeDestDir(destDirPath);
1294
+ destDirPromise.catch(() => {});
1295
+ const getRealDir = async (dirPath, errorMessage) => {
1296
+ const destDir = await destDirPromise;
1297
+ if (dirPath === destDir.symbolic) {
1298
+ validateBounds(destDir.real, destDir.real, errorMessage);
1299
+ return destDir.real;
1300
+ }
1301
+ let promise = realDirCache.get(dirPath);
1302
+ if (!promise) {
1303
+ promise = fs$1.realpath(dirPath).then((realPath) => {
1304
+ validateBounds(realPath, destDir.real, errorMessage);
1305
+ return realPath;
1306
+ });
1307
+ realDirCache.set(dirPath, promise);
1308
+ }
1309
+ const realDir = await promise;
1310
+ validateBounds(realDir, destDir.real, errorMessage);
1311
+ return realDir;
1312
+ };
1313
+ const prepareDirectory = async (dirPath, mode) => {
1314
+ let promise = dirPromises.get(dirPath);
1315
+ if (promise)
1316
+ return promise;
1317
+ promise = (async () => {
1318
+ if (dirPath === (await destDirPromise).symbolic)
1319
+ return;
1320
+ await prepareDirectory(path.dirname(dirPath));
1321
+ try {
1322
+ const stat2 = await fs$1.lstat(dirPath);
1323
+ if (stat2.isDirectory())
1324
+ return;
1325
+ if (stat2.isSymbolicLink())
1326
+ try {
1327
+ const realPath = await getRealDir(dirPath, `Symlink "${dirPath}" points outside the extraction directory.`);
1328
+ if ((await fs$1.stat(realPath)).isDirectory())
1329
+ return;
1330
+ } catch (err) {
1331
+ if (err.code === ENOENT)
1332
+ throw new Error(`Symlink "${dirPath}" points outside the extraction directory.`);
1333
+ throw err;
1334
+ }
1335
+ throw new Error(`"${dirPath}" is not a valid directory component.`);
1336
+ } catch (err) {
1337
+ if (err.code === ENOENT) {
1338
+ await fs$1.mkdir(dirPath, { mode: mode ?? options.dmode });
1339
+ return;
1340
+ }
1341
+ throw err;
1342
+ }
1343
+ })();
1344
+ dirPromises.set(dirPath, promise);
1345
+ return promise;
1346
+ };
1347
+ return {
1348
+ async ready() {
1349
+ await destDirPromise;
1350
+ },
1351
+ async preparePath(header) {
1352
+ const { name, linkname, type, mode, mtime } = header;
1353
+ const normalizedName = normalizeHeaderName(name);
1354
+ const destDir = await destDirPromise;
1355
+ const outPath = path.join(destDir.symbolic, normalizedName);
1356
+ validateBounds(outPath, destDir.symbolic, `Entry "${name}" points outside the extraction directory.`);
1357
+ if (maxDepth !== Infinity) {
1358
+ let depth = 1;
1359
+ for (const char of normalizedName)
1360
+ if (char === "/" && ++depth > maxDepth)
1361
+ throw new Error("Tar exceeds max specified depth.");
1362
+ }
1363
+ const prevOp = pathConflicts.get(normalizedName);
1364
+ if (prevOp) {
1365
+ if (prevOp === "directory" && type !== "directory" || prevOp !== "directory" && type === "directory")
1366
+ throw new Error(`Path conflict ${type} over existing ${prevOp} at "${name}"`);
1367
+ return;
1368
+ }
1369
+ const parentDir = path.dirname(outPath);
1370
+ switch (type) {
1371
+ case DIRECTORY: {
1372
+ pathConflicts.set(normalizedName, DIRECTORY);
1373
+ const safeMode = mode ? mode & 511 : undefined;
1374
+ await prepareDirectory(outPath, dmode ?? safeMode);
1375
+ if (mtime)
1376
+ await fs$1.lutimes(outPath, mtime, mtime).catch(() => {});
1377
+ return;
1378
+ }
1379
+ case FILE:
1380
+ pathConflicts.set(normalizedName, FILE);
1381
+ await prepareDirectory(parentDir);
1382
+ return outPath;
1383
+ case SYMLINK:
1384
+ pathConflicts.set(normalizedName, SYMLINK);
1385
+ if (!linkname)
1386
+ return;
1387
+ await prepareDirectory(parentDir);
1388
+ validateBounds(path.resolve(parentDir, linkname), destDir.symbolic, `Symlink "${linkname}" points outside the extraction directory.`);
1389
+ await fs$1.symlink(linkname, outPath);
1390
+ if (mtime)
1391
+ await fs$1.lutimes(outPath, mtime, mtime).catch(() => {});
1392
+ return;
1393
+ case LINK: {
1394
+ pathConflicts.set(normalizedName, LINK);
1395
+ if (!linkname)
1396
+ return;
1397
+ const normalizedLink = normalizeUnicode(linkname);
1398
+ if (path.isAbsolute(normalizedLink))
1399
+ throw new Error(`Hardlink "${linkname}" points outside the extraction directory.`);
1400
+ const linkTarget = path.join(destDir.symbolic, normalizedLink);
1401
+ validateBounds(linkTarget, destDir.symbolic, `Hardlink "${linkname}" points outside the extraction directory.`);
1402
+ await prepareDirectory(path.dirname(linkTarget));
1403
+ const realTargetParent = await getRealDir(path.dirname(linkTarget), `Hardlink "${linkname}" points outside the extraction directory.`);
1404
+ validateBounds(path.join(realTargetParent, path.basename(linkTarget)), destDir.real, `Hardlink "${linkname}" points outside the extraction directory.`);
1405
+ if (linkTarget !== outPath) {
1406
+ await prepareDirectory(parentDir);
1407
+ deferredLinks.push({
1408
+ linkTarget,
1409
+ outPath
1410
+ });
1411
+ }
1412
+ return;
1413
+ }
1414
+ default:
1415
+ return;
1416
+ }
1417
+ },
1418
+ async applyLinks() {
1419
+ for (const { linkTarget, outPath } of deferredLinks)
1420
+ try {
1421
+ await fs$1.link(linkTarget, outPath);
1422
+ } catch (err) {
1423
+ if (err.code === ENOENT)
1424
+ throw new Error(`Hardlink target "${linkTarget}" does not exist for link at "${outPath}".`);
1425
+ throw err;
1426
+ }
1427
+ }
1428
+ };
1429
+ };
1430
+ function unpackTar(directoryPath, options = {}) {
1431
+ const unpacker = createUnpacker(options);
1432
+ const opQueue = createOperationQueue(options.concurrency || cpus().length || 8);
1433
+ const pathCache = createPathCache(directoryPath, options);
1434
+ let currentFileStream = null;
1435
+ let currentWriteCallback = null;
1436
+ let queuedError = null;
1437
+ const onQueuedError = (err) => {
1438
+ queuedError ??= err;
1439
+ if (!writable.destroyed)
1440
+ writable.destroy(err);
1441
+ };
1442
+ const writable = new Writable({
1443
+ async write(chunk, _, cb) {
1444
+ try {
1445
+ unpacker.write(chunk);
1446
+ if (unpacker.isEntryActive()) {
1447
+ if (currentFileStream && currentWriteCallback) {
1448
+ let needsDrain = false;
1449
+ const writeCallback = currentWriteCallback;
1450
+ while (!unpacker.isBodyComplete()) {
1451
+ needsDrain = false;
1452
+ if (unpacker.streamBody(writeCallback) === 0)
1453
+ if (needsDrain)
1454
+ await currentFileStream.waitDrain();
1455
+ else {
1456
+ cb();
1457
+ return;
1458
+ }
1459
+ }
1460
+ while (!unpacker.skipPadding()) {
1461
+ cb();
1462
+ return;
1463
+ }
1464
+ const streamToClose = currentFileStream;
1465
+ if (streamToClose)
1466
+ opQueue.add(() => streamToClose.end()).catch(onQueuedError);
1467
+ currentFileStream = null;
1468
+ currentWriteCallback = null;
1469
+ } else if (!unpacker.skipEntry()) {
1470
+ cb();
1471
+ return;
1472
+ }
1473
+ }
1474
+ while (true) {
1475
+ const header = unpacker.readHeader();
1476
+ if (header === undefined || header === null) {
1477
+ cb();
1478
+ return;
1479
+ }
1480
+ const transformedHeader = transformHeader(header, options);
1481
+ if (!transformedHeader) {
1482
+ if (!unpacker.skipEntry()) {
1483
+ cb();
1484
+ return;
1485
+ }
1486
+ continue;
1487
+ }
1488
+ const outPath = await opQueue.add(() => pathCache.preparePath(transformedHeader));
1489
+ if (outPath) {
1490
+ const safeMode = transformedHeader.mode ? transformedHeader.mode & 511 : undefined;
1491
+ const fileStream = createFileSink(outPath, {
1492
+ mode: options.fmode ?? safeMode,
1493
+ mtime: transformedHeader.mtime ?? undefined
1494
+ });
1495
+ let needsDrain = false;
1496
+ const writeCallback = (chunk2) => {
1497
+ const writeOk = fileStream.write(chunk2);
1498
+ if (!writeOk)
1499
+ needsDrain = true;
1500
+ return writeOk;
1501
+ };
1502
+ while (!unpacker.isBodyComplete()) {
1503
+ needsDrain = false;
1504
+ if (unpacker.streamBody(writeCallback) === 0)
1505
+ if (needsDrain)
1506
+ await fileStream.waitDrain();
1507
+ else {
1508
+ currentFileStream = fileStream;
1509
+ currentWriteCallback = writeCallback;
1510
+ cb();
1511
+ return;
1512
+ }
1513
+ }
1514
+ while (!unpacker.skipPadding()) {
1515
+ currentFileStream = fileStream;
1516
+ currentWriteCallback = writeCallback;
1517
+ cb();
1518
+ return;
1519
+ }
1520
+ opQueue.add(() => fileStream.end()).catch(onQueuedError);
1521
+ } else if (!unpacker.skipEntry()) {
1522
+ cb();
1523
+ return;
1524
+ }
1525
+ }
1526
+ } catch (err) {
1527
+ cb(err);
1528
+ }
1529
+ },
1530
+ async final(cb) {
1531
+ try {
1532
+ unpacker.end();
1533
+ unpacker.validateEOF();
1534
+ await pathCache.ready();
1535
+ await opQueue.onIdle();
1536
+ if (queuedError)
1537
+ throw queuedError;
1538
+ await pathCache.applyLinks();
1539
+ cb();
1540
+ } catch (err) {
1541
+ cb(err);
1542
+ }
1543
+ },
1544
+ destroy(error, callback) {
1545
+ (async () => {
1546
+ if (currentFileStream) {
1547
+ currentFileStream.destroy(error ?? undefined);
1548
+ currentFileStream = null;
1549
+ currentWriteCallback = null;
1550
+ }
1551
+ await opQueue.onIdle();
1552
+ })().then(() => callback(error ?? null), (e) => callback(error ?? (e instanceof Error ? e : /* @__PURE__ */ new Error("Stream destroyed"))));
1553
+ }
1554
+ });
1555
+ return writable;
1556
+ }
1557
+ export {
1558
+ unpackTar,
1559
+ packTarSources,
1560
+ packTar
1561
+ };