UNPKG

2.19 kBJavaScriptView Raw
1import path from 'node:path';
2import {constants as BufferConstants} from 'node:buffer';
3import Vinyl from 'vinyl';
4import Yazl from 'yazl';
5import {getStreamAsBuffer, MaxBufferError} from 'get-stream';
6import {gulpPlugin} from 'gulp-plugin-extras';
7
8export default function gulpZip(filename, options) {
9 if (!filename) {
10 throw new Error('gulp-zip: `filename` required');
11 }
12
13 options = {
14 compress: true,
15 buffer: true,
16 ...options,
17 };
18
19 let firstFile;
20 const zip = new Yazl.ZipFile();
21
22 return gulpPlugin('gulp-zip', async file => {
23 firstFile ??= file;
24
25 // Because Windows...
26 const pathname = file.relative.replaceAll('\\', '/');
27
28 if (!pathname) {
29 return;
30 }
31
32 if (file.isDirectory()) {
33 zip.addEmptyDirectory(pathname, {
34 mtime: options.modifiedTime || file.stat.mtime || new Date(),
35 // Do *not* pass a mode for a directory, because it creates platform-dependent
36 // ZIP files (ZIP files created on Windows that cannot be opened on macOS).
37 // Re-enable if this PR is resolved: https://github.com/thejoshwolfe/yazl/pull/59
38 // mode: file.stat.mode
39 });
40 } else {
41 const stat = {
42 compress: options.compress,
43 mtime: options.modifiedTime || (file.stat ? file.stat.mtime : new Date()),
44 mode: file.stat ? file.stat.mode : null,
45 };
46
47 if (file.isStream()) {
48 zip.addReadStream(file.contents, pathname, stat);
49 }
50
51 if (file.isBuffer()) {
52 zip.addBuffer(file.contents, pathname, stat);
53 }
54 }
55 }, {
56 supportsAnyType: true,
57 async * onFinish() {
58 zip.end();
59
60 if (!firstFile) {
61 return;
62 }
63
64 let data;
65 if (options.buffer) {
66 try {
67 data = await getStreamAsBuffer(zip.outputStream, {maxBuffer: BufferConstants.MAX_LENGTH});
68 } catch (error) {
69 const error_ = error instanceof MaxBufferError ? new Error('The output ZIP file is too big to store in a buffer (larger than Buffer MAX_LENGTH). To output a stream instead, set the gulp-zip buffer option to `false`.') : error;
70 throw error_;
71 }
72 } else {
73 data = zip.outputStream;
74 }
75
76 yield new Vinyl({
77 cwd: firstFile.cwd,
78 base: firstFile.base,
79 path: path.join(firstFile.base, filename),
80 contents: data,
81 });
82 },
83 });
84}