@procedures/archive 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- 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
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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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions of the procedures of this package
|
|
3
|
+
*
|
|
4
|
+
* mark procedure new adds the types of each new procedure here. The zod schemas are in
|
|
5
|
+
* `module.ts`: an exported schema needs a written type (isolatedDeclarations).
|
|
6
|
+
*/
|
|
7
|
+
/** The formats of an archive. `tar` is a tar file without compression. */
|
|
8
|
+
export type ArchiveFormat = "tar.gz" | "tar" | "zip";
|
|
9
|
+
/** The kind of an entry of an archive. `other` is a device, a FIFO or another special file. */
|
|
10
|
+
export type ArchiveEntryKind = "file" | "directory" | "symlink" | "hardlink" | "other";
|
|
11
|
+
export interface ArchiveCreateInput {
|
|
12
|
+
/** The archive to make. */
|
|
13
|
+
output: string;
|
|
14
|
+
/** A folder: the archive gets its content, with paths relative to the folder. */
|
|
15
|
+
source?: string | undefined;
|
|
16
|
+
/** Files and folders, relative to `cwd`. A folder goes in with its content. */
|
|
17
|
+
files?: string[] | undefined;
|
|
18
|
+
/** The base folder of `files`. The default is the working folder of the process. */
|
|
19
|
+
cwd?: string | undefined;
|
|
20
|
+
/** The format. The default comes from the name of `output`: `.tar.gz`, `.tgz`, `.tar` or `.zip`. */
|
|
21
|
+
format?: ArchiveFormat | undefined;
|
|
22
|
+
/** True: replace an existing archive. The default is false: an existing archive is an error. */
|
|
23
|
+
overwrite?: boolean | undefined;
|
|
24
|
+
}
|
|
25
|
+
export interface ArchiveCreateOutput {
|
|
26
|
+
/** The absolute path of the archive. */
|
|
27
|
+
path: string;
|
|
28
|
+
format: ArchiveFormat;
|
|
29
|
+
/** The number of entries: files, folders and links. */
|
|
30
|
+
entries: number;
|
|
31
|
+
/** The size of the archive, in bytes. */
|
|
32
|
+
bytes: number;
|
|
33
|
+
}
|
|
34
|
+
export interface ArchiveExtractInput {
|
|
35
|
+
/** The archive. */
|
|
36
|
+
archive: string;
|
|
37
|
+
/** The folder that gets the content. The procedure makes it when it does not exist. */
|
|
38
|
+
target: string;
|
|
39
|
+
/** The format. The default comes from the first bytes of the archive. */
|
|
40
|
+
format?: ArchiveFormat | undefined;
|
|
41
|
+
/** True: replace an existing file. The default is false: an existing file is an error, and nothing changes. */
|
|
42
|
+
overwrite?: boolean | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface ArchiveExtractOutput {
|
|
45
|
+
/** The absolute path of the target folder. */
|
|
46
|
+
target: string;
|
|
47
|
+
format: ArchiveFormat;
|
|
48
|
+
files: number;
|
|
49
|
+
directories: number;
|
|
50
|
+
/** The symbolic links and the hard links. */
|
|
51
|
+
links: number;
|
|
52
|
+
/** The bytes of the files. */
|
|
53
|
+
bytes: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ArchiveListInput {
|
|
56
|
+
/** The archive. */
|
|
57
|
+
archive: string;
|
|
58
|
+
/** The format. The default comes from the first bytes of the archive. */
|
|
59
|
+
format?: ArchiveFormat | undefined;
|
|
60
|
+
}
|
|
61
|
+
/** One entry of an archive. */
|
|
62
|
+
export interface ArchiveEntry {
|
|
63
|
+
/** The path in the archive, as the archive has it. */
|
|
64
|
+
path: string;
|
|
65
|
+
kind: ArchiveEntryKind;
|
|
66
|
+
/** The size of the content, in bytes. */
|
|
67
|
+
size: number;
|
|
68
|
+
/** The mode bits (`0o644`), when the archive has them. */
|
|
69
|
+
mode?: number | undefined;
|
|
70
|
+
/** The time of the last change, as an ISO text, when the archive has it. */
|
|
71
|
+
mtime?: string | undefined;
|
|
72
|
+
/** The target of a link. */
|
|
73
|
+
linkTarget?: string | undefined;
|
|
74
|
+
}
|
|
75
|
+
export interface ArchiveListOutput {
|
|
76
|
+
format: ArchiveFormat;
|
|
77
|
+
entries: ArchiveEntry[];
|
|
78
|
+
/** The sum of the sizes of the entries, in bytes. */
|
|
79
|
+
bytes: number;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AAErD,+FAA+F;AAC/F,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAMvF,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC7B,oFAAoF;IACpF,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,oGAAoG;IACpG,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACnC,gGAAgG;IAChG,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,mBAAmB;IAClC,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACnC,+GAA+G;IAC/G,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CACpC;AAED,+BAA+B;AAC/B,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,gBAAgB,CAAC;IACvB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;CACf"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions of the procedures of this package
|
|
3
|
+
*
|
|
4
|
+
* mark procedure new adds the types of each new procedure here. The zod schemas are in
|
|
5
|
+
* `module.ts`: an exported schema needs a written type (isolatedDeclarations).
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/dist/walk.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The walk of `archive.create`: each file, folder and symbolic link under the inputs, in a fixed
|
|
3
|
+
* order. The walk does not follow a link: the archive gets the link itself.
|
|
4
|
+
*/
|
|
5
|
+
/** One path for the archive. */
|
|
6
|
+
export interface WalkEntry {
|
|
7
|
+
/** The name in the archive: relative, with `/`. */
|
|
8
|
+
readonly name: string;
|
|
9
|
+
/** The absolute path on the disk. */
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly kind: "file" | "directory" | "symlink";
|
|
12
|
+
readonly size: number;
|
|
13
|
+
readonly mode: number;
|
|
14
|
+
readonly mtime: Date;
|
|
15
|
+
readonly linkTarget?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** The limits and the paths to leave out (the new archive and its temporary file). */
|
|
18
|
+
export interface WalkOptions {
|
|
19
|
+
readonly maxEntries: number;
|
|
20
|
+
readonly maxBytes: number;
|
|
21
|
+
readonly exclude: ReadonlySet<string>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* This function gives the target of a link with `/`, as an archive keeps it. Windows gives `..\a.txt`
|
|
25
|
+
* for a link that Node made from `../a.txt`. On the other systems, a `\` is a part of a name.
|
|
26
|
+
*/
|
|
27
|
+
export declare function portableLinkTarget(target: string, separator?: string): string;
|
|
28
|
+
/** This function walks the names (relative to `base`) and gives each entry for the archive. */
|
|
29
|
+
export declare function walk(base: string, names: readonly string[], options: WalkOptions): Promise<WalkEntry[]>;
|
|
30
|
+
/** The names of the content of a folder, sorted. */
|
|
31
|
+
export declare function folderNames(folder: string): Promise<string[]>;
|
|
32
|
+
/** The absolute path of a name under a base. */
|
|
33
|
+
export declare function under(base: string, name: string): string;
|
|
34
|
+
//# sourceMappingURL=walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,gCAAgC;AAChC,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,sFAAsF;AACtF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACvC;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAElF;AAED,+FAA+F;AAC/F,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAkC7G;AAED,oDAAoD;AACpD,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnE;AAED,gDAAgD;AAChD,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
package/dist/walk.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The walk of `archive.create`: each file, folder and symbolic link under the inputs, in a fixed
|
|
3
|
+
* order. The walk does not follow a link: the archive gets the link itself.
|
|
4
|
+
*/
|
|
5
|
+
import { lstat, readdir, readlink } from "node:fs/promises";
|
|
6
|
+
import { join, resolve, sep } from "node:path";
|
|
7
|
+
import { ArchiveError } from "./errors.js";
|
|
8
|
+
const byName = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
9
|
+
/**
|
|
10
|
+
* This function gives the target of a link with `/`, as an archive keeps it. Windows gives `..\a.txt`
|
|
11
|
+
* for a link that Node made from `../a.txt`. On the other systems, a `\` is a part of a name.
|
|
12
|
+
*/
|
|
13
|
+
export function portableLinkTarget(target, separator = sep) {
|
|
14
|
+
return separator === "\\" ? target.replaceAll("\\", "/") : target;
|
|
15
|
+
}
|
|
16
|
+
/** This function walks the names (relative to `base`) and gives each entry for the archive. */
|
|
17
|
+
export async function walk(base, names, options) {
|
|
18
|
+
const entries = [];
|
|
19
|
+
const seen = new Set();
|
|
20
|
+
let bytes = 0;
|
|
21
|
+
const visit = async (name) => {
|
|
22
|
+
const path = resolve(base, ...name.split("/"));
|
|
23
|
+
if (options.exclude.has(path) || seen.has(name))
|
|
24
|
+
return;
|
|
25
|
+
seen.add(name);
|
|
26
|
+
let stats;
|
|
27
|
+
try {
|
|
28
|
+
stats = await lstat(path);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new ArchiveError("UNSAFE_PATH", `${path} does not exist`, name);
|
|
32
|
+
}
|
|
33
|
+
if (entries.length >= options.maxEntries)
|
|
34
|
+
throw new ArchiveError("TOO_LARGE", `The archive gets more entries than the limit of ${options.maxEntries}`, name);
|
|
35
|
+
const common = { name, path, size: 0, mode: stats.mode & 0o7777, mtime: stats.mtime };
|
|
36
|
+
if (stats.isSymbolicLink()) {
|
|
37
|
+
entries.push({ ...common, kind: "symlink", linkTarget: portableLinkTarget(await readlink(path)) });
|
|
38
|
+
}
|
|
39
|
+
else if (stats.isDirectory()) {
|
|
40
|
+
entries.push({ ...common, kind: "directory" });
|
|
41
|
+
const children = (await readdir(path)).sort(byName);
|
|
42
|
+
for (const child of children)
|
|
43
|
+
await visit(`${name}/${child}`);
|
|
44
|
+
}
|
|
45
|
+
else if (stats.isFile()) {
|
|
46
|
+
bytes += stats.size;
|
|
47
|
+
if (bytes > options.maxBytes)
|
|
48
|
+
throw new ArchiveError("TOO_LARGE", `The files have more than ${options.maxBytes} bytes`, name);
|
|
49
|
+
entries.push({ ...common, kind: "file", size: stats.size });
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
throw new ArchiveError("UNSUPPORTED_ENTRY", `${path} is a special file (a socket, a device or a FIFO)`, name);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
for (const name of names)
|
|
56
|
+
await visit(name);
|
|
57
|
+
return entries;
|
|
58
|
+
}
|
|
59
|
+
/** The names of the content of a folder, sorted. */
|
|
60
|
+
export async function folderNames(folder) {
|
|
61
|
+
return (await readdir(folder)).sort(byName);
|
|
62
|
+
}
|
|
63
|
+
/** The absolute path of a name under a base. */
|
|
64
|
+
export function under(base, name) {
|
|
65
|
+
return join(base, ...name.split("/"));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=walk.js.map
|
package/dist/walk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"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"}
|
package/dist/zip.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zip archives on `node:zlib` (roadmap R46).
|
|
3
|
+
*
|
|
4
|
+
* The package reads and writes zip itself, for two reasons. The reader needs the external
|
|
5
|
+
* attributes of each entry, to see a symbolic link, and a limit on the bytes of each entry
|
|
6
|
+
* against a zip bomb. A zip library that decodes in memory gives neither.
|
|
7
|
+
*
|
|
8
|
+
* - The reader takes the central directory: stored and deflated entries, UTF-8 names, and the
|
|
9
|
+
* zip64 fields. It refuses an encrypted entry, another method and an archive on more disks.
|
|
10
|
+
* - The extract streams each entry and stops when it gets more bytes than the entry declares.
|
|
11
|
+
* It examines the size and the CRC-32 of each entry.
|
|
12
|
+
* - The writer stores each file, or deflates it when that is smaller. It writes no zip64 fields:
|
|
13
|
+
* it refuses more than 65535 entries and an archive of 4 GiB or more.
|
|
14
|
+
*/
|
|
15
|
+
import { type FileHandle } from "node:fs/promises";
|
|
16
|
+
/** The CRC-32 of bytes, continued from `crc` (0 for new bytes). */
|
|
17
|
+
export declare function crc32(bytes: Uint8Array, crc?: number): number;
|
|
18
|
+
/** One entry of the central directory. */
|
|
19
|
+
export interface ZipEntry {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly kind: "file" | "directory" | "symlink";
|
|
22
|
+
readonly method: number;
|
|
23
|
+
readonly flags: number;
|
|
24
|
+
readonly crc: number;
|
|
25
|
+
readonly compressedSize: number;
|
|
26
|
+
readonly size: number;
|
|
27
|
+
readonly localOffset: number;
|
|
28
|
+
/** The mode bits of a Unix entry, without the type. */
|
|
29
|
+
readonly mode: number | undefined;
|
|
30
|
+
readonly mtime: Date;
|
|
31
|
+
}
|
|
32
|
+
/** This function reads the central directory of a zip. It throws `TOO_LARGE` for more than `maxEntries` entries. */
|
|
33
|
+
export declare function readZipDirectory(path: string, maxEntries: number): Promise<ZipEntry[]>;
|
|
34
|
+
/**
|
|
35
|
+
* This function writes the content of a file entry to `destination`, with the checks. The file
|
|
36
|
+
* must not exist: the caller removes an old file first, so the write never follows a link.
|
|
37
|
+
*/
|
|
38
|
+
export declare function extractZipFile(archive: string, entry: ZipEntry, destination: string, mode?: number): Promise<void>;
|
|
39
|
+
/** This function gives the target of a symbolic link entry: its content, as text. */
|
|
40
|
+
export declare function readZipLink(archive: string, entry: ZipEntry): Promise<string>;
|
|
41
|
+
/** One entry for the writer. */
|
|
42
|
+
export interface ZipWriteEntry {
|
|
43
|
+
/** The name in the archive. A folder ends with `/`: the writer adds it. */
|
|
44
|
+
readonly name: string;
|
|
45
|
+
readonly kind: "file" | "directory" | "symlink";
|
|
46
|
+
/** The content of a file, or the target of a link as UTF-8. A function loads it when the writer needs it. */
|
|
47
|
+
readonly data?: Uint8Array | (() => Promise<Uint8Array>) | undefined;
|
|
48
|
+
/** The mode bits, without the type. */
|
|
49
|
+
readonly mode?: number | undefined;
|
|
50
|
+
readonly mtime?: Date | undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* This function writes a zip to an open file. The names are not examined here: `archive.create`
|
|
54
|
+
* gives only the relative paths of a walk, and a test gives hostile names on purpose.
|
|
55
|
+
*/
|
|
56
|
+
export declare function writeZip(handle: FileHandle, entries: readonly ZipWriteEntry[]): Promise<number>;
|
|
57
|
+
//# sourceMappingURL=zip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../src/zip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAuCzD,mEAAmE;AACnE,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,SAAI,GAAG,MAAM,CAIxD;AAMD,0CAA0C;AAC1C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB;AAkFD,oHAAoH;AACpH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0E5F;AAwED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExH;AAED,qFAAqF;AACrF,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAWnF;AAMD,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;IAChD,6GAA6G;IAC7G,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,uCAAuC;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoErG"}
|