@tachybase/module-backup 0.23.8

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.
Files changed (125) hide show
  1. package/.turbo/turbo-build.log +12 -0
  2. package/README.md +118 -0
  3. package/README.zh-CN.md +118 -0
  4. package/client.d.ts +2 -0
  5. package/client.js +1 -0
  6. package/dist/client/Configuration.d.ts +2 -0
  7. package/dist/client/DuplicatorProvider.d.ts +5 -0
  8. package/dist/client/index.d.ts +5 -0
  9. package/dist/client/index.js +1 -0
  10. package/dist/client/locale/index.d.ts +4 -0
  11. package/dist/externalVersion.js +14 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +39 -0
  14. package/dist/locale/en-US.json +44 -0
  15. package/dist/locale/ja-JP.d.ts +25 -0
  16. package/dist/locale/ja-JP.js +46 -0
  17. package/dist/locale/ko_KR.json +50 -0
  18. package/dist/locale/pt-BR.d.ts +26 -0
  19. package/dist/locale/pt-BR.js +48 -0
  20. package/dist/locale/zh-CN.json +50 -0
  21. package/dist/node_modules/@hapi/topo/lib/index.d.ts +60 -0
  22. package/dist/node_modules/@hapi/topo/lib/index.js +1 -0
  23. package/dist/node_modules/@hapi/topo/package.json +1 -0
  24. package/dist/node_modules/archiver/LICENSE +22 -0
  25. package/dist/node_modules/archiver/index.js +68 -0
  26. package/dist/node_modules/archiver/lib/core.js +974 -0
  27. package/dist/node_modules/archiver/lib/error.js +40 -0
  28. package/dist/node_modules/archiver/lib/plugins/json.js +110 -0
  29. package/dist/node_modules/archiver/lib/plugins/tar.js +167 -0
  30. package/dist/node_modules/archiver/lib/plugins/zip.js +120 -0
  31. package/dist/node_modules/archiver/package.json +1 -0
  32. package/dist/node_modules/decompress/index.js +16 -0
  33. package/dist/node_modules/decompress/license +9 -0
  34. package/dist/node_modules/decompress/package.json +1 -0
  35. package/dist/node_modules/mkdirp/LICENSE +21 -0
  36. package/dist/node_modules/mkdirp/bin/cmd.js +68 -0
  37. package/dist/node_modules/mkdirp/index.js +1 -0
  38. package/dist/node_modules/mkdirp/lib/find-made.js +29 -0
  39. package/dist/node_modules/mkdirp/lib/mkdirp-manual.js +64 -0
  40. package/dist/node_modules/mkdirp/lib/mkdirp-native.js +39 -0
  41. package/dist/node_modules/mkdirp/lib/opts-arg.js +23 -0
  42. package/dist/node_modules/mkdirp/lib/path-arg.js +29 -0
  43. package/dist/node_modules/mkdirp/lib/use-native.js +10 -0
  44. package/dist/node_modules/mkdirp/package.json +1 -0
  45. package/dist/node_modules/mkdirp/readme.markdown +266 -0
  46. package/dist/node_modules/semver/LICENSE +15 -0
  47. package/dist/node_modules/semver/bin/semver.js +188 -0
  48. package/dist/node_modules/semver/classes/comparator.js +141 -0
  49. package/dist/node_modules/semver/classes/index.js +5 -0
  50. package/dist/node_modules/semver/classes/range.js +554 -0
  51. package/dist/node_modules/semver/classes/semver.js +302 -0
  52. package/dist/node_modules/semver/functions/clean.js +6 -0
  53. package/dist/node_modules/semver/functions/cmp.js +52 -0
  54. package/dist/node_modules/semver/functions/coerce.js +60 -0
  55. package/dist/node_modules/semver/functions/compare-build.js +7 -0
  56. package/dist/node_modules/semver/functions/compare-loose.js +3 -0
  57. package/dist/node_modules/semver/functions/compare.js +5 -0
  58. package/dist/node_modules/semver/functions/diff.js +65 -0
  59. package/dist/node_modules/semver/functions/eq.js +3 -0
  60. package/dist/node_modules/semver/functions/gt.js +3 -0
  61. package/dist/node_modules/semver/functions/gte.js +3 -0
  62. package/dist/node_modules/semver/functions/inc.js +19 -0
  63. package/dist/node_modules/semver/functions/lt.js +3 -0
  64. package/dist/node_modules/semver/functions/lte.js +3 -0
  65. package/dist/node_modules/semver/functions/major.js +3 -0
  66. package/dist/node_modules/semver/functions/minor.js +3 -0
  67. package/dist/node_modules/semver/functions/neq.js +3 -0
  68. package/dist/node_modules/semver/functions/parse.js +16 -0
  69. package/dist/node_modules/semver/functions/patch.js +3 -0
  70. package/dist/node_modules/semver/functions/prerelease.js +6 -0
  71. package/dist/node_modules/semver/functions/rcompare.js +3 -0
  72. package/dist/node_modules/semver/functions/rsort.js +3 -0
  73. package/dist/node_modules/semver/functions/satisfies.js +10 -0
  74. package/dist/node_modules/semver/functions/sort.js +3 -0
  75. package/dist/node_modules/semver/functions/valid.js +6 -0
  76. package/dist/node_modules/semver/index.js +1 -0
  77. package/dist/node_modules/semver/internal/constants.js +35 -0
  78. package/dist/node_modules/semver/internal/debug.js +9 -0
  79. package/dist/node_modules/semver/internal/identifiers.js +23 -0
  80. package/dist/node_modules/semver/internal/lrucache.js +40 -0
  81. package/dist/node_modules/semver/internal/parse-options.js +15 -0
  82. package/dist/node_modules/semver/internal/re.js +217 -0
  83. package/dist/node_modules/semver/package.json +1 -0
  84. package/dist/node_modules/semver/preload.js +2 -0
  85. package/dist/node_modules/semver/range.bnf +16 -0
  86. package/dist/node_modules/semver/ranges/gtr.js +4 -0
  87. package/dist/node_modules/semver/ranges/intersects.js +7 -0
  88. package/dist/node_modules/semver/ranges/ltr.js +4 -0
  89. package/dist/node_modules/semver/ranges/max-satisfying.js +25 -0
  90. package/dist/node_modules/semver/ranges/min-satisfying.js +24 -0
  91. package/dist/node_modules/semver/ranges/min-version.js +61 -0
  92. package/dist/node_modules/semver/ranges/outside.js +80 -0
  93. package/dist/node_modules/semver/ranges/simplify.js +47 -0
  94. package/dist/node_modules/semver/ranges/subset.js +247 -0
  95. package/dist/node_modules/semver/ranges/to-comparators.js +8 -0
  96. package/dist/node_modules/semver/ranges/valid.js +11 -0
  97. package/dist/server/app-migrator.d.ts +16 -0
  98. package/dist/server/app-migrator.js +61 -0
  99. package/dist/server/collection-group-manager.d.ts +4 -0
  100. package/dist/server/collection-group-manager.js +29 -0
  101. package/dist/server/commands/restore-command.d.ts +2 -0
  102. package/dist/server/commands/restore-command.js +67 -0
  103. package/dist/server/dumper.d.ts +71 -0
  104. package/dist/server/dumper.js +421 -0
  105. package/dist/server/errors/restore-check-error.d.ts +3 -0
  106. package/dist/server/errors/restore-check-error.js +32 -0
  107. package/dist/server/field-value-writer.d.ts +9 -0
  108. package/dist/server/field-value-writer.js +99 -0
  109. package/dist/server/index.d.ts +1 -0
  110. package/dist/server/index.js +33 -0
  111. package/dist/server/locale/zh-CN.d.ts +9 -0
  112. package/dist/server/locale/zh-CN.js +30 -0
  113. package/dist/server/resourcers/backup-files.d.ts +25 -0
  114. package/dist/server/resourcers/backup-files.js +206 -0
  115. package/dist/server/restorer.d.ts +35 -0
  116. package/dist/server/restorer.js +320 -0
  117. package/dist/server/server.d.ts +8 -0
  118. package/dist/server/server.js +52 -0
  119. package/dist/server/utils.d.ts +5 -0
  120. package/dist/server/utils.js +78 -0
  121. package/dist/swagger/index.d.ts +392 -0
  122. package/dist/swagger/index.js +447 -0
  123. package/package.json +48 -0
  124. package/server.d.ts +2 -0
  125. package/server.js +1 -0
