@e-mc/file-manager 0.9.9 → 0.10.1

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 (3) hide show
  1. package/README.md +42 -23
  2. package/index.js +1733 -1187
  3. package/package.json +13 -11
package/index.js CHANGED
@@ -1,14 +1,13 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
2
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
3
3
  const path = require("path");
4
4
  const fs = require("fs");
5
5
  const stream = require("stream");
6
6
  const pm = require("picomatch");
7
+ const diff = require("diff");
7
8
  const chalk = require("chalk");
8
- const util_1 = require("@e-mc/request/util");
9
- const asset_1 = require("@e-mc/document/asset");
10
- const util_2 = require("@e-mc/document/util");
11
- const types_1 = require("@e-mc/types");
9
+ const stripansi = require("strip-ansi");
10
+ const url_1 = require("url");
12
11
  const core_1 = require("@e-mc/core");
13
12
  const request_1 = require("@e-mc/request");
14
13
  const document_1 = require("@e-mc/document");
@@ -17,6 +16,10 @@ const image_1 = require("@e-mc/image");
17
16
  const watch_1 = require("@e-mc/watch");
18
17
  const compress_1 = require("@e-mc/compress");
19
18
  const cloud_1 = require("@e-mc/cloud");
19
+ const types_1 = require("@e-mc/types");
20
+ const asset_1 = require("@e-mc/document/asset");
21
+ const util_1 = require("@e-mc/document/util");
22
+ const util_2 = require("@e-mc/request/util");
20
23
  const kBaseDirectory = Symbol('baseDirectory');
21
24
  const kIncremental = Symbol('incremental');
22
25
  const kRestarting = Symbol('restarting');
@@ -31,10 +34,11 @@ const kQueuedTasks = Symbol('queuedTasks');
31
34
  const kScheduler = Symbol('scheduler');
32
35
  const kProcessTimeout = Symbol('processTimeout');
33
36
  const kDownloadStats = Symbol('downloadStats');
37
+ const kDiffSource = Symbol('diffSource');
34
38
  const kReplaceMap = Symbol('replaceMap');
35
- const PLATFORM_WIN32 = process.platform === 'win32';
36
39
  const PROCESS_STDOUT = process.stdout;
37
- const STDOUT_CURSOR = typeof process.stdout.moveCursor === 'function';
40
+ const PROCESS_STDIN = process.stdin;
41
+ const STDOUT_CURSOR = typeof PROCESS_STDOUT.moveCursor === 'function';
38
42
  const PROCESS_TIMEOUT = { filemanager: 0, compress: 0 };
39
43
  const CACHE_ETAG = {};
