@procedures/archive 0.0.0-stage → 0.2.3
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/LICENSE +21 -0
- package/README.md +95 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/format.d.ts +25 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +60 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +34 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +148 -0
- package/dist/module.js.map +1 -0
- package/dist/paths.d.ts +58 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +205 -0
- package/dist/paths.js.map +1 -0
- package/dist/procedures/archive/create.d.ts +14 -0
- package/dist/procedures/archive/create.d.ts.map +1 -0
- package/dist/procedures/archive/create.js +81 -0
- package/dist/procedures/archive/create.js.map +1 -0
- package/dist/procedures/archive/extract.d.ts +17 -0
- package/dist/procedures/archive/extract.d.ts.map +1 -0
- package/dist/procedures/archive/extract.js +101 -0
- package/dist/procedures/archive/extract.js.map +1 -0
- package/dist/procedures/archive/index.d.ts +4 -0
- package/dist/procedures/archive/index.d.ts.map +1 -0
- package/dist/procedures/archive/index.js +4 -0
- package/dist/procedures/archive/index.js.map +1 -0
- package/dist/procedures/archive/list.d.ts +15 -0
- package/dist/procedures/archive/list.d.ts.map +1 -0
- package/dist/procedures/archive/list.js +47 -0
- package/dist/procedures/archive/list.js.map +1 -0
- package/dist/register.d.ts +6 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +8 -0
- package/dist/register.js.map +1 -0
- package/dist/tar.d.ts +38 -0
- package/dist/tar.d.ts.map +1 -0
- package/dist/tar.js +193 -0
- package/dist/tar.js.map +1 -0
- package/dist/types.d.ts +81 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/walk.d.ts +34 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +67 -0
- package/dist/walk.js.map +1 -0
- package/dist/zip.d.ts +57 -0
- package/dist/zip.d.ts.map +1 -0
- package/dist/zip.js +397 -0
- package/dist/zip.js.map +1 -0
- package/package.json +77 -3
- package/src/errors.ts +33 -0
- package/src/format.ts +64 -0
- package/src/index.ts +9 -0
- package/src/module.ts +192 -0
- package/src/paths.ts +230 -0
- package/src/procedures/archive/create.ts +84 -0
- package/src/procedures/archive/extract.ts +103 -0
- package/src/procedures/archive/index.ts +3 -0
- package/src/procedures/archive/list.ts +50 -0
- package/src/register.ts +10 -0
- package/src/tar.ts +198 -0
- package/src/types.ts +101 -0
- package/src/walk.ts +85 -0
- package/src/zip.ts +419 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* archive.create procedure
|
|
3
|
+
*
|
|
4
|
+
* Make a tar.gz, tar or zip archive of a folder or of files. The procedure writes a temporary
|
|
5
|
+
* file next to the archive, and renames it at the end: a failed call leaves no part of an
|
|
6
|
+
* archive. The walk does not follow a symbolic link: the archive gets the link.
|
|
7
|
+
*/
|
|
8
|
+
import { randomBytes } from "node:crypto";
|
|
9
|
+
import { mkdir, open, readFile, rename, rm, stat } from "node:fs/promises";
|
|
10
|
+
import { dirname, resolve } from "node:path";
|
|
11
|
+
import { ArchiveError } from "../../errors.js";
|
|
12
|
+
import { DEFAULT_ARCHIVE_SETTINGS, formatOfName } from "../../format.js";
|
|
13
|
+
import { entryParts } from "../../paths.js";
|
|
14
|
+
import { createTar } from "../../tar.js";
|
|
15
|
+
import { folderNames, walk } from "../../walk.js";
|
|
16
|
+
import { writeZip } from "../../zip.js";
|
|
17
|
+
/** The base folder and the names of the input. Exactly one of `source` and `files`. */
|
|
18
|
+
async function inputNames(input) {
|
|
19
|
+
if ((input.source === undefined) === (input.files === undefined)) {
|
|
20
|
+
throw new ArchiveError("UNSAFE_PATH", "archive.create needs exactly one of source and files");
|
|
21
|
+
}
|
|
22
|
+
if (input.source !== undefined) {
|
|
23
|
+
const base = resolve(input.source);
|
|
24
|
+
const stats = await stat(base).catch(() => undefined);
|
|
25
|
+
if (!stats?.isDirectory())
|
|
26
|
+
throw new ArchiveError("UNSAFE_PATH", `The source ${base} is not a folder`);
|
|
27
|
+
return { base, names: await folderNames(base) };
|
|
28
|
+
}
|
|
29
|
+
const base = resolve(input.cwd ?? process.cwd());
|
|
30
|
+
const names = (input.files ?? []).map((name) => {
|
|
31
|
+
const parts = entryParts(name);
|
|
32
|
+
if (parts.length === 0)
|
|
33
|
+
throw new ArchiveError("UNSAFE_PATH", `The file ${JSON.stringify(name)} names the base folder: give source for a whole folder`, name);
|
|
34
|
+
return parts.join("/");
|
|
35
|
+
});
|
|
36
|
+
return { base, names };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Make a tar.gz or zip archive of a folder or of files
|
|
40
|
+
*/
|
|
41
|
+
export async function archiveCreate(input, settings = DEFAULT_ARCHIVE_SETTINGS) {
|
|
42
|
+
const format = formatOfName(input.output, input.format);
|
|
43
|
+
const output = resolve(input.output);
|
|
44
|
+
const existing = await stat(output).catch(() => undefined);
|
|
45
|
+
if (existing?.isDirectory())
|
|
46
|
+
throw new ArchiveError("EXISTS", `${output} is a folder`);
|
|
47
|
+
if (existing !== undefined && input.overwrite !== true)
|
|
48
|
+
throw new ArchiveError("EXISTS", `${output} exists: give overwrite: true to replace it`);
|
|
49
|
+
const { base, names } = await inputNames(input);
|
|
50
|
+
const temporary = `${output}.${randomBytes(6).toString("hex")}.tmp`;
|
|
51
|
+
const entries = await walk(base, names, { ...settings, exclude: new Set([output, temporary]) });
|
|
52
|
+
await mkdir(dirname(output), { recursive: true });
|
|
53
|
+
try {
|
|
54
|
+
if (format === "zip") {
|
|
55
|
+
const items = entries.map((entry) => ({
|
|
56
|
+
name: entry.name,
|
|
57
|
+
kind: entry.kind,
|
|
58
|
+
mode: entry.mode,
|
|
59
|
+
mtime: entry.mtime,
|
|
60
|
+
data: entry.kind === "file" ? () => readFile(entry.path) : entry.kind === "symlink" ? Buffer.from(entry.linkTarget ?? "", "utf8") : undefined,
|
|
61
|
+
}));
|
|
62
|
+
const handle = await open(temporary, "wx");
|
|
63
|
+
try {
|
|
64
|
+
await writeZip(handle, items);
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
await handle.close();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
await createTar(temporary, base, entries.map((entry) => entry.name), format === "tar.gz");
|
|
72
|
+
}
|
|
73
|
+
await rename(temporary, output);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
await rm(temporary, { force: true });
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
return { path: output, format, entries: entries.length, bytes: (await stat(output)).size };
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/procedures/archive/create.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAwB,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAsB,MAAM,cAAc,CAAC;AAG5D,uFAAuF;AACvF,KAAK,UAAU,UAAU,CAAC,KAAyB;IACjD,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,YAAY,CAAC,aAAa,EAAE,sDAAsD,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE;YAAE,MAAM,IAAI,YAAY,CAAC,aAAa,EAAE,cAAc,IAAI,kBAAkB,CAAC,CAAC;QACvG,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,YAAY,CAAC,aAAa,EAAE,YAAY,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,wDAAwD,EAAE,IAAI,CAAC,CAAC;QAC9J,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAyB,EAAE,QAAQ,GAAoB,wBAAwB;IACjH,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3D,IAAI,QAAQ,EAAE,WAAW,EAAE;QAAE,MAAM,IAAI,YAAY,CAAC,QAAQ,EAAE,GAAG,MAAM,cAAc,CAAC,CAAC;IACvF,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI;QAAE,MAAM,IAAI,YAAY,CAAC,QAAQ,EAAE,GAAG,MAAM,6CAA6C,CAAC,CAAC;IAEjJ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IACpE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhG,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,MAAM,KAAK,GAAoB,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACrD,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;aAC9I,CAAC,CAAC,CAAC;YACJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAChC,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,CACb,SAAS,EACT,IAAI,EACJ,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAClC,MAAM,KAAK,QAAQ,CACpB,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7F,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* archive.extract procedure
|
|
3
|
+
*
|
|
4
|
+
* Extract a tar.gz, tar or zip archive into a folder. The procedure examines all the entries
|
|
5
|
+
* before it writes a file (`planExtract()`): an entry with `..` or an absolute path, a symbolic
|
|
6
|
+
* link out of the target, an entry through a link, a special file, an existing file without
|
|
7
|
+
* `overwrite`, or an archive over the limits changes nothing.
|
|
8
|
+
*
|
|
9
|
+
* A damaged entry (its size or its CRC-32) stops the extract, and the files before it stay.
|
|
10
|
+
*/
|
|
11
|
+
import { type ArchiveSettings } from "../../format.js";
|
|
12
|
+
import type { ArchiveExtractInput, ArchiveExtractOutput } from "../../types.js";
|
|
13
|
+
/**
|
|
14
|
+
* Extract a tar.gz or zip archive into a folder, with a check of each path
|
|
15
|
+
*/
|
|
16
|
+
export declare function archiveExtract(input: ArchiveExtractInput, settings?: ArchiveSettings): Promise<ArchiveExtractOutput>;
|
|
17
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../../src/procedures/archive/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAA0C,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAI/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAqDhF;;GAEG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,QAAQ,GAAE,eAA0C,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6BpJ"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* archive.extract procedure
|
|
3
|
+
*
|
|
4
|
+
* Extract a tar.gz, tar or zip archive into a folder. The procedure examines all the entries
|
|
5
|
+
* before it writes a file (`planExtract()`): an entry with `..` or an absolute path, a symbolic
|
|
6
|
+
* link out of the target, an entry through a link, a special file, an existing file without
|
|
7
|
+
* `overwrite`, or an archive over the limits changes nothing.
|
|
8
|
+
*
|
|
9
|
+
* A damaged entry (its size or its CRC-32) stops the extract, and the files before it stay.
|
|
10
|
+
*/
|
|
11
|
+
import { lstat, mkdir, realpath, rm, symlink, unlink, utimes } from "node:fs/promises";
|
|
12
|
+
import { dirname, join, resolve } from "node:path";
|
|
13
|
+
import { DEFAULT_ARCHIVE_SETTINGS, formatOfFile } from "../../format.js";
|
|
14
|
+
import { planExtract } from "../../paths.js";
|
|
15
|
+
import { extractTar, readTarEntries } from "../../tar.js";
|
|
16
|
+
import { extractZipFile, readZipDirectory, readZipLink } from "../../zip.js";
|
|
17
|
+
/** This function removes an old file or link at a path, so a new write does not follow it. */
|
|
18
|
+
async function clear(path) {
|
|
19
|
+
const found = await lstat(path).catch(() => undefined);
|
|
20
|
+
if (found !== undefined && !found.isDirectory())
|
|
21
|
+
await unlink(path);
|
|
22
|
+
}
|
|
23
|
+
/** This function writes the checked entries of a zip, in the order of the archive. */
|
|
24
|
+
async function writeZipEntries(archive, target, planned, zipEntries) {
|
|
25
|
+
for (const entry of planned) {
|
|
26
|
+
const destination = join(target, ...entry.parts);
|
|
27
|
+
if (entry.kind === "directory") {
|
|
28
|
+
await mkdir(destination, { recursive: true });
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
await mkdir(dirname(destination), { recursive: true });
|
|
32
|
+
await clear(destination);
|
|
33
|
+
if (entry.kind === "symlink") {
|
|
34
|
+
await symlink(entry.linkTarget ?? "", destination);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const zipEntry = zipEntries[entry.index];
|
|
38
|
+
try {
|
|
39
|
+
await extractZipFile(archive, zipEntry, destination, zipEntry.mode === undefined ? undefined : zipEntry.mode & 0o777);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// A damaged entry leaves no part of its file
|
|
43
|
+
await rm(destination, { force: true });
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
await utimes(destination, zipEntry.mtime, zipEntry.mtime);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** The counts of the output. */
|
|
50
|
+
function countsOf(planned) {
|
|
51
|
+
let files = 0;
|
|
52
|
+
let directories = 0;
|
|
53
|
+
let links = 0;
|
|
54
|
+
let bytes = 0;
|
|
55
|
+
for (const entry of planned) {
|
|
56
|
+
if (entry.kind === "file") {
|
|
57
|
+
files++;
|
|
58
|
+
bytes += entry.size;
|
|
59
|
+
}
|
|
60
|
+
else if (entry.kind === "directory") {
|
|
61
|
+
directories++;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
links++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { files, directories, links, bytes };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract a tar.gz or zip archive into a folder, with a check of each path
|
|
71
|
+
*/
|
|
72
|
+
export async function archiveExtract(input, settings = DEFAULT_ARCHIVE_SETTINGS) {
|
|
73
|
+
const archive = resolve(input.archive);
|
|
74
|
+
const format = await formatOfFile(archive, input.format);
|
|
75
|
+
const overwrite = input.overwrite === true;
|
|
76
|
+
// The entries, before a write
|
|
77
|
+
let raw;
|
|
78
|
+
let zipEntries = [];
|
|
79
|
+
if (format === "zip") {
|
|
80
|
+
zipEntries = await readZipDirectory(archive, settings.maxEntries);
|
|
81
|
+
raw = [];
|
|
82
|
+
for (const [index, entry] of zipEntries.entries()) {
|
|
83
|
+
raw.push({ name: entry.name, kind: entry.kind, size: entry.size, index, ...(entry.kind === "symlink" ? { linkTarget: await readZipLink(archive, entry) } : {}) });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
raw = (await readTarEntries(archive, settings)).map((entry) => ({ name: entry.name, kind: entry.kind, size: entry.size, linkTarget: entry.linkTarget }));
|
|
88
|
+
}
|
|
89
|
+
const folder = resolve(input.target);
|
|
90
|
+
await mkdir(folder, { recursive: true });
|
|
91
|
+
const target = await realpath(folder);
|
|
92
|
+
const planned = planExtract(raw, target, { overwrite, maxBytes: settings.maxBytes, maxEntries: settings.maxEntries });
|
|
93
|
+
if (format === "zip") {
|
|
94
|
+
await writeZipEntries(archive, target, planned, zipEntries);
|
|
95
|
+
}
|
|
96
|
+
else if (planned.length > 0) {
|
|
97
|
+
await extractTar(archive, target, new Set(planned.map((entry) => entry.name)));
|
|
98
|
+
}
|
|
99
|
+
return { target, format, ...countsOf(planned) };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../../src/procedures/archive/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/procedures/archive/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/procedures/archive/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* archive.list procedure
|
|
3
|
+
*
|
|
4
|
+
* The entries of a tar.gz, tar or zip archive: the path, the kind, the size, the mode, the time
|
|
5
|
+
* and the target of a link. The list reads the archive and writes nothing.
|
|
6
|
+
*/
|
|
7
|
+
import { type ArchiveSettings } from "../../format.js";
|
|
8
|
+
import type { ArchiveEntry, ArchiveFormat, ArchiveListInput, ArchiveListOutput } from "../../types.js";
|
|
9
|
+
/** The entries of an archive of a known format. `extract` uses them too. */
|
|
10
|
+
export declare function readEntries(path: string, format: ArchiveFormat, settings: ArchiveSettings): Promise<ArchiveEntry[]>;
|
|
11
|
+
/**
|
|
12
|
+
* The entries of a tar.gz or zip archive
|
|
13
|
+
*/
|
|
14
|
+
export declare function archiveList(input: ArchiveListInput, settings?: ArchiveSettings): Promise<ArchiveListOutput>;
|
|
15
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/procedures/archive/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAA0C,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAG/F,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEvG,4EAA4E;AAC5E,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAyBzH;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,GAAE,eAA0C,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAK3I"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* archive.list procedure
|
|
3
|
+
*
|
|
4
|
+
* The entries of a tar.gz, tar or zip archive: the path, the kind, the size, the mode, the time
|
|
5
|
+
* and the target of a link. The list reads the archive and writes nothing.
|
|
6
|
+
*/
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
import { DEFAULT_ARCHIVE_SETTINGS, formatOfFile } from "../../format.js";
|
|
9
|
+
import { readTarEntries } from "../../tar.js";
|
|
10
|
+
import { readZipDirectory, readZipLink } from "../../zip.js";
|
|
11
|
+
/** The entries of an archive of a known format. `extract` uses them too. */
|
|
12
|
+
export async function readEntries(path, format, settings) {
|
|
13
|
+
if (format === "zip") {
|
|
14
|
+
const entries = await readZipDirectory(path, settings.maxEntries);
|
|
15
|
+
const result = [];
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
result.push({
|
|
18
|
+
path: entry.name,
|
|
19
|
+
kind: entry.kind,
|
|
20
|
+
size: entry.size,
|
|
21
|
+
...(entry.mode !== undefined ? { mode: entry.mode } : {}),
|
|
22
|
+
mtime: entry.mtime.toISOString(),
|
|
23
|
+
...(entry.kind === "symlink" ? { linkTarget: await readZipLink(path, entry) } : {}),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
const entries = await readTarEntries(path, settings);
|
|
29
|
+
return entries.map((entry) => ({
|
|
30
|
+
path: entry.name,
|
|
31
|
+
kind: entry.kind,
|
|
32
|
+
size: entry.size,
|
|
33
|
+
...(entry.mode !== undefined ? { mode: entry.mode & 0o7777 } : {}),
|
|
34
|
+
...(entry.mtime !== undefined ? { mtime: entry.mtime.toISOString() } : {}),
|
|
35
|
+
...(entry.linkTarget !== undefined ? { linkTarget: entry.linkTarget } : {}),
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The entries of a tar.gz or zip archive
|
|
40
|
+
*/
|
|
41
|
+
export async function archiveList(input, settings = DEFAULT_ARCHIVE_SETTINGS) {
|
|
42
|
+
const path = resolve(input.archive);
|
|
43
|
+
const format = await formatOfFile(path, input.format);
|
|
44
|
+
const entries = await readEntries(path, format, { ...settings, maxBytes: Number.MAX_SAFE_INTEGER });
|
|
45
|
+
return { format, entries, bytes: entries.reduce((sum, entry) => sum + (entry.kind === "file" ? entry.size : 0), 0) };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/procedures/archive/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,cAAc,aAAa,CAAC"}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Importing this file registers the procedures of @procedures/archive in the global registry:
|
|
3
|
+
* `import "@procedures/archive/register"`. The package root registers nothing.
|
|
4
|
+
*/
|
|
5
|
+
import { registerArchiveProcedures } from "./module.js";
|
|
6
|
+
export * from "./module.js";
|
|
7
|
+
registerArchiveProcedures();
|
|
8
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,cAAc,aAAa,CAAC;AAE5B,yBAAyB,EAAE,CAAC"}
|
package/dist/tar.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tar and tar.gz archives with `tar` (node-tar), the tar library of npm.
|
|
3
|
+
*
|
|
4
|
+
* - The list reads the headers with a `Parser`. It stops at the limit of entries or of bytes, so a
|
|
5
|
+
* compressed archive with a very large content stops early.
|
|
6
|
+
* - The extract runs after the check of `planExtract()`. It keeps the protections of node-tar:
|
|
7
|
+
* no absolute path, no `..`, and no write through a symbolic link. Its filter lets only the
|
|
8
|
+
* checked entries through, and `strict` makes each warning an error.
|
|
9
|
+
*/
|
|
10
|
+
import type { ArchiveEntryKind } from "./types.js";
|
|
11
|
+
/** One header of a tar archive. */
|
|
12
|
+
export interface TarEntryInfo {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly kind: ArchiveEntryKind;
|
|
15
|
+
readonly size: number;
|
|
16
|
+
readonly mode: number | undefined;
|
|
17
|
+
readonly mtime: Date | undefined;
|
|
18
|
+
readonly linkTarget: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* This function reads the headers of a tar or tar.gz archive. It throws `TOO_LARGE` at more than
|
|
22
|
+
* `maxEntries` entries or more than `maxBytes` bytes of files.
|
|
23
|
+
*/
|
|
24
|
+
export declare function readTarEntries(path: string, limits: {
|
|
25
|
+
maxEntries: number;
|
|
26
|
+
maxBytes: number;
|
|
27
|
+
}): Promise<TarEntryInfo[]>;
|
|
28
|
+
/**
|
|
29
|
+
* This function extracts a tar or tar.gz archive into `target`, after the check. Only the names
|
|
30
|
+
* of `allowed` pass the filter. A name that the check did not see is an error at the end.
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractTar(path: string, target: string, allowed: ReadonlySet<string>): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* This function writes a tar or tar.gz archive of the `names` (relative to `cwd`) to `file`. The
|
|
35
|
+
* names are the full list: the walk of `archive.create` gives each file and folder.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createTar(file: string, cwd: string, names: readonly string[], gzip: boolean): Promise<void>;
|
|
38
|
+
//# sourceMappingURL=tar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,mCAAmC;AACnC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AA0DD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAO5H;AA6DD;;;GAGG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB1G;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjH"}
|
package/dist/tar.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tar and tar.gz archives with `tar` (node-tar), the tar library of npm.
|
|
3
|
+
*
|
|
4
|
+
* - The list reads the headers with a `Parser`. It stops at the limit of entries or of bytes, so a
|
|
5
|
+
* compressed archive with a very large content stops early.
|
|
6
|
+
* - The extract runs after the check of `planExtract()`. It keeps the protections of node-tar:
|
|
7
|
+
* no absolute path, no `..`, and no write through a symbolic link. Its filter lets only the
|
|
8
|
+
* checked entries through, and `strict` makes each warning an error.
|
|
9
|
+
*/
|
|
10
|
+
import { createReadStream } from "node:fs";
|
|
11
|
+
import { createGunzip, gzipSync } from "node:zlib";
|
|
12
|
+
import { open, writeFile } from "node:fs/promises";
|
|
13
|
+
import { create, extract, Parser } from "tar";
|
|
14
|
+
import { ArchiveError } from "./errors.js";
|
|
15
|
+
/** The kind of a tar entry type. */
|
|
16
|
+
function kindOf(type) {
|
|
17
|
+
switch (type) {
|
|
18
|
+
case "File":
|
|
19
|
+
case "OldFile":
|
|
20
|
+
case "ContiguousFile":
|
|
21
|
+
return "file";
|
|
22
|
+
case "Directory":
|
|
23
|
+
return "directory";
|
|
24
|
+
case "SymbolicLink":
|
|
25
|
+
return "symlink";
|
|
26
|
+
case "Link":
|
|
27
|
+
return "hardlink";
|
|
28
|
+
default:
|
|
29
|
+
return "other";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** An error of node-tar as an `ArchiveError`. */
|
|
33
|
+
function archiveErrorOf(error) {
|
|
34
|
+
if (error instanceof ArchiveError)
|
|
35
|
+
return error;
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
return new ArchiveError("BAD_ARCHIVE", `The tar archive is damaged: ${message}`);
|
|
38
|
+
}
|
|
39
|
+
/** The most zero bytes of an empty tar: an empty tar of GNU tar has 10240. */
|
|
40
|
+
const MAX_EMPTY_TAR_BYTES = 1024 * 1024;
|
|
41
|
+
/**
|
|
42
|
+
* True when the content of a tar or tar.gz archive is only zero bytes: an archive without
|
|
43
|
+
* entries. node-tar calls such an archive "unrecognized". The check reads at most 1 MiB.
|
|
44
|
+
*/
|
|
45
|
+
async function isEmptyTar(path) {
|
|
46
|
+
const head = Buffer.alloc(2);
|
|
47
|
+
const handle = await open(path, "r");
|
|
48
|
+
try {
|
|
49
|
+
await handle.read(head, 0, 2, 0);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
await handle.close();
|
|
53
|
+
}
|
|
54
|
+
const input = createReadStream(path);
|
|
55
|
+
const stream = head[0] === 0x1f && head[1] === 0x8b ? input.pipe(createGunzip()) : input;
|
|
56
|
+
let bytes = 0;
|
|
57
|
+
try {
|
|
58
|
+
for await (const chunk of stream) {
|
|
59
|
+
bytes += chunk.length;
|
|
60
|
+
if (bytes > MAX_EMPTY_TAR_BYTES || chunk.some((byte) => byte !== 0))
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return bytes > 0;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
input.destroy();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* This function reads the headers of a tar or tar.gz archive. It throws `TOO_LARGE` at more than
|
|
74
|
+
* `maxEntries` entries or more than `maxBytes` bytes of files.
|
|
75
|
+
*/
|
|
76
|
+
export async function readTarEntries(path, limits) {
|
|
77
|
+
try {
|
|
78
|
+
return await parseTarEntries(path, limits);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error instanceof ArchiveError && error.code === "BAD_ARCHIVE" && error.message.includes("TAR_BAD_ARCHIVE") && (await isEmptyTar(path)))
|
|
82
|
+
return [];
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function parseTarEntries(path, limits) {
|
|
87
|
+
const entries = [];
|
|
88
|
+
let bytes = 0;
|
|
89
|
+
await new Promise((resolve, reject) => {
|
|
90
|
+
let settled = false;
|
|
91
|
+
const input = createReadStream(path);
|
|
92
|
+
const finish = (error) => {
|
|
93
|
+
if (settled)
|
|
94
|
+
return;
|
|
95
|
+
settled = true;
|
|
96
|
+
if (error === undefined) {
|
|
97
|
+
resolve();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
input.destroy();
|
|
101
|
+
reject(archiveErrorOf(error));
|
|
102
|
+
};
|
|
103
|
+
const parser = new Parser({
|
|
104
|
+
strict: true,
|
|
105
|
+
onReadEntry: (entry) => {
|
|
106
|
+
entry.resume();
|
|
107
|
+
if (settled)
|
|
108
|
+
return;
|
|
109
|
+
const kind = kindOf(entry.type);
|
|
110
|
+
if (kind === "file")
|
|
111
|
+
bytes += entry.size;
|
|
112
|
+
if (entries.length >= limits.maxEntries) {
|
|
113
|
+
finish(new ArchiveError("TOO_LARGE", `The archive has more entries than the limit of ${limits.maxEntries}`));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (bytes > limits.maxBytes) {
|
|
117
|
+
finish(new ArchiveError("TOO_LARGE", `The files of the archive have more than ${limits.maxBytes} bytes`, entry.path));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
entries.push({
|
|
121
|
+
name: entry.path,
|
|
122
|
+
kind,
|
|
123
|
+
size: entry.size,
|
|
124
|
+
mode: entry.mode,
|
|
125
|
+
mtime: entry.mtime,
|
|
126
|
+
linkTarget: entry.linkpath === undefined || entry.linkpath === "" ? undefined : entry.linkpath,
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
parser.on("warn", (code, message) => finish(new ArchiveError("BAD_ARCHIVE", `The tar archive is damaged: ${code} ${message instanceof Error ? message.message : message}`)));
|
|
131
|
+
parser.on("error", (error) => finish(error));
|
|
132
|
+
parser.on("end", () => finish());
|
|
133
|
+
input.on("error", (error) => finish(error));
|
|
134
|
+
input.on("data", (chunk) => {
|
|
135
|
+
if (settled)
|
|
136
|
+
return;
|
|
137
|
+
if (!parser.write(chunk)) {
|
|
138
|
+
input.pause();
|
|
139
|
+
parser.once("drain", () => input.resume());
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
input.on("end", () => {
|
|
143
|
+
if (!settled)
|
|
144
|
+
parser.end();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
return entries;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* This function extracts a tar or tar.gz archive into `target`, after the check. Only the names
|
|
151
|
+
* of `allowed` pass the filter. A name that the check did not see is an error at the end.
|
|
152
|
+
*/
|
|
153
|
+
export async function extractTar(path, target, allowed) {
|
|
154
|
+
const refused = [];
|
|
155
|
+
try {
|
|
156
|
+
await extract({
|
|
157
|
+
file: path,
|
|
158
|
+
cwd: target,
|
|
159
|
+
strict: true,
|
|
160
|
+
preservePaths: false,
|
|
161
|
+
preserveOwner: false,
|
|
162
|
+
// Remove an old file before the new one: the write never goes through a link or into a hard link
|
|
163
|
+
unlink: true,
|
|
164
|
+
filter: (name) => {
|
|
165
|
+
if (allowed.has(name))
|
|
166
|
+
return true;
|
|
167
|
+
refused.push(name);
|
|
168
|
+
return false;
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
throw archiveErrorOf(error);
|
|
174
|
+
}
|
|
175
|
+
const unexpected = refused.filter((name) => name.split(/[/\\]+/).some((part) => part !== "" && part !== "."));
|
|
176
|
+
if (unexpected.length > 0) {
|
|
177
|
+
throw new ArchiveError("BAD_ARCHIVE", `The archive changed during the extract: ${unexpected[0]} was not in the check`, unexpected[0]);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* This function writes a tar or tar.gz archive of the `names` (relative to `cwd`) to `file`. The
|
|
182
|
+
* names are the full list: the walk of `archive.create` gives each file and folder.
|
|
183
|
+
*/
|
|
184
|
+
export async function createTar(file, cwd, names, gzip) {
|
|
185
|
+
if (names.length === 0) {
|
|
186
|
+
// An empty tar: two blocks of zeros
|
|
187
|
+
const empty = Buffer.alloc(1024);
|
|
188
|
+
await writeFile(file, gzip ? gzipSync(empty) : empty, { flag: "wx" });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
await create({ file, cwd, gzip, portable: true, follow: false, noDirRecurse: true }, [...names]);
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=tar.js.map
|
package/dist/tar.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tar.js","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"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"}
|