zip-lib 1.2.3 → 1.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/README.md +295 -204
- package/lib/fs.d.ts +1 -0
- package/lib/fs.js +74 -61
- package/lib/index.d.ts +21 -2
- package/lib/index.js +27 -24
- package/lib/unzip.d.ts +22 -10
- package/lib/unzip.js +189 -129
- package/lib/zip.d.ts +25 -10
- package/lib/zip.js +143 -60
- package/package.json +3 -3
package/lib/unzip.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.Unzip = void 0;
|
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const fs = require("node:fs/promises");
|
|
6
6
|
const path = require("node:path");
|
|
7
|
+
const promises_1 = require("node:stream/promises");
|
|
7
8
|
const yauzl = require("yauzl");
|
|
8
9
|
const cancelable_1 = require("./cancelable");
|
|
9
10
|
const exfs = require("./fs");
|
|
@@ -41,6 +42,7 @@ class EntryContext {
|
|
|
41
42
|
this.symlinkAsFileOnWindows = symlinkAsFileOnWindows;
|
|
42
43
|
this._symlinkFileNames = [];
|
|
43
44
|
this._symlinkFolders = [];
|
|
45
|
+
this._inspectedFolders = [];
|
|
44
46
|
this._ensuredFolders = [];
|
|
45
47
|
}
|
|
46
48
|
get decodeEntryFileName() {
|
|
@@ -67,10 +69,25 @@ class EntryContext {
|
|
|
67
69
|
getFilePath() {
|
|
68
70
|
return path.resolve(path.join(this.targetFolder, this.decodeEntryFileName));
|
|
69
71
|
}
|
|
72
|
+
async inspectFolder(folder) {
|
|
73
|
+
if (this._inspectedFolders.includes(folder) || folder === path.dirname(folder)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
await this.inspectFolder(path.dirname(folder));
|
|
77
|
+
const folderStat = await exfs.statFolder(folder);
|
|
78
|
+
if (!folderStat) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (folderStat.isSymbolicLink) {
|
|
82
|
+
this.addSymlinkFolder(folder, folderStat.realpath);
|
|
83
|
+
}
|
|
84
|
+
this._inspectedFolders.push(folder);
|
|
85
|
+
}
|
|
70
86
|
async ensureFolder(folder) {
|
|
71
87
|
if (this._ensuredFolders.includes(folder)) {
|
|
72
88
|
return;
|
|
73
89
|
}
|
|
90
|
+
await this.inspectFolder(path.dirname(folder));
|
|
74
91
|
const folderStat = await exfs.ensureFolder(folder);
|
|
75
92
|
if (folderStat.isSymbolicLink) {
|
|
76
93
|
this.addSymlinkFolder(folder, folderStat.realpath);
|
|
@@ -117,98 +134,124 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
117
134
|
super();
|
|
118
135
|
this.options = options;
|
|
119
136
|
}
|
|
120
|
-
|
|
121
|
-
* Extract the zip file to the specified location.
|
|
122
|
-
* @param zipFile
|
|
123
|
-
* @param targetFolder
|
|
124
|
-
* @param options
|
|
125
|
-
*/
|
|
126
|
-
async extract(zipFile, targetFolder) {
|
|
127
|
-
let extractedEntriesCount = 0;
|
|
137
|
+
async extract(zipFileOrBuffer, targetFolder) {
|
|
128
138
|
const token = new cancelable_1.CancellationToken();
|
|
129
139
|
this.token = token;
|
|
140
|
+
const { zfile, realTargetFolder } = await this.prepareExtraction(zipFileOrBuffer, targetFolder, token);
|
|
141
|
+
this.zipFile = zfile;
|
|
142
|
+
await this.processEntries(zfile, targetFolder, realTargetFolder, token);
|
|
143
|
+
}
|
|
144
|
+
async prepareExtraction(zipFileOrBuffer, targetFolder, token) {
|
|
130
145
|
if (this.isOverwrite()) {
|
|
131
146
|
await exfs.rimraf(targetFolder);
|
|
132
147
|
}
|
|
133
148
|
if (token.isCancelled) {
|
|
134
|
-
|
|
149
|
+
throw this.canceledError();
|
|
135
150
|
}
|
|
136
151
|
await exfs.ensureFolder(targetFolder);
|
|
137
152
|
const realTargetFolder = await exfs.realpath(targetFolder);
|
|
138
|
-
const zfile = await this.openZip(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
153
|
+
const zfile = await this.openZip(zipFileOrBuffer, token);
|
|
154
|
+
return { zfile, realTargetFolder };
|
|
155
|
+
}
|
|
156
|
+
async processEntries(zfile, targetFolder, realTargetFolder, token) {
|
|
157
|
+
return await new Promise((resolve, reject) => {
|
|
158
|
+
let extractedEntriesCount = 0;
|
|
142
159
|
let anyError = null;
|
|
143
160
|
const total = zfile.entryCount;
|
|
161
|
+
const entryContext = new EntryContext(targetFolder, realTargetFolder, this.symlinkToFile());
|
|
162
|
+
const entryEvent = new EntryEvent(total);
|
|
163
|
+
const settle = this.createPromiseSettler(resolve, reject);
|
|
164
|
+
const disposeCancel = token.onCancelled(() => {
|
|
165
|
+
this.closeZip();
|
|
166
|
+
settle.reject(this.canceledError());
|
|
167
|
+
});
|
|
144
168
|
zfile.once("error", (err) => {
|
|
169
|
+
disposeCancel();
|
|
170
|
+
anyError = this.wrapError(err, token.isCancelled);
|
|
145
171
|
this.closeZip();
|
|
146
|
-
|
|
172
|
+
settle.reject(anyError);
|
|
147
173
|
});
|
|
148
174
|
zfile.once("close", () => {
|
|
175
|
+
disposeCancel();
|
|
149
176
|
this.zipFile = null;
|
|
150
177
|
if (anyError) {
|
|
151
|
-
|
|
178
|
+
settle.reject(this.wrapError(anyError, token.isCancelled));
|
|
152
179
|
}
|
|
153
|
-
else {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
// If the zip content is empty, it will not receive the
|
|
158
|
-
|
|
159
|
-
c(void 0);
|
|
160
|
-
}
|
|
180
|
+
else if (token.isCancelled) {
|
|
181
|
+
settle.reject(this.canceledError());
|
|
182
|
+
}
|
|
183
|
+
else if (extractedEntriesCount >= total) {
|
|
184
|
+
// If the zip content is empty, it will not receive the zfile.on("entry") event.
|
|
185
|
+
settle.resolve();
|
|
161
186
|
}
|
|
162
187
|
});
|
|
163
|
-
// Because openZip is an asynchronous method, openZip may not be completed when calling cancel,
|
|
164
|
-
// so we need to check if it has been canceled after the openZip method returns.
|
|
165
|
-
if (token.isCancelled) {
|
|
166
|
-
this.closeZip();
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
const entryContext = new EntryContext(targetFolder, realTargetFolder, this.symlinkToFile());
|
|
170
|
-
const entryEvent = new EntryEvent(total);
|
|
171
188
|
zfile.on("entry", async (entry) => {
|
|
172
|
-
// use UTF-8 in all situations
|
|
173
|
-
// see https://github.com/thejoshwolfe/yauzl/issues/84
|
|
174
|
-
const rawName = entry.fileName.toString("utf8");
|
|
175
|
-
// allow backslash
|
|
176
|
-
const fileName = rawName.replace(/\\/g, "/");
|
|
177
|
-
// Because `decodeStrings` is `false`, we need to manually verify the entryname
|
|
178
|
-
// see https://github.com/thejoshwolfe/yauzl#validatefilenamefilename
|
|
179
|
-
const errorMessage = yauzl.validateFileName(fileName);
|
|
180
|
-
if (errorMessage != null) {
|
|
181
|
-
anyError = new Error(errorMessage);
|
|
182
|
-
this.closeZip();
|
|
183
|
-
e(anyError);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
entryEvent.entryName = fileName;
|
|
187
|
-
this.onEntryCallback(entryEvent);
|
|
188
|
-
entryContext.decodeEntryFileName = fileName;
|
|
189
189
|
try {
|
|
190
|
-
|
|
191
|
-
entryEvent.reset();
|
|
192
|
-
zfile.readEntry();
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
await this.handleEntry(zfile, entry, entryContext, token);
|
|
196
|
-
}
|
|
190
|
+
await this.handleZipEntry(zfile, entry, entryContext, entryEvent, token);
|
|
197
191
|
extractedEntriesCount++;
|
|
198
|
-
if (extractedEntriesCount
|
|
199
|
-
|
|
192
|
+
if (extractedEntriesCount >= total) {
|
|
193
|
+
settle.resolve();
|
|
200
194
|
}
|
|
201
195
|
}
|
|
202
196
|
catch (error) {
|
|
203
197
|
anyError = this.wrapError(error, token.isCancelled);
|
|
204
198
|
this.closeZip();
|
|
205
|
-
|
|
199
|
+
settle.reject(anyError);
|
|
206
200
|
}
|
|
207
201
|
});
|
|
202
|
+
this.readNextEntry(zfile, token);
|
|
208
203
|
});
|
|
209
204
|
}
|
|
205
|
+
readNextEntry(zfile, token) {
|
|
206
|
+
if (token.isCancelled) {
|
|
207
|
+
this.closeZip();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
zfile.readEntry();
|
|
211
|
+
}
|
|
212
|
+
createPromiseSettler(resolve, reject) {
|
|
213
|
+
let settled = false;
|
|
214
|
+
return {
|
|
215
|
+
resolve: () => {
|
|
216
|
+
if (settled) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
settled = true;
|
|
220
|
+
resolve();
|
|
221
|
+
},
|
|
222
|
+
reject: (error) => {
|
|
223
|
+
if (settled) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
settled = true;
|
|
227
|
+
reject(error);
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
async handleZipEntry(zfile, entry, entryContext, entryEvent, token) {
|
|
232
|
+
// use UTF-8 in all situations
|
|
233
|
+
// see https://github.com/thejoshwolfe/yauzl/issues/84
|
|
234
|
+
const rawName = entry.fileName.toString("utf8");
|
|
235
|
+
// allow backslash
|
|
236
|
+
const fileName = rawName.replace(/\\/g, "/");
|
|
237
|
+
// Because decodeStrings is false, we need to manually verify the entry name
|
|
238
|
+
// see https://github.com/thejoshwolfe/yauzl#validatefilenamefilename
|
|
239
|
+
const errorMessage = yauzl.validateFileName(fileName);
|
|
240
|
+
if (errorMessage != null) {
|
|
241
|
+
throw new Error(errorMessage);
|
|
242
|
+
}
|
|
243
|
+
entryEvent.entryName = fileName;
|
|
244
|
+
this.onEntryCallback(entryEvent);
|
|
245
|
+
entryContext.decodeEntryFileName = fileName;
|
|
246
|
+
if (entryEvent.isPrevented) {
|
|
247
|
+
entryEvent.reset();
|
|
248
|
+
this.readNextEntry(zfile, token);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
await this.handleEntry(zfile, entry, entryContext, token);
|
|
252
|
+
}
|
|
210
253
|
/**
|
|
211
|
-
* Cancel
|
|
254
|
+
* Cancel extraction.
|
|
212
255
|
* If the cancel method is called after the extract is complete, nothing will happen.
|
|
213
256
|
*/
|
|
214
257
|
cancel() {
|
|
@@ -224,29 +267,41 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
224
267
|
this.zipFile = null;
|
|
225
268
|
}
|
|
226
269
|
}
|
|
227
|
-
openZip(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
270
|
+
async openZip(zipFileOrBuffer, token) {
|
|
271
|
+
const options = {
|
|
272
|
+
lazyEntries: true,
|
|
273
|
+
// see https://github.com/thejoshwolfe/yauzl/issues/84
|
|
274
|
+
decodeStrings: false,
|
|
275
|
+
};
|
|
276
|
+
try {
|
|
277
|
+
return await new Promise((resolve, reject) => {
|
|
278
|
+
const callback = (err, zfile) => {
|
|
279
|
+
if (err) {
|
|
280
|
+
reject(this.wrapError(err, token.isCancelled));
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
resolve(zfile);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
if (typeof zipFileOrBuffer === "string") {
|
|
287
|
+
yauzl.open(zipFileOrBuffer, options, callback);
|
|
236
288
|
}
|
|
237
289
|
else {
|
|
238
|
-
|
|
290
|
+
yauzl.fromBuffer(zipFileOrBuffer, options, callback);
|
|
239
291
|
}
|
|
240
292
|
});
|
|
241
|
-
}
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
throw this.wrapError(error, token.isCancelled);
|
|
296
|
+
}
|
|
242
297
|
}
|
|
243
298
|
async handleEntry(zfile, entry, entryContext, token) {
|
|
244
299
|
if (/\/$/.test(entryContext.decodeEntryFileName)) {
|
|
245
300
|
// Directory file names end with '/'.
|
|
246
|
-
// Note that
|
|
301
|
+
// Note that entries for directories themselves are optional.
|
|
247
302
|
// An entry's fileName implicitly requires its parent directories to exist.
|
|
248
303
|
await exfs.ensureFolder(entryContext.getFilePath());
|
|
249
|
-
|
|
304
|
+
this.readNextEntry(zfile, token);
|
|
250
305
|
}
|
|
251
306
|
else {
|
|
252
307
|
// file entry
|
|
@@ -254,13 +309,13 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
254
309
|
}
|
|
255
310
|
}
|
|
256
311
|
openZipFileStream(zfile, entry, token) {
|
|
257
|
-
return new Promise((
|
|
312
|
+
return new Promise((resolve, reject) => {
|
|
258
313
|
zfile.openReadStream(entry, (err, readStream) => {
|
|
259
314
|
if (err) {
|
|
260
|
-
|
|
315
|
+
reject(this.wrapError(err, token.isCancelled));
|
|
261
316
|
}
|
|
262
317
|
else {
|
|
263
|
-
|
|
318
|
+
resolve(readStream);
|
|
264
319
|
}
|
|
265
320
|
});
|
|
266
321
|
});
|
|
@@ -268,7 +323,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
268
323
|
async extractEntry(zfile, entry, entryContext, token) {
|
|
269
324
|
const filePath = entryContext.getFilePath();
|
|
270
325
|
const fileDir = path.dirname(filePath);
|
|
271
|
-
await entryContext.
|
|
326
|
+
await entryContext.inspectFolder(fileDir);
|
|
272
327
|
const outside = await entryContext.isOutsideTargetFolder(fileDir);
|
|
273
328
|
if (outside) {
|
|
274
329
|
const error = new Error(`Refuse to write file outside "${entryContext.targetFolder}", file: "${filePath}"`);
|
|
@@ -277,64 +332,69 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
277
332
|
}
|
|
278
333
|
const readStream = await this.openZipFileStream(zfile, entry, token);
|
|
279
334
|
await this.writeEntryToFile(readStream, entry, entryContext, token);
|
|
280
|
-
|
|
335
|
+
this.readNextEntry(zfile, token);
|
|
281
336
|
}
|
|
282
337
|
async writeEntryToFile(readStream, entry, entryContext, token) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
338
|
+
var _a;
|
|
339
|
+
try {
|
|
340
|
+
const filePath = entryContext.getFilePath();
|
|
341
|
+
const mode = this.modeFromEntry(entry);
|
|
342
|
+
// see https://unix.stackexchange.com/questions/193465/what-file-mode-is-a-symlink
|
|
343
|
+
const isSymlink = (mode & 0o170000) === 0o120000;
|
|
344
|
+
if (isSymlink) {
|
|
345
|
+
entryContext.symlinkFileNames.push(path.resolve(path.join(entryContext.targetFolder, entryContext.decodeEntryFileName)));
|
|
288
346
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const mode = this.modeFromEntry(entry);
|
|
297
|
-
// see https://unix.stackexchange.com/questions/193465/what-file-mode-is-a-symlink
|
|
298
|
-
const isSymlink = (mode & 0o170000) === 0o120000;
|
|
299
|
-
if (isSymlink) {
|
|
300
|
-
entryContext.symlinkFileNames.push(path.resolve(path.join(entryContext.targetFolder, entryContext.decodeEntryFileName)));
|
|
347
|
+
if (isSymlink && !this.symlinkToFile()) {
|
|
348
|
+
const linkContent = await this.readStreamContent(readStream, token);
|
|
349
|
+
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.safeSymlinksOnly) &&
|
|
350
|
+
entryContext.isSymlinkTargetOutsideTargetFolder(linkContent, filePath)) {
|
|
351
|
+
const error = new Error(`Dangerous link path was refused : "${entryContext.targetFolder}", file: "${filePath}", target: "${linkContent}". Set safeSymlinksOnly to false to allow writing through this symlink.`);
|
|
352
|
+
error.name = "AF_ILLEGAL_TARGET";
|
|
353
|
+
throw error;
|
|
301
354
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.safeSymlinksOnly) &&
|
|
315
|
-
entryContext.isSymlinkTargetOutsideTargetFolder(linkContent, filePath)) {
|
|
316
|
-
const error = new Error(`Dangerous link path was refused : "${entryContext.targetFolder}", file: "${filePath}", target: "${linkContent}"`);
|
|
317
|
-
error.name = "AF_ILLEGAL_TARGET";
|
|
318
|
-
e(error);
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
this.createSymlink(linkContent, filePath).then(c, e);
|
|
322
|
-
}
|
|
323
|
-
});
|
|
355
|
+
await entryContext.ensureFolder(path.dirname(filePath));
|
|
356
|
+
await this.createSymlink(linkContent, filePath);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
await entryContext.ensureFolder(path.dirname(filePath));
|
|
360
|
+
const fileStream = (0, node_fs_1.createWriteStream)(filePath, { mode });
|
|
361
|
+
const pipelinePromise = (0, promises_1.pipeline)(readStream, fileStream);
|
|
362
|
+
const disposeCancel = token.onCancelled(() => {
|
|
363
|
+
fileStream.destroy(this.canceledError());
|
|
364
|
+
});
|
|
365
|
+
try {
|
|
366
|
+
await pipelinePromise;
|
|
324
367
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
fileStream.once("close", () => c());
|
|
328
|
-
fileStream.once("error", (err) => {
|
|
329
|
-
e(this.wrapError(err, token.isCancelled));
|
|
330
|
-
});
|
|
331
|
-
readStream.pipe(fileStream);
|
|
368
|
+
finally {
|
|
369
|
+
disposeCancel();
|
|
332
370
|
}
|
|
333
371
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
throw this.wrapError(error, token.isCancelled);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
async readStreamContent(readStream, token) {
|
|
378
|
+
let linkContent = "";
|
|
379
|
+
const readPromise = new Promise((resolve, reject) => {
|
|
380
|
+
readStream.on("data", (chunk) => {
|
|
381
|
+
linkContent += typeof chunk === "string" ? chunk : chunk.toString();
|
|
382
|
+
});
|
|
383
|
+
readStream.once("end", resolve);
|
|
384
|
+
readStream.once("error", (err) => {
|
|
385
|
+
reject(this.wrapError(err, token.isCancelled));
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
const disposeCancel = token.onCancelled(() => {
|
|
389
|
+
readStream.destroy(this.canceledError());
|
|
337
390
|
});
|
|
391
|
+
try {
|
|
392
|
+
await readPromise;
|
|
393
|
+
return linkContent;
|
|
394
|
+
}
|
|
395
|
+
finally {
|
|
396
|
+
disposeCancel();
|
|
397
|
+
}
|
|
338
398
|
}
|
|
339
399
|
modeFromEntry(entry) {
|
|
340
400
|
const attr = entry.externalFileAttributes >> 16 || 33188;
|
|
@@ -342,7 +402,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
342
402
|
.map((mask) => attr & mask)
|
|
343
403
|
.reduce((a, b) => a + b, attr & 61440 /* S_IFMT */);
|
|
344
404
|
}
|
|
345
|
-
async createSymlink(linkContent,
|
|
405
|
+
async createSymlink(linkContent, filePath) {
|
|
346
406
|
let linkType = "file";
|
|
347
407
|
if (process.platform === "win32") {
|
|
348
408
|
if (/\/$/.test(linkContent)) {
|
|
@@ -351,7 +411,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
351
411
|
else {
|
|
352
412
|
let targetPath = linkContent;
|
|
353
413
|
if (!path.isAbsolute(linkContent)) {
|
|
354
|
-
targetPath = path.join(path.dirname(
|
|
414
|
+
targetPath = path.join(path.dirname(filePath), linkContent);
|
|
355
415
|
}
|
|
356
416
|
try {
|
|
357
417
|
const stat = await fs.stat(targetPath);
|
|
@@ -364,7 +424,7 @@ class Unzip extends cancelable_1.Cancelable {
|
|
|
364
424
|
}
|
|
365
425
|
}
|
|
366
426
|
}
|
|
367
|
-
await fs.symlink(linkContent,
|
|
427
|
+
await fs.symlink(linkContent, filePath, linkType);
|
|
368
428
|
}
|
|
369
429
|
isOverwrite() {
|
|
370
430
|
var _a;
|
package/lib/zip.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Cancelable } from "./cancelable";
|
|
2
2
|
export interface IZipOptions {
|
|
3
3
|
/**
|
|
4
|
-
* Indicates how to handle
|
|
4
|
+
* Indicates how to handle the given path when it is a symbolic link.
|
|
5
5
|
*
|
|
6
6
|
* `true`: add the target of the symbolic link to the zip.
|
|
7
7
|
*
|
|
8
|
-
* `false`: add symbolic link itself to the zip.
|
|
8
|
+
* `false`: add the symbolic link itself to the zip.
|
|
9
9
|
*
|
|
10
10
|
* The default value is `false`.
|
|
11
11
|
*/
|
|
@@ -13,7 +13,7 @@ export interface IZipOptions {
|
|
|
13
13
|
/**
|
|
14
14
|
* Sets the compression level.
|
|
15
15
|
*
|
|
16
|
-
* 0
|
|
16
|
+
* `0`: the file data will be stored; otherwise, the file data will be deflated.
|
|
17
17
|
*
|
|
18
18
|
* The default value is `6`.
|
|
19
19
|
*/
|
|
@@ -30,29 +30,44 @@ export declare class Zip extends Cancelable {
|
|
|
30
30
|
constructor(options?: IZipOptions | undefined);
|
|
31
31
|
private yazlFile;
|
|
32
32
|
private isPipe;
|
|
33
|
+
private isChunk;
|
|
33
34
|
private zipStream;
|
|
34
35
|
private zipFiles;
|
|
35
36
|
private zipFolders;
|
|
36
37
|
private token;
|
|
37
38
|
/**
|
|
38
|
-
* Adds a file from the file system at realPath
|
|
39
|
+
* Adds a file from the file system at `realPath` to the zip file as `metadataPath`.
|
|
39
40
|
* @param file
|
|
40
|
-
* @param metadataPath Typically metadataPath would be calculated as path.relative(root, realPath)
|
|
41
|
+
* @param metadataPath Typically, `metadataPath` would be calculated as `path.relative(root, realPath)`.
|
|
41
42
|
* A valid metadataPath must not start with "/" or /[A-Za-z]:\//, and must not contain "..".
|
|
42
43
|
*/
|
|
43
44
|
addFile(file: string, metadataPath?: string): void;
|
|
44
45
|
/**
|
|
45
|
-
* Adds a folder from the file system at realPath
|
|
46
|
+
* Adds a folder from the file system at `realPath` to the zip file as `metadataPath`.
|
|
46
47
|
* @param folder
|
|
47
|
-
* @param metadataPath Typically metadataPath would be calculated as path.relative(root, realPath)
|
|
48
|
+
* @param metadataPath Typically, `metadataPath` would be calculated as `path.relative(root, realPath)`.
|
|
48
49
|
* A valid metadataPath must not start with "/" or /[A-Za-z]:\//, and must not contain "..".
|
|
49
50
|
*/
|
|
50
51
|
addFolder(folder: string, metadataPath?: string): void;
|
|
51
52
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
53
|
+
* Zips the content and returns it as a single Buffer.
|
|
54
|
+
*
|
|
55
|
+
* @returns A promise that resolves to the zipped Buffer.
|
|
56
|
+
*/
|
|
57
|
+
archive(): Promise<Buffer>;
|
|
58
|
+
/**
|
|
59
|
+
* Zips the content and saves it directly to the specified file path.
|
|
60
|
+
*
|
|
61
|
+
* @param zipFile The absolute or relative path where the .zip file will be created.
|
|
62
|
+
* @returns A promise that resolves when the file has been fully written.
|
|
54
63
|
*/
|
|
55
64
|
archive(zipFile: string): Promise<void>;
|
|
65
|
+
private prepareArchive;
|
|
66
|
+
private bindArchiveOutput;
|
|
67
|
+
private archiveToFile;
|
|
68
|
+
private archiveToBuffer;
|
|
69
|
+
private createPromiseSettler;
|
|
70
|
+
private addQueuedEntries;
|
|
56
71
|
/**
|
|
57
72
|
* Cancel compression.
|
|
58
73
|
* If the cancel method is called after the archive is complete, nothing will happen.
|
|
@@ -62,7 +77,7 @@ export declare class Zip extends Cancelable {
|
|
|
62
77
|
private addFileStream;
|
|
63
78
|
private addSymlink;
|
|
64
79
|
private walkDir;
|
|
65
|
-
private
|
|
80
|
+
private stop;
|
|
66
81
|
private followSymlink;
|
|
67
82
|
/**
|
|
68
83
|
* Retrieves the yazl options based on the current settings.
|