@gjsify/tar 0.3.8
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/lib/esm/extract.js +102 -0
- package/lib/esm/index.js +13 -0
- package/lib/esm/parser.js +199 -0
- package/lib/tsconfig.build.tsbuildinfo +1 -0
- package/lib/types/extract.d.ts +26 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/parser.d.ts +22 -0
- package/package.json +41 -0
- package/src/extract.ts +147 -0
- package/src/index.spec.ts +280 -0
- package/src/index.ts +8 -0
- package/src/parser.ts +276 -0
- package/src/test.mts +5 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { parseTar } from "./parser.js";
|
|
4
|
+
async function extractTarball(input, destDir, opts = {}) {
|
|
5
|
+
const buf = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
6
|
+
const isGz = opts.gzip ?? (buf.length >= 2 && buf[0] === 31 && buf[1] === 139);
|
|
7
|
+
const tarBytes = isGz ? await gunzip(buf) : buf;
|
|
8
|
+
const entries = parseTar(tarBytes);
|
|
9
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
10
|
+
const strip = opts.strip ?? 1;
|
|
11
|
+
const preventEscape = opts.preventEscape ?? true;
|
|
12
|
+
const result = { files: [], directories: [], symlinks: [], skipped: 0 };
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const stripped = stripComponents(entry.name, strip);
|
|
15
|
+
if (stripped === null || stripped === "") {
|
|
16
|
+
result.skipped++;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const resolved = path.resolve(destDir, stripped);
|
|
20
|
+
if (preventEscape && !isInside(resolved, destDir)) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`tar: refusing to extract ${entry.name} outside ${destDir} (resolved=${resolved})`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (opts.filter && !opts.filter(entry, resolved)) {
|
|
26
|
+
result.skipped++;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (entry.type === "directory") {
|
|
30
|
+
fs.mkdirSync(resolved, { recursive: true });
|
|
31
|
+
result.directories.push(resolved);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (entry.type === "file") {
|
|
35
|
+
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
36
|
+
fs.writeFileSync(resolved, entry.body);
|
|
37
|
+
const overrideMode = opts.chmod?.(entry, resolved);
|
|
38
|
+
const finalMode = overrideMode ?? entry.mode & 511;
|
|
39
|
+
if (finalMode > 0) {
|
|
40
|
+
try {
|
|
41
|
+
fs.chmodSync(resolved, finalMode);
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
result.files.push(resolved);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (entry.type === "symlink") {
|
|
49
|
+
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
50
|
+
try {
|
|
51
|
+
fs.symlinkSync(entry.linkname, resolved);
|
|
52
|
+
result.symlinks.push(resolved);
|
|
53
|
+
} catch {
|
|
54
|
+
fs.writeFileSync(resolved, entry.linkname);
|
|
55
|
+
result.files.push(resolved);
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
result.skipped++;
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
async function gunzip(input) {
|
|
64
|
+
const Decomp = globalThis.DecompressionStream;
|
|
65
|
+
if (typeof Decomp !== "function") {
|
|
66
|
+
throw new Error(
|
|
67
|
+
"@gjsify/tar: globalThis.DecompressionStream is not available \u2014 import '@gjsify/compression-streams/register' on GJS to register it"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const stream = new Blob([new Uint8Array(input)]).stream().pipeThrough(new Decomp("gzip"));
|
|
71
|
+
const chunks = [];
|
|
72
|
+
let total = 0;
|
|
73
|
+
const reader = stream.getReader();
|
|
74
|
+
for (; ; ) {
|
|
75
|
+
const { value, done } = await reader.read();
|
|
76
|
+
if (done) break;
|
|
77
|
+
const chunk = value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
78
|
+
chunks.push(chunk);
|
|
79
|
+
total += chunk.length;
|
|
80
|
+
}
|
|
81
|
+
const out = new Uint8Array(total);
|
|
82
|
+
let pos = 0;
|
|
83
|
+
for (const c of chunks) {
|
|
84
|
+
out.set(c, pos);
|
|
85
|
+
pos += c.length;
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
function stripComponents(name, n) {
|
|
90
|
+
if (n <= 0) return name;
|
|
91
|
+
const parts = name.split("/").filter((s) => s !== "");
|
|
92
|
+
if (parts.length <= n) return null;
|
|
93
|
+
return parts.slice(n).join("/");
|
|
94
|
+
}
|
|
95
|
+
function isInside(child, parent) {
|
|
96
|
+
const rel = path.relative(parent, child);
|
|
97
|
+
return rel !== "" && !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
98
|
+
}
|
|
99
|
+
export {
|
|
100
|
+
extractTarball,
|
|
101
|
+
gunzip
|
|
102
|
+
};
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
const BLOCK_SIZE = 512;
|
|
2
|
+
function parseTar(buf) {
|
|
3
|
+
const out = [];
|
|
4
|
+
let pendingPaxHeader = null;
|
|
5
|
+
let pendingLongName = null;
|
|
6
|
+
let pendingLongLink = null;
|
|
7
|
+
let offset = 0;
|
|
8
|
+
while (offset + BLOCK_SIZE <= buf.length) {
|
|
9
|
+
const header = buf.subarray(offset, offset + BLOCK_SIZE);
|
|
10
|
+
if (allZeros(header)) {
|
|
11
|
+
const next = buf.subarray(offset + BLOCK_SIZE, offset + 2 * BLOCK_SIZE);
|
|
12
|
+
if (next.length === BLOCK_SIZE && allZeros(next)) break;
|
|
13
|
+
offset += BLOCK_SIZE;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (!validateChecksum(header)) {
|
|
17
|
+
throw new TarParseError(
|
|
18
|
+
`Bad header checksum at offset ${offset} \u2014 file is not a valid tar archive`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
const rawName = readString(header, 0, 100);
|
|
22
|
+
const mode = parseOctal(header, 100, 8);
|
|
23
|
+
const size = parseOctal(header, 124, 12);
|
|
24
|
+
const mtime = parseOctal(header, 136, 12);
|
|
25
|
+
const typeflag = String.fromCharCode(header[156] || 0);
|
|
26
|
+
const linkname = readString(header, 157, 100);
|
|
27
|
+
const magic = readString(header, 257, 6);
|
|
28
|
+
const prefix = readString(header, 345, 155);
|
|
29
|
+
const uname = readString(header, 265, 32);
|
|
30
|
+
const gname = readString(header, 297, 32);
|
|
31
|
+
offset += BLOCK_SIZE;
|
|
32
|
+
const body = buf.subarray(offset, offset + size);
|
|
33
|
+
offset += alignToBlock(size);
|
|
34
|
+
if (typeflag === "x") {
|
|
35
|
+
pendingPaxHeader = parsePaxRecords(body);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (typeflag === "g") {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (typeflag === "L") {
|
|
42
|
+
pendingLongName = bytesToString(body).replace(/\0+$/, "");
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (typeflag === "K") {
|
|
46
|
+
pendingLongLink = bytesToString(body).replace(/\0+$/, "");
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
let name = rawName;
|
|
50
|
+
if (magic === "ustar" && prefix !== "") {
|
|
51
|
+
name = `${prefix}/${rawName}`;
|
|
52
|
+
}
|
|
53
|
+
if (pendingLongName !== null) {
|
|
54
|
+
name = pendingLongName;
|
|
55
|
+
pendingLongName = null;
|
|
56
|
+
}
|
|
57
|
+
let resolvedLink = linkname;
|
|
58
|
+
if (pendingLongLink !== null) {
|
|
59
|
+
resolvedLink = pendingLongLink;
|
|
60
|
+
pendingLongLink = null;
|
|
61
|
+
}
|
|
62
|
+
if (pendingPaxHeader !== null) {
|
|
63
|
+
const paxName = pendingPaxHeader.get("path");
|
|
64
|
+
if (paxName !== void 0) name = paxName;
|
|
65
|
+
const paxLink = pendingPaxHeader.get("linkpath");
|
|
66
|
+
if (paxLink !== void 0) resolvedLink = paxLink;
|
|
67
|
+
const paxSize = pendingPaxHeader.get("size");
|
|
68
|
+
if (paxSize !== void 0) {
|
|
69
|
+
const overrideSize = Number(paxSize);
|
|
70
|
+
if (Number.isFinite(overrideSize)) {
|
|
71
|
+
const realStart = offset - alignToBlock(size);
|
|
72
|
+
const sliced = buf.subarray(realStart, realStart + overrideSize);
|
|
73
|
+
offset = realStart + alignToBlock(overrideSize);
|
|
74
|
+
pendingPaxHeader = null;
|
|
75
|
+
out.push(buildEntry(name, resolvedLink, typeflag, mode, mtime, uname, gname, sliced));
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
pendingPaxHeader = null;
|
|
80
|
+
}
|
|
81
|
+
out.push(buildEntry(name, resolvedLink, typeflag, mode, mtime, uname, gname, body));
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
function buildEntry(name, linkname, typeflag, mode, mtime, uname, gname, body) {
|
|
86
|
+
return {
|
|
87
|
+
name,
|
|
88
|
+
linkname,
|
|
89
|
+
type: typeflagToType(typeflag, name),
|
|
90
|
+
mode,
|
|
91
|
+
mtime,
|
|
92
|
+
body,
|
|
93
|
+
uname,
|
|
94
|
+
gname
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function typeflagToType(typeflag, name) {
|
|
98
|
+
switch (typeflag) {
|
|
99
|
+
case "0":
|
|
100
|
+
case "\0":
|
|
101
|
+
case "":
|
|
102
|
+
return name.endsWith("/") ? "directory" : "file";
|
|
103
|
+
case "1":
|
|
104
|
+
return "hardlink";
|
|
105
|
+
case "2":
|
|
106
|
+
return "symlink";
|
|
107
|
+
case "5":
|
|
108
|
+
return "directory";
|
|
109
|
+
case "x":
|
|
110
|
+
return "pax-header";
|
|
111
|
+
case "g":
|
|
112
|
+
return "pax-global";
|
|
113
|
+
case "L":
|
|
114
|
+
return "gnu-longname";
|
|
115
|
+
case "K":
|
|
116
|
+
return "gnu-longlink";
|
|
117
|
+
default:
|
|
118
|
+
return "unknown";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function parsePaxRecords(body) {
|
|
122
|
+
const out = /* @__PURE__ */ new Map();
|
|
123
|
+
let i = 0;
|
|
124
|
+
while (i < body.length) {
|
|
125
|
+
let space = i;
|
|
126
|
+
while (space < body.length && body[space] !== 32) space++;
|
|
127
|
+
if (space >= body.length) break;
|
|
128
|
+
const lenStr = bytesToString(body.subarray(i, space));
|
|
129
|
+
const len = Number(lenStr);
|
|
130
|
+
if (!Number.isFinite(len) || len <= 0) break;
|
|
131
|
+
const recordEnd = i + len;
|
|
132
|
+
if (recordEnd > body.length) break;
|
|
133
|
+
const recBytes = body.subarray(space + 1, recordEnd - 1);
|
|
134
|
+
const recText = bytesToString(recBytes);
|
|
135
|
+
const eq = recText.indexOf("=");
|
|
136
|
+
if (eq > 0) {
|
|
137
|
+
const key = recText.slice(0, eq);
|
|
138
|
+
const value = recText.slice(eq + 1);
|
|
139
|
+
out.set(key, value);
|
|
140
|
+
}
|
|
141
|
+
i = recordEnd;
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
}
|
|
145
|
+
function readString(buf, start, len) {
|
|
146
|
+
let end = start;
|
|
147
|
+
const limit = start + len;
|
|
148
|
+
while (end < limit && buf[end] !== 0) end++;
|
|
149
|
+
return bytesToString(buf.subarray(start, end));
|
|
150
|
+
}
|
|
151
|
+
function bytesToString(buf) {
|
|
152
|
+
return new TextDecoder("utf-8", { fatal: false }).decode(buf);
|
|
153
|
+
}
|
|
154
|
+
function parseOctal(buf, start, len) {
|
|
155
|
+
if (len > 0 && (buf[start] & 128) !== 0) {
|
|
156
|
+
let n = buf[start] & 127;
|
|
157
|
+
for (let i = 1; i < len; i++) n = n * 256 + buf[start + i];
|
|
158
|
+
return n;
|
|
159
|
+
}
|
|
160
|
+
let s = "";
|
|
161
|
+
for (let i = 0; i < len; i++) {
|
|
162
|
+
const c = buf[start + i];
|
|
163
|
+
if (c === 0 || c === 32) continue;
|
|
164
|
+
s += String.fromCharCode(c);
|
|
165
|
+
}
|
|
166
|
+
if (s === "") return 0;
|
|
167
|
+
return parseInt(s, 8);
|
|
168
|
+
}
|
|
169
|
+
function alignToBlock(n) {
|
|
170
|
+
return Math.ceil(n / BLOCK_SIZE) * BLOCK_SIZE;
|
|
171
|
+
}
|
|
172
|
+
function allZeros(buf) {
|
|
173
|
+
for (let i = 0; i < buf.length; i++) {
|
|
174
|
+
if (buf[i] !== 0) return false;
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
function validateChecksum(header) {
|
|
179
|
+
const stored = parseOctal(header, 148, 8);
|
|
180
|
+
let unsigned = 0;
|
|
181
|
+
let signed = 0;
|
|
182
|
+
for (let i = 0; i < BLOCK_SIZE; i++) {
|
|
183
|
+
const byte = i >= 148 && i < 156 ? 32 : header[i];
|
|
184
|
+
unsigned += byte;
|
|
185
|
+
signed += byte > 127 ? byte - 256 : byte;
|
|
186
|
+
}
|
|
187
|
+
return stored === unsigned || stored === signed;
|
|
188
|
+
}
|
|
189
|
+
class TarParseError extends Error {
|
|
190
|
+
constructor(msg) {
|
|
191
|
+
super(msg);
|
|
192
|
+
this.name = "TarParseError";
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export {
|
|
196
|
+
BLOCK_SIZE,
|
|
197
|
+
TarParseError,
|
|
198
|
+
parseTar
|
|
199
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"fileNames":["../../../../node_modules/typescript/lib/lib.es5.d.ts","../../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../../node_modules/typescript/lib/lib.es2023.d.ts","../../../../node_modules/typescript/lib/lib.es2024.d.ts","../../../../node_modules/typescript/lib/lib.es2025.d.ts","../../../../node_modules/typescript/lib/lib.esnext.d.ts","../../../../node_modules/typescript/lib/lib.dom.d.ts","../../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../../node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../../../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../../../node_modules/typescript/lib/lib.scripthost.d.ts","../../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","../../../../node_modules/typescript/lib/lib.es2024.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2024.object.d.ts","../../../../node_modules/typescript/lib/lib.es2024.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2024.regexp.d.ts","../../../../node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.es2024.string.d.ts","../../../../node_modules/typescript/lib/lib.es2025.collection.d.ts","../../../../node_modules/typescript/lib/lib.es2025.float16.d.ts","../../../../node_modules/typescript/lib/lib.es2025.intl.d.ts","../../../../node_modules/typescript/lib/lib.es2025.iterator.d.ts","../../../../node_modules/typescript/lib/lib.es2025.promise.d.ts","../../../../node_modules/typescript/lib/lib.es2025.regexp.d.ts","../../../../node_modules/typescript/lib/lib.esnext.array.d.ts","../../../../node_modules/typescript/lib/lib.esnext.collection.d.ts","../../../../node_modules/typescript/lib/lib.esnext.date.d.ts","../../../../node_modules/typescript/lib/lib.esnext.decorators.d.ts","../../../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../../../node_modules/typescript/lib/lib.esnext.error.d.ts","../../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../../node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts","../../../../node_modules/typescript/lib/lib.esnext.temporal.d.ts","../../../../node_modules/typescript/lib/lib.esnext.typedarrays.d.ts","../../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../../node_modules/typescript/lib/lib.esnext.full.d.ts","../src/parser.ts","../src/extract.ts","../src/index.ts","../../../../node_modules/@types/node/compatibility/iterators.d.ts","../../../../node_modules/@types/node/globals.typedarray.d.ts","../../../../node_modules/@types/node/buffer.buffer.d.ts","../../../../node_modules/@types/node/globals.d.ts","../../../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../../../node_modules/@types/node/web-globals/blob.d.ts","../../../../node_modules/@types/node/web-globals/console.d.ts","../../../../node_modules/@types/node/web-globals/crypto.d.ts","../../../../node_modules/@types/node/web-globals/domexception.d.ts","../../../../node_modules/@types/node/web-globals/encoding.d.ts","../../../../node_modules/@types/node/web-globals/events.d.ts","../../../../node_modules/undici-types/utility.d.ts","../../../../node_modules/undici-types/header.d.ts","../../../../node_modules/undici-types/readable.d.ts","../../../../node_modules/undici-types/fetch.d.ts","../../../../node_modules/undici-types/formdata.d.ts","../../../../node_modules/undici-types/connector.d.ts","../../../../node_modules/undici-types/client-stats.d.ts","../../../../node_modules/undici-types/client.d.ts","../../../../node_modules/undici-types/errors.d.ts","../../../../node_modules/undici-types/dispatcher.d.ts","../../../../node_modules/undici-types/global-dispatcher.d.ts","../../../../node_modules/undici-types/global-origin.d.ts","../../../../node_modules/undici-types/pool-stats.d.ts","../../../../node_modules/undici-types/pool.d.ts","../../../../node_modules/undici-types/handlers.d.ts","../../../../node_modules/undici-types/balanced-pool.d.ts","../../../../node_modules/undici-types/round-robin-pool.d.ts","../../../../node_modules/undici-types/h2c-client.d.ts","../../../../node_modules/undici-types/agent.d.ts","../../../../node_modules/undici-types/mock-interceptor.d.ts","../../../../node_modules/undici-types/mock-call-history.d.ts","../../../../node_modules/undici-types/mock-agent.d.ts","../../../../node_modules/undici-types/mock-client.d.ts","../../../../node_modules/undici-types/mock-pool.d.ts","../../../../node_modules/undici-types/snapshot-agent.d.ts","../../../../node_modules/undici-types/mock-errors.d.ts","../../../../node_modules/undici-types/proxy-agent.d.ts","../../../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../../../node_modules/undici-types/retry-handler.d.ts","../../../../node_modules/undici-types/retry-agent.d.ts","../../../../node_modules/undici-types/api.d.ts","../../../../node_modules/undici-types/cache-interceptor.d.ts","../../../../node_modules/undici-types/interceptors.d.ts","../../../../node_modules/undici-types/util.d.ts","../../../../node_modules/undici-types/cookies.d.ts","../../../../node_modules/undici-types/patch.d.ts","../../../../node_modules/undici-types/websocket.d.ts","../../../../node_modules/undici-types/eventsource.d.ts","../../../../node_modules/undici-types/diagnostics-channel.d.ts","../../../../node_modules/undici-types/content-type.d.ts","../../../../node_modules/undici-types/cache.d.ts","../../../../node_modules/undici-types/index.d.ts","../../../../node_modules/@types/node/web-globals/fetch.d.ts","../../../../node_modules/@types/node/web-globals/importmeta.d.ts","../../../../node_modules/@types/node/web-globals/messaging.d.ts","../../../../node_modules/@types/node/web-globals/navigator.d.ts","../../../../node_modules/@types/node/web-globals/performance.d.ts","../../../../node_modules/@types/node/web-globals/storage.d.ts","../../../../node_modules/@types/node/web-globals/streams.d.ts","../../../../node_modules/@types/node/web-globals/timers.d.ts","../../../../node_modules/@types/node/web-globals/url.d.ts","../../../../node_modules/@types/node/assert.d.ts","../../../../node_modules/@types/node/assert/strict.d.ts","../../../../node_modules/@types/node/async_hooks.d.ts","../../../../node_modules/@types/node/buffer.d.ts","../../../../node_modules/@types/node/child_process.d.ts","../../../../node_modules/@types/node/cluster.d.ts","../../../../node_modules/@types/node/console.d.ts","../../../../node_modules/@types/node/constants.d.ts","../../../../node_modules/@types/node/crypto.d.ts","../../../../node_modules/@types/node/dgram.d.ts","../../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../../node_modules/@types/node/dns.d.ts","../../../../node_modules/@types/node/dns/promises.d.ts","../../../../node_modules/@types/node/domain.d.ts","../../../../node_modules/@types/node/events.d.ts","../../../../node_modules/@types/node/fs.d.ts","../../../../node_modules/@types/node/fs/promises.d.ts","../../../../node_modules/@types/node/http.d.ts","../../../../node_modules/@types/node/http2.d.ts","../../../../node_modules/@types/node/https.d.ts","../../../../node_modules/@types/node/inspector.d.ts","../../../../node_modules/@types/node/inspector.generated.d.ts","../../../../node_modules/@types/node/inspector/promises.d.ts","../../../../node_modules/@types/node/module.d.ts","../../../../node_modules/@types/node/net.d.ts","../../../../node_modules/buffer/index.d.ts","../../../../node_modules/@types/node/os.d.ts","../../../../node_modules/@types/node/path.d.ts","../../../../node_modules/@types/node/path/posix.d.ts","../../../../node_modules/@types/node/path/win32.d.ts","../../../../node_modules/@types/node/perf_hooks.d.ts","../../../../node_modules/@types/node/process.d.ts","../../../../node_modules/@types/node/punycode.d.ts","../../../../node_modules/@types/node/querystring.d.ts","../../../../node_modules/@types/node/quic.d.ts","../../../../node_modules/@types/node/readline.d.ts","../../../../node_modules/@types/node/readline/promises.d.ts","../../../../node_modules/@types/node/repl.d.ts","../../../../node_modules/@types/node/sea.d.ts","../../../../node_modules/@types/node/sqlite.d.ts","../../../../node_modules/@types/node/stream.d.ts","../../../../node_modules/@types/node/stream/consumers.d.ts","../../../../node_modules/@types/node/stream/promises.d.ts","../../../../node_modules/@types/node/stream/web.d.ts","../../../../node_modules/@types/node/string_decoder.d.ts","../../../../node_modules/@types/node/test.d.ts","../../../../node_modules/@types/node/test/reporters.d.ts","../../../../node_modules/@types/node/timers.d.ts","../../../../node_modules/@types/node/timers/promises.d.ts","../../../../node_modules/@types/node/tls.d.ts","../../../../node_modules/@types/node/trace_events.d.ts","../../../../node_modules/@types/node/tty.d.ts","../../../../node_modules/@types/node/url.d.ts","../../../../node_modules/@types/node/util.d.ts","../../../../node_modules/@types/node/util/types.d.ts","../../../../node_modules/@types/node/v8.d.ts","../../../../node_modules/@types/node/vm.d.ts","../../../../node_modules/@types/node/wasi.d.ts","../../../../node_modules/@types/node/worker_threads.d.ts","../../../../node_modules/@types/node/zlib.d.ts","../../../../node_modules/@types/node/index.d.ts"],"fileIdsList":[[99,159,160,162,170,174,177,179,180,181,194],[99,161,162,170,174,177,179,180,181,194],[162,170,174,177,179,180,181,194],[99,162,170,174,177,179,180,181,194,202],[99,162,163,168,170,173,174,177,179,180,181,183,194,199,211],[99,162,163,164,170,173,174,177,179,180,181,194],[99,162,170,174,177,179,180,181,194],[99,162,165,170,174,177,179,180,181,194,212],[99,162,166,167,170,174,177,179,180,181,185,194],[99,162,167,170,174,177,179,180,181,194,199,208],[99,162,168,170,173,174,177,179,180,181,183,194],[99,161,162,169,170,174,177,179,180,181,194],[99,162,170,171,174,177,179,180,181,194],[99,162,170,172,173,174,177,179,180,181,194],[99,161,162,170,173,174,177,179,180,181,194],[99,162,170,173,174,175,177,179,180,181,194,199,211],[99,162,170,173,174,175,177,179,180,181,194,199,202],[99,149,162,170,173,174,176,177,179,180,181,183,194,199,211],[99,162,170,173,174,176,177,179,180,181,183,194,199,208,211],[99,162,170,174,176,177,178,179,180,181,194,199,208,211],[97,98,99,100,101,102,103,104,105,106,107,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218],[99,162,170,173,174,177,179,180,181,194],[99,162,170,174,177,179,181,194],[99,162,170,174,177,179,180,181,182,194,211],[99,162,170,173,174,177,179,180,181,183,194,199],[99,162,170,174,177,179,180,181,185,194],[99,162,170,174,177,179,180,181,186,194],[99,162,170,173,174,177,179,180,181,189,194],[99,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218],[99,162,170,174,177,179,180,181,191,194],[99,162,170,174,177,179,180,181,192,194],[99,162,167,170,174,177,179,180,181,183,194,202],[99,162,170,173,174,177,179,180,181,194,195],[99,162,170,174,177,179,180,181,194,196,212,215],[99,162,170,173,174,177,179,180,181,194,199,201,202],[99,162,170,174,177,179,180,181,194,200,202],[99,162,170,174,177,179,180,181,194,202,212],[99,162,170,174,177,179,180,181,194,203],[99,159,162,170,174,177,179,180,181,194,199,205,211],[99,162,170,174,177,179,180,181,194,199,204],[99,162,170,173,174,177,179,180,181,194,206,207],[99,162,170,174,177,179,180,181,194,206,207],[99,162,167,170,174,177,179,180,181,183,194,199,208],[99,162,170,174,177,179,180,181,194,209],[99,162,170,174,177,179,180,181,183,194,210],[99,162,170,174,176,177,179,180,181,192,194,211],[99,162,170,174,177,179,180,181,194,212,213],[99,162,167,170,174,177,179,180,181,194,213],[99,162,170,174,177,179,180,181,194,199,214],[99,162,170,174,177,179,180,181,182,194,215],[99,162,170,174,177,179,180,181,194,216],[99,162,165,170,174,177,179,180,181,194],[99,162,167,170,174,177,179,180,181,194],[99,162,170,174,177,179,180,181,194,212],[99,149,162,170,174,177,179,180,181,194],[99,162,170,174,177,179,180,181,194,211],[99,162,170,174,177,179,180,181,194,217],[99,162,170,174,177,179,180,181,189,194],[99,162,170,174,177,179,180,181,194,207],[99,149,162,170,173,174,175,177,179,180,181,189,194,199,202,211,214,215,217],[99,162,170,174,177,179,180,181,194,199,218],[99,114,117,120,121,162,170,174,177,179,180,181,194,211],[99,117,162,170,174,177,179,180,181,194,199,211],[99,117,121,162,170,174,177,179,180,181,194,211],[99,162,170,174,177,179,180,181,194,199],[99,111,162,170,174,177,179,180,181,194],[99,115,162,170,174,177,179,180,181,194],[99,113,114,117,162,170,174,177,179,180,181,194,211],[99,162,170,174,177,179,180,181,183,194,208],[99,162,170,174,177,179,180,181,194,219],[99,111,162,170,174,177,179,180,181,194,219],[99,113,117,162,170,174,177,179,180,181,183,194,211],[99,108,109,110,112,116,162,170,173,174,177,179,180,181,194,199,211],[99,117,126,134,162,170,174,177,179,180,181,194],[99,109,115,162,170,174,177,179,180,181,194],[99,117,143,144,162,170,174,177,179,180,181,194],[99,109,112,117,162,170,174,177,179,180,181,194,202,211,219],[99,117,162,170,174,177,179,180,181,194],[99,113,117,162,170,174,177,179,180,181,194,211],[99,108,162,170,174,177,179,180,181,194],[99,111,112,113,115,116,117,118,119,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,144,145,146,147,148,162,170,174,177,179,180,181,194],[99,117,136,139,162,170,174,177,179,180,181,194],[99,117,126,127,128,162,170,174,177,179,180,181,194],[99,115,117,127,129,162,170,174,177,179,180,181,194],[99,116,162,170,174,177,179,180,181,194],[99,109,111,117,162,170,174,177,179,180,181,194],[99,117,121,127,129,162,170,174,177,179,180,181,194],[99,121,162,170,174,177,179,180,181,194],[99,115,117,120,162,170,174,177,179,180,181,194,211],[99,109,113,117,126,162,170,174,177,179,180,181,194],[99,117,136,162,170,174,177,179,180,181,194],[99,129,162,170,174,177,179,180,181,194],[99,111,117,143,162,170,174,177,179,180,181,194,202,217,219],[94,99,162,170,174,177,179,180,181,186,194],[94,95,99,162,170,174,177,179,180,181,194]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"1e9332c23e9a907175e0ffc6a49e236f97b48838cc8aec9ce7e4cec21e544b65","impliedFormat":1},{"version":"3753fbc1113dc511214802a2342280a8b284ab9094f6420e7aa171e868679f91","impliedFormat":1},{"version":"999ca32883495a866aa5737fe1babc764a469e4cde6ee6b136a4b9ae68853e4b","impliedFormat":1},{"version":"17f13ecb98cbc39243f2eee1f16d45cd8ec4706b03ee314f1915f1a8b42f6984","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"2a2de5b9459b3fc44decd9ce6100b72f1b002ef523126c1d3d8b2a4a63d74d78","affectsGlobalScope":true,"impliedFormat":1},{"version":"f13f4b465c99041e912db5c44129a94588e1aafee35a50eab51044833f50b4ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"0bd714129fca875f7d4c477a1a392200b0bcd13fb2e80928cd334b63830ea047","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2c9037ae6cd2c52d80ceef0b3c5ffdb488627d71529cf4f63776daf11161c9a","affectsGlobalScope":true,"impliedFormat":1},{"version":"135d5cf4d345f59f1a9caadfafcd858d3d9cc68290db616cc85797224448cccc","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc238c3f81c2984751932b6aab223cd5b830e0ac6cad76389e5e9d2ffc03287d","affectsGlobalScope":true,"impliedFormat":1},{"version":"4a07f9b76d361f572620927e5735b77d6d2101c23cdd94383eb5b706e7b36357","affectsGlobalScope":true,"impliedFormat":1},{"version":"7c4e8dc6ab834cc6baa0227e030606d29e3e8449a9f67cdf5605ea5493c4db29","affectsGlobalScope":true,"impliedFormat":1},{"version":"de7ba0fd02e06cd9a5bd4ab441ed0e122735786e67dde1e849cced1cd8b46b78","affectsGlobalScope":true,"impliedFormat":1},{"version":"6148e4e88d720a06855071c3db02069434142a8332cf9c182cda551adedf3156","affectsGlobalScope":true,"impliedFormat":1},{"version":"d63dba625b108316a40c95a4425f8d4294e0deeccfd6c7e59d819efa19e23409","affectsGlobalScope":true,"impliedFormat":1},{"version":"0568d6befee03dd435bed4fc25c4e46865b24bdcb8c563fdc21f580a2c301904","affectsGlobalScope":true,"impliedFormat":1},{"version":"30d62269b05b584741f19a5369852d5d34895aa2ac4fd948956f886d15f9cc0d","affectsGlobalScope":true,"impliedFormat":1},{"version":"f128dae7c44d8f35ee42e0a437000a57c9f06cc04f8b4fb42eebf44954d53dc8","affectsGlobalScope":true,"impliedFormat":1},{"version":"ffbe6d7b295306b2ba88030f65b74c107d8d99bdcf596ea99c62a02f606108b0","affectsGlobalScope":true,"impliedFormat":1},{"version":"996fb27b15277369c68a4ba46ed138b4e9e839a02fb4ec756f7997629242fd9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"79b712591b270d4778c89706ca2cfc56ddb8c3f895840e477388f1710dc5eda9","affectsGlobalScope":true,"impliedFormat":1},{"version":"20884846cef428b992b9bd032e70a4ef88e349263f63aeddf04dda837a7dba26","affectsGlobalScope":true,"impliedFormat":1},{"version":"5fcab789c73a97cd43828ee3cc94a61264cf24d4c44472ce64ced0e0f148bdb2","affectsGlobalScope":true,"impliedFormat":1},{"version":"db59a81f070c1880ad645b2c0275022baa6a0c4f0acdc58d29d349c6efcf0903","affectsGlobalScope":true,"impliedFormat":1},{"version":"673294292640f5722b700e7d814e17aaf7d93f83a48a2c9b38f33cbc940ad8b0","affectsGlobalScope":true,"impliedFormat":1},{"version":"d786b48f934cbca483b3c6d0a798cb43bbb4ada283e76fb22c28e53ae05b9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ecb8e347cb6b2a8927c09b86263663289418df375f5e68e11a0ae683776978f","affectsGlobalScope":true,"impliedFormat":1},{"version":"142efd4ce210576f777dc34df121777be89eda476942d6d6663b03dcb53be3ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"379bc41580c2d774f82e828c70308f24a005b490c25ba34d679d84bcf05c3d9d","affectsGlobalScope":true,"impliedFormat":1},{"version":"ed484fb2aa8a1a23d0277056ec3336e0a0b52f9b8d6a961f338a642faf43235d","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ffedae1d1c2d53fdbca1c96d3c7dda544281f7d262f99b6880634f8fd8d9820","affectsGlobalScope":true,"impliedFormat":1},{"version":"83a730b125d477dd264df8ba479afab27a3dae7152b005c214ab94dc7ee44fd3","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"ef4a897cd2a3f91000c10264e400b3667c7e51e1b7365f03b62e8081dc53bde6","impliedFormat":1},{"version":"17234c87655b22074eff3bd19aede42680dd64cd9e041677e62bccc3ebd832a0","signature":"4f0ecd2a34c9771eba710a2272df1dc858ceecd6ea8de94aa33317133e4f10f6"},{"version":"f6eeb73ab79679f030164e1409936576edf98936b7df93d3cd3b22fa4b35a7ef","signature":"91b4d62baa3402e0bbf3ff41cfe96d8a6762d8165be441c3543ba41246defc85"},{"version":"11f6766297f5fd19c8d91775175968d3b1e14deed157a526b207fdea8eaa31bf","signature":"90f9fedcbd48af2d781029b08d60544a5acfcc5c8034e1d56d48b8ea8f978439"},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc2110f7decca6bfb9392e30421cfa1436479e4a6756e8fec6cbc22625d4f881","affectsGlobalScope":true,"impliedFormat":1},{"version":"096116f8fedc1765d5bd6ef360c257b4a9048e5415054b3bf3c41b07f8951b0b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"074de5b2fdead0165a2757e3aaef20f27a6347b1c36adea27d51456795b37682","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"4137ebf04166f3a325f056aa56101adc75e9dceb30404a1844eb8604d89770e2","impliedFormat":1},{"version":"ccab02f3920fc75c01174c47fcf67882a11daf16baf9e81701d0a94636e94556","impliedFormat":1},{"version":"3e11fce78ad8c0e1d1db4ba5f0652285509be3acdd519529bc8fcef85f7dafd9","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"1cc2a09e1a61a5222d4174ab358a9f9de5e906afe79dbf7363d871a7edda3955","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"b64d4d1c5f877f9c666e98e833f0205edb9384acc46e98a1fef344f64d6aba44","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"c9381908473a1c92cb8c516b184e75f4d226dad95c3a85a5af35f670064d9a2f","impliedFormat":1},{"version":"c3f5289820990ab66b70c7fb5b63cb674001009ff84b13de40619619a9c8175f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"d2ae155afe8a01cc0ae612d99117cf8ef16692ba7c4366590156fdec1bcf2d8c","impliedFormat":1},{"version":"3f5e5d9be35913db9fea42a63f3df0b7e3c8703b97670a2125587b4dbbd56d7c","impliedFormat":1},{"version":"8caeb65fdc3bfe0d13f86f67324fcb2d858ed1c55f1f0cce892eb1acfb9f3239","impliedFormat":1},{"version":"57c23df0b5f7a8e26363a3849b0bc7763f6b241207157c8e40089d1df4116f35","affectsGlobalScope":true,"impliedFormat":1},{"version":"3b8bc0c17b54081b0878673989216229e575d67a10874e84566a21025a2461ee","impliedFormat":1},{"version":"5b0db5a58b73498792a29bfebc333438e61906fef75da898b410e24e52229e6f","impliedFormat":1},{"version":"dbe055b2b29a7bab2c1ca8f259436306adb43f469dca7e639a02cd3695d3f621","impliedFormat":1},{"version":"1678b04557dca52feab73cc67610918a7f5e25bfdba3e7fa081acd625d93106d","impliedFormat":1},{"version":"e3905f6902f0b69e5eefc230daa69fdd4ab707a973ec2d086d65af1b3ea47ef0","impliedFormat":1},{"version":"2ea729503db9793f2691162fec3dd1118cab62e96d025f8eeb376d43ec293395","impliedFormat":1},{"version":"9ec87fea42b92894b0f209931a880789d43c3397d09dd99c631ae40a2f7071d1","impliedFormat":1},{"version":"c68e88cdfadfb6c8ba5fc38e58a3a166b0beae77b1f05b7d921150a32a5ffb8d","impliedFormat":1},{"version":"2bc7aa4fba46df0bd495425a7c8201437a7d465f83854fac859df2d67f664df3","impliedFormat":1},{"version":"41d17e1ad9a002feb11c8cdd2777e5bbc0cdb1e3f595d237e4dded0b6949983b","impliedFormat":1},{"version":"07e4e61e946a9c15045539ecd5f5d2d02e7aab6fa82567826857e09cf0f37c2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c4714ccc29149efb8777a1da0b04b8d2258f5d13ddbf4cd3c3d361fb531ac86","impliedFormat":1},{"version":"3ff275f84f89f8a7c0543da838f9da9614201abc4ce74c533029825adfb4433d","impliedFormat":1},{"version":"0eb5d0cbf09de5d34542b977fd6a933bb2e0817bffe8e1a541b2f1ad1b9af1ff","impliedFormat":1},{"version":"f9713757bcdfa4d58b48c0fb249e752c94a3eee8bf4532b906094246ac49ef88","impliedFormat":1},{"version":"2c2bdaa1d8ead9f68628d6d9d250e46ee8e81aa4898b4769a36956ae15e060fe","impliedFormat":1},{"version":"c32c840c62d8bd7aeb3147aa6754cd2d922b990a6b6634530cb2ebdce5adc8e9","impliedFormat":1},{"version":"e1c1a0b4d1ead0de9eca52203aeb1f771f21e6238d6fcd15aa56ac2a02f1b7bf","impliedFormat":1},{"version":"82b91e4e42e6c41bc7fc1b6c2dc5eba6a2ba98375eb1f210e6ff6bba2d54177e","impliedFormat":1},{"version":"6fe28249ac0c7bc19a79aa9264baf00efbd080e868dbe1d3052033ad1c64f206","affectsGlobalScope":true,"impliedFormat":1},{"version":"cbed824fec91efefc7bbdcb8b43d1a531fdbebd0e2ef19481501ff365a93cb70","impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"d0716593b3f2b0451bcf0c24cfa86dec2235c325c89f201934248b7c742715fc","impliedFormat":1},{"version":"ec501101c2a96133a6c695f934c8f6642149cc728571b29cbb7b770984c1088e","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"2991bca2cc0f0628a278df2a2ccdb8d6cbcb700f3761abbed62bba137d5b1790","impliedFormat":1},{"version":"ce8653341224f8b45ff46d2a06f2cacb96f841f768a886c9d8dd8ec0878b11bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"230763250f20449fa7b3c9273e1967adb0023dc890d4be1553faca658ee65971","impliedFormat":1},{"version":"c3e9078b60cb329d1221f5878e88cecfa3e74460550e605a58fcfb41a66029ff","impliedFormat":1},{"version":"a74edb3bab7394a9dbde529d60632be590def2f5f01024dbd85441587fbfbbe0","impliedFormat":1},{"version":"0ea59f7d3e51440baa64f429253759b106cfcbaf51e474cae606e02265b37cf8","impliedFormat":1},{"version":"bc18a1991ba681f03e13285fa1d7b99b03b67ee671b7bc936254467177543890","impliedFormat":1},{"version":"00049ccc87f3f37726db03c01ca68fe74fd9c0109b68c29eb9923ebec2c76b13","impliedFormat":1},{"version":"fa94bbf532b7af8f394b95fa310980d6e20bd2d4c871c6a6cb9f70f03750a44b","impliedFormat":1},{"version":"68d3f35108e2608b1f2f28b36d19d7055f31c4465cc5692cbd06c716a9fe7973","impliedFormat":1},{"version":"a6d543044570fbeed13a7f9925a868081cd2b14ef59cdd9da6ae76d41cab03d3","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fa2214bb0d64701bc6f9ce8cde2fd2ff8c571e0b23065fa04a8a5a6beb91511","impliedFormat":1},{"version":"f1c93e046fb3d9b7f8249629f4b63dc068dd839b824dd0aa39a5e68476dc9420","impliedFormat":1},{"version":"eab2f3179607acb3d44b2db2a76dd7d621c5039b145dc160a1ee733963f9d2f5","impliedFormat":1},{"version":"841983e39bd4cbb463be385e92fda11057cab368bf27100a801c492f1d86cbaa","impliedFormat":1},{"version":"6f5383b3df1cdf4ff1aa7fb0850f77042b5786b5e65ec9a9b6be56ebfe4d9036","impliedFormat":1},{"version":"62fc21ed9ccbd83bd1166de277a4b5daaa8d15b5fa614c75610d20f3b73fba87","impliedFormat":1},{"version":"e4156ddb25aa0e3b5303d372f26957b36778f0f6bbd4326359269873295e3058","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc1b433a84cae05ddc5672d4823170af78606ad21ecef60dbc4570190cbf1357","impliedFormat":1},{"version":"9d3821bc75c59577e52643324cec92fc2145642e8d17cf7ee07a3181f21d985d","impliedFormat":1},{"version":"7f78cfb2b343838612c192cb251746e3a7c62ac7675726a47e130d9b213f6580","impliedFormat":1},{"version":"201db9cf1687fab1adf5282fcba861f382b32303dc4f67c89d59655e78a25461","impliedFormat":1},{"version":"c77fb31bc17fd241d3922a9f88c59e3361cdf76d1328ba9412fc6bf7310b638d","impliedFormat":1},{"version":"0a20eaf2e4b1e3c1e1f87f7bccb0c936375b23b022baeea750519b7c9bc6ce83","impliedFormat":1},{"version":"b484ec11ba00e3a2235562a41898d55372ccabe607986c6fa4f4aba72093749f","impliedFormat":1},{"version":"a16b91b27bd6b706c687c88cbc8a7d4ee98e5ed6043026d6b84bda923c0aed67","impliedFormat":1},{"version":"694b812e0ed11285e8822cf8131e3ce7083a500b3b1d185fff9ed1089677bd0a","impliedFormat":1},{"version":"99ab6d0d660ce4d21efb52288a39fd35bb3f556980ec5463b1ae8f304a3bbc85","impliedFormat":1},{"version":"6eeded8c7e352be6e0efb83f4935ec752513c4d22043b52522b90849a49a3a11","impliedFormat":1},{"version":"6c1ad90050ffbb151cacc68e2d06ea1a26a945659391e32651f5d42b86fd7f2c","impliedFormat":1},{"version":"55cdbeebe76a1fa18bbd7e7bf73350a2173926bd3085bb050cf5a5397025ee4e","impliedFormat":1}],"root":[[94,96]],"options":{"allowImportingTsExtensions":false,"composite":true,"declaration":true,"declarationDir":"./types","experimentalDecorators":true,"module":99,"outDir":"./esm","rootDir":"../src","skipLibCheck":true,"strict":true,"target":99},"referencedMap":[[159,1],[160,1],[161,2],[99,3],[162,4],[163,5],[164,6],[97,7],[165,8],[166,9],[167,10],[168,11],[169,12],[170,13],[171,13],[172,14],[173,15],[174,16],[175,17],[100,7],[98,7],[176,18],[177,19],[178,20],[219,21],[179,22],[180,23],[181,22],[182,24],[183,25],[185,26],[186,27],[187,27],[188,27],[189,28],[190,29],[191,30],[192,31],[193,32],[194,33],[195,33],[196,34],[197,7],[198,7],[199,35],[200,36],[201,35],[202,37],[203,38],[204,39],[205,40],[206,41],[207,42],[208,43],[209,44],[210,45],[211,46],[212,47],[213,48],[214,49],[215,50],[216,51],[101,22],[102,7],[103,52],[104,53],[105,7],[106,54],[107,7],[150,55],[151,56],[152,57],[153,57],[154,58],[155,7],[156,4],[157,59],[158,56],[217,60],[218,61],[184,7],[91,7],[92,7],[16,7],[14,7],[15,7],[20,7],[19,7],[2,7],[21,7],[22,7],[23,7],[24,7],[25,7],[26,7],[27,7],[28,7],[3,7],[29,7],[30,7],[4,7],[31,7],[35,7],[32,7],[33,7],[34,7],[36,7],[37,7],[38,7],[5,7],[39,7],[40,7],[41,7],[42,7],[6,7],[46,7],[43,7],[44,7],[45,7],[47,7],[7,7],[48,7],[53,7],[54,7],[49,7],[50,7],[51,7],[52,7],[8,7],[58,7],[55,7],[56,7],[57,7],[59,7],[9,7],[60,7],[61,7],[62,7],[64,7],[63,7],[65,7],[66,7],[10,7],[67,7],[68,7],[69,7],[11,7],[70,7],[71,7],[72,7],[73,7],[74,7],[75,7],[12,7],[76,7],[77,7],[78,7],[79,7],[80,7],[1,7],[81,7],[82,7],[13,7],[83,7],[84,7],[85,7],[86,7],[93,7],[87,7],[88,7],[89,7],[90,7],[18,7],[17,7],[126,62],[138,63],[123,64],[139,65],[148,66],[114,67],[115,68],[113,69],[147,70],[142,71],[146,72],[117,73],[135,74],[116,75],[145,76],[111,77],[112,71],[118,78],[119,7],[125,79],[122,78],[109,80],[149,81],[140,82],[129,83],[128,78],[130,84],[133,85],[127,86],[131,87],[143,70],[120,88],[121,89],[134,90],[110,65],[137,91],[136,78],[124,89],[132,92],[141,7],[108,7],[144,93],[95,94],[96,95],[94,7]],"latestChangedDtsFile":"./types/index.d.ts","version":"6.0.3"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type TarEntry } from "./parser.js";
|
|
2
|
+
export interface ExtractOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Strip N leading path components from every entry name. npm tarballs put
|
|
5
|
+
* everything under `package/`, so the default is 1 (matches `npm install`).
|
|
6
|
+
*/
|
|
7
|
+
strip?: number;
|
|
8
|
+
/** Filter — return false to skip an entry. */
|
|
9
|
+
filter?: (entry: TarEntry, resolvedPath: string) => boolean;
|
|
10
|
+
/** Override file mode bits (after umask). Useful for `.bin/` to add +x. */
|
|
11
|
+
chmod?: (entry: TarEntry, resolvedPath: string) => number | undefined;
|
|
12
|
+
/** Reject entries whose resolved path escapes destDir. Default: true. */
|
|
13
|
+
preventEscape?: boolean;
|
|
14
|
+
/** Treat input as gzipped. Default: auto-detect via gzip magic bytes. */
|
|
15
|
+
gzip?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface ExtractResult {
|
|
18
|
+
files: string[];
|
|
19
|
+
directories: string[];
|
|
20
|
+
symlinks: string[];
|
|
21
|
+
skipped: number;
|
|
22
|
+
}
|
|
23
|
+
/** Extract a `.tar` or `.tar.gz` buffer into `destDir`, creating dirs as needed. */
|
|
24
|
+
export declare function extractTarball(input: Uint8Array | ArrayBuffer, destDir: string, opts?: ExtractOptions): Promise<ExtractResult>;
|
|
25
|
+
/** Decompress a gzip buffer using Web DecompressionStream (cross-platform). */
|
|
26
|
+
export declare function gunzip(input: Uint8Array): Promise<Uint8Array>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const BLOCK_SIZE = 512;
|
|
2
|
+
export type TarEntryType = "file" | "directory" | "symlink" | "hardlink" | "pax-header" | "pax-global" | "gnu-longname" | "gnu-longlink" | "unknown";
|
|
3
|
+
export interface TarEntry {
|
|
4
|
+
name: string;
|
|
5
|
+
/** Optional: link target for symlinks/hardlinks. */
|
|
6
|
+
linkname: string;
|
|
7
|
+
type: TarEntryType;
|
|
8
|
+
/** File mode (decoded from octal). */
|
|
9
|
+
mode: number;
|
|
10
|
+
/** Modification time as Unix epoch seconds. */
|
|
11
|
+
mtime: number;
|
|
12
|
+
/** File body bytes. Empty for non-file entries. */
|
|
13
|
+
body: Uint8Array;
|
|
14
|
+
/** Raw uname/gname for callers that care. */
|
|
15
|
+
uname: string;
|
|
16
|
+
gname: string;
|
|
17
|
+
}
|
|
18
|
+
/** Parse a tar archive (already-uncompressed) into entries. */
|
|
19
|
+
export declare function parseTar(buf: Uint8Array): TarEntry[];
|
|
20
|
+
export declare class TarParseError extends Error {
|
|
21
|
+
constructor(msg: string);
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gjsify/tar",
|
|
3
|
+
"version": "0.3.8",
|
|
4
|
+
"description": "Streaming .tar / .tar.gz reader for the gjsify install backend (Node + GJS)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "lib/esm/index.js",
|
|
7
|
+
"main": "lib/esm/index.js",
|
|
8
|
+
"types": "lib/types/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./lib/types/index.d.ts",
|
|
12
|
+
"default": "./lib/esm/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"clear": "rm -rf lib tsconfig.tsbuildinfo test.gjs.mjs test.node.mjs || exit 0",
|
|
17
|
+
"check": "tsc --noEmit",
|
|
18
|
+
"build": "yarn build:gjsify && yarn build:types",
|
|
19
|
+
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.mts'",
|
|
20
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
21
|
+
"build:test": "yarn build:test:gjs && yarn build:test:node",
|
|
22
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
23
|
+
"build:test:node": "gjsify build src/test.mts --app node --outfile test.node.mjs",
|
|
24
|
+
"test": "yarn build:gjsify && yarn build:test && yarn test:node && yarn test:gjs",
|
|
25
|
+
"test:gjs": "gjsify run test.gjs.mjs",
|
|
26
|
+
"test:node": "node test.node.mjs"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"gjs",
|
|
30
|
+
"node",
|
|
31
|
+
"tar",
|
|
32
|
+
"tgz",
|
|
33
|
+
"install"
|
|
34
|
+
],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@gjsify/cli": "^0.3.8",
|
|
38
|
+
"@gjsify/unit": "^0.3.8",
|
|
39
|
+
"typescript": "^6.0.3"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/extract.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// `extractTarball()` — decompress + parse + write to disk. Cross-platform
|
|
2
|
+
// (Node + GJS) — node:fs is polyfilled by @gjsify/fs on GJS.
|
|
3
|
+
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
|
|
7
|
+
import { type TarEntry, parseTar } from "./parser.js";
|
|
8
|
+
|
|
9
|
+
export interface ExtractOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Strip N leading path components from every entry name. npm tarballs put
|
|
12
|
+
* everything under `package/`, so the default is 1 (matches `npm install`).
|
|
13
|
+
*/
|
|
14
|
+
strip?: number;
|
|
15
|
+
/** Filter — return false to skip an entry. */
|
|
16
|
+
filter?: (entry: TarEntry, resolvedPath: string) => boolean;
|
|
17
|
+
/** Override file mode bits (after umask). Useful for `.bin/` to add +x. */
|
|
18
|
+
chmod?: (entry: TarEntry, resolvedPath: string) => number | undefined;
|
|
19
|
+
/** Reject entries whose resolved path escapes destDir. Default: true. */
|
|
20
|
+
preventEscape?: boolean;
|
|
21
|
+
/** Treat input as gzipped. Default: auto-detect via gzip magic bytes. */
|
|
22
|
+
gzip?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ExtractResult {
|
|
26
|
+
files: string[];
|
|
27
|
+
directories: string[];
|
|
28
|
+
symlinks: string[];
|
|
29
|
+
skipped: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Extract a `.tar` or `.tar.gz` buffer into `destDir`, creating dirs as needed. */
|
|
33
|
+
export async function extractTarball(
|
|
34
|
+
input: Uint8Array | ArrayBuffer,
|
|
35
|
+
destDir: string,
|
|
36
|
+
opts: ExtractOptions = {},
|
|
37
|
+
): Promise<ExtractResult> {
|
|
38
|
+
const buf = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
39
|
+
const isGz = opts.gzip ?? (buf.length >= 2 && buf[0] === 0x1f && buf[1] === 0x8b);
|
|
40
|
+
const tarBytes = isGz ? await gunzip(buf) : buf;
|
|
41
|
+
const entries = parseTar(tarBytes);
|
|
42
|
+
|
|
43
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
44
|
+
|
|
45
|
+
const strip = opts.strip ?? 1;
|
|
46
|
+
const preventEscape = opts.preventEscape ?? true;
|
|
47
|
+
const result: ExtractResult = { files: [], directories: [], symlinks: [], skipped: 0 };
|
|
48
|
+
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const stripped = stripComponents(entry.name, strip);
|
|
51
|
+
if (stripped === null || stripped === "") {
|
|
52
|
+
result.skipped++;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const resolved = path.resolve(destDir, stripped);
|
|
56
|
+
if (preventEscape && !isInside(resolved, destDir)) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`tar: refusing to extract ${entry.name} outside ${destDir} (resolved=${resolved})`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (opts.filter && !opts.filter(entry, resolved)) {
|
|
62
|
+
result.skipped++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (entry.type === "directory") {
|
|
67
|
+
fs.mkdirSync(resolved, { recursive: true });
|
|
68
|
+
result.directories.push(resolved);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (entry.type === "file") {
|
|
72
|
+
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
73
|
+
fs.writeFileSync(resolved, entry.body);
|
|
74
|
+
const overrideMode = opts.chmod?.(entry, resolved);
|
|
75
|
+
const finalMode = overrideMode ?? (entry.mode & 0o777);
|
|
76
|
+
if (finalMode > 0) {
|
|
77
|
+
try {
|
|
78
|
+
fs.chmodSync(resolved, finalMode);
|
|
79
|
+
} catch {
|
|
80
|
+
/* mode-set is best-effort — Windows-style FS will reject */
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
result.files.push(resolved);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (entry.type === "symlink") {
|
|
87
|
+
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
88
|
+
try {
|
|
89
|
+
fs.symlinkSync(entry.linkname, resolved);
|
|
90
|
+
result.symlinks.push(resolved);
|
|
91
|
+
} catch {
|
|
92
|
+
// Symlinks may fail on platforms without permission (Windows).
|
|
93
|
+
// Fall back to writing the link target as a plain file so the
|
|
94
|
+
// package layout is still complete.
|
|
95
|
+
fs.writeFileSync(resolved, entry.linkname);
|
|
96
|
+
result.files.push(resolved);
|
|
97
|
+
}
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// hardlink/unknown/PAX/GNU-* — count as skipped.
|
|
101
|
+
result.skipped++;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Decompress a gzip buffer using Web DecompressionStream (cross-platform). */
|
|
108
|
+
export async function gunzip(input: Uint8Array): Promise<Uint8Array> {
|
|
109
|
+
const Decomp = (globalThis as { DecompressionStream?: typeof DecompressionStream })
|
|
110
|
+
.DecompressionStream;
|
|
111
|
+
if (typeof Decomp !== "function") {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"@gjsify/tar: globalThis.DecompressionStream is not available — " +
|
|
114
|
+
"import '@gjsify/compression-streams/register' on GJS to register it",
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
const stream = new Blob([new Uint8Array(input)]).stream().pipeThrough(new Decomp("gzip"));
|
|
118
|
+
const chunks: Uint8Array[] = [];
|
|
119
|
+
let total = 0;
|
|
120
|
+
const reader = stream.getReader();
|
|
121
|
+
for (;;) {
|
|
122
|
+
const { value, done } = await reader.read();
|
|
123
|
+
if (done) break;
|
|
124
|
+
const chunk = value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
125
|
+
chunks.push(chunk);
|
|
126
|
+
total += chunk.length;
|
|
127
|
+
}
|
|
128
|
+
const out = new Uint8Array(total);
|
|
129
|
+
let pos = 0;
|
|
130
|
+
for (const c of chunks) {
|
|
131
|
+
out.set(c, pos);
|
|
132
|
+
pos += c.length;
|
|
133
|
+
}
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function stripComponents(name: string, n: number): string | null {
|
|
138
|
+
if (n <= 0) return name;
|
|
139
|
+
const parts = name.split("/").filter((s) => s !== "");
|
|
140
|
+
if (parts.length <= n) return null;
|
|
141
|
+
return parts.slice(n).join("/");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function isInside(child: string, parent: string): boolean {
|
|
145
|
+
const rel = path.relative(parent, child);
|
|
146
|
+
return rel !== "" && !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
147
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { describe, it, expect, on } from "@gjsify/unit";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import * as os from "node:os";
|
|
5
|
+
|
|
6
|
+
import { parseTar, extractTarball, gunzip, BLOCK_SIZE, type TarEntry } from "./index.js";
|
|
7
|
+
|
|
8
|
+
interface BuildTarEntry {
|
|
9
|
+
name: string;
|
|
10
|
+
body?: Uint8Array | string;
|
|
11
|
+
type?: "file" | "directory" | "symlink";
|
|
12
|
+
linkname?: string;
|
|
13
|
+
mode?: number;
|
|
14
|
+
mtime?: number;
|
|
15
|
+
paxHeader?: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function writeAscii(buf: Uint8Array, offset: number, len: number, s: string): void {
|
|
19
|
+
for (let i = 0; i < s.length && i < len; i++) buf[offset + i] = s.charCodeAt(i);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function writeOctal(buf: Uint8Array, offset: number, len: number, value: number): void {
|
|
23
|
+
const s = value.toString(8).padStart(len - 1, "0");
|
|
24
|
+
writeAscii(buf, offset, len - 1, s);
|
|
25
|
+
// last byte stays 0 (NUL terminator).
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function buildHeader(entry: {
|
|
29
|
+
name: string;
|
|
30
|
+
size: number;
|
|
31
|
+
type: "file" | "directory" | "symlink" | "x" | "L";
|
|
32
|
+
linkname?: string;
|
|
33
|
+
mode?: number;
|
|
34
|
+
mtime?: number;
|
|
35
|
+
}): Uint8Array {
|
|
36
|
+
const header = new Uint8Array(BLOCK_SIZE);
|
|
37
|
+
writeAscii(header, 0, 100, entry.name);
|
|
38
|
+
writeOctal(header, 100, 8, entry.mode ?? 0o644);
|
|
39
|
+
writeOctal(header, 108, 8, 0); // uid
|
|
40
|
+
writeOctal(header, 116, 8, 0); // gid
|
|
41
|
+
writeOctal(header, 124, 12, entry.size);
|
|
42
|
+
writeOctal(header, 136, 12, entry.mtime ?? 0);
|
|
43
|
+
// chksum left as spaces during checksum calc
|
|
44
|
+
for (let i = 148; i < 156; i++) header[i] = 0x20;
|
|
45
|
+
let typeflag = "0";
|
|
46
|
+
if (entry.type === "directory") typeflag = "5";
|
|
47
|
+
else if (entry.type === "symlink") typeflag = "2";
|
|
48
|
+
else if (entry.type === "x") typeflag = "x";
|
|
49
|
+
else if (entry.type === "L") typeflag = "L";
|
|
50
|
+
header[156] = typeflag.charCodeAt(0);
|
|
51
|
+
if (entry.linkname) writeAscii(header, 157, 100, entry.linkname);
|
|
52
|
+
writeAscii(header, 257, 6, "ustar\0");
|
|
53
|
+
writeAscii(header, 263, 2, "00");
|
|
54
|
+
// Compute checksum.
|
|
55
|
+
let sum = 0;
|
|
56
|
+
for (let i = 0; i < BLOCK_SIZE; i++) sum += header[i];
|
|
57
|
+
writeOctal(header, 148, 8, sum);
|
|
58
|
+
return header;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function alignBlock(n: number): number {
|
|
62
|
+
return Math.ceil(n / BLOCK_SIZE) * BLOCK_SIZE;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function bodyToBytes(body?: Uint8Array | string): Uint8Array {
|
|
66
|
+
if (body === undefined) return new Uint8Array(0);
|
|
67
|
+
if (typeof body === "string") return new TextEncoder().encode(body);
|
|
68
|
+
return body;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Construct a tiny ustar archive in memory for tests. */
|
|
72
|
+
function buildTar(entries: BuildTarEntry[]): Uint8Array {
|
|
73
|
+
const blocks: Uint8Array[] = [];
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
if (entry.paxHeader) {
|
|
76
|
+
// Build PAX header block: each record `<len> <key>=<value>\n`.
|
|
77
|
+
let payload = "";
|
|
78
|
+
for (const [k, v] of Object.entries(entry.paxHeader)) {
|
|
79
|
+
const inner = `${k}=${v}\n`;
|
|
80
|
+
let len = inner.length + 1;
|
|
81
|
+
while (`${len} ${inner}`.length !== len) len = `${len} ${inner}`.length;
|
|
82
|
+
payload += `${len} ${inner}`;
|
|
83
|
+
}
|
|
84
|
+
const paxBytes = new TextEncoder().encode(payload);
|
|
85
|
+
blocks.push(buildHeader({ name: "./PaxHeaders/x", size: paxBytes.length, type: "x" }));
|
|
86
|
+
const pad = new Uint8Array(alignBlock(paxBytes.length));
|
|
87
|
+
pad.set(paxBytes);
|
|
88
|
+
blocks.push(pad);
|
|
89
|
+
}
|
|
90
|
+
const body = bodyToBytes(entry.body);
|
|
91
|
+
const type = entry.type ?? "file";
|
|
92
|
+
blocks.push(
|
|
93
|
+
buildHeader({
|
|
94
|
+
name: entry.name,
|
|
95
|
+
size: type === "file" ? body.length : 0,
|
|
96
|
+
type,
|
|
97
|
+
linkname: entry.linkname,
|
|
98
|
+
mode: entry.mode,
|
|
99
|
+
mtime: entry.mtime,
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
if (type === "file") {
|
|
103
|
+
const pad = new Uint8Array(alignBlock(body.length));
|
|
104
|
+
pad.set(body);
|
|
105
|
+
blocks.push(pad);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Two trailing zero blocks mark EOF.
|
|
109
|
+
blocks.push(new Uint8Array(BLOCK_SIZE));
|
|
110
|
+
blocks.push(new Uint8Array(BLOCK_SIZE));
|
|
111
|
+
|
|
112
|
+
let total = 0;
|
|
113
|
+
for (const b of blocks) total += b.length;
|
|
114
|
+
const out = new Uint8Array(total);
|
|
115
|
+
let pos = 0;
|
|
116
|
+
for (const b of blocks) {
|
|
117
|
+
out.set(b, pos);
|
|
118
|
+
pos += b.length;
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function findEntry(entries: TarEntry[], name: string): TarEntry | undefined {
|
|
124
|
+
return entries.find((e) => e.name === name);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export default async () => {
|
|
128
|
+
await describe("@gjsify/tar — parseTar", async () => {
|
|
129
|
+
await it("parses a single file entry", async () => {
|
|
130
|
+
const buf = buildTar([{ name: "package/README.md", body: "hello" }]);
|
|
131
|
+
const entries = parseTar(buf);
|
|
132
|
+
expect(entries.length).toBe(1);
|
|
133
|
+
expect(entries[0].name).toBe("package/README.md");
|
|
134
|
+
expect(entries[0].type).toBe("file");
|
|
135
|
+
expect(new TextDecoder().decode(entries[0].body)).toBe("hello");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await it("parses files and directories with correct types/modes", async () => {
|
|
139
|
+
const buf = buildTar([
|
|
140
|
+
{ name: "package/", type: "directory", mode: 0o755 },
|
|
141
|
+
{ name: "package/index.js", body: "module.exports = 1", mode: 0o644 },
|
|
142
|
+
{ name: "package/bin/cli", body: "#!/bin/sh\necho hi\n", mode: 0o755 },
|
|
143
|
+
]);
|
|
144
|
+
const entries = parseTar(buf);
|
|
145
|
+
expect(entries.length).toBe(3);
|
|
146
|
+
const dir = findEntry(entries, "package/");
|
|
147
|
+
expect(dir).toBeTruthy();
|
|
148
|
+
expect(dir?.type).toBe("directory");
|
|
149
|
+
const cli = findEntry(entries, "package/bin/cli");
|
|
150
|
+
expect(cli?.mode).toBe(0o755);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
await it("handles a symlink entry", async () => {
|
|
154
|
+
const buf = buildTar([
|
|
155
|
+
{ name: "package/lib/link", type: "symlink", linkname: "../target" },
|
|
156
|
+
]);
|
|
157
|
+
const entries = parseTar(buf);
|
|
158
|
+
expect(entries.length).toBe(1);
|
|
159
|
+
expect(entries[0].type).toBe("symlink");
|
|
160
|
+
expect(entries[0].linkname).toBe("../target");
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
await it("respects PAX path override for long names", async () => {
|
|
164
|
+
const longName =
|
|
165
|
+
"package/" + "very-long-segment/".repeat(8) + "deeply/nested/file.js";
|
|
166
|
+
const buf = buildTar([
|
|
167
|
+
{
|
|
168
|
+
name: "package/placeholder",
|
|
169
|
+
body: "long-name body",
|
|
170
|
+
paxHeader: { path: longName },
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
173
|
+
const entries = parseTar(buf);
|
|
174
|
+
expect(entries.length).toBe(1);
|
|
175
|
+
expect(entries[0].name).toBe(longName);
|
|
176
|
+
expect(new TextDecoder().decode(entries[0].body)).toBe("long-name body");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await it("rejects garbage with a clear error", async () => {
|
|
180
|
+
const buf = new Uint8Array(BLOCK_SIZE);
|
|
181
|
+
for (let i = 0; i < buf.length; i++) buf[i] = 0x42; // not a valid tar
|
|
182
|
+
let caught: Error | null = null;
|
|
183
|
+
try {
|
|
184
|
+
parseTar(buf);
|
|
185
|
+
} catch (e) {
|
|
186
|
+
caught = e as Error;
|
|
187
|
+
}
|
|
188
|
+
expect(caught).toBeTruthy();
|
|
189
|
+
expect(String(caught?.message)).toMatch(/Bad header checksum/);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
await describe("@gjsify/tar — extractTarball (filesystem)", async () => {
|
|
194
|
+
await it("extracts files + dirs into a tmpdir, stripping leading 'package/'", async () => {
|
|
195
|
+
const buf = buildTar([
|
|
196
|
+
{ name: "package/", type: "directory", mode: 0o755 },
|
|
197
|
+
{ name: "package/package.json", body: '{"name":"x"}\n' },
|
|
198
|
+
{ name: "package/lib/index.js", body: "module.exports = 1\n" },
|
|
199
|
+
]);
|
|
200
|
+
const dest = fs.mkdtempSync(path.join(os.tmpdir(), "gjsify-tar-"));
|
|
201
|
+
try {
|
|
202
|
+
const result = await extractTarball(buf, dest);
|
|
203
|
+
expect(result.files.length).toBe(2);
|
|
204
|
+
expect(fs.existsSync(path.join(dest, "package.json"))).toBe(true);
|
|
205
|
+
expect(fs.existsSync(path.join(dest, "lib", "index.js"))).toBe(true);
|
|
206
|
+
expect(fs.readFileSync(path.join(dest, "package.json"), "utf-8")).toBe(
|
|
207
|
+
'{"name":"x"}\n',
|
|
208
|
+
);
|
|
209
|
+
} finally {
|
|
210
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
await it("rejects entries that escape destDir", async () => {
|
|
215
|
+
const buf = buildTar([
|
|
216
|
+
{ name: "package/../../etc/evil", body: "danger" },
|
|
217
|
+
]);
|
|
218
|
+
const dest = fs.mkdtempSync(path.join(os.tmpdir(), "gjsify-tar-"));
|
|
219
|
+
let caught: Error | null = null;
|
|
220
|
+
try {
|
|
221
|
+
try {
|
|
222
|
+
await extractTarball(buf, dest);
|
|
223
|
+
} catch (e) {
|
|
224
|
+
caught = e as Error;
|
|
225
|
+
}
|
|
226
|
+
expect(caught).toBeTruthy();
|
|
227
|
+
expect(String(caught?.message)).toMatch(/refusing to extract/);
|
|
228
|
+
} finally {
|
|
229
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
await it("filter() can skip entries", async () => {
|
|
234
|
+
const buf = buildTar([
|
|
235
|
+
{ name: "package/keep.js", body: "keep" },
|
|
236
|
+
{ name: "package/skip.test.js", body: "skip" },
|
|
237
|
+
]);
|
|
238
|
+
const dest = fs.mkdtempSync(path.join(os.tmpdir(), "gjsify-tar-"));
|
|
239
|
+
try {
|
|
240
|
+
const result = await extractTarball(buf, dest, {
|
|
241
|
+
filter: (entry) => !entry.name.endsWith(".test.js"),
|
|
242
|
+
});
|
|
243
|
+
expect(result.files.length).toBe(1);
|
|
244
|
+
expect(fs.existsSync(path.join(dest, "keep.js"))).toBe(true);
|
|
245
|
+
expect(fs.existsSync(path.join(dest, "skip.test.js"))).toBe(false);
|
|
246
|
+
} finally {
|
|
247
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
await on("Node.js", async () => {
|
|
253
|
+
await describe("@gjsify/tar — gzip round-trip (Node only)", async () => {
|
|
254
|
+
await it("gunzip undoes gzipSync", async () => {
|
|
255
|
+
// Use Node's zlib so we don't depend on @gjsify/zlib being
|
|
256
|
+
// bundled into the tar test.
|
|
257
|
+
const { gzipSync } = await import("node:zlib");
|
|
258
|
+
const original = new TextEncoder().encode("the quick brown fox\n");
|
|
259
|
+
const gz = gzipSync(original);
|
|
260
|
+
const round = await gunzip(new Uint8Array(gz));
|
|
261
|
+
expect(new TextDecoder().decode(round)).toBe("the quick brown fox\n");
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
await it("extractTarball auto-detects gzipped input", async () => {
|
|
265
|
+
const { gzipSync } = await import("node:zlib");
|
|
266
|
+
const tar = buildTar([
|
|
267
|
+
{ name: "package/hello.txt", body: "world" },
|
|
268
|
+
]);
|
|
269
|
+
const gz = new Uint8Array(gzipSync(tar));
|
|
270
|
+
const dest = fs.mkdtempSync(path.join(os.tmpdir(), "gjsify-tar-"));
|
|
271
|
+
try {
|
|
272
|
+
await extractTarball(gz, dest);
|
|
273
|
+
expect(fs.readFileSync(path.join(dest, "hello.txt"), "utf-8")).toBe("world");
|
|
274
|
+
} finally {
|
|
275
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
};
|
package/src/index.ts
ADDED
package/src/parser.ts
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
// Pure-JS tar parser — ustar + PAX subset, file/directory/symlink entries only.
|
|
2
|
+
// Operates on an in-memory Uint8Array. The streaming wrapper for `.tar.gz`
|
|
3
|
+
// lives in extract.ts (uses DecompressionStream to gunzip first).
|
|
4
|
+
//
|
|
5
|
+
// Reference: POSIX 1003.1-2017 ustar format and PAX extended headers
|
|
6
|
+
// (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html).
|
|
7
|
+
// Cross-checked against refs/node-tar (when present) and Bun's
|
|
8
|
+
// extract_tarball.zig.
|
|
9
|
+
|
|
10
|
+
export const BLOCK_SIZE = 512;
|
|
11
|
+
|
|
12
|
+
export type TarEntryType =
|
|
13
|
+
| "file"
|
|
14
|
+
| "directory"
|
|
15
|
+
| "symlink"
|
|
16
|
+
| "hardlink"
|
|
17
|
+
| "pax-header"
|
|
18
|
+
| "pax-global"
|
|
19
|
+
| "gnu-longname"
|
|
20
|
+
| "gnu-longlink"
|
|
21
|
+
| "unknown";
|
|
22
|
+
|
|
23
|
+
export interface TarEntry {
|
|
24
|
+
name: string;
|
|
25
|
+
/** Optional: link target for symlinks/hardlinks. */
|
|
26
|
+
linkname: string;
|
|
27
|
+
type: TarEntryType;
|
|
28
|
+
/** File mode (decoded from octal). */
|
|
29
|
+
mode: number;
|
|
30
|
+
/** Modification time as Unix epoch seconds. */
|
|
31
|
+
mtime: number;
|
|
32
|
+
/** File body bytes. Empty for non-file entries. */
|
|
33
|
+
body: Uint8Array;
|
|
34
|
+
/** Raw uname/gname for callers that care. */
|
|
35
|
+
uname: string;
|
|
36
|
+
gname: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Parse a tar archive (already-uncompressed) into entries. */
|
|
40
|
+
export function parseTar(buf: Uint8Array): TarEntry[] {
|
|
41
|
+
const out: TarEntry[] = [];
|
|
42
|
+
let pendingPaxHeader: Map<string, string> | null = null;
|
|
43
|
+
let pendingLongName: string | null = null;
|
|
44
|
+
let pendingLongLink: string | null = null;
|
|
45
|
+
|
|
46
|
+
let offset = 0;
|
|
47
|
+
while (offset + BLOCK_SIZE <= buf.length) {
|
|
48
|
+
const header = buf.subarray(offset, offset + BLOCK_SIZE);
|
|
49
|
+
if (allZeros(header)) {
|
|
50
|
+
// Two consecutive empty blocks mark EOF; tolerate one stray block.
|
|
51
|
+
const next = buf.subarray(offset + BLOCK_SIZE, offset + 2 * BLOCK_SIZE);
|
|
52
|
+
if (next.length === BLOCK_SIZE && allZeros(next)) break;
|
|
53
|
+
offset += BLOCK_SIZE;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!validateChecksum(header)) {
|
|
58
|
+
throw new TarParseError(
|
|
59
|
+
`Bad header checksum at offset ${offset} — file is not a valid tar archive`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const rawName = readString(header, 0, 100);
|
|
64
|
+
const mode = parseOctal(header, 100, 8);
|
|
65
|
+
const size = parseOctal(header, 124, 12);
|
|
66
|
+
const mtime = parseOctal(header, 136, 12);
|
|
67
|
+
const typeflag = String.fromCharCode(header[156] || 0);
|
|
68
|
+
const linkname = readString(header, 157, 100);
|
|
69
|
+
const magic = readString(header, 257, 6);
|
|
70
|
+
const prefix = readString(header, 345, 155);
|
|
71
|
+
const uname = readString(header, 265, 32);
|
|
72
|
+
const gname = readString(header, 297, 32);
|
|
73
|
+
|
|
74
|
+
offset += BLOCK_SIZE;
|
|
75
|
+
const body = buf.subarray(offset, offset + size);
|
|
76
|
+
offset += alignToBlock(size);
|
|
77
|
+
|
|
78
|
+
// PAX/GNU placeholder entries describe the *next* real entry. They
|
|
79
|
+
// never produce a TarEntry of their own — fold their info forward and
|
|
80
|
+
// continue the loop.
|
|
81
|
+
if (typeflag === "x") {
|
|
82
|
+
pendingPaxHeader = parsePaxRecords(body);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (typeflag === "g") {
|
|
86
|
+
// Global PAX — applies to remainder of stream. Not used by npm
|
|
87
|
+
// tarballs in practice; stash but never expose.
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (typeflag === "L") {
|
|
91
|
+
pendingLongName = bytesToString(body).replace(/\0+$/, "");
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (typeflag === "K") {
|
|
95
|
+
pendingLongLink = bytesToString(body).replace(/\0+$/, "");
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let name = rawName;
|
|
100
|
+
if (magic === "ustar" && prefix !== "") {
|
|
101
|
+
name = `${prefix}/${rawName}`;
|
|
102
|
+
}
|
|
103
|
+
if (pendingLongName !== null) {
|
|
104
|
+
name = pendingLongName;
|
|
105
|
+
pendingLongName = null;
|
|
106
|
+
}
|
|
107
|
+
let resolvedLink = linkname;
|
|
108
|
+
if (pendingLongLink !== null) {
|
|
109
|
+
resolvedLink = pendingLongLink;
|
|
110
|
+
pendingLongLink = null;
|
|
111
|
+
}
|
|
112
|
+
if (pendingPaxHeader !== null) {
|
|
113
|
+
const paxName = pendingPaxHeader.get("path");
|
|
114
|
+
if (paxName !== undefined) name = paxName;
|
|
115
|
+
const paxLink = pendingPaxHeader.get("linkpath");
|
|
116
|
+
if (paxLink !== undefined) resolvedLink = paxLink;
|
|
117
|
+
const paxSize = pendingPaxHeader.get("size");
|
|
118
|
+
if (paxSize !== undefined) {
|
|
119
|
+
// PAX size override — re-read body with the wider size.
|
|
120
|
+
const overrideSize = Number(paxSize);
|
|
121
|
+
if (Number.isFinite(overrideSize)) {
|
|
122
|
+
// Body already advanced by ustar size; in practice ustar
|
|
123
|
+
// size will be 0 when PAX overrides it. Re-slice from the
|
|
124
|
+
// header start.
|
|
125
|
+
const realStart = offset - alignToBlock(size);
|
|
126
|
+
const sliced = buf.subarray(realStart, realStart + overrideSize);
|
|
127
|
+
offset = realStart + alignToBlock(overrideSize);
|
|
128
|
+
pendingPaxHeader = null;
|
|
129
|
+
out.push(buildEntry(name, resolvedLink, typeflag, mode, mtime, uname, gname, sliced));
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
pendingPaxHeader = null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
out.push(buildEntry(name, resolvedLink, typeflag, mode, mtime, uname, gname, body));
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function buildEntry(
|
|
142
|
+
name: string,
|
|
143
|
+
linkname: string,
|
|
144
|
+
typeflag: string,
|
|
145
|
+
mode: number,
|
|
146
|
+
mtime: number,
|
|
147
|
+
uname: string,
|
|
148
|
+
gname: string,
|
|
149
|
+
body: Uint8Array,
|
|
150
|
+
): TarEntry {
|
|
151
|
+
return {
|
|
152
|
+
name,
|
|
153
|
+
linkname,
|
|
154
|
+
type: typeflagToType(typeflag, name),
|
|
155
|
+
mode,
|
|
156
|
+
mtime,
|
|
157
|
+
body,
|
|
158
|
+
uname,
|
|
159
|
+
gname,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function typeflagToType(typeflag: string, name: string): TarEntryType {
|
|
164
|
+
switch (typeflag) {
|
|
165
|
+
case "0":
|
|
166
|
+
case "\0":
|
|
167
|
+
case "":
|
|
168
|
+
// Some implementations encode trailing slash on dirs as type 0.
|
|
169
|
+
return name.endsWith("/") ? "directory" : "file";
|
|
170
|
+
case "1":
|
|
171
|
+
return "hardlink";
|
|
172
|
+
case "2":
|
|
173
|
+
return "symlink";
|
|
174
|
+
case "5":
|
|
175
|
+
return "directory";
|
|
176
|
+
case "x":
|
|
177
|
+
return "pax-header";
|
|
178
|
+
case "g":
|
|
179
|
+
return "pax-global";
|
|
180
|
+
case "L":
|
|
181
|
+
return "gnu-longname";
|
|
182
|
+
case "K":
|
|
183
|
+
return "gnu-longlink";
|
|
184
|
+
default:
|
|
185
|
+
return "unknown";
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function parsePaxRecords(body: Uint8Array): Map<string, string> {
|
|
190
|
+
// Each record is `<len> <key>=<value>\n`, where <len> is decimal-ascii of
|
|
191
|
+
// the entire record (including the digits + space + newline). Records can
|
|
192
|
+
// be NUL-padded; iterate until we exhaust the actual length of the
|
|
193
|
+
// payload.
|
|
194
|
+
const out = new Map<string, string>();
|
|
195
|
+
let i = 0;
|
|
196
|
+
while (i < body.length) {
|
|
197
|
+
let space = i;
|
|
198
|
+
while (space < body.length && body[space] !== 0x20) space++;
|
|
199
|
+
if (space >= body.length) break;
|
|
200
|
+
const lenStr = bytesToString(body.subarray(i, space));
|
|
201
|
+
const len = Number(lenStr);
|
|
202
|
+
if (!Number.isFinite(len) || len <= 0) break;
|
|
203
|
+
const recordEnd = i + len;
|
|
204
|
+
if (recordEnd > body.length) break;
|
|
205
|
+
const recBytes = body.subarray(space + 1, recordEnd - 1); // -1 for trailing \n
|
|
206
|
+
const recText = bytesToString(recBytes);
|
|
207
|
+
const eq = recText.indexOf("=");
|
|
208
|
+
if (eq > 0) {
|
|
209
|
+
const key = recText.slice(0, eq);
|
|
210
|
+
const value = recText.slice(eq + 1);
|
|
211
|
+
out.set(key, value);
|
|
212
|
+
}
|
|
213
|
+
i = recordEnd;
|
|
214
|
+
}
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function readString(buf: Uint8Array, start: number, len: number): string {
|
|
219
|
+
let end = start;
|
|
220
|
+
const limit = start + len;
|
|
221
|
+
while (end < limit && buf[end] !== 0) end++;
|
|
222
|
+
return bytesToString(buf.subarray(start, end));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function bytesToString(buf: Uint8Array): string {
|
|
226
|
+
// Tar headers are 7-bit ASCII. PAX values are UTF-8.
|
|
227
|
+
return new TextDecoder("utf-8", { fatal: false }).decode(buf);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function parseOctal(buf: Uint8Array, start: number, len: number): number {
|
|
231
|
+
// Strip NUL/space padding common in headers, and accept GNU base-256
|
|
232
|
+
// numeric extensions (high bit set on first byte).
|
|
233
|
+
if (len > 0 && (buf[start] & 0x80) !== 0) {
|
|
234
|
+
let n = buf[start] & 0x7f;
|
|
235
|
+
for (let i = 1; i < len; i++) n = n * 256 + buf[start + i];
|
|
236
|
+
return n;
|
|
237
|
+
}
|
|
238
|
+
let s = "";
|
|
239
|
+
for (let i = 0; i < len; i++) {
|
|
240
|
+
const c = buf[start + i];
|
|
241
|
+
if (c === 0 || c === 0x20) continue;
|
|
242
|
+
s += String.fromCharCode(c);
|
|
243
|
+
}
|
|
244
|
+
if (s === "") return 0;
|
|
245
|
+
return parseInt(s, 8);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function alignToBlock(n: number): number {
|
|
249
|
+
return Math.ceil(n / BLOCK_SIZE) * BLOCK_SIZE;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function allZeros(buf: Uint8Array): boolean {
|
|
253
|
+
for (let i = 0; i < buf.length; i++) {
|
|
254
|
+
if (buf[i] !== 0) return false;
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function validateChecksum(header: Uint8Array): boolean {
|
|
260
|
+
const stored = parseOctal(header, 148, 8);
|
|
261
|
+
let unsigned = 0;
|
|
262
|
+
let signed = 0;
|
|
263
|
+
for (let i = 0; i < BLOCK_SIZE; i++) {
|
|
264
|
+
const byte = i >= 148 && i < 156 ? 0x20 : header[i];
|
|
265
|
+
unsigned += byte;
|
|
266
|
+
signed += byte > 127 ? byte - 256 : byte;
|
|
267
|
+
}
|
|
268
|
+
return stored === unsigned || stored === signed;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export class TarParseError extends Error {
|
|
272
|
+
constructor(msg: string) {
|
|
273
|
+
super(msg);
|
|
274
|
+
this.name = "TarParseError";
|
|
275
|
+
}
|
|
276
|
+
}
|
package/src/test.mts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "ESNext",
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"experimentalDecorators": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"allowImportingTsExtensions": false,
|
|
9
|
+
"outDir": "lib/esm",
|
|
10
|
+
"rootDir": "src",
|
|
11
|
+
"declarationDir": "lib/types",
|
|
12
|
+
"composite": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"strict": true,
|
|
15
|
+
"types": ["node"]
|
|
16
|
+
},
|
|
17
|
+
"include": [
|
|
18
|
+
"src/**/*.ts"
|
|
19
|
+
],
|
|
20
|
+
"exclude": [
|
|
21
|
+
"src/test.mts"
|
|
22
|
+
]
|
|
23
|
+
}
|