zip-lib 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +380 -363
- package/fs.d.ts +19 -0
- package/{lib/fs.js → fs.js} +104 -23
- package/{lib/index.js → index.js} +3 -4
- package/package.json +43 -45
- package/{lib/unzip.js → unzip.js} +25 -7
- package/{lib/zip.d.ts → zip.d.ts} +15 -0
- package/{lib/zip.js → zip.js} +27 -16
- package/lib/util.js +0 -49
- /package/{lib/cancelable.d.ts → cancelable.d.ts} +0 -0
- /package/{lib/cancelable.js → cancelable.js} +0 -0
- /package/{lib/index.d.ts → index.d.ts} +0 -0
- /package/{lib/unzip.d.ts → unzip.d.ts} +0 -0
package/fs.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface FileEntry {
|
|
2
|
+
path: string;
|
|
3
|
+
isSymbolicLink: boolean;
|
|
4
|
+
type: FileType;
|
|
5
|
+
mtime: Date;
|
|
6
|
+
mode: number;
|
|
7
|
+
}
|
|
8
|
+
export type FileType = "file" | "dir";
|
|
9
|
+
export declare function realpath(target: string): Promise<string>;
|
|
10
|
+
export declare function readdirp(folder: string): Promise<FileEntry[]>;
|
|
11
|
+
export declare function getFileEntry(target: string): Promise<FileEntry>;
|
|
12
|
+
export declare function ensureFolder(folder: string): Promise<{
|
|
13
|
+
isDirectory: boolean;
|
|
14
|
+
isSymbolicLink: boolean;
|
|
15
|
+
realpath?: string;
|
|
16
|
+
}>;
|
|
17
|
+
export declare function pathExists(target: string): Promise<boolean>;
|
|
18
|
+
export declare function rimraf(target: string): Promise<void>;
|
|
19
|
+
export declare function isRootPath(target: string): boolean;
|
package/{lib/fs.js → fs.js}
RENAMED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.realpath = realpath;
|
|
4
|
+
exports.readdirp = readdirp;
|
|
5
|
+
exports.getFileEntry = getFileEntry;
|
|
6
|
+
exports.ensureFolder = ensureFolder;
|
|
7
|
+
exports.pathExists = pathExists;
|
|
8
|
+
exports.rimraf = rimraf;
|
|
9
|
+
exports.isRootPath = isRootPath;
|
|
4
10
|
const path = require("path");
|
|
5
|
-
const
|
|
11
|
+
const fs = require("fs/promises");
|
|
12
|
+
const util = require("node:util");
|
|
13
|
+
const fsSync = require("fs");
|
|
14
|
+
async function realpath(target) {
|
|
15
|
+
// fs.promises.realpath has a bug with long path on Windows.
|
|
16
|
+
// https://github.com/nodejs/node/issues/51031
|
|
17
|
+
return util.promisify(fsSync.realpath)(target);
|
|
18
|
+
}
|
|
6
19
|
async function readdirp(folder) {
|
|
7
20
|
const result = [];
|
|
8
|
-
const files = await
|
|
21
|
+
const files = await fs.readdir(folder);
|
|
9
22
|
for (const item of files) {
|
|
10
23
|
const file = path.join(folder, item);
|
|
11
24
|
const entry = await getFileEntry(file);
|
|
@@ -22,9 +35,8 @@ async function readdirp(folder) {
|
|
|
22
35
|
}
|
|
23
36
|
return result;
|
|
24
37
|
}
|
|
25
|
-
exports.readdirp = readdirp;
|
|
26
38
|
async function getFileEntry(target) {
|
|
27
|
-
const stat = await
|
|
39
|
+
const stat = await fs.lstat(target);
|
|
28
40
|
let isSymbolicLink = false;
|
|
29
41
|
let fileType = "file";
|
|
30
42
|
if (stat.isDirectory()) {
|
|
@@ -36,7 +48,7 @@ async function getFileEntry(target) {
|
|
|
36
48
|
// If the path is a link, we must instead use fs.stat() to find out if the
|
|
37
49
|
// link is a directory or not because lstat will always return the stat of
|
|
38
50
|
// the link which is always a file.
|
|
39
|
-
const actualStat = await
|
|
51
|
+
const actualStat = await fs.stat(target);
|
|
40
52
|
if (actualStat.isDirectory()) {
|
|
41
53
|
fileType = "dir";
|
|
42
54
|
}
|
|
@@ -50,14 +62,17 @@ async function getFileEntry(target) {
|
|
|
50
62
|
mode: stat.mode
|
|
51
63
|
};
|
|
52
64
|
}
|
|
53
|
-
exports.getFileEntry = getFileEntry;
|
|
54
65
|
async function ensureFolder(folder) {
|
|
55
66
|
// stop at root
|
|
56
67
|
if (folder === path.dirname(folder)) {
|
|
57
|
-
return Promise.resolve(
|
|
68
|
+
return Promise.resolve({
|
|
69
|
+
isDirectory: true,
|
|
70
|
+
isSymbolicLink: false
|
|
71
|
+
});
|
|
58
72
|
}
|
|
59
73
|
try {
|
|
60
|
-
await mkdir(folder);
|
|
74
|
+
const result = await mkdir(folder);
|
|
75
|
+
return result;
|
|
61
76
|
}
|
|
62
77
|
catch (error) {
|
|
63
78
|
// ENOENT: a parent folder does not exist yet, continue
|
|
@@ -70,40 +85,38 @@ async function ensureFolder(folder) {
|
|
|
70
85
|
return Promise.reject(error);
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
|
-
exports.ensureFolder = ensureFolder;
|
|
74
88
|
async function pathExists(target) {
|
|
75
89
|
try {
|
|
76
|
-
await
|
|
90
|
+
await fs.access(target);
|
|
77
91
|
return true;
|
|
78
92
|
}
|
|
79
93
|
catch (error) {
|
|
80
94
|
return false;
|
|
81
95
|
}
|
|
82
96
|
}
|
|
83
|
-
exports.pathExists = pathExists;
|
|
84
97
|
async function rimraf(target) {
|
|
85
98
|
if (isRootPath(target)) {
|
|
86
99
|
// refuse to recursively delete root
|
|
87
100
|
return Promise.reject(new Error(`Refuse to recursively delete root, path: "${target}"`));
|
|
88
101
|
}
|
|
89
102
|
try {
|
|
90
|
-
const stat = await
|
|
103
|
+
const stat = await fs.lstat(target);
|
|
91
104
|
// Folder delete (recursive) - NOT for symbolic links though!
|
|
92
105
|
if (stat.isDirectory() && !stat.isSymbolicLink()) {
|
|
93
106
|
// Children
|
|
94
|
-
const children = await
|
|
107
|
+
const children = await fs.readdir(target);
|
|
95
108
|
await Promise.all(children.map(child => rimraf(path.join(target, child))));
|
|
96
109
|
// Folder
|
|
97
|
-
await
|
|
110
|
+
await fs.rmdir(target);
|
|
98
111
|
}
|
|
99
112
|
// Single file delete
|
|
100
113
|
else {
|
|
101
114
|
// chmod as needed to allow for unlink
|
|
102
115
|
const mode = stat.mode;
|
|
103
116
|
if (!(mode & 128)) { // 128 === 0200
|
|
104
|
-
await
|
|
117
|
+
await fs.chmod(target, mode | 128);
|
|
105
118
|
}
|
|
106
|
-
return
|
|
119
|
+
return fs.unlink(target);
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
catch (error) {
|
|
@@ -112,10 +125,13 @@ async function rimraf(target) {
|
|
|
112
125
|
}
|
|
113
126
|
}
|
|
114
127
|
}
|
|
115
|
-
exports.rimraf = rimraf;
|
|
116
128
|
async function mkdir(folder) {
|
|
117
129
|
try {
|
|
118
|
-
await
|
|
130
|
+
await fs.mkdir(folder, 0o777);
|
|
131
|
+
return {
|
|
132
|
+
isDirectory: true,
|
|
133
|
+
isSymbolicLink: false,
|
|
134
|
+
};
|
|
119
135
|
}
|
|
120
136
|
catch (error) {
|
|
121
137
|
// ENOENT: a parent folder does not exist yet or folder name is invalid.
|
|
@@ -125,15 +141,81 @@ async function mkdir(folder) {
|
|
|
125
141
|
// Any other error: check if folder exists and
|
|
126
142
|
// return normally in that case if its a folder
|
|
127
143
|
try {
|
|
128
|
-
const fileStat = await
|
|
129
|
-
if (
|
|
130
|
-
|
|
144
|
+
const fileStat = await fs.lstat(folder);
|
|
145
|
+
if (fileStat.isSymbolicLink()) {
|
|
146
|
+
const realFilePath = await realpath(folder);
|
|
147
|
+
const realFileStat = await fs.lstat(realFilePath);
|
|
148
|
+
if (!realFileStat.isDirectory()) {
|
|
149
|
+
return Promise.reject(new Error(`"${folder}" exists and is not a directory.`));
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
isDirectory: false,
|
|
153
|
+
isSymbolicLink: true,
|
|
154
|
+
realpath: realFilePath,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
if (!fileStat.isDirectory()) {
|
|
159
|
+
return Promise.reject(new Error(`"${folder}" exists and is not a directory.`));
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
isDirectory: true,
|
|
163
|
+
isSymbolicLink: false,
|
|
164
|
+
};
|
|
131
165
|
}
|
|
132
166
|
}
|
|
133
167
|
catch (statError) {
|
|
134
168
|
throw error; // rethrow original error
|
|
135
169
|
}
|
|
136
170
|
}
|
|
171
|
+
// // Any other error: check if folder exists and
|
|
172
|
+
// // return normally in that case if its a folder
|
|
173
|
+
// try {
|
|
174
|
+
// if (folder.includes("dirlink")) {
|
|
175
|
+
// console.log("tttttt11111", folder);
|
|
176
|
+
// }
|
|
177
|
+
// const fileStat = await fs.lstat(folder);
|
|
178
|
+
// if (folder.includes("dirlink")) {
|
|
179
|
+
// console.log("tttttt22222", fileStat);
|
|
180
|
+
// }
|
|
181
|
+
// if (fileStat.isSymbolicLink()) {
|
|
182
|
+
// console.log("kkkkkkkkk", fileStat);
|
|
183
|
+
// const realFilePath = await realpath(folder);
|
|
184
|
+
// const realFileStat = await fs.lstat(realFilePath);
|
|
185
|
+
// if (!realFileStat.isDirectory()) {
|
|
186
|
+
// return Promise.reject(new Error(`"${folder}" exists and is not a directory.`));
|
|
187
|
+
// }
|
|
188
|
+
// return {
|
|
189
|
+
// isDirectory: false,
|
|
190
|
+
// isSymbolicLink: true,
|
|
191
|
+
// realpath: realFilePath,
|
|
192
|
+
// }
|
|
193
|
+
// } else {
|
|
194
|
+
// if (!fileStat.isDirectory()) {
|
|
195
|
+
// return Promise.reject(new Error(`"${folder}" exists and is not a directory.`));
|
|
196
|
+
// }
|
|
197
|
+
// return {
|
|
198
|
+
// isDirectory: true,
|
|
199
|
+
// isSymbolicLink: false,
|
|
200
|
+
// }
|
|
201
|
+
// }
|
|
202
|
+
// } catch (statError) {
|
|
203
|
+
// if (folder.includes("dirlink")) {
|
|
204
|
+
// console.log("yyyyy", statError);
|
|
205
|
+
// }
|
|
206
|
+
// // ignore
|
|
207
|
+
// }
|
|
208
|
+
// if (folder.includes("dirlink")) {
|
|
209
|
+
// console.log("kkkkkkkkk22222", folder);
|
|
210
|
+
// }
|
|
211
|
+
// await fs.mkdir(folder, { recursive: true, mode: 0o777 });
|
|
212
|
+
// if (folder.includes("dirlink")) {
|
|
213
|
+
// console.log("kkkkkkkkk3333333", folder);
|
|
214
|
+
// }
|
|
215
|
+
// return {
|
|
216
|
+
// isDirectory: true,
|
|
217
|
+
// isSymbolicLink: false,
|
|
218
|
+
// };
|
|
137
219
|
}
|
|
138
220
|
// "A"
|
|
139
221
|
const charA = 65;
|
|
@@ -172,4 +254,3 @@ function isRootPath(target) {
|
|
|
172
254
|
}
|
|
173
255
|
return false;
|
|
174
256
|
}
|
|
175
|
-
exports.isRootPath = isRootPath;
|
|
@@ -14,7 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
17
|
+
exports.archiveFile = archiveFile;
|
|
18
|
+
exports.archiveFolder = archiveFolder;
|
|
19
|
+
exports.extract = extract;
|
|
18
20
|
const zip_1 = require("./zip");
|
|
19
21
|
const unzip_1 = require("./unzip");
|
|
20
22
|
__exportStar(require("./zip"), exports);
|
|
@@ -30,7 +32,6 @@ function archiveFile(file, zipFile, options) {
|
|
|
30
32
|
zip.addFile(file);
|
|
31
33
|
return zip.archive(zipFile);
|
|
32
34
|
}
|
|
33
|
-
exports.archiveFile = archiveFile;
|
|
34
35
|
/**
|
|
35
36
|
* Compress all the contents of the specified folder to zip.
|
|
36
37
|
* @param folder
|
|
@@ -42,7 +43,6 @@ function archiveFolder(folder, zipFile, options) {
|
|
|
42
43
|
zip.addFolder(folder);
|
|
43
44
|
return zip.archive(zipFile);
|
|
44
45
|
}
|
|
45
|
-
exports.archiveFolder = archiveFolder;
|
|
46
46
|
/**
|
|
47
47
|
* Extract the zip file to the specified location.
|
|
48
48
|
* @param zipFile
|
|
@@ -53,4 +53,3 @@ function extract(zipFile, targetFolder, options) {
|
|
|
53
53
|
const unzip = new unzip_1.Unzip(options);
|
|
54
54
|
return unzip.extract(zipFile, targetFolder);
|
|
55
55
|
}
|
|
56
|
-
exports.extract = extract;
|
package/package.json
CHANGED
|
@@ -1,45 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "zip-lib",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "zip and unzip library for node",
|
|
5
|
-
"main": "lib/index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"compile": "rimraf ./
|
|
8
|
-
"release": "rimraf ./lib && tsc -p ./src/tsconfig.release.json",
|
|
9
|
-
"compile-test": "rimraf ./test/out && tsc -p ./test/src/tsconfig.json",
|
|
10
|
-
"test": "node ./test/src/before.js && mocha ./test/out --timeout 10000"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"@types/
|
|
38
|
-
"@types/
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "zip-lib",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "zip and unzip library for node",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"compile": "rimraf ./dist && tsc -p ./src/tsconfig.json",
|
|
8
|
+
"release": "rimraf ./lib && tsc -p ./src/tsconfig.release.json && node ./build.mjs",
|
|
9
|
+
"compile-test": "rimraf ./test/out && tsc -p ./test/src/tsconfig.json",
|
|
10
|
+
"test": "npm run compile && npm run compile-test && node ./test/src/before.js && mocha ./test/out --timeout 10000"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/fpsqdb/zip-lib.git"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"zip",
|
|
21
|
+
"folder",
|
|
22
|
+
"unzip",
|
|
23
|
+
"archive",
|
|
24
|
+
"extract",
|
|
25
|
+
"promise",
|
|
26
|
+
"async"
|
|
27
|
+
],
|
|
28
|
+
"author": "fpsqdb",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"yauzl": "^3.2.0",
|
|
32
|
+
"yazl": "^3.3.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/mocha": "^10.0.10",
|
|
36
|
+
"@types/node": "^18.19.86",
|
|
37
|
+
"@types/yauzl": "^2.10.3",
|
|
38
|
+
"@types/yazl": "^2.4.6",
|
|
39
|
+
"mocha": "^11.1.0",
|
|
40
|
+
"rimraf": "^6.0.1",
|
|
41
|
+
"typescript": "^5.8.3"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -4,8 +4,8 @@ exports.Unzip = void 0;
|
|
|
4
4
|
const yauzl = require("yauzl");
|
|
5
5
|
const exfs = require("./fs");
|
|
6
6
|
const fs_1 = require("fs");
|
|
7
|
+
const fs = require("fs/promises");
|
|
7
8
|
const path = require("path");
|
|
8
|
-
const util = require("./util");
|
|
9
9
|
const cancelable_1 = require("./cancelable");
|
|
10
10
|
class EntryEvent {
|
|
11
11
|
/**
|
|
@@ -40,6 +40,7 @@ class EntryContext {
|
|
|
40
40
|
this._realTargetFolder = _realTargetFolder;
|
|
41
41
|
this.symlinkAsFileOnWindows = symlinkAsFileOnWindows;
|
|
42
42
|
this._symlinkFileNames = [];
|
|
43
|
+
this._symlinkFolders = [];
|
|
43
44
|
}
|
|
44
45
|
get decodeEntryFileName() {
|
|
45
46
|
return this._decodeEntryFileName;
|
|
@@ -56,20 +57,31 @@ class EntryContext {
|
|
|
56
57
|
get symlinkFileNames() {
|
|
57
58
|
return this._symlinkFileNames;
|
|
58
59
|
}
|
|
60
|
+
get symlinkFolders() {
|
|
61
|
+
return this._symlinkFolders;
|
|
62
|
+
}
|
|
59
63
|
getFilePath() {
|
|
60
64
|
return path.join(this.targetFolder, this.decodeEntryFileName);
|
|
61
65
|
}
|
|
62
66
|
async isOutsideTargetFolder(tpath) {
|
|
63
|
-
if (this.symlinkFileNames.length === 0
|
|
67
|
+
if (this.symlinkFileNames.length === 0 &&
|
|
68
|
+
this.symlinkFolders.length === 0) {
|
|
64
69
|
return false;
|
|
65
70
|
}
|
|
66
71
|
if (process.platform === "win32" &&
|
|
67
72
|
this.symlinkAsFileOnWindows) {
|
|
68
73
|
return false;
|
|
69
74
|
}
|
|
75
|
+
for (const { folder, realpath } of this.symlinkFolders) {
|
|
76
|
+
if (tpath.includes(folder)) {
|
|
77
|
+
if (realpath.indexOf(this.realTargetFolder) !== 0) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
70
82
|
for (const fileName of this.symlinkFileNames) {
|
|
71
83
|
if (tpath.includes(fileName)) {
|
|
72
|
-
const realFilePath = await
|
|
84
|
+
const realFilePath = await exfs.realpath(tpath);
|
|
73
85
|
if (realFilePath.indexOf(this.realTargetFolder) !== 0) {
|
|
74
86
|
return true;
|
|
75
87
|
}
|
|
@@ -106,7 +118,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
106
118
|
return Promise.reject(this.canceledError());
|
|
107
119
|
}
|
|
108
120
|
await exfs.ensureFolder(targetFolder);
|
|
109
|
-
const realTargetFolder = await
|
|
121
|
+
const realTargetFolder = await exfs.realpath(targetFolder);
|
|
110
122
|
const zfile = await this.openZip(zipFile, token);
|
|
111
123
|
this.zipFile = zfile;
|
|
112
124
|
zfile.readEntry();
|
|
@@ -240,7 +252,13 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
240
252
|
async extractEntry(zfile, entry, entryContext, token) {
|
|
241
253
|
const filePath = entryContext.getFilePath();
|
|
242
254
|
const fileDir = path.dirname(filePath);
|
|
243
|
-
await exfs.ensureFolder(fileDir);
|
|
255
|
+
const folderStat = await exfs.ensureFolder(fileDir);
|
|
256
|
+
if (folderStat.isSymbolicLink) {
|
|
257
|
+
entryContext.symlinkFolders.push({
|
|
258
|
+
folder: fileDir,
|
|
259
|
+
realpath: folderStat.realpath,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
244
262
|
const outside = await entryContext.isOutsideTargetFolder(fileDir);
|
|
245
263
|
if (outside) {
|
|
246
264
|
const error = new Error(`Refuse to write file outside "${entryContext.targetFolder}", file: "${filePath}"`);
|
|
@@ -317,7 +335,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
317
335
|
targetPath = path.join(path.dirname(des), linkContent);
|
|
318
336
|
}
|
|
319
337
|
try {
|
|
320
|
-
const stat = await
|
|
338
|
+
const stat = await fs.stat(targetPath);
|
|
321
339
|
if (stat.isDirectory()) {
|
|
322
340
|
linkType = "dir";
|
|
323
341
|
}
|
|
@@ -327,7 +345,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
327
345
|
}
|
|
328
346
|
}
|
|
329
347
|
}
|
|
330
|
-
await
|
|
348
|
+
await fs.symlink(linkContent, des, linkType);
|
|
331
349
|
}
|
|
332
350
|
isOverwrite() {
|
|
333
351
|
if (this.options &&
|
|
@@ -10,6 +10,14 @@ export interface IZipOptions {
|
|
|
10
10
|
* The default value is `false`.
|
|
11
11
|
*/
|
|
12
12
|
followSymlinks?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Sets the compression level.
|
|
15
|
+
*
|
|
16
|
+
* 0: the file data will be stored, otherwise, the file data will be deflated.
|
|
17
|
+
*
|
|
18
|
+
* The default value is `6`.
|
|
19
|
+
*/
|
|
20
|
+
compressionLevel?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
13
21
|
}
|
|
14
22
|
/**
|
|
15
23
|
* Compress files or folders to a zip file.
|
|
@@ -56,4 +64,11 @@ export declare class Zip extends Cancelable {
|
|
|
56
64
|
private walkDir;
|
|
57
65
|
private stopPipe;
|
|
58
66
|
private followSymlink;
|
|
67
|
+
/**
|
|
68
|
+
* Retrieves the yazl options based on the current settings.
|
|
69
|
+
*
|
|
70
|
+
* @returns The yazl options with the specified compression level,
|
|
71
|
+
* or undefined if options or compressionLevel are not properly set.
|
|
72
|
+
*/
|
|
73
|
+
private getYazlOption;
|
|
59
74
|
}
|
package/{lib/zip.js → zip.js}
RENAMED
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Zip = void 0;
|
|
4
4
|
const yazl = require("yazl");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
|
+
const fs = require("fs/promises");
|
|
6
7
|
const exfs = require("./fs");
|
|
7
8
|
const path = require("path");
|
|
8
|
-
const util = require("./util");
|
|
9
9
|
const cancelable_1 = require("./cancelable");
|
|
10
10
|
/**
|
|
11
11
|
* Compress files or folders to a zip file.
|
|
@@ -28,13 +28,13 @@ class Zip extends cancelable_1.Cancelable {
|
|
|
28
28
|
* A valid metadataPath must not start with "/" or /[A-Za-z]:\//, and must not contain "..".
|
|
29
29
|
*/
|
|
30
30
|
addFile(file, metadataPath) {
|
|
31
|
-
let
|
|
32
|
-
if (!
|
|
33
|
-
|
|
31
|
+
let mPath = metadataPath;
|
|
32
|
+
if (!mPath) {
|
|
33
|
+
mPath = path.basename(file);
|
|
34
34
|
}
|
|
35
35
|
this.zipFiles.push({
|
|
36
36
|
path: file,
|
|
37
|
-
metadataPath:
|
|
37
|
+
metadataPath: mPath
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
@@ -120,11 +120,11 @@ class Zip extends cancelable_1.Cancelable {
|
|
|
120
120
|
if (entry.isSymbolicLink) {
|
|
121
121
|
if (this.followSymlink()) {
|
|
122
122
|
if (entry.type === "dir") {
|
|
123
|
-
const realPath = await
|
|
123
|
+
const realPath = await exfs.realpath(file.path);
|
|
124
124
|
await this.walkDir([{ path: realPath, metadataPath: file.metadataPath }], token);
|
|
125
125
|
}
|
|
126
126
|
else {
|
|
127
|
-
zip.addFile(file.path, file.metadataPath);
|
|
127
|
+
zip.addFile(file.path, file.metadataPath, this.getYazlOption());
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
else {
|
|
@@ -156,18 +156,12 @@ class Zip extends cancelable_1.Cancelable {
|
|
|
156
156
|
});
|
|
157
157
|
// If the file attribute is known, add the entry using `addReadStream`,
|
|
158
158
|
// this can reduce the number of calls to the `fs.stat` method.
|
|
159
|
-
zip.addReadStream(fileStream, metadataPath, {
|
|
160
|
-
mode: file.mode,
|
|
161
|
-
mtime: file.mtime
|
|
162
|
-
});
|
|
159
|
+
zip.addReadStream(fileStream, metadataPath, Object.assign(Object.assign({}, this.getYazlOption()), { mode: file.mode, mtime: file.mtime }));
|
|
163
160
|
});
|
|
164
161
|
}
|
|
165
162
|
async addSymlink(zip, file, metadataPath) {
|
|
166
|
-
const linkTarget = await
|
|
167
|
-
zip.addBuffer(Buffer.from(linkTarget), metadataPath, {
|
|
168
|
-
mtime: file.mtime,
|
|
169
|
-
mode: file.mode
|
|
170
|
-
});
|
|
163
|
+
const linkTarget = await fs.readlink(file.path);
|
|
164
|
+
zip.addBuffer(Buffer.from(linkTarget), metadataPath, Object.assign(Object.assign({}, this.getYazlOption()), { mtime: file.mtime, mode: file.mode }));
|
|
171
165
|
}
|
|
172
166
|
async walkDir(folders, token) {
|
|
173
167
|
for (const folder of folders) {
|
|
@@ -209,5 +203,22 @@ class Zip extends cancelable_1.Cancelable {
|
|
|
209
203
|
}
|
|
210
204
|
return followSymlink;
|
|
211
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Retrieves the yazl options based on the current settings.
|
|
208
|
+
*
|
|
209
|
+
* @returns The yazl options with the specified compression level,
|
|
210
|
+
* or undefined if options or compressionLevel are not properly set.
|
|
211
|
+
*/
|
|
212
|
+
getYazlOption() {
|
|
213
|
+
if (!this.options) {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
if (typeof this.options.compressionLevel !== "number") {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
compressionLevel: this.options.compressionLevel,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
212
223
|
}
|
|
213
224
|
exports.Zip = Zip;
|
package/lib/util.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.readlink = exports.symlink = exports.rmdir = exports.access = exports.readdir = exports.chmod = exports.lstat = exports.stat = exports.realpath = exports.mkdir = exports.unlink = void 0;
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const util = require("util");
|
|
6
|
-
function unlink(path) {
|
|
7
|
-
return util.promisify(fs.unlink)(path);
|
|
8
|
-
}
|
|
9
|
-
exports.unlink = unlink;
|
|
10
|
-
function mkdir(path, mode) {
|
|
11
|
-
return util.promisify(fs.mkdir)(path, mode);
|
|
12
|
-
}
|
|
13
|
-
exports.mkdir = mkdir;
|
|
14
|
-
function realpath(path) {
|
|
15
|
-
return util.promisify(fs.realpath)(path);
|
|
16
|
-
}
|
|
17
|
-
exports.realpath = realpath;
|
|
18
|
-
function stat(path) {
|
|
19
|
-
return util.promisify(fs.stat)(path);
|
|
20
|
-
}
|
|
21
|
-
exports.stat = stat;
|
|
22
|
-
function lstat(path) {
|
|
23
|
-
return util.promisify(fs.lstat)(path);
|
|
24
|
-
}
|
|
25
|
-
exports.lstat = lstat;
|
|
26
|
-
function chmod(path, mode) {
|
|
27
|
-
return util.promisify(fs.chmod)(path, mode);
|
|
28
|
-
}
|
|
29
|
-
exports.chmod = chmod;
|
|
30
|
-
function readdir(path) {
|
|
31
|
-
return util.promisify(fs.readdir)(path);
|
|
32
|
-
}
|
|
33
|
-
exports.readdir = readdir;
|
|
34
|
-
function access(path, mode) {
|
|
35
|
-
return util.promisify(fs.access)(path, mode);
|
|
36
|
-
}
|
|
37
|
-
exports.access = access;
|
|
38
|
-
function rmdir(path) {
|
|
39
|
-
return util.promisify(fs.rmdir)(path);
|
|
40
|
-
}
|
|
41
|
-
exports.rmdir = rmdir;
|
|
42
|
-
function symlink(target, path, type) {
|
|
43
|
-
return util.promisify(fs.symlink)(target, path, type);
|
|
44
|
-
}
|
|
45
|
-
exports.symlink = symlink;
|
|
46
|
-
function readlink(path) {
|
|
47
|
-
return util.promisify(fs.readlink)(path);
|
|
48
|
-
}
|
|
49
|
-
exports.readlink = readlink;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|