index.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 'use strict';
  2. const path = require('path');
  3. const BufferConstants = require('buffer').constants;
  4. const Vinyl = require('vinyl');
  5. const PluginError = require('plugin-error');
  6. const through = require('through2');
  7. const Yazl = require('yazl');
  8. const getStream = require('get-stream');
  9. module.exports = (filename, options) => {
  10. if (!filename) {
  11. throw new PluginError('gulp-zip', '`filename` required');
  12. }
  13. options = {
  14. compress: true,
  15. buffer: true,
  16. ...options
  17. };
  18. let firstFile;
  19. const zip = new Yazl.ZipFile();
  20. return through.obj((file, encoding, callback) => {
  21. if (!firstFile) {
  22. firstFile = file;
  23. }
  24. // Because Windows...
  25. const pathname = file.relative.replace(/\\/g, '/');
  26. if (!pathname) {
  27. callback();
  28. return;
  29. }
  30. if (file.isNull() && file.stat && file.stat.isDirectory && file.stat.isDirectory()) {
  31. zip.addEmptyDirectory(pathname, {
  32. mtime: options.modifiedTime || file.stat.mtime || new Date()
  33. // Do *not* pass a mode for a directory, because it creates platform-dependent
  34. // ZIP files (ZIP files created on Windows that cannot be opened on macOS).
  35. // Re-enable if this PR is resolved: https://github.com/thejoshwolfe/yazl/pull/59
  36. // mode: file.stat.mode
  37. });
  38. } else {
  39. const stat = {
  40. compress: options.compress,
  41. mtime: options.modifiedTime || (file.stat ? file.stat.mtime : new Date()),
  42. mode: file.stat ? file.stat.mode : null
  43. };
  44. if (file.isStream()) {
  45. zip.addReadStream(file.contents, pathname, stat);
  46. }
  47. if (file.isBuffer()) {
  48. zip.addBuffer(file.contents, pathname, stat);
  49. }
  50. }
  51. callback();
  52. }, function (callback) {
  53. if (!firstFile) {
  54. callback();
  55. return;
  56. }
  57. (async () => {
  58. let data;
  59. if (options.buffer) {
  60. try {
  61. data = await getStream.buffer(zip.outputStream, {maxBuffer: BufferConstants.MAX_LENGTH});
  62. } catch (error) {
  63. if (error instanceof getStream.MaxBufferError) {
  64. callback(new PluginError('gulp-zip', '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`.'));
  65. } else {
  66. callback(error);
  67. }
  68. return;
  69. }
  70. } else {
  71. data = zip.outputStream;
  72. }
  73. this.push(new Vinyl({
  74. cwd: firstFile.cwd,
  75. base: firstFile.base,
  76. path: path.join(firstFile.base, filename),
  77. contents: data
  78. }));
  79. callback();
  80. })();
  81. zip.end();
  82. });
  83. };