@@ -0,0 +1,974 @@
1
+ /**
2
+ * Archiver Core
3
+ *
4
+ * @ignore
5
+ * @license [MIT]{@link https://github.com/archiverjs/node-archiver/blob/master/LICENSE}
6
+ * @copyright (c) 2012-2014 Chris Talkington, contributors.
7
+ */
8
+ var fs = require('fs');
9
+ var glob = require('readdir-glob');
10
+ var async = require('async');
11
+ var path = require('path');
12
+ var util = require('archiver-utils');
13
+
14
+ var inherits = require('util').inherits;
15
+ var ArchiverError = require('./error');
16
+ var Transform = require('readable-stream').Transform;
17
+
18
+ var win32 = process.platform === 'win32';
19
+
20
+ /**
21
+ * @constructor
22
+ * @param {String} format The archive format to use.
23
+ * @param {(CoreOptions|TransformOptions)} options See also {@link ZipOptions} and {@link TarOptions}.
24
+ */
25
+ var Archiver = function(format, options) {
26
+ if (!(this instanceof Archiver)) {
27
+ return new Archiver(format, options);
28
+ }
29
+
30
+ if (typeof format !== 'string') {
31
+ options = format;
32
+ format = 'zip';
33
+ }
34
+
35
+ options = this.options = util.defaults(options, {
36
+ highWaterMark: 1024 * 1024,
37
+ statConcurrency: 4
38
+ });
39
+
40
+ Transform.call(this, options);
41
+
42
+ this._format = false;
43
+ this._module = false;
44
+ this._pending = 0;
45
+ this._pointer = 0;
46
+
47
+ this._entriesCount = 0;
48
+ this._entriesProcessedCount = 0;
49
+ this._fsEntriesTotalBytes = 0;
50
+ this._fsEntriesProcessedBytes = 0;
51
+
52
+ this._queue = async.queue(this._onQueueTask.bind(this), 1);
53
+ this._queue.drain(this._onQueueDrain.bind(this));
54
+
55
+ this._statQueue = async.queue(this._onStatQueueTask.bind(this), options.statConcurrency);
56
+ this._statQueue.drain(this._onQueueDrain.bind(this));
57
+
58
+ this._state = {
59
+ aborted: false,
60
+ finalize: false,
61
+ finalizing: false,
62
+ finalized: false,
63
+ modulePiped: false
64
+ };
65
+
66
+ this._streams = [];
67
+ };
68
+
69
+ inherits(Archiver, Transform);
70
+
71
+ /**
72
+ * Internal logic for `abort`.
73
+ *
74
+ * @private
75
+ * @return void
76
+ */
77
+ Archiver.prototype._abort = function() {
78
+ this._state.aborted = true;
79
+ this._queue.kill();
80
+ this._statQueue.kill();
81
+
82
+ if (this._queue.idle()) {
83
+ this._shutdown();
84
+ }
85
+ };
86
+
87
+ /**
88
+ * Internal helper for appending files.
89
+ *
90
+ * @private
91
+ * @param {String} filepath The source filepath.
92
+ * @param {EntryData} data The entry data.
93
+ * @return void
94
+ */
95
+ Archiver.prototype._append = function(filepath, data) {
96
+ data = data || {};
97
+
98
+ var task = {
99
+ source: null,
100
+ filepath: filepath
101
+ };
102
+
103
+ if (!data.name) {
104
+ data.name = filepath;
105
+ }
106
+
107
+ data.sourcePath = filepath;
108
+ task.data = data;
109
+ this._entriesCount++;
110
+
111
+ if (data.stats && data.stats instanceof fs.Stats) {
112
+ task = this._updateQueueTaskWithStats(task, data.stats);
113
+ if (task) {
114
+ if (data.stats.size) {
115
+ this._fsEntriesTotalBytes += data.stats.size;
116
+ }
117
+
118
+ this._queue.push(task);
119
+ }
120
+ } else {
121
+ this._statQueue.push(task);
122
+ }
123
+ };
124
+
125
+ /**
126
+ * Internal logic for `finalize`.
127
+ *
128
+ * @private
129
+ * @return void
130
+ */
131
+ Archiver.prototype._finalize = function() {
132
+ if (this._state.finalizing || this._state.finalized || this._state.aborted) {
133
+ return;
134
+ }
135
+
136
+ this._state.finalizing = true;
137
+
138
+ this._moduleFinalize();
139
+
140
+ this._state.finalizing = false;
141
+ this._state.finalized = true;
142
+ };
143
+
144
+ /**
145
+ * Checks the various state variables to determine if we can `finalize`.
146
+ *
147
+ * @private
148
+ * @return {Boolean}
149
+ */
150
+ Archiver.prototype._maybeFinalize = function() {
151
+ if (this._state.finalizing || this._state.finalized || this._state.aborted) {
152
+ return false;
153
+ }
154
+
155
+ if (this._state.finalize && this._pending === 0 && this._queue.idle() && this._statQueue.idle()) {
156
+ this._finalize();
157
+ return true;
158
+ }
159
+
160
+ return false;
161
+ };
162
+
163
+ /**
164
+ * Appends an entry to the module.
165
+ *
166
+ * @private
167
+ * @fires Archiver#entry
168
+ * @param {(Buffer|Stream)} source
169
+ * @param {EntryData} data
170
+ * @param {Function} callback
171
+ * @return void
172
+ */
173
+ Archiver.prototype._moduleAppend = function(source, data, callback) {
174
+ if (this._state.aborted) {
175
+ callback();
176
+ return;
177
+ }
178
+
179
+ this._module.append(source, data, function(err) {
180
+ this._task = null;
181
+
182
+ if (this._state.aborted) {
183
+ this._shutdown();
184
+ return;
185
+ }
186
+
187
+ if (err) {
188
+ this.emit('error', err);
189
+ setImmediate(callback);
190
+ return;
191
+ }
192
+
193
+ /**
194
+ * Fires when the entry's input has been processed and appended to the archive.
195
+ *
196
+ * @event Archiver#entry
197
+ * @type {EntryData}
198
+ */
199
+ this.emit('entry', data);
200
+ this._entriesProcessedCount++;
201
+
202
+ if (data.stats && data.stats.size) {
203
+ this._fsEntriesProcessedBytes += data.stats.size;
204
+ }
205
+
206
+ /**
207
+ * @event Archiver#progress
208
+ * @type {ProgressData}
209
+ */
210
+ this.emit('progress', {
211
+ entries: {
212
+ total: this._entriesCount,
213
+ processed: this._entriesProcessedCount
214
+ },
215
+ fs: {
216
+ totalBytes: this._fsEntriesTotalBytes,
217
+ processedBytes: this._fsEntriesProcessedBytes
218
+ }
219
+ });
220
+
221
+ setImmediate(callback);
222
+ }.bind(this));
223
+ };
224
+
225
+ /**
226
+ * Finalizes the module.
227
+ *
228
+ * @private
229
+ * @return void
230
+ */
231
+ Archiver.prototype._moduleFinalize = function() {
232
+ if (typeof this._module.finalize === 'function') {
233
+ this._module.finalize();
234
+ } else if (typeof this._module.end === 'function') {
235
+ this._module.end();
236
+ } else {
237
+ this.emit('error', new ArchiverError('NOENDMETHOD'));
238
+ }
239
+ };
240
+
241
+ /**
242
+ * Pipes the module to our internal stream with error bubbling.
243
+ *
244
+ * @private
245
+ * @return void
246
+ */
247
+ Archiver.prototype._modulePipe = function() {
248
+ this._module.on('error', this._onModuleError.bind(this));
249
+ this._module.pipe(this);
250
+ this._state.modulePiped = true;
251
+ };
252
+
253
+ /**
254
+ * Determines if the current module supports a defined feature.
255
+ *
256
+ * @private
257
+ * @param {String} key
258
+ * @return {Boolean}
259
+ */
260
+ Archiver.prototype._moduleSupports = function(key) {
261
+ if (!this._module.supports || !this._module.supports[key]) {
262
+ return false;
263
+ }
264
+
265
+ return this._module.supports[key];
266
+ };
267
+
268
+ /**
269
+ * Unpipes the module from our internal stream.
270
+ *
271
+ * @private
272
+ * @return void
273
+ */
274
+ Archiver.prototype._moduleUnpipe = function() {
275
+ this._module.unpipe(this);
276
+ this._state.modulePiped = false;
277
+ };
278
+
279
+ /**
280
+ * Normalizes entry data with fallbacks for key properties.
281
+ *
282
+ * @private
283
+ * @param {Object} data
284
+ * @param {fs.Stats} stats
285
+ * @return {Object}
286
+ */
287
+ Archiver.prototype._normalizeEntryData = function(data, stats) {
288
+ data = util.defaults(data, {
289
+ type: 'file',
290
+ name: null,
291
+ date: null,
292
+ mode: null,
293
+ prefix: null,
294
+ sourcePath: null,
295
+ stats: false
296
+ });
297
+
298
+ if (stats && data.stats === false) {
299
+ data.stats = stats;
300
+ }
301
+
302
+ var isDir = data.type === 'directory';
303
+
304
+ if (data.name) {
305
+ if (typeof data.prefix === 'string' && '' !== data.prefix) {
306
+ data.name = data.prefix + '/' + data.name;
307
+ data.prefix = null;
308
+ }
309
+
310
+ data.name = util.sanitizePath(data.name);
311
+
312
+ if (data.type !== 'symlink' && data.name.slice(-1) === '/') {
313
+ isDir = true;
314
+ data.type = 'directory';
315
+ } else if (isDir) {
316
+ data.name += '/';
317
+ }
318
+ }
319
+
320
+ // 511 === 0777; 493 === 0755; 438 === 0666; 420 === 0644
321
+ if (typeof data.mode === 'number') {
322
+ if (win32) {
323
+ data.mode &= 511;
324
+ } else {
325
+ data.mode &= 4095
326
+ }
327
+ } else if (data.stats && data.mode === null) {
328
+ if (win32) {
329
+ data.mode = data.stats.mode & 511;
330
+ } else {
331
+ data.mode = data.stats.mode & 4095;
332
+ }
333
+
334
+ // stat isn't reliable on windows; force 0755 for dir
335
+ if (win32 && isDir) {
336
+ data.mode = 493;
337
+ }
338
+ } else if (data.mode === null) {
339
+ data.mode = isDir ? 493 : 420;
340
+ }
341
+
342
+ if (data.stats && data.date === null) {
343
+ data.date = data.stats.mtime;
344
+ } else {
345
+ data.date = util.dateify(data.date);
346
+ }
347
+
348
+ return data;
349
+ };
350
+
351
+ /**
352
+ * Error listener that re-emits error on to our internal stream.
353
+ *
354
+ * @private
355
+ * @param {Error} err
356
+ * @return void
357
+ */
358
+ Archiver.prototype._onModuleError = function(err) {
359
+ /**
360
+ * @event Archiver#error
361
+ * @type {ErrorData}
362
+ */
363
+ this.emit('error', err);
364
+ };
365
+
366
+ /**
367
+ * Checks the various state variables after queue has drained to determine if
368
+ * we need to `finalize`.
369
+ *
370
+ * @private
371
+ * @return void
372
+ */
373
+ Archiver.prototype._onQueueDrain = function() {
374
+ if (this._state.finalizing || this._state.finalized || this._state.aborted) {
375
+ return;
376
+ }
377
+
378
+ if (this._state.finalize && this._pending === 0 && this._queue.idle() && this._statQueue.idle()) {
379
+ this._finalize();
380
+ }
381
+ };
382
+
383
+ /**
384
+ * Appends each queue task to the module.
385
+ *
386
+ * @private
387
+ * @param {Object} task
388
+ * @param {Function} callback
389
+ * @return void
390
+ */
391
+ Archiver.prototype._onQueueTask = function(task, callback) {
392
+ var fullCallback = () => {
393
+ if(task.data.callback) {
394
+ task.data.callback();
395
+ }
396
+ callback();
397
+ }
398
+
399
+ if (this._state.finalizing || this._state.finalized || this._state.aborted) {
400
+ fullCallback();
401
+ return;
402
+ }
403
+
404
+ this._task = task;
405
+ this._moduleAppend(task.source, task.data, fullCallback);
406
+ };
407
+
408
+ /**
409
+ * Performs a file stat and reinjects the task back into the queue.
410
+ *
411
+ * @private
412
+ * @param {Object} task
413
+ * @param {Function} callback
414
+ * @return void
415
+ */
416
+ Archiver.prototype._onStatQueueTask = function(task, callback) {
417
+ if (this._state.finalizing || this._state.finalized || this._state.aborted) {
418
+ callback();
419
+ return;
420
+ }
421
+
422
+ fs.lstat(task.filepath, function(err, stats) {
423
+ if (this._state.aborted) {
424
+ setImmediate(callback);
425
+ return;
426
+ }
427
+
428
+ if (err) {
429
+ this._entriesCount--;
430
+
431
+ /**
432
+ * @event Archiver#warning
433
+ * @type {ErrorData}
434
+ */
435
+ this.emit('warning', err);
436
+ setImmediate(callback);
437
+ return;
438
+ }
439
+
440
+ task = this._updateQueueTaskWithStats(task, stats);
441
+
442
+ if (task) {
443
+ if (stats.size) {
444
+ this._fsEntriesTotalBytes += stats.size;
445
+ }
446
+
447
+ this._queue.push(task);
448
+ }
449
+
450
+ setImmediate(callback);
451
+ }.bind(this));
452
+ };
453
+
454
+ /**
455
+ * Unpipes the module and ends our internal stream.
456
+ *
457
+ * @private
458
+ * @return void
459
+ */
460
+ Archiver.prototype._shutdown = function() {
461
+ this._moduleUnpipe();
462
+ this.end();
463
+ };
464
+
465
+ /**
466
+ * Tracks the bytes emitted by our internal stream.
467
+ *
468
+ * @private
469
+ * @param {Buffer} chunk
470
+ * @param {String} encoding
471
+ * @param {Function} callback
472
+ * @return void
473
+ */
474
+ Archiver.prototype._transform = function(chunk, encoding, callback) {
475
+ if (chunk) {
476
+ this._pointer += chunk.length;
477
+ }
478
+
479
+ callback(null, chunk);
480
+ };
481
+
482
+ /**
483
+ * Updates and normalizes a queue task using stats data.
484
+ *
485
+ * @private
486
+ * @param {Object} task
487
+ * @param {fs.Stats} stats
488
+ * @return {Object}
489
+ */
490
+ Archiver.prototype._updateQueueTaskWithStats = function(task, stats) {
491
+ if (stats.isFile()) {
492
+ task.data.type = 'file';
493
+ task.data.sourceType = 'stream';
494
+ task.source = util.lazyReadStream(task.filepath);
495
+ } else if (stats.isDirectory() && this._moduleSupports('directory')) {
496
+ task.data.name = util.trailingSlashIt(task.data.name);
497
+ task.data.type = 'directory';
498
+ task.data.sourcePath = util.trailingSlashIt(task.filepath);
499
+ task.data.sourceType = 'buffer';
500
+ task.source = Buffer.concat([]);
501
+ } else if (stats.isSymbolicLink() && this._moduleSupports('symlink')) {
502
+ var linkPath = fs.readlinkSync(task.filepath);
503
+ var dirName = path.dirname(task.filepath);
504
+ task.data.type = 'symlink';
505
+ task.data.linkname = path.relative(dirName, path.resolve(dirName, linkPath));
506
+ task.data.sourceType = 'buffer';
507
+ task.source = Buffer.concat([]);
508
+ } else {
509
+ if (stats.isDirectory()) {
510
+ this.emit('warning', new ArchiverError('DIRECTORYNOTSUPPORTED', task.data));
511
+ } else if (stats.isSymbolicLink()) {
512
+ this.emit('warning', new ArchiverError('SYMLINKNOTSUPPORTED', task.data));
513
+ } else {
514
+ this.emit('warning', new ArchiverError('ENTRYNOTSUPPORTED', task.data));
515
+ }
516
+
517
+ return null;
518
+ }
519
+
520
+ task.data = this._normalizeEntryData(task.data, stats);
521
+
522
+ return task;
523
+ };
524
+
525
+ /**
526
+ * Aborts the archiving process, taking a best-effort approach, by:
527
+ *
528
+ * - removing any pending queue tasks
529
+ * - allowing any active queue workers to finish
530
+ * - detaching internal module pipes
531
+ * - ending both sides of the Transform stream
532
+ *
533
+ * It will NOT drain any remaining sources.
534
+ *
535
+ * @return {this}
536
+ */
537
+ Archiver.prototype.abort = function() {
538
+ if (this._state.aborted || this._state.finalized) {
539
+ return this;
540
+ }
541
+
542
+ this._abort();
543
+
544
+ return this;
545
+ };
546
+
547
+ /**
548
+ * Appends an input source (text string, buffer, or stream) to the instance.
549
+ *
550
+ * When the instance has received, processed, and emitted the input, the `entry`
551
+ * event is fired.
552
+ *
553
+ * @fires Archiver#entry
554
+ * @param {(Buffer|Stream|String)} source The input source.
555
+ * @param {EntryData} data See also {@link ZipEntryData} and {@link TarEntryData}.
556
+ * @return {this}
557
+ */
558
+ Archiver.prototype.append = function(source, data) {
559
+ if (this._state.finalize || this._state.aborted) {
560
+ this.emit('error', new ArchiverError('QUEUECLOSED'));
561
+ return this;
562
+ }
563
+
564
+ data = this._normalizeEntryData(data);
565
+
566
+ if (typeof data.name !== 'string' || data.name.length === 0) {
567
+ this.emit('error', new ArchiverError('ENTRYNAMEREQUIRED'));
568
+ return this;
569
+ }
570
+
571
+ if (data.type === 'directory' && !this._moduleSupports('directory')) {
572
+ this.emit('error', new ArchiverError('DIRECTORYNOTSUPPORTED', { name: data.name }));
573
+ return this;
574
+ }
575
+
576
+ source = util.normalizeInputSource(source);
577
+
578
+ if (Buffer.isBuffer(source)) {
579
+ data.sourceType = 'buffer';
580
+ } else if (util.isStream(source)) {
581
+ data.sourceType = 'stream';
582
+ } else {
583
+ this.emit('error', new ArchiverError('INPUTSTEAMBUFFERREQUIRED', { name: data.name }));
584
+ return this;
585
+ }
586
+
587
+ this._entriesCount++;
588
+ this._queue.push({
589
+ data: data,
590
+ source: source
591
+ });
592
+
593
+ return this;
594
+ };
595
+
596
+ /**
597
+ * Appends a directory and its files, recursively, given its dirpath.
598
+ *
599
+ * @param {String} dirpath The source directory path.
600
+ * @param {String} destpath The destination path within the archive.
601
+ * @param {(EntryData|Function)} data See also [ZipEntryData]{@link ZipEntryData} and
602
+ * [TarEntryData]{@link TarEntryData}.
603
+ * @return {this}
604
+ */
605
+ Archiver.prototype.directory = function(dirpath, destpath, data) {
606
+ if (this._state.finalize || this._state.aborted) {
607
+ this.emit('error', new ArchiverError('QUEUECLOSED'));
608
+ return this;
609
+ }
610
+
611
+ if (typeof dirpath !== 'string' || dirpath.length === 0) {
612
+ this.emit('error', new ArchiverError('DIRECTORYDIRPATHREQUIRED'));
613
+ return this;
614
+ }
615
+
616
+ this._pending++;
617
+
618
+ if (destpath === false) {
619
+ destpath = '';
620
+ } else if (typeof destpath !== 'string'){
621
+ destpath = dirpath;
622
+ }
623
+
624
+ var dataFunction = false;
625
+ if (typeof data === 'function') {
626
+ dataFunction = data;
627
+ data = {};
628
+ } else if (typeof data !== 'object') {
629
+ data = {};
630
+ }
631
+
632
+ var globOptions = {
633
+ stat: true,
634
+ dot: true
635
+ };
636
+
637
+ function onGlobEnd() {
638
+ this._pending--;
639
+ this._maybeFinalize();
640
+ }
641
+
642
+ function onGlobError(err) {
643
+ this.emit('error', err);
644
+ }
645
+
646
+ function onGlobMatch(match){
647
+ globber.pause();
648
+
649
+ var ignoreMatch = false;
650
+ var entryData = Object.assign({}, data);
651
+ entryData.name = match.relative;
652
+ entryData.prefix = destpath;
653
+ entryData.stats = match.stat;
654
+ entryData.callback = globber.resume.bind(globber);
655
+
656
+ try {
657
+ if (dataFunction) {
658
+ entryData = dataFunction(entryData);
659
+
660
+ if (entryData === false) {
661
+ ignoreMatch = true;
662
+ } else if (typeof entryData !== 'object') {
663
+ throw new ArchiverError('DIRECTORYFUNCTIONINVALIDDATA', { dirpath: dirpath });
664
+ }
665
+ }
666
+ } catch(e) {
667
+ this.emit('error', e);
668
+ return;
669
+ }
670
+
671
+ if (ignoreMatch) {
672
+ globber.resume();
673
+ return;
674
+ }
675
+
676
+ this._append(match.absolute, entryData);
677
+ }
678
+
679
+ var globber = glob(dirpath, globOptions);
680
+ globber.on('error', onGlobError.bind(this));
681
+ globber.on('match', onGlobMatch.bind(this));
682
+ globber.on('end', onGlobEnd.bind(this));
683
+
684
+ return this;
685
+ };
686
+
687
+ /**
688
+ * Appends a file given its filepath using a
689
+ * [lazystream]{@link https://github.com/jpommerening/node-lazystream} wrapper to
690
+ * prevent issues with open file limits.
691
+ *
692
+ * When the instance has received, processed, and emitted the file, the `entry`
693
+ * event is fired.
694
+ *
695
+ * @param {String} filepath The source filepath.
696
+ * @param {EntryData} data See also [ZipEntryData]{@link ZipEntryData} and
697
+ * [TarEntryData]{@link TarEntryData}.
698
+ * @return {this}
699
+ */
700
+ Archiver.prototype.file = function(filepath, data) {
701
+ if (this._state.finalize || this._state.aborted) {
702
+ this.emit('error', new ArchiverError('QUEUECLOSED'));
703
+ return this;
704
+ }
705
+
706
+ if (typeof filepath !== 'string' || filepath.length === 0) {
707
+ this.emit('error', new ArchiverError('FILEFILEPATHREQUIRED'));
708
+ return this;
709
+ }
710
+
711
+ this._append(filepath, data);
712
+
713
+ return this;
714
+ };
715
+
716
+ /**
717
+ * Appends multiple files that match a glob pattern.
718
+ *
719
+ * @param {String} pattern The [glob pattern]{@link https://github.com/isaacs/minimatch} to match.
720
+ * @param {Object} options See [node-readdir-glob]{@link https://github.com/yqnn/node-readdir-glob#options}.
721
+ * @param {EntryData} data See also [ZipEntryData]{@link ZipEntryData} and
722
+ * [TarEntryData]{@link TarEntryData}.
723
+ * @return {this}
724
+ */
725
+ Archiver.prototype.glob = function(pattern, options, data) {
726
+ this._pending++;
727
+
728
+ options = util.defaults(options, {
729
+ stat: true,
730
+ pattern: pattern
731
+ });
732
+
733
+ function onGlobEnd() {
734
+ this._pending--;
735
+ this._maybeFinalize();
736
+ }
737
+
738
+ function onGlobError(err) {
739
+ this.emit('error', err);
740
+ }
741
+
742
+ function onGlobMatch(match){
743
+ globber.pause();
744
+ var entryData = Object.assign({}, data);
745
+ entryData.callback = globber.resume.bind(globber);
746
+ entryData.stats = match.stat;
747
+ entryData.name = match.relative;
748
+
749
+ this._append(match.absolute, entryData);
750
+ }
751
+
752
+ var globber = glob(options.cwd || '.', options);
753
+ globber.on('error', onGlobError.bind(this));
754
+ globber.on('match', onGlobMatch.bind(this));
755
+ globber.on('end', onGlobEnd.bind(this));
756
+
757
+ return this;
758
+ };
759
+
760
+ /**
761
+ * Finalizes the instance and prevents further appending to the archive
762
+ * structure (queue will continue til drained).
763
+ *
764
+ * The `end`, `close` or `finish` events on the destination stream may fire
765
+ * right after calling this method so you should set listeners beforehand to
766
+ * properly detect stream completion.
767
+ *
768
+ * @return {Promise}
769
+ */
770
+ Archiver.prototype.finalize = function() {
771
+ if (this._state.aborted) {
772
+ var abortedError = new ArchiverError('ABORTED');
773
+ this.emit('error', abortedError);
774
+ return Promise.reject(abortedError);
775
+ }
776
+
777
+ if (this._state.finalize) {
778
+ var finalizingError = new ArchiverError('FINALIZING');
779
+ this.emit('error', finalizingError);
780
+ return Promise.reject(finalizingError);
781
+ }
782
+
783
+ this._state.finalize = true;
784
+
785
+ if (this._pending === 0 && this._queue.idle() && this._statQueue.idle()) {
786
+ this._finalize();
787
+ }
788
+
789
+ var self = this;
790
+
791
+ return new Promise(function(resolve, reject) {
792
+ var errored;
793
+
794
+ self._module.on('end', function() {
795
+ if (!errored) {
796
+ resolve();
797
+ }
798
+ })
799
+
800
+ self._module.on('error', function(err) {
801
+ errored = true;
802
+ reject(err);
803
+ })
804
+ })
805
+ };
806
+
807
+ /**
808
+ * Sets the module format name used for archiving.
809
+ *
810
+ * @param {String} format The name of the format.
811
+ * @return {this}
812
+ */
813
+ Archiver.prototype.setFormat = function(format) {
814
+ if (this._format) {
815
+ this.emit('error', new ArchiverError('FORMATSET'));
816
+ return this;
817
+ }
818
+
819
+ this._format = format;
820
+
821
+ return this;
822
+ };
823
+
824
+ /**
825
+ * Sets the module used for archiving.
826
+ *
827
+ * @param {Function} module The function for archiver to interact with.
828
+ * @return {this}
829
+ */
830
+ Archiver.prototype.setModule = function(module) {
831
+ if (this._state.aborted) {
832
+ this.emit('error', new ArchiverError('ABORTED'));
833
+ return this;
834
+ }
835
+
836
+ if (this._state.module) {
837
+ this.emit('error', new ArchiverError('MODULESET'));
838
+ return this;
839
+ }
840
+
841
+ this._module = module;
842
+ this._modulePipe();
843
+
844
+ return this;
845
+ };
846
+
847
+ /**
848
+ * Appends a symlink to the instance.
849
+ *
850
+ * This does NOT interact with filesystem and is used for programmatically creating symlinks.
851
+ *
852
+ * @param {String} filepath The symlink path (within archive).
853
+ * @param {String} target The target path (within archive).
854
+ * @param {Number} mode Sets the entry permissions.
855
+ * @return {this}
856
+ */
857
+ Archiver.prototype.symlink = function(filepath, target, mode) {
858
+ if (this._state.finalize || this._state.aborted) {
859
+ this.emit('error', new ArchiverError('QUEUECLOSED'));
860
+ return this;
861
+ }
862
+
863
+ if (typeof filepath !== 'string' || filepath.length === 0) {
864
+ this.emit('error', new ArchiverError('SYMLINKFILEPATHREQUIRED'));
865
+ return this;
866
+ }
867
+
868
+ if (typeof target !== 'string' || target.length === 0) {
869
+ this.emit('error', new ArchiverError('SYMLINKTARGETREQUIRED', { filepath: filepath }));
870
+ return this;
871
+ }
872
+
873
+ if (!this._moduleSupports('symlink')) {
874
+ this.emit('error', new ArchiverError('SYMLINKNOTSUPPORTED', { filepath: filepath }));
875
+ return this;
876
+ }
877
+
878
+ var data = {};
879
+ data.type = 'symlink';
880
+ data.name = filepath.replace(/\\/g, '/');
881
+ data.linkname = target.replace(/\\/g, '/');
882
+ data.sourceType = 'buffer';
883
+
884
+ if (typeof mode === "number") {
885
+ data.mode = mode;
886
+ }
887
+
888
+ this._entriesCount++;
889
+ this._queue.push({
890
+ data: data,
891
+ source: Buffer.concat([])
892
+ });
893
+
894
+ return this;
895
+ };
896
+
897
+ /**
898
+ * Returns the current length (in bytes) that has been emitted.
899
+ *
900
+ * @return {Number}
901
+ */
902
+ Archiver.prototype.pointer = function() {
903
+ return this._pointer;
904
+ };
905
+
906
+ /**
907
+ * Middleware-like helper that has yet to be fully implemented.
908
+ *
909
+ * @private
910
+ * @param {Function} plugin
911
+ * @return {this}
912
+ */
913
+ Archiver.prototype.use = function(plugin) {
914
+ this._streams.push(plugin);
915
+ return this;
916
+ };
917
+
918
+ module.exports = Archiver;
919
+
920
+ /**
921
+ * @typedef {Object} CoreOptions
922
+ * @global
923
+ * @property {Number} [statConcurrency=4] Sets the number of workers used to
924
+ * process the internal fs stat queue.
925
+ */
926
+
927
+ /**
928
+ * @typedef {Object} TransformOptions
929
+ * @property {Boolean} [allowHalfOpen=true] If set to false, then the stream
930
+ * will automatically end the readable side when the writable side ends and vice
931
+ * versa.
932
+ * @property {Boolean} [readableObjectMode=false] Sets objectMode for readable
933
+ * side of the stream. Has no effect if objectMode is true.
934
+ * @property {Boolean} [writableObjectMode=false] Sets objectMode for writable
935
+ * side of the stream. Has no effect if objectMode is true.
936
+ * @property {Boolean} [decodeStrings=true] Whether or not to decode strings
937
+ * into Buffers before passing them to _write(). `Writable`
938
+ * @property {String} [encoding=NULL] If specified, then buffers will be decoded
939
+ * to strings using the specified encoding. `Readable`
940
+ * @property {Number} [highWaterMark=16kb] The maximum number of bytes to store
941
+ * in the internal buffer before ceasing to read from the underlying resource.
942
+ * `Readable` `Writable`
943
+ * @property {Boolean} [objectMode=false] Whether this stream should behave as a
944
+ * stream of objects. Meaning that stream.read(n) returns a single value instead
945
+ * of a Buffer of size n. `Readable` `Writable`
946
+ */
947
+
948
+ /**
949
+ * @typedef {Object} EntryData
950
+ * @property {String} name Sets the entry name including internal path.
951
+ * @property {(String|Date)} [date=NOW()] Sets the entry date.
952
+ * @property {Number} [mode=D:0755/F:0644] Sets the entry permissions.
953
+ * @property {String} [prefix] Sets a path prefix for the entry name. Useful
954
+ * when working with methods like `directory` or `glob`.
955
+ * @property {fs.Stats} [stats] Sets the fs stat data for this entry allowing
956
+ * for reduction of fs stat calls when stat data is already known.
957
+ */
958
+
959
+ /**
960
+ * @typedef {Object} ErrorData
961
+ * @property {String} message The message of the error.
962
+ * @property {String} code The error code assigned to this error.
963
+ * @property {String} data Additional data provided for reporting or debugging (where available).
964
+ */
965
+
966
+ /**
967
+ * @typedef {Object} ProgressData
968
+ * @property {Object} entries
969
+ * @property {Number} entries.total Number of entries that have been appended.
970
+ * @property {Number} entries.processed Number of entries that have been processed.
971
+ * @property {Object} fs
972
+ * @property {Number} fs.totalBytes Number of bytes that have been appended. Calculated asynchronously and might not be accurate: it growth while entries are added. (based on fs.Stats)
973
+ * @property {Number} fs.processedBytes Number of bytes that have been processed. (based on fs.Stats)
974
+ */