40
44
  const DISK = {
@@ -58,6 +62,27 @@ const MEMORY = {
58
62
  DISK_MIN: Infinity,
59
63
  DISK_MAX: 0
60
64
  };
65
+ const LOGGER = {
66
+ TITLE_SEP: '|',
67
+ TITLE_WIDTH: 6,
68
+ VALUE_WIDTH: 71,
69
+ MIN_WIDTH: 0,
70
+ MESSAGE_WIDTH: 0,
71
+ STAT_WIDTH: 0,
72
+ PERCENT_WIDTH: 0,
73
+ MESSAGE_SEP: ' | ',
74
+ MESSAGE_SEP_START: 1,
75
+ PROGRESS_SCROLLBUFFER: 5,
76
+ PROGRESS_MAXWIDTH: Infinity,
77
+ PROGRESS_USECOLOR: true,
78
+ PROGRESS_RAWMODE: false,
79
+ PROGRESS_TEXTWRAP: 'nowrap',
80
+ PROGRESS_COLOR: null,
81
+ PROGRESS_BGCOLOR: null,
82
+ PROGRESS_BOXCHAR: '■',
83
+ PROGRESS_SPACER: chalk.blackBright('|'),
84
+ PROGRESS_COMPLETE: chalk.green('100%')
85
+ };
61
86
  let SESSION_ID = 0;
62
87
  let SESSION_LIMIT = 1000;
63
88
  let ASSET_ID = 0;
@@ -65,7 +90,6 @@ let RECURSION_LIMIT = 10;
65
90
  let PROCESS_SUB_LIMIT = Math.max(require('os').cpus().length, 1) * 2;
66
91
  let LOG_TIMEELAPSED = true;
67
92
  let LOG_TIMEPROCESS = true;
68
- let LOG_FORMAT = null;
69
93
  const HTTP_CLIENT = {
70
94
  timeout: 60000,
71
95
  connectTimeout: 20 * 1000,
@@ -77,7 +101,7 @@ const HTTP_CLIENT = {
77
101
  function applyTimeout(target, options) {
78
102
  for (const name in options) {
79
103
  const value = parseTimeout(options[name]);
80
- if (value !== undefined) {
104
+ if (value !== -1) {
81
105
  target[name] = value;
82
106
  }
83
107
  }
@@ -89,23 +113,23 @@ function parseTimeout(value) {
89
113
  if ((value = (0, types_1.parseTime)(value)) > 0) {
90
114
  return value;
91
115
  }
116
+ return -1;
92
117
  }
93
118
  function withinSizeRange(uri, value, pattern) {
94
119
  const match = (pattern || /\(\s*(\d+)\s*(?:,\s*(\d+|\*)\s*)?\)/).exec(value);
95
120
  const [minSize, maxSize] = match && !match[1] ? [+match[2], !match[3] || match[3] === '*' ? Infinity : +match[3]] : [0, Infinity];
96
121
  if (minSize > 0 || maxSize < Infinity) {
97
- const fileSize = (0, util_1.getSize)(uri);
122
+ const fileSize = (0, util_2.getSize)(uri);
98
123
  if (fileSize === 0 || fileSize < minSize || fileSize > maxSize) {
99
124
  return false;
100
125
  }
101
126
  }
102
127
  return true;
103
128
  }
104
- function startMessage() {
105
- this.formatMessage(128, 'START', [new Date().toLocaleString(), this.assets.length + ' assets'], this.baseDirectory, { ...core_1.Host.LOG_STYLE_SUCCESS });
106
- }
107
- function clearAssets() {
108
- this.assets.forEach(item => unsetContent(item));
129
+ function clearAssets(host) {
130
+ for (const item of host.assets) {
131
+ unsetContent(item);
132
+ }
109
133
  }
110
134
  function unsetContent(item) {
111
135
  if ('buffer' in item) {
@@ -115,7 +139,7 @@ function unsetContent(item) {
115
139
  item.sourceUTF8 = '';
116
140
  }
117
141
  }
118
- function bundleTorrent(files, mimeType, encoding) {
142
+ function bundleTorrent(host, files, mimeType, encoding) {
119
143
  let output = '';
120
144
  for (const file of files) {
121
145
  if (core_1.Host.lookupMime(file) === mimeType) {
@@ -123,15 +147,15 @@ function bundleTorrent(files, mimeType, encoding) {
123
147
  output += fs.readFileSync(file, encoding);
124
148
  }
125
149
  catch (err) {
126
- this.writeFail(["Unable to read file", path.basename(file)], err, 32);
150
+ host.writeFail(["Unable to read file", path.basename(file)], err, 32);
127
151
  }
128
152
  }
129
153
  }
130
154
  return output;
131
155
  }
132
- function resetAssets() {
133
- this.reset();
134
- FileManager.sanitizeAssets(this.assets);
156
+ function resetAssets(host) {
157
+ host.reset();
158
+ FileManager.sanitizeAssets(host.assets);
135
159
  }
136
160
  function recurseDir(output, subDirs, options) {
137
161
  const { ignore, sortBy, recursive } = options;
@@ -162,7 +186,7 @@ function recurseDir(output, subDirs, options) {
162
186
  }
163
187
  return output;
164
188
  }
165
- function checkHash(localUri, output, options, data) {
189
+ function checkHash(host, localUri, output, options, data) {
166
190
  let algorithm, digest, value;
167
191
  if ((0, types_1.isObject)(options)) {
168
192
  ({ algorithm, digest, value } = options);
@@ -172,21 +196,21 @@ function checkHash(localUri, output, options, data) {
172
196
  }
173
197
  if ((0, types_1.isString)(value)) {
174
198
  algorithm || (algorithm = "sha256");
175
- if (!data) {
199
+ if (!data && localUri) {
176
200
  try {
177
201
  data = fs.readFileSync(localUri);
178
202
  }
179
203
  catch (err) {
180
204
  if (output && core_1.Host.isErrorCode(err, 'ENOENT')) {
181
- this.addLog(this.statusType.WARN, algorithm + ' -> ENOENT -> No checksum performed', path.basename(localUri), value);
205
+ host.addLog(host.statusType.WARN, algorithm + ': ENOENT -> No checksum performed', path.basename(localUri), value);
182
206
  return true;
183
207
  }
184
- this.addLog(this.statusType.WARN, err, path.basename(localUri), value);
208
+ host.addLog(host.statusType.WARN, err, path.basename(localUri), value);
185
209
  return false;
186
210
  }
187
211
  }
188
- if ((value = value.toLowerCase()) === core_1.Host.asHash(data, { algorithm, digest })) {
189
- this.formatMessage(32, algorithm, ["Checksum matched" + (output ? ' (output)' : ''), path.basename(localUri)], value, { ...core_1.Host.LOG_STYLE_INFO, queue: true });
212
+ if (data && (value = value.toLowerCase()) === core_1.Host.asHash(data, algorithm, digest)) {
213
+ host.formatMessage(32, algorithm, ["Checksum matched" + (output ? ' (output)' : ''), localUri && path.basename(localUri)], value, { ...core_1.Host.LOG_STYLE_INFO, queue: true });
190
214
  return true;
191
215
  }
192
216
  return false;
@@ -194,7 +218,7 @@ function checkHash(localUri, output, options, data) {
194
218
  return true;
195
219
  }
196
220
  function validatePaths(values, patterns, include, dot) {
197
- const items = patterns.map(value => !value.startsWith('*') && /[\\/]/.test(value) ? [core_1.Permission.toPosix(path.resolve(value)), { nocase: PLATFORM_WIN32, dot }] : [value.replace(/(?:^\\|\\+)/g, '/'), { matchBase: true, nocase: PLATFORM_WIN32, dot }]);
221
+ const items = patterns.map(value => isMatchRoot(value) ? [core_1.Permission.toPosix(path.resolve(value)), { nocase: core_1.Host.PLATFORM_WIN32, dot }] : [sanitizePath(value), { matchBase: true, nocase: core_1.Host.PLATFORM_WIN32, dot }]);
198
222
  return values.filter(value => {
199
223
  for (const [pattern, options] of items) {
200
224
  if (pm.isMatch(core_1.Permission.toPosix(value), pattern, options)) {
@@ -223,130 +247,527 @@ function filterPaths(values, include, exclude, dot) {
223
247
  }
224
248
  return values;
225
249
  }
226
- function abortedHost() {
227
- if (this.finalizeState === 6) {
228
- this.restarting = false;
229
- this.performFinalize(true);
230
- return this.done;
250
+ function abortedHost(host) {
251
+ if (host.finalizeState === 6) {
252
+ host.restarting = false;
253
+ host.performFinalize(true);
254
+ return host.done;
231
255
  }
232
256
  return false;
233
257
  }
234
258
  function formatMinutes(elapsed) {
235
- let result = '';
236
- if (elapsed >= 3600000) {
237
- const h = Math.floor(elapsed / 3600000);
238
- elapsed -= h * 3600000;
239
- result = h + ':';
259
+ if (elapsed < 1000) {
260
+ return elapsed + 'ms';
240
261
  }
241
- if (elapsed >= 60000) {
242
- const m = Math.floor(elapsed / 60000);
243
- elapsed -= m * 60000;
244
- result += padStart(m, result ? '0' : ' ') + ':';
262
+ if (elapsed < 60000) {
263
+ return (elapsed / 1000).toPrecision(3) + 's';
245
264
  }
246
- else {
247
- result += ' 0:';
248
- }
249
- if (elapsed >= 1000) {
250
- const s = Math.floor(elapsed / 1000);
251
- result += padStart(s, '0');
252
- }
253
- else {
254
- result += '00';
255
- }
256
- return result;
265
+ return (0, types_1.formatTime)(elapsed, ':');
257
266
  }
258
- function observeFile(instance) {
259
- instance.on('file:delete', (value, options) => this.delete(value, !!options?.emptyDir));
260
- instance.on('file:copy', value => this.add(value));
267
+ function observeFile(host, instance) {
268
+ instance.on('file:delete', (value, options) => host.delete(value, !!options?.emptyDir));
269
+ instance.on('file:copy', value => host.add(value));
261
270
  instance.on('file:move', (value, options) => {
262
- this.add(value);
271
+ host.add(value);
263
272
  const src = options?.outSrc;
264
273
  if (src) {
265
- this.delete(src);
274
+ host.delete(src);
266
275
  }
267
276
  });
268
277
  instance.on('dir:remove', value => {
269
- if (this.removeCwd(value)) {
270
- if (PLATFORM_WIN32) {
271
- value = value.toLowerCase();
272
- }
278
+ if (host.removeCwd(value)) {
279
+ value = matchPathname(value);
273
280
  if (!value.endsWith(path.sep)) {
274
281
  value += path.sep;
275
282
  }
276
- for (const name of this.files) {
277
- if ((PLATFORM_WIN32 ? name.toLowerCase() : name).startsWith(value)) {
278
- this.files.delete(name);
283
+ for (const name of host.files) {
284
+ if (matchPathname(name).startsWith(value)) {
285
+ host.files.delete(name);
279
286
  }
280
287
  }
281
288
  }
282
289
  });
283
290
  }
284
- function collectErrors() {
291
+ function clearModule(instance, items) {
292
+ const { moduleName, errors } = instance;
293
+ if (errors.length > 0) {
294
+ for (const value of errors) {
295
+ items.push(`[${moduleName}] ` + (core_1.Host.asString(value) || "Unknown"));
296
+ }
297
+ errors.length = 0;
298
+ }
299
+ }
300
+ function collectErrors(host) {
285
301
  const result = [];
286
- const clearModule = (instance) => {
287
- const { moduleName, errors } = instance;
288
- if (errors.length) {
289
- errors.forEach(value => result.push(`[${moduleName}] ` + (core_1.Host.asString(value) || "Unknown")));
290
- errors.length = 0;
291
- }
292
- };
293
- this.modules.forEach(instance => clearModule(instance));
294
- this.subProcesses.forEach(instance => clearModule(instance));
295
- clearModule(this);
296
- if (!this.restarting) {
302
+ for (const instance of host.modules) {
303
+ clearModule(instance, result);
304
+ }
305
+ for (const instance of host.subProcesses) {
306
+ clearModule(instance, result);
307
+ }
308
+ clearModule(host, result);
309
+ if (!host.restarting) {
297
310
  queueMicrotask(() => {
298
- this.flushLog();
299
- this.modules.forEach(instance => instance.flushLog());
300
- this.subProcesses.forEach(instance => instance.flushLog());
301
- this.close();
302
- clearAssets.call(this);
311
+ if (!host.silent) {
312
+ host.flushLog();
313
+ }
314
+ for (const instance of host.modules) {
315
+ if (!instance.silent) {
316
+ instance.flushLog();
317
+ }
318
+ }
319
+ for (const instance of host.subProcesses) {
320
+ if (!instance.silent) {
321
+ instance.flushLog();
322
+ }
323
+ }
324
+ host.close();
325
+ clearAssets(host);
303
326
  });
304
327
  }
305
328
  else {
306
- clearAssets.call(this);
329
+ clearAssets(host);
307
330
  }
308
331
  return result;
309
332
  }
310
- function rejectModule(err, type, hint) {
311
- this.writeFail(["Handled rejection", this.moduleName + (hint ? ': ' + hint : '')], err, type);
333
+ function setHttpCacheLimit(value, type, disk) {
334
+ if (value === undefined) {
335
+ return;
336
+ }
337
+ if (typeof value === 'string') {
338
+ value = (0, types_1.formatSize)(value);
339
+ }
340
+ if (value >= 0) {
341
+ switch (type) {
342
+ case 1:
343
+ (disk ? DISK : MEMORY).LIMIT = value;
344
+ break;
345
+ case 2:
346
+ MEMORY.LIMIT_ALL = value;
347
+ break;
348
+ case 3:
349
+ MEMORY.DISK_MIN = value;
350
+ break;
351
+ case 4:
352
+ MEMORY.DISK_MAX = value;
353
+ break;
354
+ }
355
+ }
356
+ else if (value === -1) {
357
+ switch (type) {
358
+ case 3:
359
+ MEMORY.DISK_MIN = Infinity;
360
+ break;
361
+ case 4:
362
+ MEMORY.DISK_MAX = 0;
363
+ break;
364
+ }
365
+ }
366
+ }
367
+ function rejectModule(instance, err, type, hint) {
368
+ instance.writeFail(["Handled rejection", instance.moduleName + (hint ? ': ' + hint : '')], err, type);
369
+ }
370
+ function errorAsset(instance, err, localUri, type = 4) {
371
+ rejectModule(instance, err, type, path.basename(localUri));
372
+ }
373
+ function removeFiles(host, items) {
374
+ if (items.size > 0) {
375
+ for (const value of items) {
376
+ host.deleteFile(value, { emptyDir: true });
377
+ }
378
+ items.clear();
379
+ }
380
+ }
381
+ function createImageInstance(host, mimeMap, mimeType, constructor, ...params) {
382
+ const instance = new constructor(...params);
383
+ instance.host = host;
384
+ instance.init(host.config);
385
+ observeFile(host, instance);
386
+ mimeMap.set(mimeType, { constructor, instance, params });
387
+ return instance;
388
+ }
389
+ function clearQueue(data, attr) {
390
+ if (attr && data[attr]) {
391
+ for (const item of data[attr]) {
392
+ item.invalid = true;
393
+ }
394
+ data[attr] = undefined;
395
+ }
396
+ }
397
+ function hasEtag(item, cacheable, fallback) {
398
+ if (!cacheable || !(0, types_1.existsFlag)(item.flags)) {
399
+ return false;
400
+ }
401
+ switch (item.incremental) {
402
+ case false:
403
+ case "none":
404
+ case "exists":
405
+ case "staging":
406
+ return false;
407
+ case "etag":
408
+ return true;
409
+ default:
410
+ return fallback;
411
+ }
412
+ }
413
+ function processHeaders(item, headers, lastModified, mainEtag) {
414
+ const contentLength = parseInt(headers['content-length']);
415
+ if (contentLength > 0) {
416
+ item.contentLength = contentLength;
417
+ }
418
+ else if ('contentLength' in item) {
419
+ item.contentLength = undefined;
420
+ }
421
+ const etag = headers.etag;
422
+ if (etag) {
423
+ if (mainEtag) {
424
+ CACHE_ETAG[item.uri] = etag;
425
+ }
426
+ return item.etag = etag;
427
+ }
428
+ if (lastModified) {
429
+ return item.lastModified = headers['last-modified'];
430
+ }
431
+ }
432
+ function errorPermission(host, item) {
433
+ host.writeFail(["Unable to read file", item.uri], (0, types_1.errorValue)("Operation not permitted", item.uri || "Unknown"), 8192);
434
+ item.invalid = true;
435
+ }
436
+ function copyDownload(host, item, queued) {
437
+ const uriMap = new Map();
438
+ for (const file of queued) {
439
+ const destUri = file.localUri;
440
+ let items = uriMap.get(destUri);
441
+ if (!items) {
442
+ const pathname = path.dirname(destUri);
443
+ if (!core_1.Host.createDir(pathname)) {
444
+ file.invalid = true;
445
+ continue;
446
+ }
447
+ uriMap.set(destUri, items = []);
448
+ }
449
+ file.etag = item.etag;
450
+ file.lastModified = item.lastModified;
451
+ items.push(file);
452
+ }
453
+ const buffer = item.sourceUTF8 || item.buffer;
454
+ for (const [destUri, items] of uriMap) {
455
+ try {
456
+ if (buffer) {
457
+ fs.writeFileSync(destUri, buffer);
458
+ }
459
+ else {
460
+ fs.copyFileSync(item.localUri, destUri);
461
+ }
462
+ for (const queue of items) {
463
+ host.performAsyncTask();
464
+ void host.transformAsset(new FileThread(host, queue, 1));
465
+ }
466
+ }
467
+ catch (err) {
468
+ for (const queue of items) {
469
+ queue.invalid = true;
470
+ }
471
+ host.writeFail([buffer ? "Unable to write buffer" : "Unable to copy file", path.basename(item.localUri)], err, 32);
472
+ }
473
+ }
474
+ }
475
+ function setBufferTarget(item, buffer) {
476
+ if (typeof buffer === 'string') {
477
+ item.sourceUTF8 = buffer;
478
+ }
479
+ else {
480
+ item.buffer = buffer;
481
+ }
482
+ }
483
+ function writeBufferCache(host, localUri, buffer, encoding) {
484
+ fs.writeFileSync(localUri, buffer);
485
+ host.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
486
+ }
487
+ function nextScheduled(scheduler, pid) {
488
+ if (pid > 0) {
489
+ const found = scheduler.status.find(item => item.id === pid);
490
+ if (found) {
491
+ found.endTime || (found.endTime = Date.now());
492
+ }
493
+ }
494
+ --scheduler.count;
495
+ if (scheduler.queue.length > 0) {
496
+ const params = scheduler.queue.pop();
497
+ void this.scheduleTask(...params);
498
+ }
499
+ else if (scheduler.transform.length > 0) {
500
+ do {
501
+ const args = scheduler.transform.shift();
502
+ void this.transformAsset(args[0], args[1], true);
503
+ } while (scheduler.transform.length > 0 && scheduler.queue.length === 0);
504
+ }
505
+ }
506
+ async function doVerifyChecksum(root, from, options, nested) {
507
+ if ((0, types_1.isObject)(from)) {
508
+ options = from;
509
+ from = undefined;
510
+ }
511
+ else {
512
+ options || (options = {});
513
+ }
514
+ const { digest, sortBy = 0, recursive = false, ignore = [], include, exclude, verbose = true, joinRoot } = options;
515
+ const parent = recursive === 1 && typeof verbose !== 'number';
516
+ let algorithm = options.algorithm;
517
+ from || (from = checksumFile(algorithm));
518
+ if (!algorithm) {
519
+ switch (algorithm = path.extname(from).substring(1).toLowerCase()) {
520
+ case 'md5':
521
+ case 'sha1':
522
+ case 'sha224':
523
+ case 'sha256':
524
+ case 'sha384':
525
+ case 'sha512':
526
+ case 'ripemd':
527
+ case 'ripemd-160':
528
+ break;
529
+ default:
530
+ algorithm = undefined;
531
+ break;
532
+ }
533
+ }
534
+ if (verbose) {
535
+ (0, types_1.setLogCurrent)(null);
536
+ }
537
+ let pass = 0, fail = [], missing = [];
538
+ try {
539
+ const filename = path.basename(from);
540
+ const files = [];
541
+ from = joinRoot ? path.join(root, filename) : path.resolve(from);
542
+ recurseDir(files, [root], { ignore: [...ignore, from], sortBy, recursive });
543
+ const items = fs.readFileSync(from, 'utf-8').split('\n').map(item => {
544
+ const index = item.indexOf(' ');
545
+ return [item.substring(0, index), path.join(root, item.substring(index + 1))];
546
+ });
547
+ const checked = include || exclude ? filterPaths(items.map(item => item[1]), include, exclude, options.dot) : null;
548
+ let valid;
549
+ for (const [previous, pathname] of items) {
550
+ if (checked !== null && !checked.includes(pathname) || recursive === 1 && path.basename(pathname) === filename) {
551
+ continue;
552
+ }
553
+ if (files.includes(pathname)) {
554
+ const hash = await FileManager.readHash(pathname, { algorithm, digest });
555
+ if (hash !== previous) {
556
+ fail.push(pathname);
557
+ }
558
+ else {
559
+ if (verbose) {
560
+ process.stdout.write("+" + ' ' + pathname + '\n');
561
+ }
562
+ ++pass;
563
+ }
564
+ valid = true;
565
+ }
566
+ else if (!ignore.includes(pathname)) {
567
+ missing.push(pathname);
568
+ }
569
+ }
570
+ if (parent) {
571
+ const checksum = files.filter(value => path.basename(value) === filename);
572
+ if (checksum.length > 0) {
573
+ const current = items.map(item => item[1]);
574
+ const tasks = checksum.map(async (pathname) => doVerifyChecksum(path.dirname(pathname), filename, { ...options, ignore: current, joinRoot: true }, true));
575
+ await Promise.all(tasks).then(group => {
576
+ for (const item of group) {
577
+ if (item) {
578
+ const [f, m, p] = item;
579
+ if (f.length > 0) {
580
+ fail.push(...f);
581
+ }
582
+ if (m.length > 0) {
583
+ missing.push(...m);
584
+ }
585
+ pass += p;
586
+ valid = true;
587
+ }
588
+ }
589
+ });
590
+ }
591
+ }
592
+ if (valid) {
593
+ options.outPath = from;
594
+ }
595
+ else if (options.throwsEmpty) {
596
+ throw checksumError(algorithm);
597
+ }
598
+ }
599
+ catch (err) {
600
+ if (options.throwsEmpty) {
601
+ throw err;
602
+ }
603
+ FileManager.writeFail(["Unable to read directory", root], err, 32);
604
+ return null;
605
+ }
606
+ if (parent) {
607
+ if (fail.length > 0) {
608
+ fail = Array.from(new Set(fail));
609
+ }
610
+ if (missing.length > 0) {
611
+ missing = Array.from(new Set(missing));
612
+ }
613
+ }
614
+ if (verbose && !nested) {
615
+ const max = Math.max(...fail.concat(missing).map(item => item.length));
616
+ writeLog(fail, "-", max);
617
+ writeLog(missing, "?", max);
618
+ }
619
+ return [fail, missing, pass];
620
+ }
621
+ function writeLog(items, symbol, max) {
622
+ const [bg, fg] = symbol === "-" ? ['\x1b[31m', '\x1b[89m'] : ['\x1b[33m', '\x1b[89m'];
623
+ items.forEach((value, index) => {
624
+ process.stdout.write(bg + symbol + ` ${value.padEnd(max)} (${(index + 1).toString()})${fg}\n`);
625
+ });
626
+ }
627
+ function writeProgressBar(bars, length) {
628
+ if (bars > 0) {
629
+ const leading = bars < length ? (--bars, 1) : 0;
630
+ let result = bars > 0 ? LOGGER.PROGRESS_USECOLOR ? chalk.yellow.bold(LOGGER.PROGRESS_BOXCHAR).repeat(bars) : '#'.repeat(bars) : '';
631
+ if (leading > 0) {
632
+ result += chalk.grey(LOGGER.PROGRESS_BOXCHAR.repeat(length - bars));
633
+ }
634
+ return result;
635
+ }
636
+ return '';
637
+ }
638
+ function formatSegment(endTime, ...values) {
639
+ if (endTime === -1) {
640
+ values[0] = chalk.red(values[0]);
641
+ values[1] = chalk.grey.bold(values[1]);
642
+ values[2] = chalk.grey.bold(values[2]);
643
+ }
644
+ else if (endTime) {
645
+ values[0] = chalk.yellow.bold(values[0]);
646
+ values[1] = chalk.cyan.bold(values[1]);
647
+ values[2] = chalk.cyan(values[2]);
648
+ }
649
+ else {
650
+ values[0] = chalk.yellow(values[0]);
651
+ }
652
+ return values;
653
+ }
654
+ function tryPackage(host, target, type) {
655
+ if ((0, types_1.isString)(target)) {
656
+ try {
657
+ return require(target);
658
+ }
659
+ catch (err) {
660
+ host.checkPackage(err, target, ["Unable to load handler", host.moduleName], type);
661
+ }
662
+ return null;
663
+ }
664
+ return target;
665
+ }
666
+ function setLogMinWidth() {
667
+ LOGGER.MIN_WIDTH = LOGGER.TITLE_WIDTH + 2 + LOGGER.VALUE_WIDTH + 1;
668
+ LOGGER.MESSAGE_WIDTH = LOGGER.MIN_WIDTH + LOGGER.MESSAGE_SEP_START;
669
+ LOGGER.PERCENT_WIDTH = LOGGER.MIN_WIDTH + 8;
670
+ LOGGER.STAT_WIDTH = LOGGER.PERCENT_WIDTH + 11 + 13;
312
671
  }
313
- const padStart = (value, char) => value > 9 ? value.toString() : char + value;
672
+ const closeResponse = (client) => client?.destroy();
673
+ const isCacheable = (item) => item.initialValue?.cacheable !== false;
674
+ const isMatchRoot = (value) => !value.startsWith('*') && /[\\/]/.test(value);
675
+ const hasIncremental = (value) => value === "etag" || value === "exists";
676
+ const matchPathname = (value) => core_1.Host.PLATFORM_WIN32 ? value.toLowerCase() : value;
677
+ const sanitizePath = (value) => value.replace(/(?:^\\|\\+)/g, '/');
678
+ const equalAddress = (value, other) => value === other || decodeURIComponent(value) === decodeURIComponent(other);
679
+ const formatPercent = (value) => Math.round(value).toString().padStart(3) + '%';
680
+ const checkEOF = (value) => /\n$/.test(value) ? value : value + '\n';
314
681
  const checksumFile = (algorithm) => "checksum" + '.' + ((0, types_1.isString)(algorithm) ? algorithm.toLowerCase() : "sha256");
315
682
  const checksumError = (algorithm) => new Error("Invalid parameters" + ` (${algorithm || "sha256"})`);
316
683
  const isFunction = (value) => typeof value === 'function';
317
684
  const ignoreAsset = (item, exists) => item.invalid || (0, types_1.hasBit)(item.flags, 1 | (!exists ? 128 : 0));
685
+ const validateChecksum = (host, item, buffer, localUri = item.localUri) => !item.checksum || checkHash(host, localUri, false, item.checksum, buffer);
686
+ const errorAbsolute = (hint) => (0, types_1.errorValue)("Path is not absolute", hint);
318
687
  class Scheduler {
319
688
  constructor() {
320
689
  this.id = 0;
321
690
  this.count = 0;
322
- this.length = 0;
691
+ this.statusHeight = 0;
692
+ this.scrollHeight = 0;
693
+ this.pending = 0;
323
694
  this.updated = 0;
324
- this.titleWidth = 6;
325
- this.valueWidth = 71;
326
695
  this.limit = PROCESS_SUB_LIMIT;
327
696
  this.queue = [];
328
697
  this.transform = [];
329
698
  this.status = [];
699
+ this.scroll = [];
330
700
  this.logCurrent = null;
331
- if (LOG_FORMAT) {
332
- this.titleWidth = LOG_FORMAT.title.width;
333
- this.valueWidth = LOG_FORMAT.value.width;
334
- }
701
+ this.screenReset = false;
702
+ this.listener = null;
703
+ this._columns = -1;
335
704
  }
336
705
  add(id, url) {
337
- const valueWidth = this.valueWidth;
338
- if (url.length > valueWidth) {
339
- url = url.substring(0, valueWidth - 3) + '...';
706
+ if (url.length > LOGGER.VALUE_WIDTH) {
707
+ url = url.substring(0, LOGGER.VALUE_WIDTH - 3) + '...';
340
708
  }
341
709
  else {
342
- url = url.padEnd(valueWidth);
710
+ url = url.padEnd(LOGGER.VALUE_WIDTH);
343
711
  }
344
712
  this.status.push(new TaskStatus(id, url));
345
713
  }
346
714
  reset() {
347
715
  this.status = [];
348
- this.length = 0;
716
+ this.scroll = [];
717
+ this.statusHeight = 0;
718
+ this.scrollHeight = 0;
349
719
  this.logCurrent = null;
720
+ this._columns = -1;
721
+ if (this.listener) {
722
+ PROCESS_STDIN.setRawMode(false);
723
+ PROCESS_STDIN.removeListener('keypress', this.listener);
724
+ this.listener = null;
725
+ }
726
+ }
727
+ section(redraw) {
728
+ if (redraw) {
729
+ PROCESS_STDOUT.write(chalk.blackBright('-'.repeat(PROCESS_STDOUT.columns)) + '\n');
730
+ }
731
+ else {
732
+ PROCESS_STDOUT.moveCursor(0, 1);
733
+ }
734
+ }
735
+ get barLength() {
736
+ if (this.rawMode) {
737
+ if (this._columns === -1) {
738
+ PROCESS_STDIN.setRawMode(true);
739
+ this.listener = (ch, key) => {
740
+ if (key.ctrl) {
741
+ PROCESS_STDIN.setRawMode(false);
742
+ }
743
+ };
744
+ PROCESS_STDIN.on('keypress', this.listener);
745
+ }
746
+ PROCESS_STDIN.pause();
747
+ PROCESS_STDIN.resume();
748
+ }
749
+ const columns = PROCESS_STDOUT.columns;
750
+ if (columns !== this._columns) {
751
+ if (this._columns !== -1) {
752
+ for (const item of this.status) {
753
+ item.current = '';
754
+ item.finished = '';
755
+ }
756
+ this.scroll = [];
757
+ this.logCurrent = null;
758
+ PROCESS_STDOUT.write('\x1bc');
759
+ this.screenReset = true;
760
+ }
761
+ this._columns = columns;
762
+ }
763
+ const width = columns - LOGGER.STAT_WIDTH;
764
+ if (width < 0) {
765
+ return columns >= LOGGER.PERCENT_WIDTH ? 1 : NaN;
766
+ }
767
+ return width >= 10 ? Math.max(Math.min(width, LOGGER.PROGRESS_MAXWIDTH), 10) : -1;
768
+ }
769
+ get rawMode() {
770
+ return core_1.Host.PLATFORM_WIN32 && LOGGER.PROGRESS_RAWMODE;
350
771
  }
351
772
  }
352
773
  class TaskStatus {
@@ -359,7 +780,8 @@ class TaskStatus {
359
780
  this.startTime = Date.now();
360
781
  this.endTime = 0;
361
782
  this.dataTime = null;
362
- this.output = '';
783
+ this.current = '';
784
+ this.finished = '';
363
785
  }
364
786
  }
365
787
  class HttpDiskCache {
@@ -373,10 +795,10 @@ class HttpDiskCache {
373
795
  this._excludeExt = [];
374
796
  this._includeExt = [];
375
797
  this._items = [];
376
- this[KEnabled] = enabled;
798
+ this.enabled = enabled;
377
799
  }
378
800
  has(uri) {
379
- if (!this[KEnabled]) {
801
+ if (!this.enabled) {
380
802
  return false;
381
803
  }
382
804
  try {
@@ -391,7 +813,7 @@ class HttpDiskCache {
391
813
  if (flags === 0) {
392
814
  return true;
393
815
  }
394
- if (flags & 10) {
816
+ if (flags & (2 | 8)) {
395
817
  const ext = path.extname(uri.pathname).substring(1);
396
818
  if (ext) {
397
819
  if (flags & 2) {
@@ -404,9 +826,12 @@ class HttpDiskCache {
404
826
  }
405
827
  }
406
828
  }
407
- return flags & 1 ? this._include.includes(uri.origin) : !this._exclude.includes(uri.origin);
829
+ if ((flags & 1) && !this._include.includes(uri.origin) || (flags & 4) && this._exclude.includes(uri.origin)) {
830
+ return false;
831
+ }
832
+ return true;
408
833
  }
409
- add(uri, etag, target, { buffer, contentLength = (0, util_1.getSize)(target) } = {}) {
834
+ add(uri, etag, target, { buffer, contentLength = (0, util_2.getSize)(target) } = {}) {
410
835
  let tempDir;
411
836
  if (contentLength <= this.limit && (tempDir = this.host.getCacheDir(uri))) {
412
837
  const baseDir = path.join(tempDir, etag);
@@ -423,7 +848,9 @@ class HttpDiskCache {
423
848
  }
424
849
  const expires = this.expires;
425
850
  if (expires > 0 && expires < Infinity) {
426
- setTimeout(() => this.clear(target), Math.min(expires, core_1.Host.MAX_TIMEOUT));
851
+ setTimeout(() => {
852
+ this.clear(target);
853
+ }, Math.min(expires, core_1.Host.MAX_TIMEOUT));
427
854
  }
428
855
  }
429
856
  catch {
@@ -461,7 +888,7 @@ class HttpDiskCache {
461
888
  }
462
889
  }
463
890
  else {
464
- this._flags &= ~3;
891
+ this._flags &= ~(1 | 2);
465
892
  }
466
893
  }
467
894
  get include() {
@@ -483,7 +910,7 @@ class HttpDiskCache {
483
910
  }
484
911
  }
485
912
  else {
486
- this._flags &= ~12;
913
+ this._flags &= ~(4 | 8);
487
914
  }
488
915
  }
489
916
  get exclude() {
@@ -511,7 +938,9 @@ class HttpMemoryCache extends HttpDiskCache {
511
938
  }
512
939
  this._items.push(MEMORY.CACHE[uri] = [Date.now(), buffer, encoding, contentLength, uri, etag]);
513
940
  if (this.expires < Infinity) {
514
- setTimeout(() => this.clear(uri), Math.min(this.expires, core_1.Host.MAX_TIMEOUT));
941
+ setTimeout(() => {
942
+ this.clear(uri);
943
+ }, Math.min(this.expires, core_1.Host.MAX_TIMEOUT));
515
944
  }
516
945
  ++MEMORY.TOTAL;
517
946
  return;
@@ -556,7 +985,7 @@ class HttpMemoryCache extends HttpDiskCache {
556
985
  }
557
986
  }
558
987
  purge(percent, limit) {
559
- FileManager.purgeMemory(percent, limit);
988
+ void FileManager.purgeMemory(percent, limit);
560
989
  }
561
990
  withinDisk(value) {
562
991
  if (typeof value !== 'number') {
@@ -565,6 +994,397 @@ class HttpMemoryCache extends HttpDiskCache {
565
994
  return value >= this.toDisk[0] && value <= this.toDisk[1];
566
995
  }
567
996
  }
997
+ class ProcessGroup {
998
+ constructor() {
999
+ this.emptied = [];
1000
+ this.completed = Object.create(null);
1001
+ this.processing = Object.create(null);
1002
+ this.downloading = Object.create(null);
1003
+ this.appending = Object.create(null);
1004
+ this.bundling = Object.create(null);
1005
+ this.originCount = Object.create(null);
1006
+ }
1007
+ }
1008
+ class ProcessFile {
1009
+ constructor(host, file, localUri, groupData) {
1010
+ this.host = host;
1011
+ this.file = file;
1012
+ this.localUri = localUri;
1013
+ this.groupData = groupData;
1014
+ }
1015
+ createFolder(pathname, emptyDir) {
1016
+ const emptied = this.groupData.emptied;
1017
+ if (!emptied.includes(pathname)) {
1018
+ if (emptyDir && core_1.Host.removeDir(pathname, true)) {
1019
+ emptied.push(pathname);
1020
+ }
1021
+ else if (core_1.Host.createDir(pathname)) {
1022
+ emptied.push(pathname);
1023
+ }
1024
+ else {
1025
+ this.file.invalid = true;
1026
+ this.host.writeFail("Unable to create directory", (0, types_1.errorValue)("Path not found", pathname));
1027
+ return false;
1028
+ }
1029
+ }
1030
+ return true;
1031
+ }
1032
+ queued(pathname, emptyDir, content) {
1033
+ var _p, _q, _r;
1034
+ if (!this.createFolder(pathname, emptyDir)) {
1035
+ return true;
1036
+ }
1037
+ const { host, groupData: group, file, localUri } = this;
1038
+ const { bundleId, bundleIndex = -1 } = file;
1039
+ if (!(0, types_1.isEmpty)(bundleId) && bundleIndex >= 0) {
1040
+ const items = (_p = group.appending)[localUri] || (_p[localUri] = []);
1041
+ (_q = group.bundling)[_r = file.uri] || (_q[_r] = []);
1042
+ if (bundleIndex > 0) {
1043
+ items[bundleIndex - 1] = file;
1044
+ const url = file.url;
1045
+ if (file.fetchType === 1 && (host.cacheToDisk.has(url) || host.cacheToMemory.has(url))) {
1046
+ const parent = host.assets.find(item => item.bundleIndex === 0 && item.bundleId === bundleId);
1047
+ if (parent) {
1048
+ (parent.bundleQueue || (parent.bundleQueue = [])).push(new Promise(resolve => {
1049
+ host.Request.open(url, { method: 'HEAD', httpVersion: 1 })
1050
+ .on('response', res => {
1051
+ if (res.statusCode < 300) {
1052
+ processHeaders(file, res.headers, false, false);
1053
+ }
1054
+ resolve(file);
1055
+ })
1056
+ .on('error', () => {
1057
+ resolve(file);
1058
+ })
1059
+ .on('timeout', () => {
1060
+ resolve(file);
1061
+ });
1062
+ }));
1063
+ }
1064
+ }
1065
+ return true;
1066
+ }
1067
+ }
1068
+ else if (!content && file.filename) {
1069
+ const previous = group.completed[localUri];
1070
+ if (previous) {
1071
+ if (file.uri === previous.uri) {
1072
+ file.etag = previous.etag;
1073
+ file.lastModified = previous.lastModified;
1074
+ }
1075
+ void host.transformAsset(new FileThread(host, file, 1));
1076
+ return true;
1077
+ }
1078
+ const queue = group.processing[localUri];
1079
+ if (queue) {
1080
+ queue.push(file);
1081
+ return true;
1082
+ }
1083
+ group.processing[localUri] = [file];
1084
+ }
1085
+ return false;
1086
+ }
1087
+ received(err, incremental, fetched, binary, checked) {
1088
+ const { host, file } = this;
1089
+ const localUri = this.localUri;
1090
+ if (err) {
1091
+ file.invalid = true;
1092
+ host.completeAsyncTask(err, localUri);
1093
+ return;
1094
+ }
1095
+ if (file.checksum && !checked && !checkHash(host, localUri, false, file.checksum, file.buffer)) {
1096
+ file.invalid = true;
1097
+ host.filesToRemove.add(localUri);
1098
+ host.completeAsyncTask();
1099
+ host.writeFail(["Checksum did not match", path.basename(localUri)], (0, types_1.errorValue)(file.uri || localUri, "Invalid checksum"), { type: 32, queue: true });
1100
+ return;
1101
+ }
1102
+ if (fetched) {
1103
+ host.fetchedAssets.push(file);
1104
+ }
1105
+ else {
1106
+ host.copiedAssets.push(file);
1107
+ }
1108
+ if (binary) {
1109
+ void host.transformAsset(new FileThread(host, file, 1));
1110
+ }
1111
+ else {
1112
+ void this.finalize(incremental);
1113
+ }
1114
+ }
1115
+ async finalize(incremental) {
1116
+ const { host, file, localUri, groupData } = this;
1117
+ const bundleStart = file.bundleIndex === 0 && !(0, types_1.isEmpty)(file.bundleId) ? host.incremental !== "staging" && host[kRecursionLimit] === RECURSION_LIMIT ? 2 : 1 : 0;
1118
+ groupData.completed[localUri] = file;
1119
+ if (bundleStart > 0) {
1120
+ host.setAssetContent(file, host.getUTF8String(file, localUri));
1121
+ let success = true, error, checkEtag = !file.trailingContent && hasEtag(file, bundleStart === 2, incremental === "etag");
1122
+ if (file.bundleQueue) {
1123
+ error = await Promise.all(file.bundleQueue).then(() => null).catch((err) => err);
1124
+ delete file.bundleQueue;
1125
+ }
1126
+ const items = groupData.appending[localUri];
1127
+ if (items) {
1128
+ if (error) {
1129
+ for (const queue of items) {
1130
+ queue.invalid = true;
1131
+ }
1132
+ success = false;
1133
+ }
1134
+ else {
1135
+ const tasks = [];
1136
+ for (const queue of items) {
1137
+ const encoding = queue.encoding || (queue.encoding = 'utf-8');
1138
+ const { uri, fetchType: type } = queue;
1139
+ let tempFile;
1140
+ if (checkEtag && queue.trailingContent) {
1141
+ checkEtag = false;
1142
+ }
1143
+ const verifyBundle = (value, etag, checked) => {
1144
+ if (!queue.invalid) {
1145
+ if (!checked && !validateChecksum(host, queue, value, localUri)) {
1146
+ queue.invalid = true;
1147
+ return;
1148
+ }
1149
+ if (value instanceof Buffer) {
1150
+ value = value.toString(encoding);
1151
+ }
1152
+ const url = queue.url;
1153
+ if (etag && host.cacheToMemory.has(url)) {
1154
+ host.cacheToMemory.add(url, encodeURIComponent(etag), value, {
1155
+ encoding,
1156
+ contentLength: queue.contentLength,
1157
+ toDisk: !tempFile && isCacheable(queue) ? queue.filename || queue.localUri && path.basename(queue.localUri) : ''
1158
+ });
1159
+ }
1160
+ host.setAssetContent(queue, value, { localUri, bundleIndex: queue.bundleIndex, bundleReplace: queue.bundleReplace });
1161
+ }
1162
+ };
1163
+ if (queue.content) {
1164
+ verifyBundle(queue.content);
1165
+ checkEtag = false;
1166
+ }
1167
+ else if (uri) {
1168
+ if (type === 1 || type === 2) {
1169
+ const url = queue.url;
1170
+ const options = {
1171
+ url,
1172
+ encoding,
1173
+ statusMessage: uri + ` (${queue.bundleIndex})`
1174
+ };
1175
+ let etag, pipeTo;
1176
+ if (type === 2) {
1177
+ options.socketPath = queue.socketPath;
1178
+ options.httpVersion = 1;
1179
+ }
1180
+ else if (url) {
1181
+ if (etag = queue.etag) {
1182
+ const valid = incremental !== false || file.incremental === true;
1183
+ const cached = valid && MEMORY.CACHE[uri];
1184
+ const etagDir = encodeURIComponent(etag);
1185
+ if (cached) {
1186
+ if (etagDir === cached[5]) {
1187
+ const source = cached[1];
1188
+ if (validateChecksum(host, queue, source, localUri)) {
1189
+ verifyBundle(typeof source === 'string' ? source : source.toString(encoding), '', true);
1190
+ host.addDownload(Buffer.byteLength(source, encoding), types_1.DOWNLOAD_TYPE.CACHE);
1191
+ continue;
1192
+ }
1193
+ }
1194
+ else {
1195
+ host.cacheToMemory.clear(uri);
1196
+ }
1197
+ }
1198
+ if (host.cacheToDisk.has(url) && isCacheable(queue)) {
1199
+ const baseDir = path.join(host.getCacheDir(url), etagDir);
1200
+ pipeTo = path.join(baseDir, path.basename(localUri));
1201
+ try {
1202
+ if (valid && (0, util_2.hasSize)(pipeTo)) {
1203
+ const buffer = fs.readFileSync(pipeTo, { encoding });
1204
+ if (validateChecksum(host, queue, localUri, buffer)) {
1205
+ verifyBundle(buffer, etag, true);
1206
+ host.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
1207
+ continue;
1208
+ }
1209
+ }
1210
+ if (!fs.existsSync(baseDir)) {
1211
+ fs.mkdirSync(baseDir);
1212
+ }
1213
+ tempFile = path.join(baseDir, (0, types_1.incrementUUID)());
1214
+ options.pipeTo = tempFile;
1215
+ }
1216
+ catch {
1217
+ pipeTo = undefined;
1218
+ }
1219
+ }
1220
+ }
1221
+ if ((groupData.originCount[url.origin] || 0) <= 1) {
1222
+ options.httpVersion = 1;
1223
+ }
1224
+ options.connected = (headers) => {
1225
+ etag = processHeaders(queue, headers, !!host.Watch, false);
1226
+ return true;
1227
+ };
1228
+ }
1229
+ tasks.push(new Promise((resolve, reject) => {
1230
+ void host.scheduleTask(url || uri, options, (data) => {
1231
+ if (data) {
1232
+ verifyBundle(data, etag);
1233
+ }
1234
+ else {
1235
+ queue.invalid = true;
1236
+ }
1237
+ const downloaded = groupData.bundling[uri];
1238
+ if ((0, types_1.isArray)(downloaded)) {
1239
+ if (data && !queue.invalid) {
1240
+ if (typeof data === 'string') {
1241
+ queue.sourceUTF8 = data;
1242
+ }
1243
+ else {
1244
+ queue.buffer = data;
1245
+ }
1246
+ copyDownload(host, queue, downloaded);
1247
+ }
1248
+ else {
1249
+ for (const item of downloaded) {
1250
+ item.invalid = true;
1251
+ }
1252
+ }
1253
+ }
1254
+ if (tempFile && (!pipeTo || core_1.Host.isPath(pipeTo) || !core_1.Host.renameFile(tempFile, pipeTo, false))) {
1255
+ queueMicrotask(() => {
1256
+ fs.unlink(tempFile, () => { });
1257
+ });
1258
+ }
1259
+ resolve();
1260
+ }, (err) => {
1261
+ queue.invalid = true;
1262
+ if (tempFile) {
1263
+ queueMicrotask(() => {
1264
+ fs.unlink(tempFile, () => { });
1265
+ });
1266
+ }
1267
+ reject(err);
1268
+ }, 1);
1269
+ }));
1270
+ }
1271
+ else if (type) {
1272
+ const mimeType = queue.mimeType || file.mimeType;
1273
+ const pathname = host.getTempDir({ uuidDir: true });
1274
+ if (!pathname || !mimeType) {
1275
+ queue.invalid = true;
1276
+ tasks.push(Promise.reject(!pathname ? new Error("Unable to create temp directory") : (0, types_1.errorValue)("MIME not found", uri)));
1277
+ break;
1278
+ }
1279
+ tasks.push(new Promise((resolve, reject) => {
1280
+ void host.scheduleTask(queue.url || uri, { pathname, binOpts: queue.binOpts || file.binOpts }, (result) => {
1281
+ if (result.length > 0) {
1282
+ verifyBundle(bundleTorrent(host, result, mimeType, encoding));
1283
+ }
1284
+ else {
1285
+ queue.invalid = true;
1286
+ }
1287
+ queueMicrotask(() => {
1288
+ core_1.Host.removeDir(pathname);
1289
+ });
1290
+ resolve();
1291
+ }, (err) => {
1292
+ queue.invalid = true;
1293
+ queueMicrotask(() => {
1294
+ core_1.Host.removeDir(pathname);
1295
+ });
1296
+ reject(err);
1297
+ }, 4);
1298
+ }));
1299
+ }
1300
+ else if (host.canRead(uri)) {
1301
+ tasks.push(fs.promises.readFile(uri, encoding)
1302
+ .then(data => {
1303
+ verifyBundle(data);
1304
+ host.addDownload(Buffer.byteLength(data, encoding), types_1.DOWNLOAD_TYPE.DISK);
1305
+ })
1306
+ .catch(() => {
1307
+ queue.invalid = true;
1308
+ }));
1309
+ }
1310
+ else {
1311
+ checkEtag = false;
1312
+ errorPermission(host, file);
1313
+ }
1314
+ }
1315
+ }
1316
+ if (tasks.length > 0) {
1317
+ success = await Promise.all(tasks)
1318
+ .then(() => true)
1319
+ .catch((err) => {
1320
+ host.writeFail(["Unable to download file", 'bundle: ' + path.basename(localUri)], err, 1024);
1321
+ return false;
1322
+ });
1323
+ }
1324
+ else if (checkEtag && core_1.Host.isPath(localUri)) {
1325
+ host.completeAsyncTask();
1326
+ groupData.appending[localUri] = undefined;
1327
+ return;
1328
+ }
1329
+ }
1330
+ }
1331
+ if (success) {
1332
+ if (!host.fetchedAssets.includes(file)) {
1333
+ host.fetchedAssets.push(file);
1334
+ }
1335
+ void host.transformAsset(new FileThread(host, file, 1));
1336
+ }
1337
+ else {
1338
+ file.invalid = true;
1339
+ unsetContent(file);
1340
+ host.completeAsyncTask(error);
1341
+ queueMicrotask(() => {
1342
+ host.deleteFile(localUri, { emptyDir: true });
1343
+ });
1344
+ }
1345
+ groupData.appending[localUri] = undefined;
1346
+ return;
1347
+ }
1348
+ const { downloading, processing } = groupData;
1349
+ const uri = file.uri;
1350
+ const processed = processing[localUri];
1351
+ const downloaded = downloading[uri];
1352
+ if ((0, types_1.isArray)(downloaded)) {
1353
+ copyDownload(host, file, downloaded);
1354
+ }
1355
+ if (processed) {
1356
+ for (const item of processed) {
1357
+ if (item !== file) {
1358
+ if (item.uri === file.uri) {
1359
+ item.etag = file.etag;
1360
+ item.lastModified = file.lastModified;
1361
+ }
1362
+ host.performAsyncTask();
1363
+ }
1364
+ void host.transformAsset(new FileThread(host, item, 1));
1365
+ }
1366
+ processing[localUri] = undefined;
1367
+ }
1368
+ else {
1369
+ void host.transformAsset(new FileThread(host, file, 1));
1370
+ }
1371
+ if (downloaded) {
1372
+ downloading[uri] = undefined;
1373
+ }
1374
+ }
1375
+ abort(err, preceding) {
1376
+ const { host, file, localUri, groupData } = this;
1377
+ const uri = file.uri;
1378
+ clearQueue(groupData.processing, localUri);
1379
+ clearQueue(groupData.downloading, uri);
1380
+ clearQueue(groupData.appending, localUri);
1381
+ file.invalid = true;
1382
+ if (!preceding) {
1383
+ host.completeAsyncTask();
1384
+ }
1385
+ host.writeFail(["Unable to download file", uri], err, err instanceof Error && err.message.startsWith("Timeout was exceeded") ? 16384 : 1024);
1386
+ }
1387
+ }
568
1388
  class FileThread extends core_1.AbortComponent {
569
1389
  constructor(host, file, threadCount) {
570
1390
  super();
@@ -644,15 +1464,15 @@ class FileManager extends core_1.Host {
644
1464
  return false;
645
1465
  }
646
1466
  const { process: proc, download, request, error, logger } = settings;
647
- if (proc && (0, types_1.isPlainObject)(proc.thread)) {
648
- const limit = (0, util_1.asInt)(proc.thread.sub_limit);
1467
+ if (proc?.thread) {
1468
+ const limit = (0, util_2.asInt)(proc.thread.sub_limit);
649
1469
  if (limit > 0) {
650
1470
  PROCESS_SUB_LIMIT = limit;
651
1471
  }
652
1472
  }
653
1473
  if ((0, types_1.isPlainObject)(request)) {
654
1474
  let { timeout, disk, buffer, connect } = request;
655
- if ((timeout = (0, util_1.fromSeconds)(timeout)) >= 0) {
1475
+ if ((timeout = (0, util_2.fromSeconds)(timeout)) >= 0) {
656
1476
  HTTP_CLIENT.timeout = timeout;
657
1477
  }
658
1478
  if (disk) {
@@ -667,7 +1487,7 @@ class FileManager extends core_1.Host {
667
1487
  request_1.loadSettings({ process: settings.process, request, download }, password);
668
1488
  }
669
1489
  if (error) {
670
- const limit = (0, util_1.asInt)(error.recursion_limit);
1490
+ const limit = (0, util_2.asInt)(error.recursion_limit);
671
1491
  if (limit >= 0 && limit < Infinity) {
672
1492
  RECURSION_LIMIT = limit;
673
1493
  }
@@ -680,16 +1500,63 @@ class FileManager extends core_1.Host {
680
1500
  else if (id && (id = +id) > 0) {
681
1501
  SESSION_LIMIT = Math.pow(10, id);
682
1502
  }
1503
+ if (logger.progress) {
1504
+ let { scroll_buffer, max_width, use_color, text_wrap, color, bg_color, raw_mode, box_char } = logger.progress;
1505
+ if ((scroll_buffer = (0, util_2.asInt)(scroll_buffer)) >= 0 && scroll_buffer <= 16) {
1506
+ LOGGER.PROGRESS_SCROLLBUFFER = scroll_buffer;
1507
+ }
1508
+ if (max_width === 'auto' || max_width === '100%') {
1509
+ LOGGER.PROGRESS_MAXWIDTH = Infinity;
1510
+ }
1511
+ else if ((max_width = (0, util_2.asInt)(max_width)) >= 10) {
1512
+ LOGGER.PROGRESS_MAXWIDTH = max_width;
1513
+ }
1514
+ if (typeof use_color === 'boolean') {
1515
+ LOGGER.PROGRESS_USECOLOR = use_color;
1516
+ }
1517
+ switch (text_wrap) {
1518
+ case 'ellipsis':
1519
+ case 'nowrap':
1520
+ case 'ellipsis-end':
1521
+ case 'nowrap-end':
1522
+ LOGGER.PROGRESS_TEXTWRAP = text_wrap;
1523
+ break;
1524
+ }
1525
+ if ((0, types_1.isString)(color)) {
1526
+ LOGGER.PROGRESS_COLOR = color;
1527
+ }
1528
+ if ((0, types_1.isString)(bg_color)) {
1529
+ LOGGER.PROGRESS_BGCOLOR = bg_color;
1530
+ }
1531
+ if ((0, types_1.isString)(box_char) && box_char.length === 1) {
1532
+ LOGGER.PROGRESS_BOXCHAR = box_char;
1533
+ }
1534
+ if (typeof raw_mode === 'boolean') {
1535
+ LOGGER.PROGRESS_RAWMODE = raw_mode;
1536
+ if (raw_mode && core_1.Host.PLATFORM_WIN32) {
1537
+ require('readline').emitKeypressEvents(PROCESS_STDIN);
1538
+ }
1539
+ }
1540
+ }
683
1541
  }
684
- LOG_FORMAT = this.LOG_FORMAT;
1542
+ const { title, value, message } = this.LOG_FORMAT;
1543
+ LOGGER.TITLE_WIDTH = title.width;
1544
+ LOGGER.TITLE_SEP = title.braces;
1545
+ LOGGER.VALUE_WIDTH = value.width;
1546
+ const [L, R] = message.braces;
1547
+ const Lch = L.trim();
1548
+ const Rch = R.trim();
1549
+ LOGGER.MESSAGE_SEP = Lch.length + Rch.length === 1 ? ` ${Rch + Lch} ` : (R ? R[0] === ' ' ? R : ' ' + R.trimEnd() : '') + (L ? L[L.length - 1] === ' ' ? L : L.trimStart() + ' ' : '');
1550
+ LOGGER.MESSAGE_SEP_START = Lch.trimEnd().length;
685
1551
  LOG_TIMEELAPSED = this.hasLogType(128);
686
1552
  LOG_TIMEPROCESS = this.hasLogType(256);
1553
+ setLogMinWidth();
687
1554
  return true;
688
1555
  }
689
1556
  static sanitizeAssets(assets, exclusions = []) {
690
- assets.forEach(item => {
1557
+ for (const item of assets) {
691
1558
  if ((0, types_1.ignoreFlag)(item.flags)) {
692
- return;
1559
+ continue;
693
1560
  }
694
1561
  const initialValue = item.initialValue;
695
1562
  for (const attr in initialValue) {
@@ -725,7 +1592,7 @@ class FileManager extends core_1.Host {
725
1592
  break;
726
1593
  }
727
1594
  }
728
- });
1595
+ }
729
1596
  return assets;
730
1597
  }
731
1598
  static async writeChecksum(root, to, options) {
@@ -748,13 +1615,13 @@ class FileManager extends core_1.Host {
748
1615
  if (recursive === 1 && path.basename(pathname) === filename) {
749
1616
  continue;
750
1617
  }
751
- const current = await this.readHash(pathname, { algorithm, digest }) + ' ' + (path.sep === '\\' ? pathname.replace(/(?:^\\|\\+)/g, '/') : pathname).substring(root.length).replace(/^\//, '');
1618
+ const current = await this.readHash(pathname, { algorithm, digest }) + ' ' + (path.sep === '\\' ? sanitizePath(pathname) : pathname).substring(root.length).replace(/^\//, '');
752
1619
  if (verbose) {
753
1620
  process.stdout.write(current + '\n');
754
1621
  }
755
1622
  output.push(current);
756
1623
  }
757
- if (output.length) {
1624
+ if (output.length > 0) {
758
1625
  fs.writeFileSync(to, output.join('\n'), 'utf-8');
759
1626
  options.outPath = to;
760
1627
  }
@@ -777,118 +1644,7 @@ class FileManager extends core_1.Host {
777
1644
  return result;
778
1645
  }
779
1646
  static async verifyChecksum(root, from, options) {
780
- if ((0, types_1.isObject)(from)) {
781
- options = from;
782
- from = undefined;
783
- }
784
- else {
785
- options || (options = {});
786
- }
787
- const { digest, sortBy = 0, recursive = false, ignore = [], include, exclude, verbose = true, joinRoot } = options;
788
- const parent = recursive === 1 && typeof verbose !== 'number';
789
- let algorithm = options.algorithm;
790
- from || (from = checksumFile(algorithm));
791
- if (!algorithm) {
792
- switch (algorithm = path.extname(from).substring(1).toLowerCase()) {
793
- case 'md5':
794
- case 'sha1':
795
- case 'sha224':
796
- case 'sha256':
797
- case 'sha384':
798
- case 'sha512':
799
- break;
800
- default:
801
- algorithm = undefined;
802
- break;
803
- }
804
- }
805
- let pass = 0, fail = [], missing = [];
806
- try {
807
- const filename = path.basename(from);
808
- const files = [];
809
- from = joinRoot ? path.join(root, filename) : path.resolve(from);
810
- recurseDir(files, [root], { ignore: [...ignore, from], sortBy, recursive });
811
- const items = fs.readFileSync(from, 'utf-8').split('\n').map(item => {
812
- const index = item.indexOf(' ');
813
- return [item.substring(0, index), path.join(root, item.substring(index + 1))];
814
- });
815
- const checked = include || exclude ? filterPaths(items.map(item => item[1]), include, exclude, options.dot) : null;
816
- let valid;
817
- for (const [previous, pathname] of items) {
818
- if (checked !== null && !checked.includes(pathname) || recursive === 1 && path.basename(pathname) === filename) {
819
- continue;
820
- }
821
- if (files.includes(pathname)) {
822
- const hash = await this.readHash(pathname, { algorithm, digest });
823
- if (hash !== previous) {
824
- fail.push(pathname);
825
- }
826
- else {
827
- if (verbose) {
828
- process.stdout.write("+" + ' ' + pathname + '\n');
829
- }
830
- ++pass;
831
- }
832
- valid = true;
833
- }
834
- else if (!ignore.includes(pathname)) {
835
- missing.push(pathname);
836
- }
837
- }
838
- if (parent) {
839
- const nested = files.filter(value => path.basename(value) === filename);
840
- if (nested.length) {
841
- const current = items.map(item => item[1]);
842
- const tasks = nested.map(async (pathname) => this.verifyChecksum(path.dirname(pathname), filename, { ...options, ignore: current, joinRoot: true, verbose: (verbose ? 1 : 0) }));
843
- await Promise.all(tasks).then(group => {
844
- for (const item of group) {
845
- if (item) {
846
- const [f, m, p] = item;
847
- if (f.length) {
848
- fail.push(...f);
849
- }
850
- if (m.length) {
851
- missing.push(...m);
852
- }
853
- pass += p;
854
- valid = true;
855
- }
856
- }
857
- });
858
- }
859
- }
860
- if (valid) {
861
- options.outPath = from;
862
- }
863
- else if (options.throwsEmpty) {
864
- throw checksumError(algorithm);
865
- }
866
- }
867
- catch (err) {
868
- if (options.throwsEmpty) {
869
- throw err;
870
- }
871
- this.writeFail(["Unable to read directory", root], err, 32);
872
- return null;
873
- }
874
- if (parent) {
875
- if (fail.length) {
876
- fail = Array.from(new Set(fail));
877
- }
878
- if (missing.length) {
879
- missing = Array.from(new Set(missing));
880
- }
881
- }
882
- if (verbose === true) {
883
- const max = Math.max(...fail.concat(missing).map(item => item.length));
884
- const writeLog = (items, symbol) => {
885
- const [bg, fg] = symbol === "-" ? ['\x1b[31m', '\x1b[89m'] : ['\x1b[33m', '\x1b[89m'];
886
- items.forEach((value, index) => process.stdout.write(bg + symbol + ` ${value.padEnd(max)} (${(index + 1).toString()})${fg}\n`));
887
- };
888
- writeLog(fail, "-");
889
- writeLog(missing, "?");
890
- }
891
- return [fail, missing, pass];
1647
+ return doVerifyChecksum(root, from, options, false);
892
1648
  }
893
1649
  static createFileThread(host, file) {
894
1650
  return new FileThread(host, file, 0);
@@ -896,7 +1652,7 @@ class FileManager extends core_1.Host {
896
1652
  static setTimeout(options) {
897
1653
  applyTimeout(PROCESS_TIMEOUT, options);
898
1654
  }
899
- static defineHttpCache({ enabled, expires, limit, limit_all, include, exclude, to_disk, purge_amount }, disk) {
1655
+ static defineHttpCache({ enabled, expires, limit, limit_all, include, exclude, to_disk, purge_amount }, disk = false) {
900
1656
  const cache = disk ? DISK : MEMORY;
901
1657
  if (typeof enabled === 'boolean') {
902
1658
  cache.ENABLED = enabled;
@@ -904,70 +1660,37 @@ class FileManager extends core_1.Host {
904
1660
  cache.EXPIRES = expires ? (0, types_1.parseExpires)(expires) : 0;
905
1661
  cache.INCLUDE = (0, types_1.isArray)(include) ? include.slice(0) : [];
906
1662
  cache.EXCLUDE = (0, types_1.isArray)(exclude) ? exclude.slice(0) : [];
907
- const setLimit = (value, type) => {
908
- if (value !== undefined) {
909
- if (typeof value === 'string') {
910
- value = (0, types_1.formatSize)(value);
911
- }
912
- if (value >= 0) {
913
- switch (type) {
914
- case 1:
915
- (disk ? DISK : MEMORY).LIMIT = value;
916
- break;
917
- case 2:
918
- MEMORY.LIMIT_ALL = value;
919
- break;
920
- case 3:
921
- MEMORY.DISK_MIN = value;
922
- break;
923
- case 4:
924
- MEMORY.DISK_MAX = value;
925
- break;
926
- }
927
- }
928
- else if (value === -1) {
929
- switch (type) {
930
- case 3:
931
- MEMORY.DISK_MIN = Infinity;
932
- break;
933
- case 4:
934
- MEMORY.DISK_MAX = 0;
935
- break;
936
- }
937
- }
938
- }
939
- };
940
- setLimit(limit, 1);
1663
+ setHttpCacheLimit(limit, 1, disk);
941
1664
  if (disk) {
942
1665
  return;
943
1666
  }
944
- setLimit(limit_all, 2);
1667
+ setHttpCacheLimit(limit_all, 2, disk);
945
1668
  if (to_disk) {
946
1669
  let limit_disk;
947
1670
  if (Array.isArray(to_disk)) {
948
1671
  [to_disk, limit_disk] = to_disk;
949
1672
  }
950
- setLimit(to_disk, 3);
951
- setLimit(limit_disk, 4);
1673
+ setHttpCacheLimit(to_disk, 3, disk);
1674
+ setHttpCacheLimit(limit_disk, 4, disk);
952
1675
  }
953
- if ((purge_amount = (0, util_1.asFloat)(purge_amount)) > 0) {
1676
+ if ((purge_amount = (0, util_2.asFloat)(purge_amount)) > 0) {
954
1677
  MEMORY.PURGE = Math.min(purge_amount, 1);
955
1678
  }
956
1679
  }
957
1680
  static defineHttpConnect({ timeout, retry_wait, retry_after, retry_limit, redirect_limit }) {
958
- if ((timeout = (0, util_1.fromSeconds)(timeout)) >= 0) {
1681
+ if ((timeout = (0, util_2.fromSeconds)(timeout)) >= 0) {
959
1682
  HTTP_CLIENT.connectTimeout = timeout;
960
1683
  }
961
- if ((retry_wait = (0, util_1.fromSeconds)(retry_wait)) >= 0) {
1684
+ if ((retry_wait = (0, util_2.fromSeconds)(retry_wait)) >= 0) {
962
1685
  HTTP_CLIENT.retryWait = Math.min(retry_wait, 600 * 1000);
963
1686
  }
964
- if ((retry_after = (0, util_1.fromSeconds)(retry_after)) >= 0) {
1687
+ if ((retry_after = (0, util_2.fromSeconds)(retry_after)) >= 0) {
965
1688
  HTTP_CLIENT.retryAfter = Math.min(retry_after, this.MAX_TIMEOUT);
966
1689
  }
967
- if ((retry_limit = (0, util_1.asInt)(retry_limit)) >= 0) {
1690
+ if ((retry_limit = (0, util_2.asInt)(retry_limit)) >= 0) {
968
1691
  HTTP_CLIENT.retryLimit = retry_limit;
969
1692
  }
970
- if ((redirect_limit = (0, util_1.asInt)(redirect_limit)) >= 0) {
1693
+ if ((redirect_limit = (0, util_2.asInt)(redirect_limit)) >= 0) {
971
1694
  HTTP_CLIENT.redirectLimit = redirect_limit;
972
1695
  }
973
1696
  }
@@ -1003,9 +1726,10 @@ class FileManager extends core_1.Host {
1003
1726
  this[_g] = null;
1004
1727
  this[_h] = RECURSION_LIMIT;
1005
1728
  this[_j] = new Scheduler();
1006
- this[_k] = {};
1007
- this[_l] = [[0, 0], [0, 0], [0, 0]];
1729
+ this[_k] = [[0, 0], [0, 0], [0, 0]];
1730
+ this[_l] = null;
1008
1731
  this[_m] = {};
1732
+ this[_o] = null;
1009
1733
  if (isFunction(permission)) {
1010
1734
  postFinalize = permission;
1011
1735
  permission = undefined;
@@ -1055,15 +1779,26 @@ class FileManager extends core_1.Host {
1055
1779
  }
1056
1780
  this.cacheToDisk = new HttpDiskCache(this, DISK.ENABLED);
1057
1781
  this.cacheToMemory = new HttpMemoryCache(this, MEMORY.ENABLED);
1058
- if (MEMORY.INCLUDE.length) {
1782
+ if (MEMORY.INCLUDE.length > 0) {
1059
1783
  this.cacheToMemory.include = MEMORY.INCLUDE;
1060
1784
  }
1061
- else if (MEMORY.EXCLUDE.length) {
1785
+ if (MEMORY.EXCLUDE.length > 0) {
1062
1786
  this.cacheToMemory.exclude = MEMORY.EXCLUDE;
1063
1787
  }
1064
1788
  if (threads) {
1065
1789
  this.setTaskLimit(threads);
1066
1790
  }
1791
+ if ((0, types_1.isPlainObject)(config.log) && (0, types_1.isArray)(config.log.showDiff) && this.incremental !== "staging") {
1792
+ this[kDiffSource] = [
1793
+ config.log.showDiff.map(item => {
1794
+ if (!(0, types_1.hasGlob)(item)) {
1795
+ return item;
1796
+ }
1797
+ return isMatchRoot(item) ? pm(core_1.Permission.toPosix(item), { nocase: core_1.Host.PLATFORM_WIN32 }) : pm(sanitizePath(item), { matchBase: true, nocase: core_1.Host.PLATFORM_WIN32 });
1798
+ }),
1799
+ {}
1800
+ ];
1801
+ }
1067
1802
  const request = new request_1();
1068
1803
  request.host = this;
1069
1804
  this.Request = request;
@@ -1073,11 +1808,11 @@ class FileManager extends core_1.Host {
1073
1808
  else {
1074
1809
  request.init(config).apply({ client: HTTP_CLIENT });
1075
1810
  if (!this.queued) {
1076
- startMessage.call(this);
1811
+ this.startMessage();
1077
1812
  }
1078
1813
  }
1079
1814
  }
1080
- *[(_b = Symbol.toStringTag, _c = kRestarting, _d = kDelayed, _e = kCleared, _f = kFinalizedState, _g = KTimerMain, _h = kRecursionLimit, _j = kScheduler, _k = kProcessTimeout, _l = kDownloadStats, _m = kReplaceMap, Symbol.iterator)]() {
1815
+ *[(_b = Symbol.toStringTag, _c = kRestarting, _d = kDelayed, _e = kCleared, _f = kFinalizedState, _g = KTimerMain, _h = kRecursionLimit, _j = kScheduler, _k = kDownloadStats, _l = kReplaceMap, _m = kProcessTimeout, _o = kDiffSource, Symbol.iterator)]() {
1081
1816
  for (const file of this.files) {
1082
1817
  yield file;
1083
1818
  }
@@ -1183,7 +1918,7 @@ class FileManager extends core_1.Host {
1183
1918
  for (const { instance } of this.Document) {
1184
1919
  instance.restart();
1185
1920
  }
1186
- startMessage.call(this);
1921
+ this.startMessage();
1187
1922
  this.processAssets(emptyDir);
1188
1923
  }
1189
1924
  else {
@@ -1205,7 +1940,7 @@ class FileManager extends core_1.Host {
1205
1940
  const instance = new cloud_1(args[0], args[1]);
1206
1941
  instance.host = this;
1207
1942
  instance.init(this.config);
1208
- observeFile.call(this, instance);
1943
+ observeFile(this, instance);
1209
1944
  return this.Cloud = instance;
1210
1945
  }
1211
1946
  }
@@ -1230,16 +1965,20 @@ class FileManager extends core_1.Host {
1230
1965
  this.contentToReplace.clear();
1231
1966
  this.processing.length = 0;
1232
1967
  this.Request.reset();
1233
- this.modules.forEach(instance => instance.reset());
1968
+ for (const instance of this.modules) {
1969
+ instance.reset();
1970
+ }
1234
1971
  this.emptyDir.clear();
1235
1972
  if (!this.restarting) {
1236
1973
  this.close();
1237
1974
  this._pendingResult = null;
1238
1975
  }
1239
- clearAssets.call(this);
1976
+ clearAssets(this);
1240
1977
  this.cleared = false;
1241
1978
  this[kDelayed] = 0;
1242
1979
  this[kScheduler] = new Scheduler();
1980
+ this[kDownloadStats] = [[0, 0], [0, 0], [0, 0]];
1981
+ this.clearStorage();
1243
1982
  this.finalizeState = 0;
1244
1983
  return true;
1245
1984
  }
@@ -1253,8 +1992,12 @@ class FileManager extends core_1.Host {
1253
1992
  if (options.all) {
1254
1993
  value = path.resolve(value);
1255
1994
  (options.id ? [this.assets.find(item => item.id === options.id)].filter(item => item) : this.assets.filter(item => item.localUri === value)).forEach(asset => {
1256
- asset.transforms?.forEach(file => this.deleteFile(file, emptyDir));
1257
- asset.descendants?.forEach(file => this.deleteFile(file, emptyDir));
1995
+ asset.transforms?.forEach(file => {
1996
+ this.deleteFile(file, emptyDir);
1997
+ });
1998
+ asset.descendants?.forEach(file => {
1999
+ this.deleteFile(file, emptyDir);
2000
+ });
1258
2001
  });
1259
2002
  }
1260
2003
  }
@@ -1270,89 +2013,62 @@ class FileManager extends core_1.Host {
1270
2013
  return;
1271
2014
  }
1272
2015
  this.finalizeState = 5;
1273
- startMessage.call(this);
2016
+ this.startMessage();
1274
2017
  this.processAssets(...options.args);
1275
2018
  }
1276
2019
  install(name, ...args) {
1277
2020
  if (this.aborted) {
1278
2021
  return;
1279
2022
  }
1280
- let target = args.shift();
2023
+ let Target = args.shift();
1281
2024
  switch (name) {
1282
2025
  case 'document':
1283
- if ((0, types_1.isString)(target)) {
1284
- try {
1285
- target = require(target);
1286
- }
1287
- catch (err) {
1288
- this.checkPackage(err, target, ["Unable to load handler", this.moduleName], 4);
1289
- }
1290
- }
1291
- if (isFunction(target) && target.prototype instanceof document_1) {
1292
- const instance = new target(...args);
2026
+ if (isFunction(Target = tryPackage(this, Target, 4)) && Target.prototype instanceof document_1) {
2027
+ const instance = new Target(...args);
1293
2028
  instance.host = this;
1294
2029
  instance.init(this.getDocumentAssets(instance), this.config);
1295
- observeFile.call(this, instance);
1296
- this.Document.push({ instance, constructor: target, params: args });
2030
+ observeFile(this, instance);
2031
+ this.Document.push({ instance, constructor: Target, params: args });
1297
2032
  return instance;
1298
2033
  }
1299
2034
  break;
1300
2035
  case 'task':
1301
- if ((0, types_1.isString)(target)) {
1302
- try {
1303
- target = require(target);
1304
- }
1305
- catch (err) {
1306
- this.checkPackage(err, target, ["Unable to load handler", this.moduleName], 4);
1307
- }
1308
- }
1309
- if (isFunction(target) && target.prototype instanceof task_1 && (0, types_1.isPlainObject)(args[0])) {
1310
- const instance = new target(...args);
2036
+ if (isFunction(Target = tryPackage(this, Target, 4)) && Target.prototype instanceof task_1 && (0, types_1.isPlainObject)(args[0])) {
2037
+ const instance = new Target(...args);
1311
2038
  instance.host = this;
1312
2039
  instance.init(this.config);
1313
- observeFile.call(this, instance);
1314
- this.Task.push({ instance, constructor: target, params: args });
2040
+ observeFile(this, instance);
2041
+ this.Task.push({ instance, constructor: Target, params: args });
1315
2042
  return instance;
1316
2043
  }
1317
2044
  break;
1318
2045
  case 'cloud': {
1319
2046
  const database = this.dataSourceItems.filter(item => item.source === 'cloud');
1320
2047
  let instance;
1321
- if ((0, types_1.isString)(target)) {
2048
+ if ((0, types_1.isString)(Target)) {
1322
2049
  const module = args.shift();
1323
2050
  if ((0, types_1.isObject)(module)) {
1324
- if (target === "@e-mc/cloud") {
2051
+ if (Target === "@e-mc/cloud") {
1325
2052
  instance = new cloud_1(module, database);
1326
2053
  }
1327
- else {
1328
- try {
1329
- const Handler = require(target);
1330
- if (isFunction(Handler) && Handler.prototype instanceof core_1.ClientDb) {
1331
- instance = new Handler(module, database);
1332
- }
1333
- else {
1334
- throw (0, types_1.errorMessage)(this.moduleName, "Not a Cloud constructor", target);
1335
- }
1336
- }
1337
- catch (err) {
1338
- this.checkPackage(err, target, ["Unable to load handler", this.moduleName], 64);
1339
- }
2054
+ else if (isFunction(Target = tryPackage(this, Target, 64)) && Target.prototype instanceof core_1.ClientDb) {
2055
+ instance = new Target(module, database);
1340
2056
  }
1341
2057
  }
1342
2058
  }
1343
- else if ((0, types_1.isObject)(target)) {
1344
- instance = new cloud_1(target, database);
2059
+ else if ((0, types_1.isObject)(Target)) {
2060
+ instance = new cloud_1(Target, database);
1345
2061
  }
1346
2062
  if (instance) {
1347
2063
  instance.host = this;
1348
2064
  instance.init(this.config);
1349
- observeFile.call(this, instance);
2065
+ observeFile(this, instance);
1350
2066
  return this.Cloud = instance;
1351
2067
  }
1352
2068
  break;
1353
2069
  }
1354
2070
  case 'watch': {
1355
- const instance = (0, types_1.isObject)(target) ? new watch_1(target) : new watch_1({ interval: target, port: args[0], secure: { port: args[1] }, extensions: args[2] });
2071
+ const instance = (0, types_1.isObject)(Target) ? new watch_1(Target) : new watch_1({ interval: Target, port: args[0], secure: { port: args[1] }, extensions: args[2] });
1356
2072
  instance.host = this;
1357
2073
  instance.init(this.config);
1358
2074
  instance.whenModified = (assets, sanitize, postFinalize) => {
@@ -1395,7 +2111,7 @@ class FileManager extends core_1.Host {
1395
2111
  }
1396
2112
  mimeMap.set(mimeType, constructor);
1397
2113
  }
1398
- if (mimeMap.size) {
2114
+ if (mimeMap.size > 0) {
1399
2115
  manager.install('image', mimeMap, ...params);
1400
2116
  }
1401
2117
  }
@@ -1417,47 +2133,29 @@ class FileManager extends core_1.Host {
1417
2133
  return manager;
1418
2134
  };
1419
2135
  return this.Watch = instance;
1420
- }
1421
- case 'image': {
1422
- const createInstance = (mimeMap, mimeType, constructor, ...params) => {
1423
- const instance = new constructor(...params);
1424
- instance.host = this;
1425
- instance.init(this.config);
1426
- observeFile.call(this, instance);
1427
- mimeMap.set(mimeType, { constructor, instance, params });
1428
- return instance;
1429
- };
1430
- if (target instanceof Map) {
2136
+ }
2137
+ case 'image': {
2138
+ if (Target instanceof Map) {
1431
2139
  const mimeMap = new Map();
1432
- for (const [mimeType, constructor] of target) {
2140
+ for (const [mimeType, constructor] of Target) {
1433
2141
  if (constructor.prototype instanceof image_1) {
1434
- createInstance(mimeMap, mimeType, constructor, args[0]);
2142
+ createImageInstance(this, mimeMap, mimeType, constructor, args[0]);
1435
2143
  }
1436
2144
  }
1437
- if (mimeMap.size) {
2145
+ if (mimeMap.size > 0) {
1438
2146
  this.Image = mimeMap;
1439
2147
  }
1440
2148
  }
1441
- else {
1442
- if ((0, types_1.isString)(target)) {
1443
- try {
1444
- target = require(target);
1445
- }
1446
- catch (err) {
1447
- this.checkPackage(err, target, ["Unable to load handler", this.moduleName], 2048);
1448
- }
1449
- }
1450
- if (isFunction(target) && target.prototype instanceof image_1) {
1451
- return createInstance(this.Image ?? (this.Image = new Map()), 'handler', target, ...args);
1452
- }
2149
+ else if (isFunction(Target = tryPackage(this, Target, 2048)) && Target.prototype instanceof image_1) {
2150
+ return createImageInstance(this, this.Image ?? (this.Image = new Map()), 'handler', Target, ...args);
1453
2151
  }
1454
2152
  break;
1455
2153
  }
1456
2154
  case 'compress': {
1457
- const instance = new compress_1(target);
2155
+ const instance = new compress_1(Target);
1458
2156
  instance.host = this;
1459
2157
  instance.init();
1460
- observeFile.call(this, instance);
2158
+ observeFile(this, instance);
1461
2159
  return this.Compress = instance;
1462
2160
  }
1463
2161
  }
@@ -1487,7 +2185,6 @@ class FileManager extends core_1.Host {
1487
2185
  if (!(0, types_1.isString)(value)) {
1488
2186
  return;
1489
2187
  }
1490
- const isSame = (a, b) => a === b || decodeURIComponent(a) === decodeURIComponent(b);
1491
2188
  const result = (assets || this.assets).filter(item => {
1492
2189
  const { uri, flags } = item;
1493
2190
  if (uri && (!instance || this.hasDocument(instance, item.document)) && (!item.invalid || assets || (0, types_1.mainFlag)(flags) || (0, types_1.usingFlag)(flags) || (0, types_1.cloneFlag)(flags) || (0, types_1.watchFlag)(flags))) {
@@ -1505,35 +2202,37 @@ class FileManager extends core_1.Host {
1505
2202
  return true;
1506
2203
  }
1507
2204
  }
1508
- if (isSame(uri, value)) {
2205
+ if (equalAddress(uri, value)) {
1509
2206
  return true;
1510
2207
  }
1511
2208
  const indexA = uri.indexOf('#');
1512
2209
  const indexB = value.indexOf('#');
1513
2210
  if (indexA !== -1 || indexB !== -1) {
1514
- return isSame(indexA !== -1 ? uri.substring(0, indexA) : uri, indexB !== -1 ? value.substring(0, indexB) : value);
2211
+ return equalAddress(indexA !== -1 ? uri.substring(0, indexA) : uri, indexB !== -1 ? value.substring(0, indexB) : value);
1515
2212
  }
1516
2213
  }
1517
2214
  return false;
1518
2215
  });
1519
2216
  if (replaced) {
1520
2217
  const map = this[kReplaceMap];
1521
- const target = pathname || core_1.Host.toPosix(value);
1522
- const found = [];
1523
- for (const relative in map) {
1524
- const item = map[relative];
1525
- if (origin && item.url && item.url.origin !== origin) {
1526
- continue;
1527
- }
1528
- if (path.basename(relative) === path.basename(target) && path.dirname(target).endsWith(path.dirname(relative))) {
1529
- found.push([item, relative]);
2218
+ if (map) {
2219
+ const target = pathname || core_1.Host.toPosix(value);
2220
+ const found = [];
2221
+ for (const relative in map) {
2222
+ const item = map[relative];
2223
+ if (origin && item.url && item.url.origin !== origin) {
2224
+ continue;
2225
+ }
2226
+ if (path.basename(relative) === path.basename(target) && path.dirname(target).endsWith(path.dirname(relative))) {
2227
+ found.push([item, relative]);
2228
+ }
1530
2229
  }
1531
- }
1532
- if (found.length) {
1533
- if (result.length === 0) {
1534
- return found.sort((a, b) => b[1].length - a[1].length)[0][0];
2230
+ if (found.length > 0) {
2231
+ if (result.length === 0) {
2232
+ return found.sort((a, b) => b[1].length - a[1].length)[0][0];
2233
+ }
2234
+ result.push(...found.map(item => item[0]));
1535
2235
  }
1536
- result.push(...found.map(item => item[0]));
1537
2236
  }
1538
2237
  }
1539
2238
  return result.sort((a, b) => {
@@ -1566,7 +2265,7 @@ class FileManager extends core_1.Host {
1566
2265
  removeCwd(value) {
1567
2266
  if (typeof value === 'string') {
1568
2267
  let baseDir = this.baseDirectory + path.sep, leading = value.substring(0, baseDir.length);
1569
- if (PLATFORM_WIN32) {
2268
+ if (core_1.Host.PLATFORM_WIN32) {
1570
2269
  baseDir = baseDir.toLowerCase();
1571
2270
  leading = leading.toLowerCase();
1572
2271
  }
@@ -1621,7 +2320,7 @@ class FileManager extends core_1.Host {
1621
2320
  if (localUri && !this.assets.find(item => item.localUri === localUri && !item.invalid)) {
1622
2321
  this.filesToRemove.add(localUri);
1623
2322
  }
1624
- this[kReplaceMap][core_1.Host.joinPath(file.pathname, file.filename)] = file;
2323
+ (this[kReplaceMap] || (this[kReplaceMap] = {}))[core_1.Host.joinPath(file.pathname, file.filename)] = file;
1625
2324
  }
1626
2325
  }
1627
2326
  unsetContent(file);
@@ -1691,7 +2390,8 @@ class FileManager extends core_1.Host {
1691
2390
  this.finalizeState = 1;
1692
2391
  this.finalize()
1693
2392
  .then(() => {
1694
- const errors = collectErrors.call(this);
2393
+ this.diffMessage();
2394
+ const errors = collectErrors(this);
1695
2395
  const files = Array.from(this.files).sort((a, b) => {
1696
2396
  const sep = path.sep;
1697
2397
  if (a.includes(sep) && !b.includes(sep)) {
@@ -1702,9 +2402,7 @@ class FileManager extends core_1.Host {
1702
2402
  }
1703
2403
  return a < b ? -1 : 1;
1704
2404
  });
1705
- if (LOG_TIMEELAPSED) {
1706
- this.writeTimeElapsed('END', this.baseDirectory, this.startTime, errors.length > 0 ? { failed: true, ...core_1.Host.LOG_STYLE_FAIL } : { ...core_1.Host.LOG_STYLE_SUCCESS });
1707
- }
2405
+ this.endMessage(errors);
1708
2406
  this.resetState();
1709
2407
  const log = this.config.log;
1710
2408
  let useNumeric, showSize;
@@ -1712,19 +2410,46 @@ class FileManager extends core_1.Host {
1712
2410
  ({ useNumeric, showSize } = log);
1713
2411
  }
1714
2412
  const items = showSize === false ? files : files.map(name => {
1715
- const size = (0, util_1.getSize)(path.join(this.baseDirectory, name));
2413
+ const size = (0, util_2.getSize)(path.join(this.baseDirectory, name));
1716
2414
  return { name, size: useNumeric ? size : (0, types_1.formatSize)(size) };
1717
2415
  });
1718
2416
  this.emit('end', items, errors, this.collectLog());
1719
2417
  this.done = true;
1720
2418
  })
1721
- .catch((err) => this.abortFinalize(err));
2419
+ .catch((err) => {
2420
+ this.abortFinalize(err);
2421
+ });
1722
2422
  }
1723
2423
  }
1724
2424
  hasDocument(instance, document) {
1725
2425
  const moduleName = instance.moduleName;
1726
2426
  return document === moduleName || Array.isArray(document) && document.includes(moduleName);
1727
2427
  }
2428
+ checkFilename(file, pathname = '') {
2429
+ let filename = file.filename;
2430
+ if (filename) {
2431
+ if (!pathname) {
2432
+ pathname = file.pathname || '';
2433
+ }
2434
+ const assets = this.assets;
2435
+ let target = matchPathname(path.join(pathname, filename)), modified;
2436
+ for (let i = 0, j = 1, length = assets.length; i < length; ++i) {
2437
+ const item = assets[i];
2438
+ if (item !== file && item.filename && target === matchPathname(path.join(item.pathname || '', item.filename))) {
2439
+ const ext = path.extname(filename);
2440
+ filename = path.basename(filename, ext) + '_' + j + ext;
2441
+ target = matchPathname(path.join(pathname, filename));
2442
+ modified = true;
2443
+ i = -1;
2444
+ ++j;
2445
+ }
2446
+ }
2447
+ if (modified) {
2448
+ return file.filename = filename;
2449
+ }
2450
+ }
2451
+ return '';
2452
+ }
1728
2453
  setLocalUri(file, replace) {
1729
2454
  let uri = file.uri, type;
1730
2455
  if (uri && !file.url && !file.content && !file.base64 && !file.dataView) {
@@ -1737,13 +2462,12 @@ class FileManager extends core_1.Host {
1737
2462
  file.uri = file.url.toString();
1738
2463
  }
1739
2464
  catch (err) {
1740
- this.writeFail(['Unable to parse URL', uri], err, 1024);
2465
+ this.writeFail(["Unable to resolve file", uri], err, { type: 1024, fatal: !!file.document });
1741
2466
  return { pathname: '', localUri: '' };
1742
2467
  }
1743
2468
  }
1744
2469
  else {
1745
2470
  try {
1746
- const errorAbsolute = (value) => (0, types_1.errorValue)("Path is not absolute", value);
1747
2471
  if (!(file.uri = core_1.Host.resolveFile(uri))) {
1748
2472
  throw errorAbsolute(uri);
1749
2473
  }
@@ -1760,12 +2484,15 @@ class FileManager extends core_1.Host {
1760
2484
  }
1761
2485
  }
1762
2486
  catch (err) {
1763
- this.writeFail(['Unable to resolve file location', uri], err, 32);
2487
+ this.writeFail(['Unable to resolve file location', uri], err, { type: 32, fatal: !!file.document });
1764
2488
  return { pathname: '', localUri: '' };
1765
2489
  }
1766
2490
  }
1767
2491
  }
1768
2492
  const url = file.url;
2493
+ if (file.pathname) {
2494
+ file.pathname = core_1.Host.toPosix(file.pathname);
2495
+ }
1769
2496
  if (url) {
1770
2497
  if (url.protocol.startsWith('http')) {
1771
2498
  type = 1;
@@ -1776,12 +2503,32 @@ class FileManager extends core_1.Host {
1776
2503
  else if (core_1.Host.isFile(url, 's/ftp')) {
1777
2504
  type = 3;
1778
2505
  }
2506
+ let filename = file.filename;
2507
+ if (!filename && !file.document && type !== 4) {
2508
+ filename = url.pathname.split('/').pop();
2509
+ if (filename.includes('.')) {
2510
+ const mimeType = file.mimeType || core_1.Host.lookupMime(filename);
2511
+ if (mimeType) {
2512
+ file.filename = filename;
2513
+ file.mimeType = mimeType;
2514
+ this.checkFilename(file);
2515
+ }
2516
+ }
2517
+ else if (file.mimeType && filename) {
2518
+ const ext = core_1.Host.lookupMime(file.mimeType, true);
2519
+ if (ext) {
2520
+ filename += '.' + ext;
2521
+ file.filename = filename;
2522
+ this.checkFilename(file);
2523
+ }
2524
+ }
2525
+ }
1779
2526
  }
1780
2527
  file.fetchType = type;
1781
2528
  if (file.document) {
1782
2529
  for (const { instance } of this.Document) {
1783
- if (this.hasDocument(instance, file.document)) {
1784
- instance.setLocalUri?.(file, replace);
2530
+ if (instance.setLocalUri && this.hasDocument(instance, file.document)) {
2531
+ instance.setLocalUri(file, replace);
1785
2532
  }
1786
2533
  }
1787
2534
  }
@@ -1869,7 +2616,7 @@ class FileManager extends core_1.Host {
1869
2616
  return this.getTempDir({ pathname: url.hostname + '_' + (url.port || (url.protocol === 'https:' ? '443' : '80')), moduleDir: true, createDir });
1870
2617
  }
1871
2618
  setAssetContent(file, content, options) {
1872
- let trailing = (0, util_2.concatString)(file.trailingContent);
2619
+ let trailing = (0, util_1.concatString)(file.trailingContent);
1873
2620
  if (file.document) {
1874
2621
  for (const { instance } of this.Document) {
1875
2622
  if (instance.resolveUri && this.hasDocument(instance, file.document)) {
@@ -1912,8 +2659,8 @@ class FileManager extends core_1.Host {
1912
2659
  return content;
1913
2660
  }
1914
2661
  let replacing, newline;
1915
- const getSeparator = (value) => newline || (newline = (0, util_2.getNewline)(value));
1916
- if (content && (replacing = this.contentToReplace.get(localUri)) && replacing.length) {
2662
+ const getSeparator = (value) => newline || (newline = (0, util_1.getNewline)(value));
2663
+ if (content && (replacing = this.contentToReplace.get(localUri)) && replacing.length > 0) {
1917
2664
  for (let i = 0, value, match; i < replacing.length; ++i) {
1918
2665
  if ((0, types_1.isString)(value = appending[i])) {
1919
2666
  if (replacing[i] && (match = new RegExp(replacing[i], 'i').exec(content))) {
@@ -1944,7 +2691,7 @@ class FileManager extends core_1.Host {
1944
2691
  const localUri = file.localUri;
1945
2692
  if (buffer && localUri) {
1946
2693
  try {
1947
- this.writeFile(localUri, buffer, { ...options, throwsPermission: true });
2694
+ void this.writeFile(localUri, buffer, { ...options, throwsPermission: true });
1948
2695
  return file.buffer = buffer;
1949
2696
  }
1950
2697
  catch (err) {
@@ -2079,8 +2826,10 @@ class FileManager extends core_1.Host {
2079
2826
  tasks.push(instance.tryFile(file.buffer || localUri, output, options).then(() => {
2080
2827
  const outFile = options.outFile;
2081
2828
  if (outFile) {
2082
- if (condition?.includes('%') && (0, util_1.getSize)(outFile) >= (0, util_1.getSize)(localUri)) {
2083
- queueMicrotask(() => this.deleteFile(outFile));
2829
+ if (condition?.includes('%') && (0, util_2.getSize)(outFile) >= (0, util_2.getSize)(localUri)) {
2830
+ queueMicrotask(() => {
2831
+ this.deleteFile(outFile);
2832
+ });
2084
2833
  }
2085
2834
  else {
2086
2835
  this.add(outFile, file, types_1.FILE_TYPE.COMPRESSED);
@@ -2097,7 +2846,7 @@ class FileManager extends core_1.Host {
2097
2846
  }
2098
2847
  }
2099
2848
  }
2100
- if (tasks.length) {
2849
+ if (tasks.length > 0) {
2101
2850
  return Promise.all(tasks);
2102
2851
  }
2103
2852
  }
@@ -2109,7 +2858,7 @@ class FileManager extends core_1.Host {
2109
2858
  if (!this.aborted) {
2110
2859
  if (!override) {
2111
2860
  const processTask = this[kScheduler];
2112
- if (processTask.queue.length) {
2861
+ if (processTask.queue.length > 0) {
2113
2862
  processTask.transform.push([data, parent]);
2114
2863
  return false;
2115
2864
  }
@@ -2120,7 +2869,6 @@ class FileManager extends core_1.Host {
2120
2869
  file.mimeType = mimeType;
2121
2870
  data.mimeType = mimeType;
2122
2871
  }
2123
- const errorAsset = (instance, err, type = 4) => rejectModule.call(instance, err, type, path.basename(localUri));
2124
2872
  if (file.tasks) {
2125
2873
  const taskName = [];
2126
2874
  let handler;
@@ -2132,12 +2880,16 @@ class FileManager extends core_1.Host {
2132
2880
  if (this.openThread(instance, data, this.getProcessTimeout(handler))) {
2133
2881
  instance.using(data)
2134
2882
  .finally(() => this.closeThread(instance, data))
2135
- .catch((err) => errorAsset(instance, err));
2883
+ .catch((err) => {
2884
+ errorAsset(instance, err, localUri);
2885
+ });
2136
2886
  }
2137
2887
  }
2138
2888
  else if (!this.aborted) {
2139
2889
  this.addProcessTimeout(instance, file, this.getProcessTimeout(handler));
2140
- await instance.using(data).catch((err) => errorAsset(instance, err));
2890
+ await instance.using(data).catch((err) => {
2891
+ errorAsset(instance, err, localUri);
2892
+ });
2141
2893
  }
2142
2894
  taskName.push(moduleName);
2143
2895
  }
@@ -2155,12 +2907,16 @@ class FileManager extends core_1.Host {
2155
2907
  if (this.openThread(instance, data, this.getProcessTimeout(handler))) {
2156
2908
  instance.using(data, command)
2157
2909
  .finally(() => this.closeThread(instance, data))
2158
- .catch((err) => errorAsset(instance, err, 2048));
2910
+ .catch((err) => {
2911
+ errorAsset(instance, err, localUri, 2048);
2912
+ });
2159
2913
  }
2160
2914
  }
2161
2915
  else if (!this.aborted) {
2162
2916
  this.addProcessTimeout(instance, file, this.getProcessTimeout(handler));
2163
- await instance.using(data, command).catch((err) => errorAsset(instance, err, 2048));
2917
+ await instance.using(data, command).catch((err) => {
2918
+ errorAsset(instance, err, localUri, 2048);
2919
+ });
2164
2920
  }
2165
2921
  }
2166
2922
  }
@@ -2175,12 +2931,16 @@ class FileManager extends core_1.Host {
2175
2931
  if (this.openThread(instance, data, this.getProcessTimeout(handler))) {
2176
2932
  instance.using(data)
2177
2933
  .finally(() => this.closeThread(instance, data))
2178
- .catch((err) => errorAsset(instance, err));
2934
+ .catch((err) => {
2935
+ errorAsset(instance, err, localUri);
2936
+ });
2179
2937
  }
2180
2938
  }
2181
2939
  else if (!this.aborted) {
2182
2940
  this.addProcessTimeout(instance, file, this.getProcessTimeout(handler));
2183
- await instance.using(data).catch((err) => errorAsset(instance, err));
2941
+ await instance.using(data).catch((err) => {
2942
+ errorAsset(instance, err, localUri);
2943
+ });
2184
2944
  }
2185
2945
  }
2186
2946
  }
@@ -2227,7 +2987,7 @@ class FileManager extends core_1.Host {
2227
2987
  if (index !== -1) {
2228
2988
  this.processing.splice(index, 1);
2229
2989
  }
2230
- data.queuedTasks.forEach(task => {
2990
+ for (const task of data.queuedTasks) {
2231
2991
  try {
2232
2992
  task();
2233
2993
  }
@@ -2235,7 +2995,7 @@ class FileManager extends core_1.Host {
2235
2995
  this.writeFail(["Unable to perform task", path.basename(this.getLocalUri(data))], err);
2236
2996
  }
2237
2997
  this.removeAsyncTask();
2238
- });
2998
+ }
2239
2999
  this.performFinalize();
2240
3000
  return true;
2241
3001
  }
@@ -2284,7 +3044,7 @@ class FileManager extends core_1.Host {
2284
3044
  result = value;
2285
3045
  }
2286
3046
  else if (typeof value === 'string') {
2287
- if ((result = (0, util_1.byteLength)(value, encoding)) === 0) {
3047
+ if ((result = (0, util_2.byteLength)(value, encoding)) === 0) {
2288
3048
  return 0;
2289
3049
  }
2290
3050
  }
@@ -2347,18 +3107,21 @@ class FileManager extends core_1.Host {
2347
3107
  return callback;
2348
3108
  };
2349
3109
  if (this.aborted) {
3110
+ this.clearStorage();
2350
3111
  const pending = this._pendingResult;
2351
3112
  if (pending) {
2352
- queueMicrotask(() => abortedHost.call(this));
3113
+ queueMicrotask(() => {
3114
+ abortedHost(this);
3115
+ });
2353
3116
  this._pendingResult = null;
2354
3117
  return pending;
2355
3118
  }
2356
3119
  return new Promise(resolve => {
2357
3120
  this.on('end', listener(resolve));
2358
3121
  queueMicrotask(() => {
2359
- if (!abortedHost.call(this)) {
3122
+ if (!abortedHost(this)) {
2360
3123
  this.restarting = false;
2361
- this.emit('end', [], collectErrors.call(this), this.collectLog());
3124
+ this.emit('end', [], collectErrors(this), this.collectLog());
2362
3125
  this.done = true;
2363
3126
  }
2364
3127
  });
@@ -2378,7 +3141,7 @@ class FileManager extends core_1.Host {
2378
3141
  }
2379
3142
  this.finalizeState = 0;
2380
3143
  case 2:
2381
- resetAssets.call(this);
3144
+ resetAssets(this);
2382
3145
  break;
2383
3146
  }
2384
3147
  return this._pendingResult || (this._pendingResult = new Promise((resolve, reject) => {
@@ -2392,9 +3155,10 @@ class FileManager extends core_1.Host {
2392
3155
  }
2393
3156
  }));
2394
3157
  }
2395
- processAssets(emptyDir, targeted) {
3158
+ processAssets(emptyDir = false, targeted) {
3159
+ var _p;
2396
3160
  if (this.aborted) {
2397
- abortedHost.call(this);
3161
+ abortedHost(this);
2398
3162
  return;
2399
3163
  }
2400
3164
  if (this.finalizeState === 5) {
@@ -2402,561 +3166,127 @@ class FileManager extends core_1.Host {
2402
3166
  }
2403
3167
  else if (this._pendingResult) {
2404
3168
  return;
2405
- }
2406
- if (!this.canWrite(this.baseDirectory, { ownPermissionOnly: true })) {
2407
- this.writeFail("Unsupported access", new Error(this.baseDirectory), 8192);
2408
- this.cleared = true;
2409
- if (this.queued) {
2410
- this.joinQueue({ reject: true });
2411
- }
2412
- return;
2413
- }
2414
- switch (this.finalizeState) {
2415
- case 0:
2416
- if (this.delayed === 0 && !this.cleared) {
2417
- break;
2418
- }
2419
- case 1:
2420
- case 3:
2421
- case 4:
2422
- return;
2423
- case 2:
2424
- resetAssets.call(this);
2425
- break;
2426
- }
2427
- if (this.queued) {
2428
- const length = arguments.length;
2429
- const args = new Array(length);
2430
- for (let i = 0; i < length; ++i) {
2431
- args[i] = arguments[i];
2432
- }
2433
- if (this.joinQueue({ args })) {
2434
- this.finalizeState = 4;
2435
- return;
2436
- }
2437
- }
2438
- if (targeted) {
2439
- this.using(true, ...targeted);
2440
- }
2441
- this.clearProcessTimeout();
2442
- this[KTimerMain] = setInterval(() => {
2443
- const { processing, processTimeout, finalizeState } = this;
2444
- if (finalizeState === 4) {
2445
- return;
2446
- }
2447
- const currentTime = Date.now();
2448
- let aborted;
2449
- for (let i = 0; i < processing.length; ++i) {
2450
- const data = processing[i];
2451
- const file = data.file;
2452
- const processModule = file.processModule;
2453
- let expired = processTimeout > 0 && currentTime - data.startTime >= processTimeout, moduleName;
2454
- if (processModule && !expired) {
2455
- for (const name in processModule) {
2456
- const { startTime, timeout } = processModule[name];
2457
- if (timeout > 0 && currentTime - startTime >= timeout) {
2458
- moduleName = name;
2459
- expired = true;
2460
- break;
2461
- }
2462
- }
2463
- }
2464
- if (expired || data.aborted) {
2465
- let threadCount = data.threadCount + data.queuedTasks.length;
2466
- while (threadCount-- > 0) {
2467
- this.removeAsyncTask();
2468
- }
2469
- file.invalid = true;
2470
- const localUri = file.localUri;
2471
- if (expired) {
2472
- data.abort(new Error("Timeout was exceeded"));
2473
- if (localUri) {
2474
- this.deleteFile(localUri, { id: file.id, emptyDir: true, all: true });
2475
- }
2476
- }
2477
- (moduleName && this.find(moduleName) || this).formatFail(16384, "FAIL!", ["Unable to process file", moduleName || 'main'], (0, types_1.errorValue)(expired ? "Timeout was exceeded" : "Aborted", localUri), { queue: false, startTime: data.startTime });
2478
- processing.splice(i--, 1);
2479
- aborted = true;
2480
- }
2481
- }
2482
- if (this.processing.length === 0 && this.aborted) {
2483
- this.performFinalize(true);
2484
- }
2485
- else if (aborted) {
2486
- this.performFinalize();
2487
- }
2488
- }, types_1.THRESHOLD.FILEMANAGER_INTERVAL);
2489
- const { assets, cacheToDisk, cacheToMemory, fetchedAssets, Watch: watch } = this;
2490
- const downloadable = new Map();
2491
- const completed = Object.create(null);
2492
- const processing = Object.create(null);
2493
- const downloading = Object.create(null);
2494
- const appending = Object.create(null);
2495
- const bundling = Object.create(null);
2496
- const originCount = Object.create(null);
2497
- const emptied = [this.baseDirectory];
2498
- const staging = this[kIncremental] === "staging";
2499
- const incremental = this.config.incremental;
2500
- const isCacheable = (file) => file.initialValue?.cacheable !== false;
2501
- const hasIncremental = (value) => value === "etag" || value === "exists";
2502
- let cacheable = false, cacheOpen = false, cacheEtag = false;
2503
- if (!staging) {
2504
- cacheable = this[kRecursionLimit] === RECURSION_LIMIT;
2505
- if (cacheable) {
2506
- if (cacheOpen = hasIncremental(incremental)) {
2507
- this[kIncremental] = incremental;
2508
- }
2509
- cacheEtag = incremental === "etag";
2510
- }
2511
- else {
2512
- this[kIncremental] = "none";
2513
- }
2514
- }
2515
- const targeting = this._usingObjects.size > 0;
2516
- const hasEtag = (file) => {
2517
- if (!cacheable || !(0, types_1.existsFlag)(file.flags)) {
2518
- return false;
2519
- }
2520
- switch (file.incremental) {
2521
- case false:
2522
- case "none":
2523
- case "exists":
2524
- case "staging":
2525
- return false;
2526
- case "etag":
2527
- return true;
2528
- default:
2529
- return cacheEtag;
2530
- }
2531
- };
2532
- const applyHeaders = (file, headers, lastModified, mainEtag) => {
2533
- let contentLength = headers['content-length'];
2534
- if ((contentLength = parseInt(contentLength)) > 0) {
2535
- file.contentLength = contentLength;
2536
- }
2537
- else {
2538
- contentLength = 0;
2539
- }
2540
- const etag = headers.etag;
2541
- if (etag) {
2542
- if (mainEtag) {
2543
- CACHE_ETAG[file.uri] = etag;
2544
- }
2545
- return file.etag = etag;
2546
- }
2547
- if (lastModified && watch) {
2548
- return file.lastModified = headers['last-modified'];
2549
- }
2550
- };
2551
- const checkQueue = (file, localUri, pathname, content) => {
2552
- var _o;
2553
- if (!createFolder(file, pathname)) {
2554
- return true;
2555
- }
2556
- const { bundleId, bundleIndex = -1 } = file;
2557
- if (!(0, types_1.isEmpty)(bundleId) && bundleIndex >= 0) {
2558
- const items = appending[localUri] || (appending[localUri] = []);
2559
- bundling[_o = file.uri] || (bundling[_o] = []);
2560
- if (bundleIndex > 0) {
2561
- items[bundleIndex - 1] = file;
2562
- let url, parent;
2563
- if (file.fetchType === 1 && (cacheToDisk.has(url = file.url) || cacheToMemory.has(url)) && (parent = assets.find(item => item.bundleIndex === 0 && item.bundleId === bundleId))) {
2564
- (parent.bundleQueue || (parent.bundleQueue = [])).push(new Promise(resolve => {
2565
- this.Request.open(url, { method: 'HEAD', httpVersion: 1 })
2566
- .on('response', res => {
2567
- if (res.statusCode < 300) {
2568
- applyHeaders(file, res.headers);
2569
- }
2570
- resolve(file);
2571
- })
2572
- .on('error', () => resolve(file))
2573
- .on('timeout', () => resolve(file));
2574
- }));
2575
- }
2576
- return true;
2577
- }
2578
- }
2579
- else if (!content && file.filename) {
2580
- const previous = completed[localUri];
2581
- if (previous) {
2582
- if (file.uri === previous.uri) {
2583
- file.etag = previous.etag;
2584
- file.lastModified = previous.lastModified;
2585
- }
2586
- this.transformAsset(new FileThread(this, file, 1));
2587
- return true;
2588
- }
2589
- const queue = processing[localUri];
2590
- if (queue) {
2591
- queue.push(file);
2592
- return true;
2593
- }
2594
- processing[localUri] = [file];
2595
- }
2596
- return false;
2597
- };
2598
- const copyDownload = (file, queued) => {
2599
- const uriMap = new Map();
2600
- for (const item of queued) {
2601
- const destUri = item.localUri;
2602
- let items = uriMap.get(destUri);
2603
- if (!items) {
2604
- const pathname = path.dirname(destUri);
2605
- if (!core_1.Host.createDir(pathname)) {
2606
- item.invalid = true;
2607
- continue;
2608
- }
2609
- uriMap.set(destUri, items = []);
2610
- }
2611
- item.etag = file.etag;
2612
- item.lastModified = file.lastModified;
2613
- items.push(item);
2614
- }
2615
- const buffer = file.sourceUTF8 || file.buffer;
2616
- for (const [destUri, items] of uriMap) {
2617
- try {
2618
- if (buffer) {
2619
- fs.writeFileSync(destUri, buffer);
2620
- }
2621
- else {
2622
- fs.copyFileSync(file.localUri, destUri);
2623
- }
2624
- for (const queue of items) {
2625
- this.performAsyncTask();
2626
- this.transformAsset(new FileThread(this, queue, 1));
2627
- }
2628
- }
2629
- catch (err) {
2630
- items.forEach(queue => queue.invalid = true);
2631
- this.writeFail([buffer ? "Unable to write buffer" : "Unable to copy file", path.basename(file.localUri)], err, 32);
2632
- }
2633
- }
2634
- };
2635
- const processQueue = async (file, localUri) => {
2636
- completed[localUri] = file;
2637
- if (file.bundleIndex === 0 && !(0, types_1.isEmpty)(file.bundleId)) {
2638
- this.setAssetContent(file, this.getUTF8String(file, localUri));
2639
- const bundleQueue = file.bundleQueue;
2640
- let success = true, error, checkEtag = !file.trailingContent && hasEtag(file);
2641
- if (bundleQueue) {
2642
- error = await Promise.all(bundleQueue).then(() => null).catch((err) => err);
2643
- delete file.bundleQueue;
2644
- }
2645
- const items = appending[localUri];
2646
- if (items) {
2647
- if (error) {
2648
- items.forEach(queue => queue.invalid = true);
2649
- success = false;
2650
- }
2651
- else {
2652
- const tasks = [];
2653
- for (const queue of items) {
2654
- const encoding = queue.encoding || (queue.encoding = 'utf-8');
2655
- const { uri, fetchType: type } = queue;
2656
- let tempFile;
2657
- if (checkEtag && queue.trailingContent) {
2658
- checkEtag = false;
2659
- }
2660
- const checksumValid = (buffer) => !queue.checksum || checkHash.call(this, queue.localUri || localUri, false, queue.checksum, buffer);
2661
- const verifyBundle = (value, etag, checked) => {
2662
- if (!queue.invalid) {
2663
- if (!checked && !checksumValid(value)) {
2664
- queue.invalid = true;
2665
- return;
2666
- }
2667
- if (value instanceof Buffer) {
2668
- value = value.toString(encoding);
2669
- }
2670
- const url = queue.url;
2671
- if (etag && cacheToMemory.has(url)) {
2672
- cacheToMemory.add(url, encodeURIComponent(etag), value, {
2673
- encoding,
2674
- contentLength: queue.contentLength,
2675
- toDisk: !tempFile && isCacheable(queue) ? queue.filename || queue.localUri && path.basename(queue.localUri) : ''
2676
- });
2677
- }
2678
- this.setAssetContent(queue, value, { localUri, bundleIndex: queue.bundleIndex, bundleReplace: queue.bundleReplace });
2679
- }
2680
- };
2681
- if (queue.content) {
2682
- verifyBundle(queue.content);
2683
- checkEtag = false;
2684
- }
2685
- else if (uri) {
2686
- if (type === 1 || type === 2) {
2687
- const url = queue.url;
2688
- const options = {
2689
- url,
2690
- encoding,
2691
- statusMessage: uri + ` (${queue.bundleIndex})`
2692
- };
2693
- let etag, pipeTo;
2694
- if (type === 2) {
2695
- options.socketPath = queue.socketPath;
2696
- options.httpVersion = 1;
2697
- }
2698
- else if (url) {
2699
- if (etag = queue.etag) {
2700
- const valid = incremental !== false || file.incremental === true;
2701
- const cached = valid && MEMORY.CACHE[uri];
2702
- const etagDir = encodeURIComponent(etag);
2703
- if (cached) {
2704
- if (etagDir === cached[5]) {
2705
- const source = cached[1];
2706
- if (checksumValid(source)) {
2707
- verifyBundle(typeof source === 'string' ? source : source.toString(encoding), '', true);
2708
- this.addDownload(Buffer.byteLength(source, encoding), types_1.DOWNLOAD_TYPE.CACHE);
2709
- continue;
2710
- }
2711
- }
2712
- else {
2713
- cacheToMemory.clear(uri);
2714
- }
2715
- }
2716
- if (cacheToDisk.has(url) && isCacheable(queue)) {
2717
- const baseDir = path.join(this.getCacheDir(url), etagDir);
2718
- pipeTo = path.join(baseDir, path.basename(localUri));
2719
- try {
2720
- if (valid && (0, util_1.hasSize)(pipeTo)) {
2721
- const buffer = fs.readFileSync(pipeTo, { encoding });
2722
- if (checksumValid(buffer)) {
2723
- verifyBundle(buffer, etag, true);
2724
- this.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
2725
- continue;
2726
- }
2727
- }
2728
- if (!fs.existsSync(baseDir)) {
2729
- fs.mkdirSync(baseDir);
2730
- }
2731
- tempFile = path.join(baseDir, (0, types_1.incrementUUID)());
2732
- options.pipeTo = tempFile;
2733
- }
2734
- catch {
2735
- pipeTo = undefined;
2736
- }
2737
- }
2738
- }
2739
- if ((originCount[url.origin] || 0) <= 1) {
2740
- options.httpVersion = 1;
2741
- }
2742
- options.connected = (headers) => {
2743
- etag = applyHeaders(queue, headers, true);
2744
- return true;
2745
- };
2746
- }
2747
- tasks.push(new Promise((resolve, reject) => {
2748
- this.scheduleTask(url || uri, options, (data) => {
2749
- if (data) {
2750
- verifyBundle(data, etag);
2751
- }
2752
- else {
2753
- queue.invalid = true;
2754
- }
2755
- const downloaded = bundling[uri];
2756
- if ((0, types_1.isArray)(downloaded)) {
2757
- if (data && !queue.invalid) {
2758
- if (typeof data === 'string') {
2759
- queue.sourceUTF8 = data;
2760
- }
2761
- else {
2762
- queue.buffer = data;
2763
- }
2764
- copyDownload(queue, downloaded);
2765
- }
2766
- else {
2767
- downloaded.forEach(item => item.invalid = true);
2768
- }
2769
- }
2770
- if (tempFile && (!pipeTo || core_1.Host.isPath(pipeTo) || !core_1.Host.renameFile(tempFile, pipeTo, false))) {
2771
- queueMicrotask(() => fs.unlink(tempFile, () => { }));
2772
- }
2773
- resolve();
2774
- }, (err) => {
2775
- queue.invalid = true;
2776
- if (tempFile) {
2777
- queueMicrotask(() => fs.unlink(tempFile, () => { }));
2778
- }
2779
- reject(err);
2780
- }, 1);
2781
- }));
2782
- }
2783
- else if (type) {
2784
- const mimeType = queue.mimeType || file.mimeType;
2785
- const pathname = this.getTempDir({ uuidDir: true });
2786
- if (!pathname || !mimeType) {
2787
- queue.invalid = true;
2788
- tasks.push(Promise.reject(!pathname ? new Error("Unable to create temp directory") : (0, types_1.errorValue)("MIME not found", uri)));
2789
- break;
2790
- }
2791
- tasks.push(new Promise((resolve, reject) => {
2792
- this.scheduleTask(queue.url || uri, { pathname, binOpts: queue.binOpts || file.binOpts }, (result) => {
2793
- if (result.length) {
2794
- verifyBundle(bundleTorrent.call(this, result, mimeType, encoding));
2795
- }
2796
- else {
2797
- queue.invalid = true;
2798
- }
2799
- queueMicrotask(() => core_1.Host.removeDir(pathname));
2800
- resolve();
2801
- }, (err) => {
2802
- queue.invalid = true;
2803
- queueMicrotask(() => core_1.Host.removeDir(pathname));
2804
- reject(err);
2805
- }, 4);
2806
- }));
2807
- }
2808
- else if (this.canRead(uri)) {
2809
- tasks.push(fs.promises.readFile(uri, encoding)
2810
- .then(data => {
2811
- verifyBundle(data);
2812
- this.addDownload(Buffer.byteLength(data, encoding), types_1.DOWNLOAD_TYPE.DISK);
2813
- })
2814
- .catch(() => {
2815
- queue.invalid = true;
2816
- }));
2817
- }
2818
- else {
2819
- checkEtag = false;
2820
- errorPermission(file);
2821
- }
2822
- }
2823
- }
2824
- if (tasks.length) {
2825
- success = await Promise.all(tasks)
2826
- .then(() => true)
2827
- .catch((err) => {
2828
- this.writeFail(["Unable to download file", 'bundle: ' + path.basename(localUri)], err, 1024);
2829
- return false;
2830
- });
2831
- }
2832
- else if (checkEtag && core_1.Host.isPath(localUri)) {
2833
- this.completeAsyncTask();
2834
- appending[localUri] = undefined;
2835
- return;
3169
+ }
3170
+ if (!this.canWrite(this.baseDirectory, { ownPermissionOnly: true })) {
3171
+ this.writeFail("Unsupported access", new Error(this.baseDirectory), 8192);
3172
+ this.cleared = true;
3173
+ if (this.queued) {
3174
+ this.joinQueue({ reject: true });
3175
+ }
3176
+ return;
3177
+ }
3178
+ switch (this.finalizeState) {
3179
+ case 0:
3180
+ if (this.delayed === 0 && !this.cleared) {
3181
+ break;
3182
+ }
3183
+ case 1:
3184
+ case 3:
3185
+ case 4:
3186
+ return;
3187
+ case 2:
3188
+ resetAssets(this);
3189
+ break;
3190
+ }
3191
+ if (this.queued) {
3192
+ const length = arguments.length;
3193
+ const args = new Array(length);
3194
+ for (let i = 0; i < length; ++i) {
3195
+ args[i] = arguments[i];
3196
+ }
3197
+ if (this.joinQueue({ args })) {
3198
+ this.finalizeState = 4;
3199
+ return;
3200
+ }
3201
+ }
3202
+ if (targeted) {
3203
+ this.using(true, ...targeted);
3204
+ }
3205
+ this.clearProcessTimeout();
3206
+ this[KTimerMain] = setInterval(() => {
3207
+ if (this.finalizeState === 4) {
3208
+ return;
3209
+ }
3210
+ const { processing, processTimeout } = this;
3211
+ const currentTime = Date.now();
3212
+ let aborted;
3213
+ for (let i = 0; i < processing.length; ++i) {
3214
+ const data = processing[i];
3215
+ const file = data.file;
3216
+ const processModule = file.processModule;
3217
+ let expired = processTimeout > 0 && currentTime - data.startTime >= processTimeout, moduleName;
3218
+ if (processModule && !expired) {
3219
+ for (const name in processModule) {
3220
+ const { startTime, timeout } = processModule[name];
3221
+ if (timeout > 0 && currentTime - startTime >= timeout) {
3222
+ moduleName = name;
3223
+ expired = true;
3224
+ break;
2836
3225
  }
2837
3226
  }
2838
3227
  }
2839
- if (success) {
2840
- if (!fetchedAssets.includes(file)) {
2841
- fetchedAssets.push(file);
3228
+ if (expired || data.aborted) {
3229
+ let threadCount = data.threadCount + data.queuedTasks.length;
3230
+ while (threadCount-- > 0) {
3231
+ this.removeAsyncTask();
2842
3232
  }
2843
- this.transformAsset(new FileThread(this, file, 1));
2844
- }
2845
- else {
2846
3233
  file.invalid = true;
2847
- unsetContent(file);
2848
- this.completeAsyncTask(error);
2849
- queueMicrotask(() => this.deleteFile(localUri, { emptyDir: true }));
2850
- }
2851
- appending[localUri] = undefined;
2852
- return;
2853
- }
2854
- const uri = file.uri;
2855
- const processed = processing[localUri];
2856
- const downloaded = downloading[uri];
2857
- if ((0, types_1.isArray)(downloaded)) {
2858
- copyDownload(file, downloaded);
2859
- }
2860
- if (processed) {
2861
- for (const item of processed) {
2862
- if (item !== file) {
2863
- if (item.uri === file.uri) {
2864
- item.etag = file.etag;
2865
- item.lastModified = file.lastModified;
3234
+ const localUri = file.localUri;
3235
+ if (expired) {
3236
+ data.abort(new Error("Timeout was exceeded"));
3237
+ if (localUri) {
3238
+ this.deleteFile(localUri, { id: file.id, emptyDir: true, all: true });
2866
3239
  }
2867
- this.performAsyncTask();
2868
3240
  }
2869
- this.transformAsset(new FileThread(this, item, 1));
3241
+ (moduleName && this.find(moduleName) || this).formatFail(16384, "FAIL!", ["Unable to process file", moduleName || 'main'], (0, types_1.errorValue)(expired ? "Timeout was exceeded" : "Aborted", localUri), { queue: false, startTime: data.startTime });
3242
+ processing.splice(i--, 1);
3243
+ aborted = true;
2870
3244
  }
2871
- processing[localUri] = undefined;
2872
- }
2873
- else {
2874
- this.transformAsset(new FileThread(this, file, 1));
2875
3245
  }
2876
- downloading[uri] = undefined;
2877
- };
2878
- const clearQueue = (data, attr) => {
2879
- if (attr && data[attr]) {
2880
- data[attr].forEach(item => item.invalid = true);
2881
- data[attr] = undefined;
3246
+ if (this.processing.length === 0 && this.aborted) {
3247
+ this.performFinalize(true);
2882
3248
  }
2883
- };
2884
- const errorRequest = (file, localUri, err, preceding) => {
2885
- const uri = file.uri;
2886
- clearQueue(processing, localUri);
2887
- clearQueue(downloading, uri);
2888
- clearQueue(appending, localUri);
2889
- file.invalid = true;
2890
- if (!preceding) {
2891
- this.completeAsyncTask();
3249
+ else if (aborted) {
3250
+ this.performFinalize();
2892
3251
  }
2893
- this.writeFail(["Unable to download file", uri], err, err instanceof Error && err.message.startsWith("Timeout was exceeded") ? 16384 : 1024);
2894
- };
2895
- const errorPermission = (file) => {
2896
- this.writeFail(["Unable to read file", file.uri], (0, types_1.errorValue)("Operation not permitted", file.uri || "Unknown"), 8192);
2897
- file.invalid = true;
2898
- };
2899
- const createFolder = (file, pathname) => {
2900
- if (!emptied.includes(pathname)) {
2901
- if (emptyDir && core_1.Host.removeDir(pathname, true)) {
2902
- emptied.push(pathname);
2903
- }
2904
- else if (core_1.Host.createDir(pathname)) {
2905
- emptied.push(pathname);
2906
- }
2907
- else {
2908
- file.invalid = true;
2909
- this.writeFail("Unable to create directory", (0, types_1.errorValue)("Path not found", pathname));
2910
- return false;
3252
+ }, types_1.THRESHOLD.FILEMANAGER_INTERVAL);
3253
+ const { assets, cacheToDisk, cacheToMemory, fetchedAssets } = this;
3254
+ const downloadable = new Map();
3255
+ const staging = this[kIncremental] === "staging";
3256
+ const incremental = this.config.incremental;
3257
+ const checkDest = (src, localUri) => staging || !(0, util_2.hasSameStat)(src, localUri);
3258
+ let cacheable = false, cacheOpen = false, cacheEtag = false;
3259
+ if (!staging) {
3260
+ cacheable = this[kRecursionLimit] === RECURSION_LIMIT;
3261
+ if (cacheable) {
3262
+ if (cacheOpen = hasIncremental(incremental)) {
3263
+ this[kIncremental] = incremental;
2911
3264
  }
2912
- }
2913
- return true;
2914
- };
2915
- const fileReceived = (item, localUri, err, fetched, binary, checked) => {
2916
- if (err) {
2917
- item.invalid = true;
2918
- this.completeAsyncTask(err, localUri);
2919
- return;
2920
- }
2921
- if (item.checksum && !checked && !checkHash.call(this, localUri, false, item.checksum, item.buffer)) {
2922
- item.invalid = true;
2923
- this.filesToRemove.add(localUri);
2924
- this.completeAsyncTask();
2925
- this.writeFail(["Checksum did not match", path.basename(localUri)], (0, types_1.errorValue)(item.uri || localUri, "Invalid checksum"), { type: 32, queue: true });
2926
- return;
2927
- }
2928
- if (fetched) {
2929
- fetchedAssets.push(item);
2930
- }
2931
- else {
2932
- this.copiedAssets.push(item);
2933
- }
2934
- if (binary) {
2935
- this.transformAsset(new FileThread(this, item, 1));
3265
+ cacheEtag = incremental === "etag";
2936
3266
  }
2937
3267
  else {
2938
- processQueue(item, localUri);
3268
+ this[kIncremental] = "none";
2939
3269
  }
2940
- };
3270
+ }
3271
+ const targeting = this._usingObjects.size > 0;
3272
+ const groupData = new ProcessGroup();
2941
3273
  const imported = assets.filter(item => item.imported && (0, types_1.isArray)(item.imported));
2942
3274
  for (let item of assets) {
2943
3275
  if (item.invalid || (0, types_1.ignoreFlag)(item.flags)) {
2944
3276
  continue;
2945
3277
  }
2946
- let { filename, uri } = item;
2947
- if (!filename) {
2948
- if (!(uri && core_1.Host.isFile(uri, 'torrent'))) {
3278
+ let download = this.setLocalUri(item), uri = item.uri;
3279
+ if (!item.filename) {
3280
+ if (item.fetchType !== 4) {
2949
3281
  item.invalid = true;
2950
3282
  continue;
2951
3283
  }
2952
3284
  item.filename = '';
2953
3285
  }
2954
3286
  if (targeting && !this.contains(item, (other) => (0, asset_1.isEqual)(item, other))) {
2955
- this.setLocalUri(item);
2956
3287
  item.invalid = true;
2957
3288
  continue;
2958
3289
  }
2959
- let download = this.setLocalUri(item);
2960
3290
  const localUri = download.localUri;
2961
3291
  if (!localUri) {
2962
3292
  item.invalid = true;
@@ -2977,7 +3307,7 @@ class FileManager extends core_1.Host {
2977
3307
  item.incremental = undefined;
2978
3308
  }
2979
3309
  }
2980
- if (valid && filename) {
3310
+ if (valid && item.filename) {
2981
3311
  const etag = (cacheEtag && type !== "exists" || type === "etag") && !!uri;
2982
3312
  if (etag && imported.some(file => file.imported.includes(uri))) {
2983
3313
  item.incremental = "none";
@@ -2993,7 +3323,7 @@ class FileManager extends core_1.Host {
2993
3323
  }
2994
3324
  return false;
2995
3325
  };
2996
- if ((!etag || item.fetchType === 1 && ((0, types_1.isEmpty)(bundleId) || bundleIndex <= 0)) && (!watch || !item.watch || setBuffer(item))) {
3326
+ if ((!etag || item.fetchType === 1 && ((0, types_1.isEmpty)(bundleId) || bundleIndex <= 0)) && (!this.Watch || !item.watch || setBuffer(item))) {
2997
3327
  let childBundle, childDownload;
2998
3328
  if (!(0, types_1.isEmpty)(bundleId) && bundleIndex > 0) {
2999
3329
  const target = assets.find(parent => parent.bundleIndex === 0 && parent.bundleId === bundleId);
@@ -3029,7 +3359,7 @@ class FileManager extends core_1.Host {
3029
3359
  setBuffer(item);
3030
3360
  }
3031
3361
  const checksumOutput = item.checksumOutput;
3032
- if (core_1.Host.isPath(localUri) && (!checksumOutput || checkHash.call(this, localUri, true, checksumOutput))) {
3362
+ if (core_1.Host.isPath(localUri) && (!checksumOutput || checkHash(this, localUri, true, checksumOutput))) {
3033
3363
  item.flags |= 128;
3034
3364
  if (!etag || item.fetchType !== 1 || checksumOutput) {
3035
3365
  if (bundleIndex === 0 && !(0, types_1.isEmpty)(bundleId)) {
@@ -3047,14 +3377,15 @@ class FileManager extends core_1.Host {
3047
3377
  else if (cached) {
3048
3378
  try {
3049
3379
  const buffer = cached[1];
3050
- if (!item.checksum || checkHash.call(this, localUri, false, item.checksum, buffer)) {
3380
+ if (!item.checksum || checkHash(this, localUri, false, item.checksum, buffer)) {
3051
3381
  fs.writeFileSync(localUri, buffer);
3052
3382
  if (item.willChange && Buffer.isBuffer(buffer)) {
3053
3383
  item.buffer = buffer;
3054
3384
  }
3055
- if (!(checksumOutput && (0, types_1.isEmpty)(bundleId) && checkHash.call(this, localUri, true, checksumOutput, buffer))) {
3385
+ if (!(checksumOutput && (0, types_1.isEmpty)(bundleId) && checkHash(this, localUri, true, checksumOutput, buffer))) {
3056
3386
  this.performAsyncTask();
3057
- fileReceived(item, localUri, null, true, false, true);
3387
+ const target = new ProcessFile(this, item, localUri, groupData);
3388
+ target.received(null, incremental, true, false, true);
3058
3389
  }
3059
3390
  continue;
3060
3391
  }
@@ -3082,6 +3413,10 @@ class FileManager extends core_1.Host {
3082
3413
  }
3083
3414
  downloadable.set(item, download);
3084
3415
  }
3416
+ const { downloading, bundling, originCount } = groupData;
3417
+ const watching = !!this.Watch;
3418
+ const processTask = this[kScheduler];
3419
+ const diffSource = this[kDiffSource];
3085
3420
  if (downloadable.size > 1 && this.Request.httpVersion !== 1) {
3086
3421
  for (const { url } of downloadable.keys()) {
3087
3422
  if (url?.protocol === 'https:') {
@@ -3095,47 +3430,61 @@ class FileManager extends core_1.Host {
3095
3430
  break;
3096
3431
  }
3097
3432
  const { pathname, localUri } = download;
3433
+ const target = new ProcessFile(this, item, localUri, groupData);
3434
+ if (diffSource && core_1.Host.isPath(localUri, true) && diffSource[0].some(pattern => typeof pattern === 'string' ? pattern === item.mimeType || pattern === item.mimeType?.split('/')[1] : pattern(localUri))) {
3435
+ try {
3436
+ const encoding = image_1.isBinary(item.mimeType) ? 'base64' : item.encoding || 'utf-8';
3437
+ (_p = diffSource[1])[localUri] || (_p[localUri] = [fs.readFileSync(localUri, encoding), encoding]);
3438
+ }
3439
+ catch (err) {
3440
+ this.formatMessage(32, "WARN!", ["Unable to read file", path.basename(localUri)], err, { ...core_1.Host.LOG_STYLE_WARN });
3441
+ }
3442
+ }
3098
3443
  if (item.content) {
3099
- if (!checkQueue(item, localUri, pathname, true)) {
3444
+ if (!target.queued(pathname, emptyDir, true)) {
3100
3445
  const content = item.content;
3101
3446
  item.sourceUTF8 = content;
3102
3447
  this.performAsyncTask();
3103
- fs.writeFile(localUri, content, item.encoding || (item.encoding = 'utf-8'), err => fileReceived(item, localUri, err));
3448
+ fs.writeFile(localUri, content, item.encoding || (item.encoding = 'utf-8'), err => {
3449
+ target.received(err, incremental);
3450
+ });
3104
3451
  }
3105
3452
  continue;
3106
3453
  }
3107
3454
  if (item.dataView) {
3108
- if (createFolder(item, pathname)) {
3455
+ if (target.createFolder(pathname, emptyDir)) {
3109
3456
  this.performAsyncTask();
3110
3457
  const dataView = item.dataView;
3111
3458
  fs.writeFile(localUri, dataView, err => {
3112
3459
  if (!err) {
3113
3460
  item.buffer = Buffer.isBuffer(dataView) ? dataView : Buffer.from(dataView.buffer);
3114
3461
  }
3115
- fileReceived(item, localUri, err, false, true);
3462
+ target.received(err, incremental, false, true);
3116
3463
  });
3117
3464
  }
3118
3465
  continue;
3119
3466
  }
3120
3467
  if (item.base64) {
3121
- if (createFolder(item, pathname)) {
3468
+ if (target.createFolder(pathname, emptyDir)) {
3122
3469
  this.performAsyncTask();
3123
- fs.writeFile(localUri, item.base64, 'base64', err => fileReceived(item, localUri, err, false, true));
3470
+ fs.writeFile(localUri, item.base64, 'base64', err => {
3471
+ target.received(err, incremental, false, true);
3472
+ });
3124
3473
  }
3125
3474
  continue;
3126
3475
  }
3127
3476
  const uri = item.uri;
3128
3477
  if (!uri) {
3129
3478
  if (item.buffer) {
3130
- if (createFolder(item, pathname)) {
3479
+ if (target.createFolder(pathname, emptyDir)) {
3131
3480
  this.performAsyncTask();
3132
- this.scheduleTask(localUri, item.buffer, () => {
3133
- fileReceived(item, localUri, null, false, true);
3481
+ void this.scheduleTask(localUri, item.buffer, () => {
3482
+ target.received(null, incremental, false, true);
3134
3483
  }, (err) => {
3135
- fileReceived(item, localUri, err);
3484
+ target.received(err);
3136
3485
  }).then(code => {
3137
3486
  if (code === -1) {
3138
- fileReceived(item, localUri, (0, types_1.errorValue)("Not able to read buffer", path.basename(localUri)));
3487
+ target.received((0, types_1.errorValue)("Not able to read buffer", path.basename(localUri)));
3139
3488
  }
3140
3489
  });
3141
3490
  }
@@ -3144,7 +3493,6 @@ class FileManager extends core_1.Host {
3144
3493
  item.invalid = true;
3145
3494
  continue;
3146
3495
  }
3147
- const checkDest = (src) => staging || !(0, util_1.hasSameStat)(src, localUri);
3148
3496
  const type = item.fetchType || 0;
3149
3497
  const bundleMain = item.bundleIndex === 0 && !(0, types_1.isEmpty)(item.bundleId);
3150
3498
  if (type === 1 || type === 2) {
@@ -3152,15 +3500,15 @@ class FileManager extends core_1.Host {
3152
3500
  if (bundling[uri] && (0, types_1.isEmpty)(item.bundleId)) {
3153
3501
  bundling[uri].push(item);
3154
3502
  }
3155
- else if ((checkEtag = hasEtag(item)) || !checkQueue(item, localUri, pathname)) {
3156
- if (type !== 1 && !checkDest(uri)) {
3157
- fileReceived(item, localUri, null);
3503
+ else if ((checkEtag = hasEtag(item, cacheable, cacheEtag)) || !target.queued(pathname, emptyDir, false)) {
3504
+ if (type === 2 && !checkDest(uri, localUri)) {
3505
+ target.received(null, incremental);
3158
3506
  }
3159
3507
  else if (!checkEtag && downloading[uri]) {
3160
3508
  downloading[uri].push(item);
3161
3509
  }
3162
- else if (type !== 1 && !this.canRead(uri)) {
3163
- errorPermission(item);
3510
+ else if (type === 2 && !this.canRead(uri)) {
3511
+ errorPermission(this, item);
3164
3512
  }
3165
3513
  else {
3166
3514
  if (!checkEtag) {
@@ -3173,12 +3521,11 @@ class FileManager extends core_1.Host {
3173
3521
  cacheBuffer = cacheToMemory.has(url);
3174
3522
  mainEtag = (0, types_1.mainFlag)(item.flags) && (cacheEtag || item.incremental === "etag");
3175
3523
  }
3176
- const closeResponse = () => client?.destroy();
3177
3524
  const downloadUri = (request, etagDir) => {
3178
3525
  if (checkEtag) {
3179
3526
  item.flags &= ~128;
3180
3527
  }
3181
- closeResponse();
3528
+ closeResponse(client);
3182
3529
  const location = request.url.toString();
3183
3530
  request.encoding = encoding;
3184
3531
  request.pipeTo = localUri;
@@ -3187,7 +3534,7 @@ class FileManager extends core_1.Host {
3187
3534
  request.method = 'GET';
3188
3535
  request.httpVersion = (originCount[request.url.origin] || 0) <= 1 ? 1 : undefined;
3189
3536
  request.connected = headers => {
3190
- applyHeaders(item, headers, true, mainEtag);
3537
+ processHeaders(item, headers, watching, mainEtag);
3191
3538
  return item.willChange || !!etagDir && (cacheDir || !item.contentLength || cacheToMemory.within(item.contentLength)) || this.hasLog('progress');
3192
3539
  };
3193
3540
  }
@@ -3196,14 +3543,14 @@ class FileManager extends core_1.Host {
3196
3543
  request.method = undefined;
3197
3544
  request.httpVersion = 1;
3198
3545
  }
3199
- this.scheduleTask(request.url, request, (data) => {
3546
+ void this.scheduleTask(request.url, request, (data) => {
3200
3547
  if (typeof data === 'string') {
3201
3548
  item.sourceUTF8 = data;
3202
3549
  }
3203
3550
  else if (data) {
3204
3551
  item.buffer = data;
3205
3552
  }
3206
- fileReceived(item, localUri, null, type === 1);
3553
+ target.received(null, incremental, type === 1);
3207
3554
  if (etagDir) {
3208
3555
  queueMicrotask(() => {
3209
3556
  if (cacheBuffer && data) {
@@ -3215,7 +3562,7 @@ class FileManager extends core_1.Host {
3215
3562
  });
3216
3563
  }
3217
3564
  }, (err) => {
3218
- errorRequest(item, localUri, err);
3565
+ target.abort(err);
3219
3566
  }, 1);
3220
3567
  };
3221
3568
  this.performAsyncTask();
@@ -3224,13 +3571,15 @@ class FileManager extends core_1.Host {
3224
3571
  (function checkHeaders(href) {
3225
3572
  const request = this.Request;
3226
3573
  try {
3227
- const target = request.opts(href, { method: 'HEAD', httpVersion: 1 });
3228
- (client = request.open(href, target))
3574
+ ++processTask.pending;
3575
+ const opts = request.opts(href, { method: 'HEAD', httpVersion: 1 });
3576
+ (client = request.open(href, opts))
3229
3577
  .on('response', res => {
3578
+ --processTask.pending;
3230
3579
  const statusCode = res.statusCode;
3231
3580
  if (statusCode < 300) {
3232
- const etag = applyHeaders(item, res.headers, false, mainEtag);
3233
- let etagDir = '', tempDir;
3581
+ const etag = processHeaders(item, res.headers, false, mainEtag);
3582
+ let etagDir = null, tempDir;
3234
3583
  if (etag) {
3235
3584
  if (cacheDir || mainEtag) {
3236
3585
  tempDir = this.getCacheDir(href);
@@ -3242,13 +3591,13 @@ class FileManager extends core_1.Host {
3242
3591
  let buffer;
3243
3592
  if (cached) {
3244
3593
  if (etagDir === cached[5] && (!encoding || encoding === cached[2])) {
3245
- if (item.checksum && !checkHash.call(this, localUri, false, item.checksum, cached[1])) {
3594
+ if (item.checksum && !checkHash(this, localUri, false, item.checksum, cached[1])) {
3246
3595
  tempDir = undefined;
3247
3596
  }
3248
3597
  else {
3249
3598
  if (checkEtag) {
3250
3599
  this.completeAsyncTask(null, localUri);
3251
- closeResponse();
3600
+ closeResponse(client);
3252
3601
  return;
3253
3602
  }
3254
3603
  buffer = cached[1];
@@ -3262,68 +3611,56 @@ class FileManager extends core_1.Host {
3262
3611
  }
3263
3612
  }
3264
3613
  try {
3265
- const setBuffer = () => {
3266
- if (typeof buffer === 'string') {
3267
- item.sourceUTF8 = buffer;
3268
- }
3269
- else if (buffer) {
3270
- item.buffer = buffer;
3271
- }
3272
- };
3273
3614
  let pipeAs;
3274
- if (tempDir && (0, util_1.hasSize)(pipeAs = path.join(tempDir, etagDir, path.basename(localUri)))) {
3615
+ if (tempDir && (0, util_2.hasSize)(pipeAs = path.join(tempDir, etagDir, path.basename(localUri)))) {
3275
3616
  if (!checkEtag) {
3276
3617
  if (cacheBuffer && !buffer) {
3277
3618
  buffer = fs.readFileSync(pipeAs, encoding);
3278
- if (item.checksum && !checkHash.call(this, localUri, false, item.checksum, buffer)) {
3279
- downloadUri(target, etagDir);
3619
+ if (item.checksum && !checkHash(this, localUri, false, item.checksum, buffer)) {
3620
+ downloadUri(opts, etagDir);
3280
3621
  return;
3281
3622
  }
3282
3623
  if (cacheToMemory.within(item.contentLength = Buffer.byteLength(buffer, encoding))) {
3283
3624
  cacheToMemory.add(location, etagDir, buffer, { encoding, contentLength: item.contentLength, tempFile: pipeAs });
3284
3625
  }
3285
3626
  }
3286
- if (checkDest(pipeAs)) {
3287
- const writeBuffer = () => {
3288
- fs.writeFileSync(localUri, buffer);
3289
- this.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
3290
- };
3627
+ if (checkDest(pipeAs, localUri)) {
3291
3628
  if (buffer) {
3292
- writeBuffer();
3629
+ writeBufferCache(this, localUri, buffer, encoding);
3293
3630
  }
3294
3631
  else if (item.checksum) {
3295
3632
  buffer = fs.readFileSync(pipeAs, encoding);
3296
- if (!checkHash.call(this, localUri, false, item.checksum, buffer)) {
3297
- downloadUri(target, etagDir);
3633
+ if (!checkHash(this, localUri, false, item.checksum, buffer)) {
3634
+ downloadUri(opts, etagDir);
3298
3635
  return;
3299
3636
  }
3300
- writeBuffer();
3637
+ writeBufferCache(this, localUri, buffer, encoding);
3301
3638
  }
3302
3639
  else {
3303
3640
  fs.copyFileSync(pipeAs, localUri);
3304
3641
  this.addDownload(pipeAs, types_1.DOWNLOAD_TYPE.CACHE);
3305
3642
  }
3306
3643
  }
3307
- if (item.willChange) {
3308
- setBuffer();
3644
+ if (item.willChange && buffer) {
3645
+ setBufferTarget(item, buffer);
3309
3646
  }
3310
- fileReceived(item, localUri, null, true, false, true);
3647
+ target.received(null, incremental, true, false, true);
3311
3648
  }
3312
3649
  else {
3313
3650
  this.completeAsyncTask(null, localUri);
3314
3651
  }
3315
- closeResponse();
3652
+ closeResponse(client);
3316
3653
  return;
3317
3654
  }
3318
3655
  if (buffer) {
3319
- setBuffer();
3656
+ setBufferTarget(item, buffer);
3320
3657
  fs.writeFileSync(localUri, buffer);
3321
3658
  this.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
3322
3659
  if (checkEtag) {
3323
3660
  item.flags &= ~128;
3324
3661
  }
3325
- fileReceived(item, localUri, null, true, false, true);
3326
- closeResponse();
3662
+ target.received(null, incremental, true, false, true);
3663
+ closeResponse(client);
3327
3664
  if (pipeAs) {
3328
3665
  fs.writeFile(pipeAs, buffer, () => { });
3329
3666
  }
@@ -3334,10 +3671,10 @@ class FileManager extends core_1.Host {
3334
3671
  }
3335
3672
  }
3336
3673
  }
3337
- downloadUri(target, etagDir);
3674
+ downloadUri(opts, etagDir);
3338
3675
  }
3339
3676
  else if (statusCode < 400) {
3340
- closeResponse();
3677
+ closeResponse(client);
3341
3678
  const location = res.headers.location;
3342
3679
  if (location && ++redirects <= HTTP_CLIENT.redirectLimit) {
3343
3680
  try {
@@ -3347,29 +3684,32 @@ class FileManager extends core_1.Host {
3347
3684
  catch {
3348
3685
  }
3349
3686
  }
3350
- errorRequest(item, localUri, (0, types_1.errorMessage)(statusCode, 'Exceeded redirect limit', url.toString()));
3687
+ target.abort((0, types_1.errorMessage)(statusCode, "Exceeded redirect limit", url.toString()));
3351
3688
  }
3352
3689
  else {
3353
- downloadUri(target, null);
3690
+ downloadUri(opts, null);
3354
3691
  }
3355
3692
  })
3356
3693
  .on('error', err => {
3694
+ --processTask.pending;
3357
3695
  if (!client.destroyed) {
3358
- if ((0, util_1.checkRetryable)(err)) {
3359
- downloadUri(target, null);
3696
+ if ((0, util_2.checkRetryable)(err)) {
3697
+ downloadUri(opts, null);
3360
3698
  }
3361
3699
  else {
3362
- errorRequest(item, localUri, err);
3700
+ target.abort(err);
3363
3701
  }
3364
3702
  }
3365
3703
  })
3366
3704
  .on('timeout', () => {
3705
+ --processTask.pending;
3367
3706
  if (!client.destroyed) {
3368
- downloadUri(target, null);
3707
+ downloadUri(opts, null);
3369
3708
  }
3370
3709
  });
3371
3710
  }
3372
3711
  catch {
3712
+ --processTask.pending;
3373
3713
  downloadUri(request.opts(href), null);
3374
3714
  }
3375
3715
  }).bind(this)(url);
@@ -3380,30 +3720,30 @@ class FileManager extends core_1.Host {
3380
3720
  }
3381
3721
  }
3382
3722
  }
3383
- else if (type) {
3723
+ else if (type === 3 || type === 4) {
3384
3724
  if (bundleMain && !item.mimeType) {
3385
- errorRequest(item, localUri, (0, types_1.errorValue)("MIME not found", uri), true);
3725
+ target.abort((0, types_1.errorValue)("MIME not found", uri), true);
3386
3726
  }
3387
- else if (!checkQueue(item, localUri, pathname)) {
3727
+ else if (!target.queued(pathname, emptyDir, false)) {
3388
3728
  if (downloading[uri]) {
3389
3729
  downloading[uri].push(item);
3390
3730
  continue;
3391
3731
  }
3392
3732
  downloading[uri] = [];
3393
3733
  this.performAsyncTask();
3394
- this.scheduleTask(item.url || uri, { pathname, binOpts: item.binOpts }, (result) => {
3734
+ void this.scheduleTask(item.url || uri, { pathname, binOpts: item.binOpts }, (result) => {
3395
3735
  if (result.length === 0) {
3396
- errorRequest(item, localUri, (0, types_1.errorValue)("No files were successfully downloaded", uri));
3736
+ target.abort((0, types_1.errorValue)("No files were successfully downloaded", uri));
3397
3737
  }
3398
3738
  else if (bundleMain) {
3399
3739
  const encoding = item.encoding || (item.encoding = 'utf-8');
3400
- fs.writeFile(localUri, bundleTorrent.call(this, result, item.mimeType, encoding), encoding, err => {
3740
+ fs.writeFile(localUri, bundleTorrent(this, result, item.mimeType, encoding), encoding, err => {
3401
3741
  if (!err) {
3402
3742
  fetchedAssets.push(item);
3403
- processQueue(item, localUri);
3743
+ void target.finalize(incremental);
3404
3744
  }
3405
3745
  else {
3406
- errorRequest(item, localUri, err);
3746
+ target.abort(err);
3407
3747
  }
3408
3748
  });
3409
3749
  }
@@ -3428,44 +3768,44 @@ class FileManager extends core_1.Host {
3428
3768
  }
3429
3769
  if (found) {
3430
3770
  fetchedAssets.push(item);
3431
- processQueue(item, localUri);
3771
+ void target.finalize(incremental);
3432
3772
  }
3433
3773
  else {
3434
3774
  item.filename = '';
3435
3775
  item.localUri = '';
3436
3776
  item.mimeType = '';
3437
- clearQueue(processing, localUri);
3777
+ clearQueue(groupData.processing, localUri);
3438
3778
  clearQueue(downloading, uri);
3439
3779
  this.completeAsyncTask();
3440
3780
  }
3441
3781
  }
3442
3782
  }, (err) => {
3443
- errorRequest(item, localUri, err);
3783
+ target.abort(err);
3444
3784
  }, 4);
3445
3785
  }
3446
3786
  }
3447
3787
  else if (!this.canRead(uri)) {
3448
- errorPermission(item);
3788
+ errorPermission(this, item);
3449
3789
  }
3450
- else if (!checkQueue(item, localUri, pathname)) {
3790
+ else if (!target.queued(pathname, emptyDir, false)) {
3451
3791
  this.performAsyncTask();
3452
- if (checkDest(uri)) {
3792
+ if (checkDest(uri, localUri)) {
3453
3793
  fs.copyFile(uri, localUri, err => {
3454
3794
  if (!err) {
3455
3795
  this.addDownload(localUri, types_1.DOWNLOAD_TYPE.DISK);
3456
3796
  }
3457
- fileReceived(item, localUri, err);
3797
+ target.received(err);
3458
3798
  });
3459
3799
  }
3460
3800
  else {
3461
- fileReceived(item, localUri, null);
3801
+ target.received(null, incremental);
3462
3802
  }
3463
3803
  }
3464
3804
  }
3465
3805
  this.cleared = true;
3466
3806
  }
3467
3807
  updateProgress(name, ...args) {
3468
- if (name === 'request' && STDOUT_CURSOR) {
3808
+ if (name === 'request' && this.hasLog('progress') && STDOUT_CURSOR) {
3469
3809
  const processTask = this[kScheduler];
3470
3810
  const status = processTask.status;
3471
3811
  const id = args[0];
@@ -3491,39 +3831,76 @@ class FileManager extends core_1.Host {
3491
3831
  else if (processTask.updated + 100 > currentTime) {
3492
3832
  return;
3493
3833
  }
3494
- const length = status.length;
3495
3834
  const logCurrent = (0, types_1.getLogCurrent)();
3496
- const formatSegment = (endTime, value) => endTime ? value : chalk.bgGray.black(value);
3497
- let redraw = processTask.logCurrent !== logCurrent;
3498
- if (redraw || length > processTask.length) {
3499
- this.pauseLog();
3835
+ const statusHeight = status.length;
3836
+ const barLength = processTask.barLength;
3837
+ const barIncrement = 100 / barLength;
3838
+ const initial = processTask.logCurrent !== logCurrent;
3839
+ let redraw = false, scrollHeight = 0, logDelayed;
3840
+ if ((logDelayed = core_1.Host.getLogDelayed()) && logDelayed.length > 0) {
3841
+ logDelayed = logDelayed.filter(item => typeof item[4].progressBar !== 'boolean');
3842
+ scrollHeight = Math.min(logDelayed.length, LOGGER.PROGRESS_SCROLLBUFFER);
3843
+ }
3844
+ else {
3845
+ logDelayed = null;
3846
+ }
3847
+ if (initial || statusHeight > processTask.statusHeight || scrollHeight > processTask.scrollHeight) {
3848
+ if (this.logState !== 0) {
3849
+ this.pauseLog('progress');
3850
+ }
3851
+ if (!initial) {
3852
+ PROCESS_STDOUT.write('\n'.repeat(statusHeight + scrollHeight - processTask.statusHeight - processTask.scrollHeight));
3853
+ }
3854
+ processTask.statusHeight = statusHeight;
3855
+ processTask.scrollHeight = scrollHeight;
3500
3856
  processTask.logCurrent = logCurrent;
3501
- PROCESS_STDOUT.write('\n'.repeat(redraw ? length : length - processTask.length));
3502
- processTask.length = length;
3503
3857
  redraw = true;
3504
3858
  }
3505
- PROCESS_STDOUT.moveCursor(0, -length);
3859
+ if (initial) {
3860
+ processTask.section(true);
3861
+ }
3862
+ else {
3863
+ PROCESS_STDOUT.moveCursor(0, -(statusHeight + 1 + 1 + (scrollHeight > 0 ? 1 + scrollHeight : 0)));
3864
+ }
3506
3865
  processTask.updated = currentTime;
3507
- const titleWidth = processTask.titleWidth;
3508
- let finished = true;
3509
- for (let i = 0; i < length; ++i) {
3510
- const item = status[i];
3511
- const { receivedBytes, endTime } = item;
3512
- if (!endTime) {
3513
- finished = false;
3514
- }
3515
- if (!redraw && item.previousBytes === receivedBytes) {
3516
- PROCESS_STDOUT.moveCursor(0, 1);
3517
- continue;
3866
+ const summary = new TaskStatus(-1, chalk.bold(`${statusHeight} requests`.padEnd(LOGGER.VALUE_WIDTH)));
3867
+ const spacer = LOGGER.PROGRESS_SPACER;
3868
+ let finished = processTask.pending === 0;
3869
+ for (let i = 0; i <= statusHeight; ++i) {
3870
+ const item = i === statusHeight ? summary : status[i];
3871
+ let { receivedBytes, endTime } = item;
3872
+ if (i === statusHeight) {
3873
+ processTask.section(redraw);
3874
+ if (finished) {
3875
+ endTime = 1;
3876
+ }
3518
3877
  }
3519
- if (item.output) {
3520
- PROCESS_STDOUT.clearLine(0);
3521
- PROCESS_STDOUT.write(item.output);
3522
- continue;
3878
+ else {
3879
+ if (!endTime) {
3880
+ finished = false;
3881
+ }
3882
+ if (i === 0) {
3883
+ summary.dataTime = item.dataTime;
3884
+ summary.startTime = item.startTime;
3885
+ }
3886
+ summary.receivedBytes += receivedBytes;
3887
+ summary.totalBytes += item.totalBytes;
3888
+ if (item.previousBytes === receivedBytes) {
3889
+ if (!redraw) {
3890
+ PROCESS_STDOUT.moveCursor(0, 1);
3891
+ continue;
3892
+ }
3893
+ const value = item.finished || item.current;
3894
+ if (value) {
3895
+ PROCESS_STDOUT.clearLine(0);
3896
+ PROCESS_STDOUT.write(value);
3897
+ continue;
3898
+ }
3899
+ }
3900
+ item.previousBytes = receivedBytes;
3523
3901
  }
3524
3902
  let percent = 0, bars = 0;
3525
- item.previousBytes = receivedBytes;
3526
- if (endTime) {
3903
+ if (endTime > 0) {
3527
3904
  if (receivedBytes === item.totalBytes) {
3528
3905
  bars = -1;
3529
3906
  }
@@ -3531,34 +3908,126 @@ class FileManager extends core_1.Host {
3531
3908
  else if (receivedBytes > item.totalBytes) {
3532
3909
  item.totalBytes = receivedBytes;
3533
3910
  percent = 99;
3534
- bars = 24;
3911
+ bars = barIncrement > 0 ? barLength - 1 : NaN;
3535
3912
  }
3536
3913
  else {
3537
3914
  percent = (receivedBytes / item.totalBytes) * 100;
3538
- bars = Math.trunc(percent / 4);
3915
+ bars = barIncrement > 0 ? Math.round(percent / barIncrement) : NaN;
3539
3916
  }
3540
3917
  const diffTime = currentTime - item.startTime;
3541
- const time = formatSegment(endTime, formatMinutes(diffTime).padStart(titleWidth));
3542
- const size = formatSegment(endTime, (0, types_1.formatSize)(receivedBytes, { unit: receivedBytes < 1048576 ? 'KB' : receivedBytes < 1073741824 ? 'MB' : 'GB', unitSeparator: ' ', fixedDecimals: true, decimalPlaces: 2 }).padStart(9));
3543
- const speed = formatSegment(endTime, (0, util_1.getTransferRate)(receivedBytes, item.dataTime ? (0, types_1.convertTime)(process.hrtime(item.dataTime), false) * 1000 : diffTime, ' ').padStart(10));
3544
- let output = time + ` ${chalk.blackBright(':')} ${endTime && bars !== -1 ? chalk.bgBlack.gray(item.url) : item.url}| ${size} |`;
3545
- if (!isNaN(percent)) {
3546
- output += speed + ` |${bars === -1 ? chalk.bgBlack.green.bold('>'.repeat(25)) : (bars > 0 ? chalk.yellow('>'.repeat(bars)) : '') + (25 - bars > 0 ? chalk.gray((endTime ? '#' : '-').repeat(25 - bars)) : '')}| ` + (endTime ? bars === -1 ? chalk.bold('100%') : chalk.red('ERR!') : Math.trunc(percent).toString().padStart(3) + '%');
3918
+ const unit = receivedBytes < 1048576 ? 'KB' : receivedBytes < 1073741824 ? 'MB' : 'GB';
3919
+ const [time, size, speed] = formatSegment(endTime > 0 ? bars === 0 ? -1 : endTime : 0, formatMinutes(diffTime).padStart(LOGGER.TITLE_WIDTH), (0, types_1.formatSize)(receivedBytes, { unit, unitSeparator: ' ', fixedDecimals: true, decimalPlaces: unit === 'KB' ? 0 : unit === 'MB' ? 1 : 2 }).padStart(8), (0, util_2.getTransferRate)(receivedBytes, item.dataTime ? (0, types_1.convertTime)(process.hrtime(item.dataTime), false) * 1000 : diffTime, ' ').padStart(10));
3920
+ let output = time + ` ${chalk.blackBright(LOGGER.TITLE_SEP)} ` + (endTime > 0 && bars === 0 ? chalk.grey(item.url) : item.url) + spacer;
3921
+ if (barLength === 1) {
3922
+ output += ` ${endTime > 0 ? bars === 0 ? chalk.red('ERR!') : LOGGER.PROGRESS_COMPLETE : formatPercent(percent)} ` + spacer;
3923
+ }
3924
+ else if (!isNaN(barLength)) {
3925
+ output += ` ${size} ` + spacer;
3926
+ if (endTime > 0) {
3927
+ output += ` ${speed} ${spacer} ${bars === 0 ? chalk.red('ERR!') : LOGGER.PROGRESS_COMPLETE} ` + spacer;
3928
+ }
3929
+ else if (!isNaN(percent)) {
3930
+ output += ` ${speed} ${spacer} ${formatPercent(percent)} ` + spacer;
3931
+ if (bars >= 0) {
3932
+ output += writeProgressBar(bars, barLength);
3933
+ }
3934
+ }
3547
3935
  }
3548
3936
  output += '\n';
3937
+ if (!LOGGER.PROGRESS_USECOLOR) {
3938
+ output = stripansi(output);
3939
+ }
3549
3940
  PROCESS_STDOUT.clearLine(0);
3550
3941
  PROCESS_STDOUT.write(output);
3551
- if (endTime) {
3552
- item.output = output;
3942
+ if (endTime > 0) {
3943
+ item.finished = output;
3944
+ }
3945
+ else {
3946
+ item.current = output;
3947
+ }
3948
+ }
3949
+ const cleared = finished && this.cleared;
3950
+ if (logDelayed) {
3951
+ processTask.section(redraw);
3952
+ const { PROGRESS_COLOR: color, PROGRESS_BGCOLOR: bgColor, PROGRESS_USECOLOR: useColor, PROGRESS_TEXTWRAP: messageTextWrap } = LOGGER;
3953
+ const scroll = processTask.scroll;
3954
+ let start = 0, end = 0, output, last;
3955
+ if (cleared) {
3956
+ logDelayed = this._logDelayed;
3957
+ end = Math.min(logDelayed.length, scrollHeight);
3958
+ }
3959
+ else {
3960
+ [start, end] = [Math.max(0, logDelayed.length - scrollHeight), logDelayed.length];
3961
+ }
3962
+ for (let i = 0; start < end; ++i, ++start) {
3963
+ let item = logDelayed[start];
3964
+ if (cleared) {
3965
+ last = item;
3966
+ }
3967
+ else {
3968
+ if (!redraw && scroll[i] === item) {
3969
+ PROCESS_STDOUT.moveCursor(0, 1);
3970
+ continue;
3971
+ }
3972
+ const options = { ...item[4], messageTextWrap, broadcastId: '' };
3973
+ if (!useColor) {
3974
+ options.useColor = false;
3975
+ }
3976
+ else if (color || bgColor) {
3977
+ options.useColor = true;
3978
+ if (color) {
3979
+ options.titleColor = color;
3980
+ options.valueColor = color;
3981
+ options.hintColor = color;
3982
+ options.messageColor = color;
3983
+ }
3984
+ if (bgColor) {
3985
+ options.titleBgColor = bgColor;
3986
+ options.valueBgColor = bgColor;
3987
+ options.hintBgColor = bgColor;
3988
+ options.messageBgColor = bgColor;
3989
+ }
3990
+ }
3991
+ scroll[i] = item;
3992
+ item = item.slice(0);
3993
+ item[4] = options;
3994
+ }
3995
+ PROCESS_STDOUT.clearLine(0);
3996
+ core_1.Host.formatMessage(...item);
3997
+ output = true;
3998
+ }
3999
+ if (last) {
4000
+ if (end < scrollHeight) {
4001
+ for (let i = end; i < scrollHeight; ++i) {
4002
+ PROCESS_STDOUT.clearLine(0);
4003
+ PROCESS_STDOUT.moveCursor(0, 1);
4004
+ }
4005
+ PROCESS_STDOUT.moveCursor(0, end - scrollHeight);
4006
+ }
4007
+ const index = logDelayed.findIndex(item => item === last);
4008
+ if (index !== -1) {
4009
+ logDelayed.splice(0, index + 1);
4010
+ }
4011
+ }
4012
+ else if (output) {
4013
+ processTask.logCurrent = (0, types_1.getLogCurrent)();
3553
4014
  }
3554
4015
  }
3555
- if (finished) {
3556
- this.resumeLog();
4016
+ if (cleared) {
4017
+ this.resumeLog('progress');
3557
4018
  processTask.reset();
3558
4019
  }
4020
+ else if (initial) {
4021
+ if (processTask.screenReset) {
4022
+ processTask.screenReset = false;
4023
+ }
4024
+ else {
4025
+ PROCESS_STDOUT.write('\n');
4026
+ }
4027
+ }
3559
4028
  }
3560
4029
  }
3561
- scheduleTask(url, data, thenCallback, catchCallback, priority = 0) {
4030
+ async scheduleTask(url, data, thenCallback, catchCallback, priority = 0) {
3562
4031
  if (typeof thenCallback === 'number') {
3563
4032
  priority = thenCallback;
3564
4033
  thenCallback = undefined;
@@ -3569,25 +4038,6 @@ class FileManager extends core_1.Host {
3569
4038
  scheduler.queue.sort((a, b) => b[4] - a[4]);
3570
4039
  return Promise.resolve(0);
3571
4040
  }
3572
- const nextTask = (pid) => {
3573
- if (pid > 0) {
3574
- const found = scheduler.status.find(item => item.id === pid);
3575
- if (found) {
3576
- found.endTime || (found.endTime = Date.now());
3577
- }
3578
- }
3579
- --scheduler.count;
3580
- if (scheduler.queue.length) {
3581
- const params = scheduler.queue.pop();
3582
- this.scheduleTask(...params);
3583
- }
3584
- else if (scheduler.transform.length) {
3585
- do {
3586
- const args = scheduler.transform.shift();
3587
- this.transformAsset(args[0], args[1], true);
3588
- } while (scheduler.transform.length && scheduler.queue.length === 0);
3589
- }
3590
- };
3591
4041
  let id = 0, target;
3592
4042
  if ((0, types_1.isPlainObject)(data)) {
3593
4043
  ++scheduler.count;
@@ -3595,7 +4045,7 @@ class FileManager extends core_1.Host {
3595
4045
  target = this.fetchFiles(url, data);
3596
4046
  }
3597
4047
  else {
3598
- if (this.hasLog('progress') && STDOUT_CURSOR) {
4048
+ if (STDOUT_CURSOR && this.hasLog('progress')) {
3599
4049
  id = ++scheduler.id;
3600
4050
  data.progressId = id;
3601
4051
  }
@@ -3608,7 +4058,7 @@ class FileManager extends core_1.Host {
3608
4058
  }
3609
4059
  else {
3610
4060
  if (data instanceof URL && data.protocol === 'file:') {
3611
- data = core_1.Host.resolveFile(data);
4061
+ data = (0, url_1.fileURLToPath)(data);
3612
4062
  }
3613
4063
  if ((0, types_1.isString)(data) && core_1.Host.isPath(data, true) && this.canRead(data)) {
3614
4064
  data = fs.createReadStream(data);
@@ -3617,19 +4067,19 @@ class FileManager extends core_1.Host {
3617
4067
  if (data instanceof stream.Readable) {
3618
4068
  ++scheduler.count;
3619
4069
  target = new Promise((resolve, reject) => {
3620
- const writeable = fs.createWriteStream(url);
3621
- writeable.on('finish', () => {
4070
+ const writable = fs.createWriteStream(url);
4071
+ writable.on('finish', () => {
3622
4072
  resolve(1);
3623
4073
  });
3624
- writeable.on('error', reject);
4074
+ writable.on('error', reject);
3625
4075
  data.on('error', reject);
3626
- data.pipe(writeable);
4076
+ data.pipe(writable);
3627
4077
  });
3628
4078
  }
3629
4079
  }
3630
4080
  if (target) {
3631
4081
  if (thenCallback) {
3632
- target.then(thenCallback);
4082
+ void target.then(thenCallback);
3633
4083
  }
3634
4084
  if (catchCallback) {
3635
4085
  target.catch(catchCallback);
@@ -3637,7 +4087,7 @@ class FileManager extends core_1.Host {
3637
4087
  if (id > 0) {
3638
4088
  scheduler.add(id, url.toString());
3639
4089
  }
3640
- return target.finally(nextTask.bind(this, id));
4090
+ return target.finally(nextScheduled.bind(this, scheduler, id));
3641
4091
  }
3642
4092
  return Promise.resolve(-1);
3643
4093
  }
@@ -3648,53 +4098,57 @@ class FileManager extends core_1.Host {
3648
4098
  }
3649
4099
  async finalizeCompress(assets) {
3650
4100
  const compress = this.Compress;
3651
- if (!(assets.length && compress)) {
4101
+ if (!(assets.length > 0 && compress)) {
3652
4102
  return;
3653
4103
  }
3654
4104
  const tasks = [];
3655
4105
  for (const item of assets) {
3656
- const localUri = item.localUri;
3657
- if (!(localUri && image_1.isBinary(item.mimeType))) {
4106
+ if (!image_1.isBinary(item.mimeType)) {
3658
4107
  continue;
3659
4108
  }
3660
- const files = [localUri];
4109
+ const files = [[item.localUri, item.mimeType || '']];
3661
4110
  if (item.transforms) {
3662
- files.push(...item.transforms);
3663
- }
3664
- const format = item.mimeType.split('/').pop();
3665
- for (const file of files) {
3666
- const output = item.compress.filter(({ condition }) => !condition || withinSizeRange(file, condition));
3667
- if (!(output.length && this.has(file))) {
3668
- continue;
3669
- }
3670
- const found = output.filter(value => value.format === format);
3671
- for (const config of found.length ? found : output) {
3672
- const options = {
3673
- ...config,
3674
- timeout: this[kProcessTimeout].compress ?? PROCESS_TIMEOUT.compress,
3675
- proxyUrl: (uri) => {
3676
- const proxy = this.Request.proxyOf(uri);
3677
- return proxy ? proxy.host.href : '';
3678
- }
3679
- };
3680
- tasks.push(compress.tryImage(item.buffer && files.length === 1 ? item.buffer : file, file, options)
3681
- .then(result => {
3682
- if (result instanceof Buffer && file === localUri) {
3683
- item.buffer = result;
4111
+ files.push(...item.transforms.map(img => [img, core_1.Host.lookupMime(img)]));
4112
+ }
4113
+ tasks.push(new Promise(async (resolve) => {
4114
+ for (const [file, mimeType] of files) {
4115
+ const ext = mimeType.split('/')[1];
4116
+ const output = item.compress.filter(({ format, condition }) => (!format || format === ext) && (!condition || withinSizeRange(file, condition)));
4117
+ if (output.length > 0 && this.has(file)) {
4118
+ for (let i = 0, length = output.length, buffer = null; i < length; ++i) {
4119
+ const options = output[i];
4120
+ options.mimeType = mimeType;
4121
+ options.timeout ?? (options.timeout = this[kProcessTimeout].compress ?? PROCESS_TIMEOUT.compress);
4122
+ await compress.tryImage(buffer || files.length === 1 && item.buffer || file, file, options)
4123
+ .then(result => {
4124
+ if (result) {
4125
+ if (file === item.localUri) {
4126
+ item.buffer = result instanceof Uint8Array ? Buffer.from(result) : result;
4127
+ }
4128
+ if (i < length - 1) {
4129
+ buffer = Buffer.from(result);
4130
+ }
4131
+ }
4132
+ })
4133
+ .catch((err) => {
4134
+ this.writeFail(["Unable to compress file", path.basename(file)], err, 8);
4135
+ });
3684
4136
  }
3685
- })
3686
- .catch((err) => this.writeFail(["Unable to compress file", path.basename(file)], err, { type: 8, startTime: options.startTime })));
4137
+ }
3687
4138
  }
3688
- }
4139
+ resolve();
4140
+ }));
3689
4141
  }
3690
- if (tasks.length) {
3691
- return Promise.all(tasks);
4142
+ if (tasks.length > 0) {
4143
+ await Promise.all(tasks);
3692
4144
  }
3693
4145
  }
3694
4146
  async finalizeDocument() {
3695
4147
  for (const { instance, constructor } of this.Document) {
3696
- if (constructor.finalize && instance.assets.length) {
3697
- await constructor.finalize.call(this, instance).catch((err) => rejectModule.call(instance, err, 4));
4148
+ if (constructor.finalize && instance.assets.length > 0) {
4149
+ await constructor.finalize.call(this, instance).catch((err) => {
4150
+ rejectModule(instance, err, 4);
4151
+ });
3698
4152
  if (this.aborted) {
3699
4153
  return;
3700
4154
  }
@@ -3702,11 +4156,13 @@ class FileManager extends core_1.Host {
3702
4156
  }
3703
4157
  }
3704
4158
  async finalizeTask(assets) {
3705
- if (assets.length) {
4159
+ if (assets.length > 0) {
3706
4160
  for (const { instance, constructor } of this.Task) {
3707
4161
  const items = assets.filter(item => item.tasks.find(data => data.handler === instance.moduleName));
3708
- if (items.length) {
3709
- await constructor.finalize.call(this, instance, items).catch((err) => rejectModule.call(instance, err, 4));
4162
+ if (items.length > 0) {
4163
+ await constructor.finalize.call(this, instance, items).catch((err) => {
4164
+ rejectModule(instance, err, 4);
4165
+ });
3710
4166
  if (this.aborted) {
3711
4167
  return;
3712
4168
  }
@@ -3717,11 +4173,36 @@ class FileManager extends core_1.Host {
3717
4173
  async finalizeCloud() {
3718
4174
  const cloud = this.Cloud;
3719
4175
  if (cloud) {
3720
- return cloud_1.finalize.call(this, cloud).catch((err) => rejectModule.call(cloud, err, 64));
4176
+ await cloud_1.finalize.call(this, cloud).catch((err) => {
4177
+ rejectModule(cloud, err, 64);
4178
+ });
4179
+ }
4180
+ }
4181
+ async finalizeChecksum() {
4182
+ let checksum = this.config.checksum;
4183
+ if (!checksum) {
4184
+ return;
4185
+ }
4186
+ if (typeof checksum === 'boolean' || checksum === 1) {
4187
+ checksum = { recursive: checksum };
4188
+ }
4189
+ else if ((0, types_1.isString)(checksum)) {
4190
+ const items = checksum.split('.');
4191
+ checksum = items.length > 1 ? { algorithm: items[items.length - 1], filename: checksum } : { algorithm: checksum };
4192
+ }
4193
+ if ((0, types_1.isPlainObject)(checksum)) {
4194
+ const baseDirectory = this.baseDirectory;
4195
+ checksum.joinRoot = true;
4196
+ checksum.throwsEmpty = true;
4197
+ const sumTime = LOG_TIMEELAPSED ? process.hrtime() : 0;
4198
+ const files = (await FileManager.writeChecksum(baseDirectory, checksum.filename, checksum));
4199
+ if (sumTime) {
4200
+ this.writeTimeElapsed(checksum.algorithm || "sha256", [baseDirectory, files.length + (files.length === 1 ? ' file' : ' files')], sumTime, { ...core_1.Host.LOG_STYLE_WARN });
4201
+ }
3721
4202
  }
3722
4203
  }
3723
4204
  async finalizeCleanup() {
3724
- if (this.emptyDir.size) {
4205
+ if (this.emptyDir.size > 0) {
3725
4206
  for (const value of Array.from(this.emptyDir).reverse()) {
3726
4207
  try {
3727
4208
  fs.rmdirSync(value);
@@ -3731,8 +4212,10 @@ class FileManager extends core_1.Host {
3731
4212
  }
3732
4213
  }
3733
4214
  for (const { instance, constructor } of this.Document) {
3734
- if (constructor.cleanup && instance.assets.length) {
3735
- await constructor.cleanup.call(this, instance).catch((err) => rejectModule.call(instance, err, 4));
4215
+ if (constructor.cleanup && instance.assets.length > 0) {
4216
+ await constructor.cleanup.call(this, instance).catch((err) => {
4217
+ rejectModule(instance, err, 4);
4218
+ });
3736
4219
  }
3737
4220
  }
3738
4221
  }
@@ -3745,17 +4228,11 @@ class FileManager extends core_1.Host {
3745
4228
  }
3746
4229
  const startTime = process.hrtime();
3747
4230
  const filesToRemove = this.filesToRemove;
3748
- const removeFiles = () => {
3749
- if (filesToRemove.size) {
3750
- filesToRemove.forEach(value => this.deleteFile(value, { emptyDir: true }));
3751
- filesToRemove.clear();
3752
- }
3753
- };
3754
4231
  for (const [file, output] of this.filesToCompare) {
3755
4232
  const localUri = file.localUri;
3756
- let minFile = localUri, minSize = (0, util_1.getSize)(minFile);
4233
+ let minFile = localUri, minSize = (0, util_2.getSize)(minFile);
3757
4234
  for (const other of output) {
3758
- const size = (0, util_1.getSize)(other);
4235
+ const size = (0, util_2.getSize)(other);
3759
4236
  if (minSize === 0 || size > 0 && size < minSize) {
3760
4237
  filesToRemove.add(minFile);
3761
4238
  minFile = other;
@@ -3769,12 +4246,16 @@ class FileManager extends core_1.Host {
3769
4246
  this.replace(file, minFile);
3770
4247
  }
3771
4248
  }
3772
- removeFiles();
3773
- await this.finalizeCompress(this.assets.filter(item => item.compress && !ignoreAsset(item))).catch((err) => rejectModule.call(this, err, 8));
4249
+ removeFiles(this, filesToRemove);
4250
+ await this.finalizeCompress(this.assets.filter(item => item.compress && !ignoreAsset(item))).catch((err) => {
4251
+ rejectModule(this, err, 8);
4252
+ });
3774
4253
  if (this.aborted) {
3775
4254
  return (0, types_1.createAbortError)(true);
3776
4255
  }
3777
- await this.finalizeDocument().catch((err) => rejectModule.call(this, err, 4));
4256
+ await this.finalizeDocument().catch((err) => {
4257
+ rejectModule(this, err, 4);
4258
+ });
3778
4259
  if (this.aborted) {
3779
4260
  return (0, types_1.createAbortError)(true);
3780
4261
  }
@@ -3788,62 +4269,62 @@ class FileManager extends core_1.Host {
3788
4269
  }
3789
4270
  }
3790
4271
  }
3791
- removeFiles();
3792
- await this.finalizeTask(this.taskAssets.filter(item => item.tasks?.find(data => !data.preceding) && item.localUri && this.has(item.localUri) && !ignoreAsset(item))).catch((err) => rejectModule.call(this, err, 4));
4272
+ removeFiles(this, filesToRemove);
4273
+ await this.finalizeTask(this.taskAssets.filter(item => item.tasks?.find(data => !data.preceding) && item.localUri && this.has(item.localUri) && !ignoreAsset(item))).catch((err) => {
4274
+ rejectModule(this, err, 4);
4275
+ });
3793
4276
  if (this.aborted) {
3794
4277
  return (0, types_1.createAbortError)(true);
3795
4278
  }
3796
- removeFiles();
4279
+ removeFiles(this, filesToRemove);
3797
4280
  for (const item of this.assets) {
3798
4281
  if (item.checksumOutput && !ignoreAsset(item)) {
3799
4282
  const localUri = item.localUri;
3800
- if (!filesToRemove.has(localUri) && !checkHash.call(this, localUri, true, item.checksumOutput)) {
4283
+ if (!filesToRemove.has(localUri) && !checkHash(this, localUri, true, item.checksumOutput)) {
3801
4284
  item.invalid = true;
3802
4285
  filesToRemove.add(localUri);
3803
4286
  this.writeFail(["Checksum did not match", path.basename(localUri)], (0, types_1.errorValue)(localUri, "Invalid checksum"), { type: 32, startTime, queue: true });
3804
4287
  }
3805
4288
  }
3806
4289
  }
3807
- removeFiles();
3808
- await this.finalizeCloud().catch((err) => rejectModule.call(this, err, 64));
4290
+ removeFiles(this, filesToRemove);
4291
+ await this.finalizeCloud().catch((err) => {
4292
+ rejectModule(this, err, 64);
4293
+ });
3809
4294
  if (this.aborted) {
3810
4295
  return (0, types_1.createAbortError)(true);
3811
4296
  }
3812
- removeFiles();
4297
+ removeFiles(this, filesToRemove);
3813
4298
  if (this.Compress) {
3814
4299
  const tasks = [];
3815
- this.assets.forEach(item => item.compress && !ignoreAsset(item, true) && tasks.push(this.compressFile(item, false)));
3816
- if (tasks.length) {
4300
+ for (const item of this.assets) {
4301
+ if (item.compress && !ignoreAsset(item, true)) {
4302
+ tasks.push(this.compressFile(item, false));
4303
+ }
4304
+ }
4305
+ if (tasks.length > 0) {
3817
4306
  await Promise.allSettled(tasks);
3818
4307
  }
3819
4308
  }
3820
- let checksum = this.config.checksum;
3821
- if (checksum) {
3822
- if (typeof checksum === 'boolean' || checksum === 1) {
3823
- checksum = { recursive: checksum };
3824
- }
3825
- else if ((0, types_1.isString)(checksum)) {
3826
- const items = checksum.split('.');
3827
- checksum = items.length > 1 ? { algorithm: items[items.length - 1], filename: checksum } : { algorithm: checksum };
3828
- }
3829
- if ((0, types_1.isPlainObject)(checksum)) {
3830
- const baseDirectory = this.baseDirectory;
3831
- checksum.joinRoot = true;
3832
- checksum.throwsEmpty = true;
3833
- const sumTime = LOG_TIMEELAPSED ? process.hrtime() : 0;
3834
- try {
3835
- const files = (await FileManager.writeChecksum(baseDirectory, checksum.filename, checksum));
3836
- if (sumTime) {
3837
- this.writeTimeElapsed(checksum.algorithm || "sha256", [baseDirectory, files.length + (files.length === 1 ? ' file' : ' files')], sumTime, { ...core_1.Host.LOG_STYLE_WARN });
3838
- }
3839
- }
3840
- catch (err) {
3841
- this.writeFail(["Unable to read directory", path.basename(baseDirectory)], err, { type: 32, startTime });
3842
- }
3843
- }
4309
+ await this.finalizeChecksum().catch((err) => {
4310
+ rejectModule(this, err, 32);
4311
+ });
4312
+ await this.finalizeCleanup().catch((err) => {
4313
+ rejectModule(this, err, 1);
4314
+ });
4315
+ removeFiles(this, filesToRemove);
4316
+ this.closeMessage(startTime);
4317
+ this.Watch?.start(this.assets);
4318
+ }
4319
+ close() {
4320
+ this.Request.close();
4321
+ }
4322
+ startMessage() {
4323
+ if (!this.silent) {
4324
+ this.formatMessage(128, 'START', [new Date().toLocaleString(), this.assets.length + ' assets'], this.baseDirectory, { ...core_1.Host.LOG_STYLE_SUCCESS });
3844
4325
  }
3845
- await this.finalizeCleanup().catch((err) => rejectModule.call(this, err, 1));
3846
- removeFiles();
4326
+ }
4327
+ closeMessage(startTime) {
3847
4328
  if (LOG_TIMEELAPSED) {
3848
4329
  const [http, disk, cache] = this[kDownloadStats];
3849
4330
  const errorCount = this.errorCount;
@@ -3867,16 +4348,81 @@ class FileManager extends core_1.Host {
3867
4348
  const bufferCount = Object.keys(MEMORY.CACHE).length;
3868
4349
  message.push('BUFFER ' + (bufferCount > 1 ? bufferCount + ' / ' : '') + (0, types_1.formatSize)(MEMORY.SIZE));
3869
4350
  }
3870
- this.writeTimeElapsed('CLOSE', ['No further modifications', message.length ? ` ${message.join(chalk.blackBright(' )( '))} ` : ''], startTime, { ...core_1.Host.LOG_STYLE_WARN });
4351
+ this.writeTimeElapsed('CLOSE', ['No further modifications', message.length > 0 ? message.join(chalk.blackBright(LOGGER.MESSAGE_SEP)) : ''], startTime, { ...core_1.Host.LOG_STYLE_WARN });
3871
4352
  }
3872
- this.Watch?.start(this.assets);
3873
4353
  }
3874
- close() {
3875
- this.Request.close();
4354
+ diffMessage() {
4355
+ const diffSource = this[kDiffSource]?.[1];
4356
+ if (!diffSource) {
4357
+ return;
4358
+ }
4359
+ const output = [];
4360
+ const addHeader = (pathname, summary) => {
4361
+ output.push(chalk.blackBright('-'.repeat(LOGGER.MESSAGE_WIDTH)), ' ' + (summary === 'deleted' ? chalk.yellow(pathname) : pathname), chalk.blackBright('-'.repeat(LOGGER.MESSAGE_WIDTH - summary.length - 1)) + ' ' + chalk.bold(summary));
4362
+ };
4363
+ let divider = false;
4364
+ for (const pathname in diffSource) {
4365
+ if (core_1.Host.isPath(pathname, true)) {
4366
+ const [content, encoding] = diffSource[pathname];
4367
+ const hunks = diff.structuredPatch('', '', checkEOF(content), checkEOF(fs.readFileSync(pathname, encoding)), '', '', { context: 0 }).hunks;
4368
+ const length = hunks.length;
4369
+ if (length === 0) {
4370
+ continue;
4371
+ }
4372
+ const lastHunk = hunks[length - 1];
4373
+ const oldMax = lastHunk.oldStart + lastHunk.oldLines;
4374
+ const newMax = lastHunk.newStart + lastHunk.newLines;
4375
+ const posLength = Math.max(Math.max(oldMax, newMax).toString().length, Math.min(oldMax, newMax).toString().length);
4376
+ addHeader(pathname, length + ` hunk${length > 1 ? 's' : ''}`);
4377
+ for (const { lines, oldLines, oldStart, newStart, newLines } of hunks) {
4378
+ for (let i = 0, j = oldStart, k = oldLines, l = 0, q = lines.length, added = false; i < q && k > 0; ++i) {
4379
+ const line = lines[i].substring(1);
4380
+ output.push(` ${chalk[!line && k === 1 ? 'grey' : added ? 'green' : 'red']((j + l++).toString().padStart(posLength))} ${chalk[added ? 'green' : 'red'](line)}`);
4381
+ if (--k === 0 && !added) {
4382
+ j = newStart;
4383
+ k = newLines;
4384
+ l = 0;
4385
+ added = true;
4386
+ }
4387
+ }
4388
+ }
4389
+ divider = true;
4390
+ }
4391
+ else {
4392
+ addHeader(pathname, 'deleted');
4393
+ divider = false;
4394
+ }
4395
+ }
4396
+ if (output.length > 0) {
4397
+ if (divider) {
4398
+ output.push(chalk.blackBright('-'.repeat(LOGGER.MESSAGE_WIDTH)));
4399
+ }
4400
+ output.push('');
4401
+ if (this.broadcastId && core_1.Host.hasLogType(2)) {
4402
+ core_1.Host.formatMessage(2, '', '', output.join('\n'), { broadcastId: this.broadcastId, rawOutput: true });
4403
+ }
4404
+ else {
4405
+ process.stdout.write(output.join('\n'));
4406
+ (0, types_1.setLogCurrent)(null);
4407
+ }
4408
+ }
4409
+ }
4410
+ endMessage(errors) {
4411
+ if (LOG_TIMEELAPSED) {
4412
+ this.writeTimeElapsed('END', this.baseDirectory, this.startTime, errors.length > 0 ? { failed: true, ...core_1.Host.LOG_STYLE_FAIL } : { ...core_1.Host.LOG_STYLE_SUCCESS });
4413
+ }
4414
+ }
4415
+ clearStorage() {
4416
+ if (this[kDiffSource]) {
4417
+ this[kDiffSource][1] = {};
4418
+ }
4419
+ this.contentToAppend.clear();
4420
+ this.contentToReplace.clear();
3876
4421
  }
3877
4422
  resetState() {
3878
4423
  this.finalizeState = 2;
3879
4424
  this._pendingResult = null;
4425
+ this.clearStorage();
3880
4426
  }
3881
4427
  abortFinalize(err) {
3882
4428
  if (!this.restarting) {
@@ -3886,7 +4432,7 @@ class FileManager extends core_1.Host {
3886
4432
  else {
3887
4433
  this.finalizeState = 4;
3888
4434
  }
3889
- this.emit('end', [], collectErrors.call(this), this.collectLog());
4435
+ this.emit('end', [], collectErrors(this), this.collectLog());
3890
4436
  if (!this.restarting) {
3891
4437
  this.done = true;
3892
4438
  }
@@ -3928,9 +4474,9 @@ class FileManager extends core_1.Host {
3928
4474
  const start = Math.max(queue.length - available, 0);
3929
4475
  const items = queue.slice(start);
3930
4476
  queue.splice(queue.length - items.length);
3931
- items.forEach(params => {
3932
- this.scheduleTask(...params);
3933
- });
4477
+ for (const params of items) {
4478
+ void this.scheduleTask(...params);
4479
+ }
3934
4480
  }
3935
4481
  }
3936
4482
  }
@@ -3942,5 +4488,5 @@ class FileManager extends core_1.Host {
3942
4488
  return Array.from(this.modules).reduce((a, b) => a + b.errors.length, this.errors.length);
3943
4489
  }
3944
4490
  }
3945
-
4491
+ setLogMinWidth();
3946
4492
  module.exports = FileManager;