@e-mc/file-manager 0.0.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.
package/index.js ADDED
@@ -0,0 +1,3314 @@
1
+ "use strict";
2
+ /* eslint @typescript-eslint/no-explicit-any: "off" */
3
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ const path = require("path");
6
+ const fs = require("fs");
7
+ const lib_v4_1 = require("../module/lib-v4");
8
+ const util_1 = require("../request/util");
9
+ const asset_1 = require("../document/asset");
10
+ const util_2 = require("../document/util");
11
+ const types_1 = require("../types");
12
+ const request_1 = require("../request");
13
+ const document_1 = require("../document");
14
+ const task_1 = require("../task");
15
+ const image_1 = require("../image");
16
+ const watch_1 = require("../watch");
17
+ const compress_1 = require("../compress");
18
+ const cloud_1 = require("../cloud");
19
+ const core_1 = require("../core");
20
+ const kBaseDirectory = Symbol('baseDirectory');
21
+ const kIncremental = Symbol('incremental');
22
+ const kRestarting = Symbol('restarting');
23
+ const kDelayed = Symbol('delayed');
24
+ const kCleared = Symbol('cleared');
25
+ const KTimerMain = Symbol('timerMain');
26
+ const KEnabled = Symbol('enabled');
27
+ const kRecursionLimit = Symbol('recursionLimit');
28
+ const kHost = Symbol('host');
29
+ const kQueuedTasks = Symbol('queuedTasks');
30
+ const kProcessTimeout = Symbol('processTimeout');
31
+ const kDownloadStats = Symbol('downloadStats');
32
+ const kReplaceMap = Symbol('replaceMap');
33
+ const PLATFORM_WIN32 = process.platform === 'win32';
34
+ const PROCESS_TIMEOUT = { filemanager: 0, compress: 0 };
35
+ const CACHE_ETAG = {};
36
+ const DISK = {
37
+ ENABLED: false,
38
+ EXPIRES: 0,
39
+ LIMIT: (0, types_1.formatSize)('1gb'),
40
+ INCLUDE: [],
41
+ EXCLUDE: []
42
+ };
43
+ const MEMORY = {
44
+ ENABLED: false,
45
+ CACHE: {},
46
+ SIZE: 0,
47
+ TOTAL: 0,
48
+ EXPIRES: 0,
49
+ LIMIT: (0, types_1.formatSize)('100mb'),
50
+ LIMIT_ALL: (0, types_1.formatSize)('512mb'),
51
+ INCLUDE: [],
52
+ EXCLUDE: [],
53
+ PURGE: 0.25,
54
+ DISK_MIN: Infinity,
55
+ DISK_MAX: 0
56
+ };
57
+ let SESSION_ID = 0;
58
+ let SESSION_LIMIT = 1000;
59
+ let ASSET_ID = 0;
60
+ let RECURSION_LIMIT = 10;
61
+ let LOG_TIMEELAPSED = true;
62
+ let LOG_TIMEPROCESS = true;
63
+ const HTTP_CLIENT = {
64
+ timeout: 60000 /* TIME.m */,
65
+ connectTimeout: 20 * 1000 /* TIME.S */,
66
+ redirectLimit: 3,
67
+ retryWait: 1000 /* TIME.S */,
68
+ retryAfter: 30 * 1000 /* TIME.S */,
69
+ retryLimit: 10
70
+ };
71
+ function applyTimeout(target, options) {
72
+ for (const name in options) {
73
+ const value = parseTimeout(options[name]);
74
+ if (value !== undefined) {
75
+ target[name] = value;
76
+ }
77
+ }
78
+ }
79
+ function parseTimeout(value) {
80
+ if (+value === 0) {
81
+ return 0;
82
+ }
83
+ if ((value = (0, types_1.parseTime)(value)) > 0) {
84
+ return value;
85
+ }
86
+ }
87
+ function withinSizeRange(uri, value, pattern) {
88
+ const match = (pattern || /\(\s*(\d+)\s*(?:,\s*(\d+|\*)\s*)?\)/).exec(value);
89
+ const [minSize, maxSize] = match && !match[1] ? [+match[2], !match[3] || match[3] === '*' ? Infinity : +match[3]] : [0, Infinity];
90
+ if (minSize > 0 || maxSize < Infinity) {
91
+ const fileSize = (0, lib_v4_1.getSize)(uri);
92
+ if (fileSize === 0 || fileSize < minSize || fileSize > maxSize) {
93
+ return false;
94
+ }
95
+ }
96
+ return true;
97
+ }
98
+ function startMessage() {
99
+ this.formatMessage(128 /* LOG_TYPE.TIME_ELAPSED */, 'START', [new Date().toLocaleString(), this.assets.length + ' assets'], this.baseDirectory, { ...core_1.Host.LOG_STYLE_SUCCESS });
100
+ }
101
+ function clearAssets() {
102
+ this.assets.forEach(item => {
103
+ if ('buffer' in item) {
104
+ delete item.buffer;
105
+ }
106
+ if ('sourceUTF8' in item) {
107
+ delete item.sourceUTF8;
108
+ }
109
+ });
110
+ }
111
+ function bundleTorrent(files, mimeType, encoding) {
112
+ let output = '';
113
+ for (const file of files) {
114
+ if (core_1.Host.lookupMime(file) === mimeType) {
115
+ try {
116
+ output += fs.readFileSync(file, encoding);
117
+ }
118
+ catch (err) {
119
+ this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(file)], err, 32 /* LOG_TYPE.FILE */);
120
+ }
121
+ }
122
+ }
123
+ return output;
124
+ }
125
+ function resetAssets() {
126
+ this.reset();
127
+ FileManager.sanitizeAssets(this.assets);
128
+ }
129
+ function abortedHost() {
130
+ if (this.finalizeState === 6 /* FINALIZE_STATE.ABORTED */) {
131
+ this.restarting = false;
132
+ this.performFinalize(true);
133
+ return this.done;
134
+ }
135
+ return false;
136
+ }
137
+ function observeFile(instance) {
138
+ instance.on('file:delete', (value, options) => this.delete(value, !!options?.emptyDir));
139
+ instance.on('file:copy', value => this.add(value));
140
+ instance.on('file:move', (value, options) => {
141
+ this.add(value);
142
+ const src = options?.outSrc;
143
+ if (src) {
144
+ this.delete(src);
145
+ }
146
+ });
147
+ instance.on('dir:remove', value => {
148
+ if (this.removeCwd(value)) {
149
+ if (PLATFORM_WIN32) {
150
+ value = value.toLowerCase();
151
+ }
152
+ if (value[value.length - 1] !== path.sep) {
153
+ value += path.sep;
154
+ }
155
+ for (const name of this.files) {
156
+ if ((PLATFORM_WIN32 ? name.toLowerCase() : name).startsWith(value)) {
157
+ this.files.delete(name);
158
+ }
159
+ }
160
+ }
161
+ });
162
+ }
163
+ function setCpuUsage() {
164
+ const usage = core_1.Host.initCpuUsage(this);
165
+ if ('startCPU' in this) {
166
+ this.startCPU = usage;
167
+ }
168
+ }
169
+ function collectErrors() {
170
+ const result = [];
171
+ const clearModule = (instance) => {
172
+ const { moduleName, errors } = instance;
173
+ if (errors.length) {
174
+ errors.forEach(value => result.push(`[${moduleName}] ` + (core_1.Host.asString(value) || "Unknown" /* ERR_MESSAGE.UNKNOWN */)));
175
+ errors.length = 0;
176
+ }
177
+ };
178
+ this.modules.forEach(instance => clearModule(instance));
179
+ this.subProcesses.forEach(instance => clearModule(instance));
180
+ clearModule(this);
181
+ if (!this.restarting) {
182
+ queueMicrotask(() => {
183
+ this.flushLog();
184
+ this.modules.forEach(instance => instance.flushLog());
185
+ this.subProcesses.forEach(instance => instance.flushLog());
186
+ this.close();
187
+ clearAssets.call(this);
188
+ });
189
+ }
190
+ else {
191
+ clearAssets.call(this);
192
+ }
193
+ return result;
194
+ }
195
+ function rejectModule(err, type, hint) {
196
+ this.writeFail(["Handled rejection" /* ERR_MESSAGE.HANDLED_REJECTION */, this.moduleName + (hint ? ': ' + hint : '')], err, type);
197
+ }
198
+ const isFunction = (value) => typeof value === 'function';
199
+ const ignoreAsset = (item, exists) => item.invalid || (0, types_1.hasBit)(item.flags, 1 /* ASSET_FLAG.IGNORE */ | (!exists ? 128 /* ASSET_FLAG.EXISTS */ : 0));
200
+ class HttpDiskCache {
201
+ constructor(host, enabled) {
202
+ this.host = host;
203
+ this.limit = DISK.LIMIT;
204
+ this.expires = DISK.EXPIRES;
205
+ this._flags = 0;
206
+ this._exclude = [];
207
+ this._include = [];
208
+ this._excludeExt = [];
209
+ this._includeExt = [];
210
+ this._items = [];
211
+ this[KEnabled] = enabled;
212
+ }
213
+ has(uri) {
214
+ if (!this[KEnabled]) {
215
+ return false;
216
+ }
217
+ try {
218
+ if (typeof uri === 'string') {
219
+ uri = new URL(uri);
220
+ }
221
+ }
222
+ catch {
223
+ return false;
224
+ }
225
+ const flags = this._flags;
226
+ if (flags === 0) {
227
+ return true;
228
+ }
229
+ if (flags & 10) {
230
+ let ext = path.extname(uri.pathname);
231
+ if (ext) {
232
+ ext = ext.substring(1);
233
+ if (flags & 2) {
234
+ if (!this._includeExt.some(value => value === ext)) {
235
+ return false;
236
+ }
237
+ }
238
+ else if ((flags & 8) && this._excludeExt.some(value => value === ext)) {
239
+ return false;
240
+ }
241
+ }
242
+ }
243
+ return flags & 1 ? this._include.includes(uri.origin) : !this._exclude.includes(uri.origin);
244
+ }
245
+ add(uri, etag, target, { buffer, contentLength = (0, lib_v4_1.getSize)(target) } = {}) {
246
+ let tempDir;
247
+ if (contentLength <= this.limit && (tempDir = this.host.getCacheDir(uri))) {
248
+ const baseDir = path.join(tempDir, etag);
249
+ const tempUri = path.join(baseDir, path.basename(target));
250
+ try {
251
+ if (!fs.existsSync(baseDir)) {
252
+ fs.mkdirSync(baseDir);
253
+ }
254
+ if (buffer) {
255
+ fs.writeFileSync(tempUri, buffer);
256
+ }
257
+ else {
258
+ fs.copyFileSync(target, tempUri);
259
+ }
260
+ const expires = this.expires;
261
+ if (expires > 0 && expires < Infinity) {
262
+ setTimeout(() => this.clear(target), Math.min(expires, core_1.Host.MAX_TIMEOUT));
263
+ }
264
+ }
265
+ catch {
266
+ }
267
+ }
268
+ }
269
+ within(value) {
270
+ if (typeof value !== 'number') {
271
+ value = value.contentLength;
272
+ }
273
+ return value > 0 && value <= this.limit;
274
+ }
275
+ clear(pathname) {
276
+ core_1.Host.removeDir(path.dirname(pathname));
277
+ }
278
+ set enabled(value) {
279
+ this[KEnabled] = value;
280
+ }
281
+ get enabled() {
282
+ return this[KEnabled];
283
+ }
284
+ set include(value) {
285
+ this._include = [];
286
+ this._includeExt = [];
287
+ if ((0, types_1.isArray)(value)) {
288
+ for (const item of value) {
289
+ if (core_1.Host.isURL(item)) {
290
+ this._include.push(item);
291
+ this._flags |= 1;
292
+ }
293
+ else {
294
+ this._includeExt.push(item);
295
+ this._flags |= 2;
296
+ }
297
+ }
298
+ }
299
+ else {
300
+ this._flags &= ~3;
301
+ }
302
+ }
303
+ get include() {
304
+ return this._include.concat(this._includeExt);
305
+ }
306
+ set exclude(value) {
307
+ this._exclude = [];
308
+ this._excludeExt = [];
309
+ if ((0, types_1.isArray)(value)) {
310
+ for (const item of value) {
311
+ if (core_1.Host.isURL(item)) {
312
+ this._exclude.push(item);
313
+ this._flags |= 4;
314
+ }
315
+ else {
316
+ this._excludeExt.push(item);
317
+ this._flags |= 8;
318
+ }
319
+ }
320
+ }
321
+ else {
322
+ this._flags &= ~12;
323
+ }
324
+ }
325
+ get exclude() {
326
+ return this._exclude.concat(this._excludeExt);
327
+ }
328
+ }
329
+ class HttpMemoryCache extends HttpDiskCache {
330
+ constructor(host, enabled) {
331
+ super(host, enabled && core_1.Host.enabled("memory.settings.users" /* KEY_NAME.MEMORY_SETTINGS_USERS */, host.username));
332
+ this.limit = MEMORY.LIMIT;
333
+ this.expires = MEMORY.EXPIRES;
334
+ this.toDisk = [MEMORY.DISK_MIN, MEMORY.DISK_MAX];
335
+ }
336
+ has(uri) {
337
+ return this.expires > 0 && super.has(uri);
338
+ }
339
+ add(uri, etag, buffer, { encoding, toDisk, contentLength = Buffer.byteLength(buffer, encoding) } = {}) {
340
+ if (contentLength <= this.limit) {
341
+ if (uri instanceof URL) {
342
+ uri = uri.href;
343
+ }
344
+ MEMORY.SIZE += contentLength;
345
+ if (MEMORY.SIZE >= MEMORY.LIMIT_ALL) {
346
+ this.purge(MEMORY.PURGE);
347
+ }
348
+ this._items.push(MEMORY.CACHE[uri] = [Date.now(), buffer, encoding, contentLength, uri, etag]);
349
+ if (this.expires < Infinity) {
350
+ setTimeout(() => this.clear(uri), Math.min(this.expires, core_1.Host.MAX_TIMEOUT));
351
+ }
352
+ ++MEMORY.TOTAL;
353
+ return;
354
+ }
355
+ let tempDir;
356
+ if (toDisk && this.withinDisk(contentLength) && (tempDir = this.host.getCacheDir(uri))) {
357
+ try {
358
+ const baseDir = path.join(tempDir, etag);
359
+ if (!fs.existsSync(baseDir)) {
360
+ fs.mkdirSync(baseDir);
361
+ }
362
+ fs.writeFileSync(path.join(baseDir, toDisk), buffer);
363
+ return;
364
+ }
365
+ catch {
366
+ }
367
+ }
368
+ this.clear(uri);
369
+ }
370
+ clear(uri) {
371
+ let items;
372
+ if (uri) {
373
+ const item = MEMORY.CACHE[uri instanceof URL ? uri.href : uri];
374
+ if (!item) {
375
+ return;
376
+ }
377
+ items = [item];
378
+ }
379
+ else {
380
+ items = this._items;
381
+ }
382
+ for (const item of items) {
383
+ const expired = MEMORY.CACHE[uri = item[4]];
384
+ if (expired) {
385
+ const size = expired[3];
386
+ if (size > 0) {
387
+ MEMORY.SIZE -= size;
388
+ }
389
+ delete MEMORY.CACHE[uri];
390
+ --MEMORY.TOTAL;
391
+ }
392
+ }
393
+ }
394
+ purge(percent, limit) {
395
+ FileManager.purgeMemory(percent, limit);
396
+ }
397
+ withinDisk(value) {
398
+ if (typeof value !== 'number') {
399
+ value = value.contentLength;
400
+ }
401
+ return value >= this.toDisk[0] && value <= this.toDisk[1];
402
+ }
403
+ }
404
+ class FileThread extends core_1.AbortComponent {
405
+ constructor(host, file, threadCount) {
406
+ super();
407
+ this.file = file;
408
+ this.threadCount = threadCount;
409
+ this.mimeType = '';
410
+ this.startTime = Date.now();
411
+ this[_a] = [];
412
+ this[kHost] = host;
413
+ }
414
+ openThread(instance, timeout = 0) {
415
+ return this.host.openThread(instance, this, timeout);
416
+ }
417
+ closeThread(instance, callback) {
418
+ return this.host.closeThread(instance, this, callback);
419
+ }
420
+ getObject(data) {
421
+ const result = { ...data, file: this.file };
422
+ result.mimeType || (result.mimeType = this.mimeType);
423
+ return result;
424
+ }
425
+ get host() {
426
+ return this[kHost];
427
+ }
428
+ get queuedTasks() {
429
+ return this[kQueuedTasks];
430
+ }
431
+ }
432
+ _a = kQueuedTasks;
433
+ class FileManager extends core_1.Host {
434
+ static async purgeMemory(percent = 1, limit = 0, parent) {
435
+ if (typeof limit === 'boolean') {
436
+ parent = limit;
437
+ limit = 0;
438
+ }
439
+ let result = 0;
440
+ if (limit === 0 || (parent === undefined && limit >= MEMORY.SIZE) || (parent !== undefined && limit > MEMORY.TOTAL)) {
441
+ const cache = MEMORY.CACHE;
442
+ if (percent >= 1) {
443
+ for (const uri in cache) {
444
+ delete cache[uri];
445
+ ++result;
446
+ }
447
+ MEMORY.SIZE = 0;
448
+ MEMORY.TOTAL = 0;
449
+ }
450
+ else if (percent > 0) {
451
+ const bufferSize = Math.ceil(MEMORY.SIZE * percent);
452
+ const items = [];
453
+ let purgeSize = 0;
454
+ for (const uri in cache) {
455
+ const item = cache[uri];
456
+ if (item) {
457
+ items.push([item, uri]);
458
+ }
459
+ }
460
+ items.sort((a, b) => a[0][0] - b[0][0]);
461
+ for (const [item, uri] of items) {
462
+ const size = item[3];
463
+ if (size > 0) {
464
+ purgeSize += size;
465
+ MEMORY.SIZE -= size;
466
+ }
467
+ delete MEMORY.CACHE[uri];
468
+ ++result;
469
+ if (purgeSize >= bufferSize) {
470
+ break;
471
+ }
472
+ }
473
+ MEMORY.TOTAL = items.length - result;
474
+ }
475
+ }
476
+ return result + (parent && result > 0 ? await super.purgeMemory(typeof parent === 'number' && parent > 0 ? parent : percent, limit, true) : 0);
477
+ }
478
+ static loadSettings(settings, permission, password) {
479
+ if (super.loadSettings(settings, permission, password)) {
480
+ const { download, request, error, logger } = settings;
481
+ if ((0, types_1.isPlainObject)(request)) {
482
+ let { timeout, disk, buffer, connect } = request;
483
+ if ((timeout = (0, util_1.fromSeconds)(timeout)) >= 0) {
484
+ HTTP_CLIENT.timeout = timeout;
485
+ }
486
+ if (disk) {
487
+ this.defineHttpCache(disk, true);
488
+ }
489
+ if (buffer) {
490
+ this.defineHttpCache(buffer);
491
+ }
492
+ if (connect) {
493
+ this.defineHttpConnect(connect);
494
+ }
495
+ request_1.default.loadSettings({ process: settings.process, request, download }, password);
496
+ }
497
+ if (error) {
498
+ const value = (0, util_1.asInt)(error.recursion_limit);
499
+ if (value >= 0 && value < Infinity) {
500
+ RECURSION_LIMIT = value;
501
+ }
502
+ }
503
+ if (logger) {
504
+ let value = logger.session_id;
505
+ if (value === true) {
506
+ SESSION_LIMIT = 1000;
507
+ }
508
+ else if (value && (value = +value) > 0) {
509
+ SESSION_LIMIT = Math.pow(10, value);
510
+ }
511
+ }
512
+ LOG_TIMEELAPSED = this.hasLogType(128 /* LOG_TYPE.TIME_ELAPSED */);
513
+ LOG_TIMEPROCESS = this.hasLogType(256 /* LOG_TYPE.TIME_PROCESS */);
514
+ return true;
515
+ }
516
+ return false;
517
+ }
518
+ static sanitizeAssets(assets, exclusions = []) {
519
+ assets.forEach(item => {
520
+ if ((0, types_1.ignoreFlag)(item.flags)) {
521
+ return;
522
+ }
523
+ const initialValue = item.initialValue;
524
+ for (const attr in initialValue) {
525
+ const value = initialValue[attr];
526
+ if (attr in item && typeof value === 'string') {
527
+ item[attr] = value;
528
+ }
529
+ }
530
+ for (const attr in item) {
531
+ switch (attr) {
532
+ case 'flags':
533
+ item.flags &= ~(128 /* ASSET_FLAG.EXISTS */ | 16 /* ASSET_FLAG.MODIFIED */);
534
+ break;
535
+ case 'watch':
536
+ if ((0, types_1.isPlainObject)(item.watch) && item.watch.assets) {
537
+ delete item.watch.assets;
538
+ }
539
+ case 'buffer':
540
+ case 'sourceUTF8':
541
+ case 'sourceFiles':
542
+ case 'transforms':
543
+ case 'descendants':
544
+ case 'torrentFiles':
545
+ case 'initialValue':
546
+ case 'processModule':
547
+ case 'etag':
548
+ case 'lastModified':
549
+ case 'contentLength':
550
+ case 'invalid':
551
+ if (!exclusions.includes(attr)) {
552
+ delete item[attr];
553
+ }
554
+ break;
555
+ }
556
+ }
557
+ });
558
+ return assets;
559
+ }
560
+ static createFileThread(host, file) {
561
+ return new FileThread(host, file, 0);
562
+ }
563
+ static setTimeout(options) {
564
+ applyTimeout(PROCESS_TIMEOUT, options);
565
+ }
566
+ static defineHttpCache({ enabled, expires, limit, limit_all, include, exclude, to_disk, purge_amount }, disk) {
567
+ const cache = disk ? DISK : MEMORY;
568
+ if (typeof enabled === 'boolean') {
569
+ cache.ENABLED = enabled;
570
+ }
571
+ cache.EXPIRES = expires ? (0, types_1.parseExpires)(expires) : 0;
572
+ cache.INCLUDE = (0, types_1.isArray)(include) ? include.slice(0) : [];
573
+ cache.EXCLUDE = (0, types_1.isArray)(exclude) ? exclude.slice(0) : [];
574
+ const setLimit = (value, type) => {
575
+ if (value !== undefined) {
576
+ if (typeof value === 'string') {
577
+ value = (0, types_1.formatSize)(value);
578
+ }
579
+ if (value >= 0) {
580
+ switch (type) {
581
+ case 1:
582
+ (disk ? DISK : MEMORY).LIMIT = value;
583
+ break;
584
+ case 2:
585
+ MEMORY.LIMIT_ALL = value;
586
+ break;
587
+ case 3:
588
+ MEMORY.DISK_MIN = value;
589
+ break;
590
+ case 4:
591
+ MEMORY.DISK_MAX = value;
592
+ break;
593
+ }
594
+ }
595
+ else if (value === -1) {
596
+ switch (type) {
597
+ case 3:
598
+ MEMORY.DISK_MIN = Infinity;
599
+ break;
600
+ case 4:
601
+ MEMORY.DISK_MAX = 0;
602
+ break;
603
+ }
604
+ }
605
+ }
606
+ };
607
+ setLimit(limit, 1);
608
+ if (disk) {
609
+ return;
610
+ }
611
+ setLimit(limit_all, 2);
612
+ if (to_disk) {
613
+ let limit_disk;
614
+ if (Array.isArray(to_disk)) {
615
+ [to_disk, limit_disk] = to_disk;
616
+ }
617
+ setLimit(to_disk, 3);
618
+ setLimit(limit_disk, 4);
619
+ }
620
+ if ((purge_amount = (0, util_1.asFloat)(purge_amount)) > 0) {
621
+ MEMORY.PURGE = Math.min(purge_amount, 1);
622
+ }
623
+ }
624
+ static defineHttpConnect({ timeout, retry_wait, retry_after, retry_limit, redirect_limit }) {
625
+ if ((timeout = (0, util_1.fromSeconds)(timeout)) >= 0) {
626
+ HTTP_CLIENT.connectTimeout = timeout;
627
+ }
628
+ if ((retry_wait = (0, util_1.fromSeconds)(retry_wait)) >= 0) {
629
+ HTTP_CLIENT.retryWait = Math.min(retry_wait, 600 * 1000 /* TIME.S */);
630
+ }
631
+ if ((retry_after = (0, util_1.fromSeconds)(retry_after)) >= 0) {
632
+ HTTP_CLIENT.retryAfter = Math.min(retry_after, this.MAX_TIMEOUT);
633
+ }
634
+ if ((retry_limit = (0, util_1.asInt)(retry_limit)) >= 0) {
635
+ HTTP_CLIENT.retryLimit = retry_limit;
636
+ }
637
+ if ((redirect_limit = (0, util_1.asInt)(redirect_limit)) >= 0) {
638
+ HTTP_CLIENT.redirectLimit = redirect_limit;
639
+ }
640
+ }
641
+ constructor(baseDirectory, config, permission, postFinalize) {
642
+ super(config);
643
+ this.archiving = false;
644
+ this.finalizeState = 0 /* FINALIZE_STATE.READY */;
645
+ this.processTimeout = PROCESS_TIMEOUT.filemanager;
646
+ this.Document = [];
647
+ this.Task = [];
648
+ this.Image = null;
649
+ this.Cloud = null;
650
+ this.Watch = null;
651
+ this.Compress = null;
652
+ this[_b] = 'FileManager';
653
+ this.documentAssets = [];
654
+ this.taskAssets = [];
655
+ this.dataSourceItems = [];
656
+ this.files = new Set();
657
+ this.filesQueued = new Set();
658
+ this.filesToRemove = new Set();
659
+ this.filesToCompare = new Map();
660
+ this.contentToAppend = new Map();
661
+ this.contentToReplace = new Map();
662
+ this.processing = [];
663
+ this.fetchedAssets = [];
664
+ this.copiedAssets = [];
665
+ this.emptyDir = new Set();
666
+ this._moduleName = 'filemanager';
667
+ this._pendingResult = null;
668
+ this[_c] = 'none';
669
+ this[_d] = false;
670
+ this[_e] = 0;
671
+ this[_f] = false;
672
+ this[_g] = null;
673
+ this[_h] = RECURSION_LIMIT;
674
+ this[_j] = {};
675
+ this[_k] = [[0, 0], [0, 0], [0, 0]];
676
+ this[_l] = {};
677
+ if (typeof permission === 'boolean') {
678
+ this.archiving = permission;
679
+ permission = undefined;
680
+ }
681
+ else if (isFunction(permission)) {
682
+ postFinalize = permission;
683
+ permission = undefined;
684
+ }
685
+ else if (!core_1.Host.isPermission(permission)) {
686
+ permission = undefined;
687
+ }
688
+ if (LOG_TIMEPROCESS) {
689
+ setCpuUsage.call(this);
690
+ }
691
+ this[kBaseDirectory] = path.normalize(baseDirectory[baseDirectory.length - 1] === path.sep ? baseDirectory.substring(0, baseDirectory.length - 1) : baseDirectory);
692
+ this.permission = permission || core_1.Host.getPermissionFromSettings();
693
+ this.sessionId = (++SESSION_ID === SESSION_LIMIT ? SESSION_ID = 1 : SESSION_ID).toString();
694
+ const { assets = [], dataSource, timeout } = config;
695
+ let targeted;
696
+ for (let i = 0, length = assets.length; i < length; ++i) {
697
+ const item = assets[i];
698
+ const encoding = item.encoding;
699
+ if (item.document) {
700
+ this.documentAssets.push(item);
701
+ }
702
+ if (item.tasks) {
703
+ this.taskAssets.push(item);
704
+ }
705
+ if (encoding) {
706
+ switch (encoding) {
707
+ case 'utf-8':
708
+ break;
709
+ case 'utf-16':
710
+ case 'utf-16be':
711
+ case 'utf-16le':
712
+ item.encoding = 'utf16le';
713
+ break;
714
+ default:
715
+ item.encoding = (0, types_1.getEncoding)(encoding);
716
+ break;
717
+ }
718
+ }
719
+ if ((0, types_1.usingFlag)(item.flags)) {
720
+ (targeted || (targeted = [])).push(item);
721
+ }
722
+ item.id || (item.id = ++ASSET_ID);
723
+ }
724
+ this._assets = assets.slice(0);
725
+ if (targeted) {
726
+ this.using(...targeted);
727
+ }
728
+ if (Array.isArray(dataSource)) {
729
+ this.dataSourceItems.push(...dataSource);
730
+ }
731
+ if (this.willAbort(this)) {
732
+ this.abortable = true;
733
+ }
734
+ if ((0, types_1.isPlainObject)(timeout)) {
735
+ applyTimeout(this[kProcessTimeout], timeout);
736
+ }
737
+ if (isFunction(postFinalize)) {
738
+ this.on('end', postFinalize);
739
+ }
740
+ this.cacheToDisk = new HttpDiskCache(this, DISK.ENABLED);
741
+ this.cacheToMemory = new HttpMemoryCache(this, MEMORY.ENABLED);
742
+ if (MEMORY.INCLUDE.length) {
743
+ this.cacheToMemory.include = MEMORY.INCLUDE;
744
+ }
745
+ else if (MEMORY.EXCLUDE.length) {
746
+ this.cacheToMemory.exclude = MEMORY.EXCLUDE;
747
+ }
748
+ const request = new request_1.default();
749
+ request.host = this;
750
+ this.Request = request;
751
+ if (this.aborted) {
752
+ this.finalizeState = 6 /* FINALIZE_STATE.ABORTED */;
753
+ }
754
+ else {
755
+ request.init(config).apply({ client: HTTP_CLIENT });
756
+ if (!this.queued) {
757
+ startMessage.call(this);
758
+ }
759
+ }
760
+ }
761
+ *[(_b = Symbol.toStringTag, _c = kIncremental, _d = kRestarting, _e = kDelayed, _f = kCleared, _g = KTimerMain, _h = kRecursionLimit, _j = kProcessTimeout, _k = kDownloadStats, _l = kReplaceMap, Symbol.iterator)]() {
762
+ for (const file of this.files) {
763
+ yield file;
764
+ }
765
+ }
766
+ add(value, parent, type = types_1.FILE_TYPE.TRANSFORM) {
767
+ const file = this.removeCwd(value);
768
+ if (file) {
769
+ this.files.add(file);
770
+ if (parent) {
771
+ if (type & types_1.FILE_TYPE.TRANSFORM) {
772
+ const transforms = parent.transforms;
773
+ if (!transforms) {
774
+ parent.transforms = [value];
775
+ }
776
+ else if (!transforms.includes(value)) {
777
+ transforms.push(value);
778
+ }
779
+ }
780
+ if (type & types_1.FILE_TYPE.TORRENT) {
781
+ const torrent = parent.torrentFiles;
782
+ if (!torrent) {
783
+ parent.torrentFiles = [value];
784
+ }
785
+ else if (!torrent.includes(value)) {
786
+ torrent.push(value);
787
+ }
788
+ }
789
+ if ((type & types_1.FILE_TYPE.SOURCEMAP) || (type & types_1.FILE_TYPE.COMPRESSED)) {
790
+ const connected = parent.descendants;
791
+ if (!connected) {
792
+ parent.descendants = [value];
793
+ }
794
+ else if (!connected.includes(value)) {
795
+ connected.push(value);
796
+ }
797
+ }
798
+ }
799
+ }
800
+ return this;
801
+ }
802
+ delete(value, emptyDir = true) {
803
+ if (this.files.delete(this.removeCwd(value))) {
804
+ if (emptyDir) {
805
+ let dir = this.baseDirectory;
806
+ for (const seg of path.dirname(value).substring(this.baseDirectory.length + 1).split(path.sep)) {
807
+ if (seg) {
808
+ dir += path.sep + seg;
809
+ this.emptyDir.add(dir);
810
+ }
811
+ }
812
+ }
813
+ return true;
814
+ }
815
+ return false;
816
+ }
817
+ has(value) {
818
+ return this.files.has(this.removeCwd(value));
819
+ }
820
+ keys() {
821
+ return this.files.keys();
822
+ }
823
+ values() {
824
+ return this.files.values();
825
+ }
826
+ entries() {
827
+ return this.files.entries();
828
+ }
829
+ forEach(predicate, thisArg) {
830
+ this.files.forEach(predicate, thisArg);
831
+ }
832
+ clear() {
833
+ core_1.Host.removeDir(this.baseDirectory, true);
834
+ this.files.clear();
835
+ }
836
+ get size() {
837
+ return this.files.size;
838
+ }
839
+ abort() {
840
+ this.Request.abort();
841
+ super.abort();
842
+ }
843
+ willAbort(value) {
844
+ if ((0, types_1.isObject)(value)) {
845
+ value = value.moduleName;
846
+ }
847
+ const error = this.config.error;
848
+ return !!error && (0, types_1.isArray)(error.abort) && error.abort.includes(value);
849
+ }
850
+ restart(recursive, exclusions, emptyDir) {
851
+ if (recursive === 'abort') {
852
+ this.restarting = false;
853
+ this.performFinalize(true);
854
+ return;
855
+ }
856
+ if (typeof exclusions === 'boolean') {
857
+ emptyDir = exclusions;
858
+ exclusions = undefined;
859
+ }
860
+ if (this.restartable && (!recursive || --this[kRecursionLimit] >= 0)) {
861
+ if (this.reset()) {
862
+ this.finalizeState = 5 /* FINALIZE_STATE.RESTARTED */;
863
+ FileManager.sanitizeAssets(this.assets, exclusions);
864
+ for (const { instance } of this.Document) {
865
+ instance.restart();
866
+ }
867
+ startMessage.call(this);
868
+ this.processAssets(emptyDir);
869
+ }
870
+ else {
871
+ this.writeFail('Unable to restart during finalization', (0, types_1.errorMessage)('Session ID', this.sessionId));
872
+ }
873
+ }
874
+ else {
875
+ this.restarting = false;
876
+ }
877
+ }
878
+ loadModule(name, ...args) {
879
+ const loaded = super.loadModule(name, ...args);
880
+ if (loaded) {
881
+ return loaded;
882
+ }
883
+ switch (name) {
884
+ case 'cloud': {
885
+ const instance = new cloud_1.default(args[0]);
886
+ instance.host = this;
887
+ instance.init(this.config);
888
+ observeFile.call(this, instance);
889
+ return this.Cloud = instance;
890
+ }
891
+ case 'watch': {
892
+ const instance = new watch_1.default(...args);
893
+ instance.host = this;
894
+ instance.init(this.config);
895
+ observeFile.call(this, instance);
896
+ return this.Watch = instance;
897
+ }
898
+ case 'compress': {
899
+ const instance = new compress_1.default(args[0]);
900
+ instance.host = this;
901
+ instance.init();
902
+ observeFile.call(this, instance);
903
+ return this.Compress = instance;
904
+ }
905
+ default:
906
+ return null;
907
+ }
908
+ }
909
+ reset() {
910
+ if (this.finalizeState === 1 /* FINALIZE_STATE.COMMIT */) {
911
+ return false;
912
+ }
913
+ super.reset();
914
+ this.clearProcessTimeout();
915
+ this.files.clear();
916
+ this.filesQueued.clear();
917
+ this.filesToRemove.clear();
918
+ this.filesToCompare.clear();
919
+ this.contentToAppend.clear();
920
+ this.contentToReplace.clear();
921
+ this.processing.length = 0;
922
+ this.Request.reset();
923
+ this.modules.forEach(instance => instance.reset());
924
+ this.emptyDir.clear();
925
+ if (!this.restarting) {
926
+ this.close();
927
+ this._pendingResult = null;
928
+ }
929
+ clearAssets.call(this);
930
+ this.cleared = false;
931
+ this[kDelayed] = 0;
932
+ this.finalizeState = 0 /* FINALIZE_STATE.READY */;
933
+ return true;
934
+ }
935
+ deleteFile(value, options = {}, callback) {
936
+ if (super.deleteFile(value, options, callback)) {
937
+ let emptyDir = false;
938
+ if ((0, types_1.isPlainObject)(options)) {
939
+ if (options.emptyDir) {
940
+ emptyDir = true;
941
+ }
942
+ if (options.all) {
943
+ value = path.resolve(value);
944
+ (options.id ? [this.assets.find(item => item.id === options.id)].filter(item => item) : this.assets.filter(item => item.localUri === value)).forEach(asset => {
945
+ asset.transforms?.forEach(file => this.deleteFile(file, emptyDir));
946
+ asset.descendants?.forEach(file => this.deleteFile(file, emptyDir));
947
+ });
948
+ }
949
+ }
950
+ this.delete(value, emptyDir);
951
+ return true;
952
+ }
953
+ return false;
954
+ }
955
+ resumeThread(options) {
956
+ if (this.aborted || options.aborted) {
957
+ this.finalizeState = 0 /* FINALIZE_STATE.READY */;
958
+ this.performFinalize(true);
959
+ return;
960
+ }
961
+ this.finalizeState = 5 /* FINALIZE_STATE.RESTARTED */;
962
+ startMessage.call(this);
963
+ this.processAssets(...options.args);
964
+ }
965
+ install(name, ...args) {
966
+ if (this.aborted) {
967
+ return;
968
+ }
969
+ const target = args.shift();
970
+ switch (name) {
971
+ case 'document':
972
+ if (isFunction(target) && target.prototype instanceof document_1.default) {
973
+ const instance = new target(...args);
974
+ instance.host = this;
975
+ instance.init(this.getDocumentAssets(instance), this.config);
976
+ observeFile.call(this, instance);
977
+ this.Document.push({ instance, constructor: target, params: args });
978
+ return instance;
979
+ }
980
+ break;
981
+ case 'task':
982
+ if (isFunction(target) && target.prototype instanceof task_1.default && (0, types_1.isPlainObject)(args[0])) {
983
+ const instance = new target(...args);
984
+ instance.host = this;
985
+ instance.init(this.config);
986
+ observeFile.call(this, instance);
987
+ this.Task.push({ instance, constructor: target, params: args });
988
+ return instance;
989
+ }
990
+ break;
991
+ case 'cloud': {
992
+ const database = this.dataSourceItems.filter(item => item.source === 'cloud');
993
+ let instance;
994
+ if (typeof target === 'string') {
995
+ const module = args.shift();
996
+ if ((0, types_1.isObject)(module)) {
997
+ if (target === "@e-mc/cloud" /* PACKAGE_NAME.CLOUD */) {
998
+ instance = new cloud_1.default(module, database);
999
+ }
1000
+ else {
1001
+ try {
1002
+ const Handler = require(target);
1003
+ if (isFunction(Handler) && Handler.prototype instanceof cloud_1.default) {
1004
+ instance = new Handler(module, database);
1005
+ }
1006
+ else {
1007
+ throw (0, types_1.errorMessage)(this.moduleName, "Not a Cloud constructor" /* ERR_CLOUD.CONSTRUCTOR */, target);
1008
+ }
1009
+ }
1010
+ catch (err) {
1011
+ this.checkPackage(err, target, ["Unable to load handler" /* ERR_MESSAGE.LOAD_HANDLER */, this.moduleName], 64 /* LOG_TYPE.CLOUD */);
1012
+ }
1013
+ }
1014
+ }
1015
+ }
1016
+ else if ((0, types_1.isObject)(target)) {
1017
+ instance = new cloud_1.default(target, database);
1018
+ }
1019
+ if (instance) {
1020
+ instance.host = this;
1021
+ instance.init(this.config);
1022
+ observeFile.call(this, instance);
1023
+ return this.Cloud = instance;
1024
+ }
1025
+ break;
1026
+ }
1027
+ case 'watch': {
1028
+ const instance = (0, types_1.isObject)(target) ? new watch_1.default(target) : new watch_1.default(target, args[0], args[1], args[2]);
1029
+ instance.host = this;
1030
+ instance.init(this.config);
1031
+ instance.whenModified = (assets, sanitize, postFinalize) => {
1032
+ if (typeof sanitize === 'function') {
1033
+ postFinalize = sanitize;
1034
+ sanitize = true;
1035
+ }
1036
+ if (sanitize) {
1037
+ FileManager.sanitizeAssets(assets);
1038
+ for (const { instance: document, constructor } of this.Document) {
1039
+ if (constructor.sanitizeAssets) {
1040
+ constructor.sanitizeAssets(assets.filter(item => this.hasDocument(document, item.document)));
1041
+ }
1042
+ }
1043
+ }
1044
+ const manager = new FileManager(this.baseDirectory, { ...this.config, incremental: 'none', assets }, postFinalize);
1045
+ for (const { constructor, params } of this.Document) {
1046
+ manager.install('document', constructor, ...params);
1047
+ }
1048
+ for (const { constructor, params } of this.Task) {
1049
+ manager.install('task', constructor, ...params);
1050
+ }
1051
+ if (this.Cloud) {
1052
+ manager.install('cloud', this.Cloud.module);
1053
+ }
1054
+ if (this.Image) {
1055
+ for (const handler of this.Image) {
1056
+ if ((0, types_1.isPlainObject)(handler)) {
1057
+ const image = handler.instance;
1058
+ image.reset();
1059
+ image.host = manager;
1060
+ observeFile.call(manager, image);
1061
+ }
1062
+ }
1063
+ manager.Image = this.Image;
1064
+ }
1065
+ manager.Compress = this.Compress;
1066
+ manager.sessionId = this.sessionId;
1067
+ manager.permission = this.permission;
1068
+ manager.cacheToDisk = this.cacheToDisk;
1069
+ manager.cacheToMemory = this.cacheToMemory;
1070
+ if (postFinalize) {
1071
+ try {
1072
+ manager.processAssets();
1073
+ }
1074
+ catch (err) {
1075
+ manager.writeFail("Unknown" /* ERR_MESSAGE.UNKNOWN */, err, { startTime: manager.startTime });
1076
+ }
1077
+ }
1078
+ return manager;
1079
+ };
1080
+ return this.Watch = instance;
1081
+ }
1082
+ case 'image':
1083
+ if (target instanceof Map) {
1084
+ const handler = new Map();
1085
+ for (const [mimeType, constructor] of target) {
1086
+ if (constructor.prototype instanceof image_1.default) {
1087
+ const instance = new constructor(args[0]);
1088
+ instance.host = this;
1089
+ instance.init(this.config);
1090
+ observeFile.call(this, instance);
1091
+ handler.set(mimeType, { constructor, instance, params: [] });
1092
+ }
1093
+ }
1094
+ if (handler.size) {
1095
+ this.Image = handler;
1096
+ }
1097
+ }
1098
+ break;
1099
+ case 'compress': {
1100
+ const instance = new compress_1.default(target);
1101
+ instance.host = this;
1102
+ instance.init();
1103
+ observeFile.call(this, instance);
1104
+ return this.Compress = instance;
1105
+ }
1106
+ }
1107
+ }
1108
+ findAsset(value, instance) {
1109
+ let assets, replaced;
1110
+ if ((0, types_1.isPlainObject)(instance)) {
1111
+ ({ instance, assets, replaced } = instance);
1112
+ }
1113
+ let origin, pathname;
1114
+ if (typeof value === 'string') {
1115
+ if (core_1.Host.isURL(value, 'file')) {
1116
+ try {
1117
+ ({ origin, pathname, href: value } = new URL(value));
1118
+ }
1119
+ catch {
1120
+ return;
1121
+ }
1122
+ }
1123
+ else {
1124
+ value = core_1.Host.resolveFile(value);
1125
+ }
1126
+ }
1127
+ else {
1128
+ ({ origin, pathname, href: value } = value);
1129
+ }
1130
+ if (value) {
1131
+ const isSame = (a, b) => a === b || decodeURIComponent(a) === decodeURIComponent(b);
1132
+ const result = (assets || this.assets).filter(item => {
1133
+ let { uri, flags } = item;
1134
+ 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))) {
1135
+ if (origin) {
1136
+ if (!item.url) {
1137
+ try {
1138
+ if ((item.url = new URL(uri)).href === value) {
1139
+ return true;
1140
+ }
1141
+ }
1142
+ catch {
1143
+ }
1144
+ }
1145
+ else if (item.url.href === value) {
1146
+ return true;
1147
+ }
1148
+ }
1149
+ if (isSame(uri, value)) {
1150
+ return true;
1151
+ }
1152
+ const indexA = uri.indexOf('#');
1153
+ const indexB = value.indexOf('#');
1154
+ if (indexA !== -1 || indexB !== -1) {
1155
+ if (indexA !== -1) {
1156
+ uri = uri.substring(0, indexA);
1157
+ }
1158
+ if (indexB !== -1) {
1159
+ value = value.substring(0, indexB);
1160
+ }
1161
+ return isSame(uri, value);
1162
+ }
1163
+ }
1164
+ return false;
1165
+ });
1166
+ if (replaced) {
1167
+ const map = this[kReplaceMap];
1168
+ const target = pathname || core_1.Host.toPosix(value);
1169
+ const found = [];
1170
+ for (const relative in map) {
1171
+ const item = map[relative];
1172
+ if (origin && item.url && item.url.origin !== origin) {
1173
+ continue;
1174
+ }
1175
+ if (path.basename(relative) === path.basename(target) && path.dirname(target).endsWith(path.dirname(relative))) {
1176
+ found.push([item, relative]);
1177
+ }
1178
+ }
1179
+ if (found.length) {
1180
+ if (result.length === 0) {
1181
+ return found.sort((a, b) => b[1].length - a[1].length)[0][0];
1182
+ }
1183
+ result.push(...found.map(item => item[0]));
1184
+ }
1185
+ }
1186
+ return result.sort((a, b) => {
1187
+ if ((a.content || a.base64) && !b.content && !b.base64 || a.uri === value && b.uri !== value) {
1188
+ return -1;
1189
+ }
1190
+ if ((b.content || b.base64) && !a.content && !a.base64 || b.uri === value && a.uri !== value) {
1191
+ return 1;
1192
+ }
1193
+ const bundleId = a.bundleId;
1194
+ if (((0, types_1.isEmpty)(bundleId) || a.bundleIndex === 0) && ((0, types_1.isEmpty)(b.bundleId) || b.bundleIndex === 0)) {
1195
+ if (a.id && b.id) {
1196
+ return a.id < b.id ? -1 : 1;
1197
+ }
1198
+ }
1199
+ else if (!(0, types_1.isEmpty)(bundleId) && bundleId === b.bundleId) {
1200
+ return a.bundleIndex < b.bundleIndex ? -1 : 1;
1201
+ }
1202
+ return 0;
1203
+ })[0];
1204
+ }
1205
+ }
1206
+ removeAsset(file) {
1207
+ const localUri = file.localUri;
1208
+ if (this.has(localUri)) {
1209
+ this.filesToRemove.add(localUri);
1210
+ return true;
1211
+ }
1212
+ return false;
1213
+ }
1214
+ removeCwd(value) {
1215
+ if (typeof value === 'string') {
1216
+ let baseDir = this.baseDirectory + path.sep, leading = value.substring(0, baseDir.length);
1217
+ if (PLATFORM_WIN32) {
1218
+ baseDir = baseDir.toLowerCase();
1219
+ leading = leading.toLowerCase();
1220
+ }
1221
+ if (leading === baseDir) {
1222
+ return value.substring(baseDir.length);
1223
+ }
1224
+ }
1225
+ return '';
1226
+ }
1227
+ replace(file, replaceWith, mimeType) {
1228
+ let ignoreExt, rewritePath;
1229
+ if ((0, types_1.isPlainObject)(mimeType)) {
1230
+ ({ mimeType, ignoreExt, rewritePath } = mimeType);
1231
+ }
1232
+ const { pathname, filename, localUri } = file;
1233
+ if (replaceWith !== localUri) {
1234
+ const name = path.basename(replaceWith);
1235
+ if (!ignoreExt && localUri && path.extname(localUri) === path.extname(replaceWith)) {
1236
+ try {
1237
+ if (!core_1.Host.renameFile(replaceWith, localUri)) {
1238
+ this.filesToRemove.add(replaceWith);
1239
+ }
1240
+ }
1241
+ catch (err) {
1242
+ this.writeFail(["Unable to rename file" /* ERR_MESSAGE.RENAME_FILE */, name], err, 32 /* LOG_TYPE.FILE */);
1243
+ return false;
1244
+ }
1245
+ }
1246
+ else {
1247
+ (0, asset_1.setInitialValue)(file);
1248
+ if (rewritePath || !localUri) {
1249
+ file.pathname = this.removeCwd(path.dirname(replaceWith));
1250
+ }
1251
+ file.filename = name;
1252
+ const replacePath = this.setLocalUri(file, true).localUri;
1253
+ if (replaceWith !== replacePath) {
1254
+ try {
1255
+ if (!core_1.Host.renameFile(replaceWith, replacePath)) {
1256
+ this.filesToRemove.add(replaceWith);
1257
+ }
1258
+ }
1259
+ catch (err) {
1260
+ file.pathname = pathname;
1261
+ file.filename = filename;
1262
+ this.setLocalUri(file, true);
1263
+ this.writeFail(["Unable to rename file" /* ERR_MESSAGE.RENAME_FILE */, name], err, 32 /* LOG_TYPE.FILE */);
1264
+ return false;
1265
+ }
1266
+ }
1267
+ file.mimeType = mimeType || core_1.Host.lookupMime(name) || file.mimeType;
1268
+ this.add(replaceWith);
1269
+ if (localUri && !this.assets.find(item => item.localUri === localUri && !item.invalid)) {
1270
+ this.filesToRemove.add(localUri);
1271
+ }
1272
+ this[kReplaceMap][core_1.Host.joinPath(file.pathname, file.filename)] = file;
1273
+ }
1274
+ }
1275
+ delete file.buffer;
1276
+ delete file.sourceUTF8;
1277
+ return true;
1278
+ }
1279
+ rename(file, value) {
1280
+ const segments = [file.pathname, value];
1281
+ if (file.moveTo) {
1282
+ segments.unshift(file.moveTo);
1283
+ }
1284
+ const oldPath = file.localUri;
1285
+ const newPath = path.join(this.baseDirectory, ...segments);
1286
+ if (oldPath !== newPath) {
1287
+ if (oldPath) {
1288
+ const copy = this.assets.find(other => file !== other && oldPath === other.localUri);
1289
+ try {
1290
+ if (fs.existsSync(oldPath)) {
1291
+ if (copy) {
1292
+ fs.copyFileSync(oldPath, newPath);
1293
+ }
1294
+ else if (!core_1.Host.renameFile(oldPath, newPath)) {
1295
+ this.filesToRemove.add(oldPath);
1296
+ }
1297
+ }
1298
+ }
1299
+ catch (err) {
1300
+ this.writeFail(["Unable to rename file" /* ERR_MESSAGE.RENAME_FILE */, path.basename(value)], err, 32 /* LOG_TYPE.FILE */);
1301
+ return false;
1302
+ }
1303
+ if (!copy) {
1304
+ this.delete(oldPath);
1305
+ }
1306
+ }
1307
+ (0, asset_1.setInitialValue)(file);
1308
+ file.filename = value;
1309
+ this.add(file.localUri = this.setLocalUri(file, true).localUri);
1310
+ }
1311
+ return true;
1312
+ }
1313
+ performAsyncTask() {
1314
+ ++this[kDelayed];
1315
+ }
1316
+ removeAsyncTask() {
1317
+ --this[kDelayed];
1318
+ }
1319
+ completeAsyncTask(err, uri, parent, type) {
1320
+ if (this[kDelayed] !== Infinity) {
1321
+ if (!err && uri) {
1322
+ this.add(uri, parent, type);
1323
+ }
1324
+ this.removeAsyncTask();
1325
+ this.performFinalize();
1326
+ }
1327
+ if (err) {
1328
+ this.writeFail(["Unknown" /* ERR_MESSAGE.UNKNOWN */, uri], err, 32 /* LOG_TYPE.FILE */);
1329
+ }
1330
+ }
1331
+ performFinalize(override) {
1332
+ const state = this.finalizeState;
1333
+ if (state === 0 /* FINALIZE_STATE.READY */ && (this.cleared && this[kDelayed] <= 0 || override) || (this.aborted || state === 3 /* FINALIZE_STATE.RESTART */) && override) {
1334
+ this.clearProcessTimeout();
1335
+ this[kDelayed] = Infinity;
1336
+ const resetState = () => {
1337
+ this.finalizeState = 2 /* FINALIZE_STATE.END */;
1338
+ this._pendingResult = null;
1339
+ };
1340
+ const aborted = (err) => {
1341
+ if (!this.restarting) {
1342
+ this.writeFail(["Transaction was not completed" /* ERR_MESSAGE.INCOMPLETE */, this.baseDirectory], err);
1343
+ resetState();
1344
+ }
1345
+ else {
1346
+ this.finalizeState = 4 /* FINALIZE_STATE.QUEUED */;
1347
+ }
1348
+ this.emit('end', [], collectErrors.call(this), this.collectLog());
1349
+ if (!this.restarting) {
1350
+ this.done = true;
1351
+ }
1352
+ };
1353
+ if (this.aborted) {
1354
+ aborted((0, types_1.createAbortError)());
1355
+ return;
1356
+ }
1357
+ this.finalizeState = 1 /* FINALIZE_STATE.COMMIT */;
1358
+ this.finalize()
1359
+ .then(() => {
1360
+ const errors = collectErrors.call(this);
1361
+ const files = Array.from(this.files).sort((a, b) => {
1362
+ const sep = path.sep;
1363
+ if (a.indexOf(sep) !== -1 && b.indexOf(sep) === -1) {
1364
+ return -1;
1365
+ }
1366
+ if (a.indexOf(sep) === -1 && b.indexOf(sep) !== -1) {
1367
+ return 1;
1368
+ }
1369
+ return a < b ? -1 : 1;
1370
+ });
1371
+ if (LOG_TIMEELAPSED) {
1372
+ this.writeTimeElapsed('END', this.baseDirectory, this.startTime, errors.length > 0 ? { failed: true, ...core_1.Host.LOG_STYLE_FAIL } : { ...core_1.Host.LOG_STYLE_SUCCESS });
1373
+ }
1374
+ resetState();
1375
+ const log = this.config.log;
1376
+ let useNumeric = false, showSize = true;
1377
+ if ((0, types_1.isPlainObject)(log)) {
1378
+ ({ useNumeric, showSize = true } = log);
1379
+ }
1380
+ const items = !showSize ? files : files.map(name => {
1381
+ const size = (0, lib_v4_1.getSize)(path.join(this.baseDirectory, name));
1382
+ return { name, size: useNumeric ? size : (0, types_1.formatSize)(size) };
1383
+ });
1384
+ this.emit('end', items, errors, this.collectLog());
1385
+ this.done = true;
1386
+ })
1387
+ .catch(err => aborted(err));
1388
+ }
1389
+ }
1390
+ hasDocument(instance, document) {
1391
+ const moduleName = instance.moduleName;
1392
+ return document === moduleName || Array.isArray(document) && document.includes(moduleName);
1393
+ }
1394
+ setLocalUri(file, replace) {
1395
+ let uri = file.uri, torrent;
1396
+ if (uri && !file.content && !file.base64 && !file.url) {
1397
+ if (core_1.Host.isFile(uri, 'torrent')) {
1398
+ torrent = true;
1399
+ }
1400
+ else if (core_1.Host.isURL(uri, 'file')) {
1401
+ if (!core_1.Host.isFile(uri, 's/ftp')) {
1402
+ try {
1403
+ file.url = new URL(uri);
1404
+ file.uri = file.url.toString();
1405
+ }
1406
+ catch (err) {
1407
+ this.writeFail(['Unable to parse URL', uri], err, 1024 /* LOG_TYPE.HTTP */);
1408
+ return { pathname: '', localUri: '' };
1409
+ }
1410
+ }
1411
+ }
1412
+ else {
1413
+ try {
1414
+ const errorAbsolute = (value) => (0, types_1.errorValue)('Path not absolute', value);
1415
+ if (!(file.uri = core_1.Host.resolveFile(uri))) {
1416
+ throw errorAbsolute(uri);
1417
+ }
1418
+ if (file.socketPath) {
1419
+ if (!path.isAbsolute(file.socketPath)) {
1420
+ throw errorAbsolute(file.socketPath);
1421
+ }
1422
+ if (!path.isAbsolute(uri = file.uri)) {
1423
+ throw errorAbsolute(uri);
1424
+ }
1425
+ const url = new URL('file://' + uri);
1426
+ file.url = url;
1427
+ file.uri = url.toString();
1428
+ }
1429
+ }
1430
+ catch (err) {
1431
+ this.writeFail(['Unable to resolve file location', uri], err, 32 /* LOG_TYPE.FILE */);
1432
+ return { pathname: '', localUri: '' };
1433
+ }
1434
+ }
1435
+ }
1436
+ const url = file.url;
1437
+ let type;
1438
+ if (url) {
1439
+ if (url.protocol.startsWith('http')) {
1440
+ type = 1 /* FETCH_TYPE.HTTP */;
1441
+ }
1442
+ else if (file.socketPath && url.protocol === 'file:') {
1443
+ type = 2 /* FETCH_TYPE.UNIX_SOCKET */;
1444
+ }
1445
+ }
1446
+ if (!type && uri) {
1447
+ if (core_1.Host.isFile(uri, 'torrent')) {
1448
+ type = 4 /* FETCH_TYPE.TORRENT */;
1449
+ }
1450
+ else if (core_1.Host.isFile(uri, 's/ftp')) {
1451
+ type = 3 /* FETCH_TYPE.FTP */;
1452
+ }
1453
+ }
1454
+ file.fetchType = type;
1455
+ const segments = [];
1456
+ if (file.moveTo) {
1457
+ segments.push(file.moveTo);
1458
+ }
1459
+ if (file.pathname) {
1460
+ segments.push(file.pathname = core_1.Host.toPosix(file.pathname));
1461
+ }
1462
+ if (file.document) {
1463
+ for (const { instance } of this.Document) {
1464
+ if (instance.setLocalUri && this.hasDocument(instance, file.document)) {
1465
+ instance.setLocalUri(file, replace);
1466
+ }
1467
+ }
1468
+ }
1469
+ const pathname = segments.length ? path.join(this.baseDirectory, ...segments) : this.baseDirectory;
1470
+ const localUri = file.filename ? path.join(pathname, file.filename) : pathname;
1471
+ file.localUri = localUri;
1472
+ if (!torrent) {
1473
+ file.mimeType || (file.mimeType = file.url && core_1.Host.lookupMime(path.basename(file.url.pathname)) || core_1.Host.lookupMime(file.filename));
1474
+ }
1475
+ return { pathname, localUri };
1476
+ }
1477
+ getLocalUri(data) {
1478
+ return data.file.localUri || '';
1479
+ }
1480
+ getMimeType(data) {
1481
+ return data.mimeType || (data.mimeType = data.file.mimeType || core_1.Host.lookupMime(path.basename(this.getLocalUri(data))));
1482
+ }
1483
+ getDocumentAssets(instance, condition) {
1484
+ return this.documentAssets.filter(item => this.hasDocument(instance, item.document) && (!condition || condition(item)));
1485
+ }
1486
+ getDataSourceItems(instance, condition) {
1487
+ return this.dataSourceItems.filter(item => this.hasDocument(instance, item.document) && (!condition || condition(item)));
1488
+ }
1489
+ getUTF8String(file, uri) {
1490
+ let sourceUTF8 = file.sourceUTF8;
1491
+ if (!sourceUTF8) {
1492
+ file.encoding = (0, types_1.getEncoding)(file.encoding);
1493
+ if (file.buffer) {
1494
+ sourceUTF8 = file.buffer.toString(file.encoding);
1495
+ delete file.buffer;
1496
+ }
1497
+ else if (uri || (uri = file.localUri)) {
1498
+ try {
1499
+ sourceUTF8 = fs.readFileSync(uri, file.encoding);
1500
+ }
1501
+ catch (err) {
1502
+ this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(uri)], err, 32 /* LOG_TYPE.FILE */);
1503
+ }
1504
+ }
1505
+ if (sourceUTF8?.[0] === '\uFEFF' && file.encoding !== 'utf16le') {
1506
+ sourceUTF8 = sourceUTF8.substring(1);
1507
+ }
1508
+ return file.sourceUTF8 = sourceUTF8 || '';
1509
+ }
1510
+ return sourceUTF8;
1511
+ }
1512
+ getBuffer(file) {
1513
+ if (file.buffer) {
1514
+ return file.buffer;
1515
+ }
1516
+ const uri = file.localUri;
1517
+ if (uri) {
1518
+ try {
1519
+ return fs.readFileSync(uri);
1520
+ }
1521
+ catch (err) {
1522
+ this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(uri)], err, 32 /* LOG_TYPE.FILE */);
1523
+ }
1524
+ }
1525
+ return file.base64 ? Buffer.from(file.base64, 'base64') : null;
1526
+ }
1527
+ getCacheDir(url, createDir = true) {
1528
+ if (typeof url === 'string') {
1529
+ try {
1530
+ url = new URL(url);
1531
+ }
1532
+ catch {
1533
+ return '';
1534
+ }
1535
+ }
1536
+ return this.getTempDir({ pathname: url.hostname + '_' + (url.port || (url.protocol === 'https:' ? '443' : '80')), moduleDir: true, createDir });
1537
+ }
1538
+ setAssetContent(file, content, options) {
1539
+ let trailing = (0, util_2.concatString)(file.trailingContent);
1540
+ if (file.document) {
1541
+ for (const { instance } of this.Document) {
1542
+ if (instance.resolveUri && this.hasDocument(instance, file.document)) {
1543
+ if (trailing) {
1544
+ [content, trailing] = instance.resolveUri(file, content, trailing);
1545
+ }
1546
+ else {
1547
+ content = instance.resolveUri(file, content);
1548
+ }
1549
+ }
1550
+ }
1551
+ }
1552
+ if (trailing) {
1553
+ content += trailing;
1554
+ file.trailingContent = trailing;
1555
+ }
1556
+ if (options) {
1557
+ const { localUri, bundleIndex = 0 } = options;
1558
+ if (bundleIndex > 0) {
1559
+ let appending = this.contentToAppend.get(localUri), replacing = this.contentToReplace.get(localUri);
1560
+ if (!appending) {
1561
+ this.contentToAppend.set(localUri, appending = []);
1562
+ }
1563
+ if (!replacing) {
1564
+ this.contentToReplace.set(localUri, replacing = []);
1565
+ }
1566
+ appending[bundleIndex - 1] = content;
1567
+ if ((0, types_1.isString)(options.bundleReplace)) {
1568
+ replacing[bundleIndex - 1] = options.bundleReplace;
1569
+ }
1570
+ file.invalid = true;
1571
+ return '';
1572
+ }
1573
+ }
1574
+ return file.sourceUTF8 = content;
1575
+ }
1576
+ getAssetContent({ localUri, document, mimeType }, content) {
1577
+ const appending = this.contentToAppend.get(localUri);
1578
+ if (appending) {
1579
+ let newline;
1580
+ const getSeparator = (value) => newline || (newline = (0, util_2.getNewline)(value));
1581
+ if (content) {
1582
+ const replacing = this.contentToReplace.get(localUri);
1583
+ if (replacing?.length) {
1584
+ for (let i = 0; i < replacing.length; ++i) {
1585
+ let value = appending[i];
1586
+ if ((0, types_1.isString)(value)) {
1587
+ if (replacing[i]) {
1588
+ const match = new RegExp(replacing[i], 'i').exec(content);
1589
+ if (match) {
1590
+ if (document) {
1591
+ for (const { instance } of this.Document) {
1592
+ if (instance.replaceContent && this.hasDocument(instance, document)) {
1593
+ const output = instance.replaceContent(value, match, mimeType);
1594
+ if (output) {
1595
+ value = output;
1596
+ break;
1597
+ }
1598
+ }
1599
+ }
1600
+ }
1601
+ content = content.substring(0, match.index) + value + getSeparator(content) + content.substring(match.index + match[0].length);
1602
+ continue;
1603
+ }
1604
+ }
1605
+ content += getSeparator(content) + value;
1606
+ }
1607
+ }
1608
+ return content;
1609
+ }
1610
+ }
1611
+ return (content || '') + appending.reduce((a, b) => b ? a + getSeparator(b) + b : a, '');
1612
+ }
1613
+ return content;
1614
+ }
1615
+ writeBuffer(file, options) {
1616
+ const buffer = file.sourceUTF8 ? Buffer.from(file.sourceUTF8, file.encoding || (file.encoding = 'utf-8')) : file.buffer;
1617
+ const localUri = file.localUri;
1618
+ if (buffer && localUri) {
1619
+ try {
1620
+ this.writeFile(localUri, buffer, { ...options, throwsPermission: true });
1621
+ return file.buffer = buffer;
1622
+ }
1623
+ catch (err) {
1624
+ this.writeFail(["Unable to write file" /* ERR_MESSAGE.WRITE_FILE */, path.basename(localUri)], err, 8192 /* LOG_TYPE.PERMISSION */);
1625
+ }
1626
+ }
1627
+ return null;
1628
+ }
1629
+ writeImage(document, output) {
1630
+ output.baseDirectory || (output.baseDirectory = this.baseDirectory);
1631
+ for (const { instance } of this.Document) {
1632
+ if (instance.writeImage && this.hasDocument(instance, document) && instance.writeImage(output)) {
1633
+ return true;
1634
+ }
1635
+ }
1636
+ return false;
1637
+ }
1638
+ addCopy(data, saveAs, replace = true) {
1639
+ const localUri = this.getLocalUri(data);
1640
+ if (!localUri) {
1641
+ return;
1642
+ }
1643
+ const document = data.file.document;
1644
+ const ext = path.extname(localUri).substring(1);
1645
+ let output;
1646
+ saveAs || (saveAs = ext);
1647
+ if (document) {
1648
+ for (const { instance } of this.Document) {
1649
+ if (instance.addCopy && this.hasDocument(instance, document) && (output = instance.addCopy(data, saveAs, replace))) {
1650
+ this.filesQueued.add(output);
1651
+ return output;
1652
+ }
1653
+ }
1654
+ }
1655
+ if (data.outputType && this.getMimeType(data) === data.outputType || ext === saveAs) {
1656
+ if (!replace || this.filesQueued.has(localUri)) {
1657
+ let i = 1;
1658
+ do {
1659
+ output = (0, types_1.renameExt)(localUri, '__copy__.' + (i > 1 ? `(${i}).` : '') + saveAs);
1660
+ } while (this.filesQueued.has(output) && ++i);
1661
+ try {
1662
+ fs.copyFileSync(localUri, output);
1663
+ }
1664
+ catch (err) {
1665
+ this.writeFail(["Unable to copy file" /* ERR_MESSAGE.COPY_FILE */, path.basename(localUri)], err, 32 /* LOG_TYPE.FILE */);
1666
+ return;
1667
+ }
1668
+ }
1669
+ }
1670
+ else {
1671
+ let i = 1;
1672
+ do {
1673
+ output = (0, types_1.renameExt)(localUri, (i > 1 ? `(${i}).` : '') + saveAs);
1674
+ if (replace) {
1675
+ break;
1676
+ }
1677
+ } while (this.filesQueued.has(output) && ++i);
1678
+ }
1679
+ this.filesQueued.add(output || (output = localUri));
1680
+ return output;
1681
+ }
1682
+ async findMime(file, rename) {
1683
+ const localUri = file.localUri;
1684
+ if (!localUri) {
1685
+ return '';
1686
+ }
1687
+ let mimeType = '', ext;
1688
+ try {
1689
+ const result = await core_1.Host.resolveMime(file.buffer || localUri);
1690
+ if (result) {
1691
+ ({ mime: mimeType, ext } = result);
1692
+ }
1693
+ }
1694
+ catch (err) {
1695
+ this.writeFail(["Unable to read buffer" /* ERR_MESSAGE.READ_BUFFER */, path.basename(localUri)], err, 32 /* LOG_TYPE.FILE */);
1696
+ }
1697
+ if (rename) {
1698
+ if (!ext) {
1699
+ file.invalid = true;
1700
+ }
1701
+ else {
1702
+ const output = (0, types_1.renameExt)(localUri, ext);
1703
+ if (localUri !== output) {
1704
+ try {
1705
+ const success = core_1.Host.renameFile(localUri, output);
1706
+ this.replace(file, output, mimeType);
1707
+ if (!success) {
1708
+ this.filesToRemove.add(localUri);
1709
+ }
1710
+ }
1711
+ catch (err) {
1712
+ this.writeFail(["Unable to rename file" /* ERR_MESSAGE.RENAME_FILE */, path.basename(output)], err, 32 /* LOG_TYPE.FILE */);
1713
+ }
1714
+ }
1715
+ }
1716
+ }
1717
+ if (mimeType) {
1718
+ file.mimeType = mimeType;
1719
+ }
1720
+ return mimeType;
1721
+ }
1722
+ compressFile(file, overwrite = true) {
1723
+ const { localUri, compress } = file;
1724
+ const instance = this.Compress;
1725
+ if (instance && compress && localUri && (this.has(localUri) || (0, types_1.existsFlag)(file.flags))) {
1726
+ const tasks = [];
1727
+ for (const config of compress) {
1728
+ const { format, condition } = config;
1729
+ let output;
1730
+ switch (format) {
1731
+ case 'br':
1732
+ config.mimeType || (config.mimeType = file.mimeType);
1733
+ case 'gz':
1734
+ output = localUri + '.' + format;
1735
+ break;
1736
+ case 'woff':
1737
+ case 'woff2':
1738
+ output = (0, types_1.renameExt)(localUri, format);
1739
+ config.filename = file.filename;
1740
+ config.etag = file.etag;
1741
+ break;
1742
+ default:
1743
+ if (format && typeof instance.compressors[format] === 'function') {
1744
+ output = (0, types_1.renameExt)(localUri, format);
1745
+ }
1746
+ break;
1747
+ }
1748
+ if (output && (!condition || withinSizeRange(localUri, condition))) {
1749
+ try {
1750
+ if (overwrite || !fs.existsSync(output) || !(0, types_1.existsFlag)(file.flags) && fs.statSync(output).mtimeMs < this.startTime) {
1751
+ config.timeout = this[kProcessTimeout].compress ?? PROCESS_TIMEOUT.compress;
1752
+ tasks.push(instance.tryFile(file.buffer || localUri, output, config, (err, result) => {
1753
+ if (err) {
1754
+ this.writeFail(["Unable to compress file" /* ERR_MESSAGE.COMPRESS_FILE */, path.basename(localUri)], err, { type: 8 /* LOG_TYPE.COMPRESS */, startTime: config.startTime });
1755
+ }
1756
+ else if ((0, types_1.isString)(result)) {
1757
+ if (condition?.includes('%') && (0, lib_v4_1.getSize)(result) >= (0, lib_v4_1.getSize)(localUri)) {
1758
+ queueMicrotask(() => this.deleteFile(result));
1759
+ }
1760
+ else {
1761
+ this.add(result, file, types_1.FILE_TYPE.COMPRESSED);
1762
+ }
1763
+ }
1764
+ }));
1765
+ }
1766
+ }
1767
+ catch (err) {
1768
+ this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(output)], err, 32 /* LOG_TYPE.FILE */);
1769
+ }
1770
+ }
1771
+ }
1772
+ if (tasks.length) {
1773
+ return Promise.all(tasks);
1774
+ }
1775
+ }
1776
+ return Promise.resolve([]);
1777
+ }
1778
+ async transformAsset(data, parent) {
1779
+ const file = data.file;
1780
+ const localUri = this.getLocalUri(data);
1781
+ if (!this.aborted) {
1782
+ this.processing.push(data);
1783
+ let mimeType = file.mimeType;
1784
+ if ((mimeType?.endsWith('unknown') || file.commands && !mimeType) && (mimeType = await this.findMime(data.file, true))) {
1785
+ file.mimeType = mimeType;
1786
+ data.mimeType = mimeType;
1787
+ }
1788
+ const errorAsset = (instance, err, type = 4 /* LOG_TYPE.PROCESS */) => rejectModule.call(instance, err, type, path.basename(localUri));
1789
+ if (file.tasks) {
1790
+ const taskName = [];
1791
+ for (const { task, handler: moduleName, preceding } of file.tasks) {
1792
+ if (task && preceding && moduleName && !taskName.includes(moduleName) && !data.aborted) {
1793
+ const handler = this.Task.find(item => item.instance.moduleName === moduleName);
1794
+ if (handler) {
1795
+ const { instance, constructor } = handler;
1796
+ if (instance.using || constructor.using) {
1797
+ try {
1798
+ if (instance.threadable) {
1799
+ if (this.openThread(instance, data, this.getProcessTimeout(handler))) {
1800
+ (instance.using ? instance.using(data) : constructor.using.call(this, instance, [file], true))
1801
+ .then(() => this.closeThread(instance, data))
1802
+ .catch(err => {
1803
+ this.closeThread(instance, data);
1804
+ errorAsset(instance, err);
1805
+ });
1806
+ }
1807
+ }
1808
+ else if (!this.aborted) {
1809
+ this.addProcessTimeout(instance, file, this.getProcessTimeout(handler));
1810
+ await (instance.using ? instance.using(data) : constructor.using.call(this, instance, [file], true));
1811
+ }
1812
+ }
1813
+ catch (err) {
1814
+ errorAsset(instance, err);
1815
+ }
1816
+ taskName.push(moduleName);
1817
+ }
1818
+ }
1819
+ }
1820
+ }
1821
+ }
1822
+ if (image_1.default.isBinary(mimeType)) {
1823
+ if (file.commands && this.Image) {
1824
+ const handler = this.Image.get(mimeType) || this.Image.get('handler');
1825
+ if (handler) {
1826
+ const { instance, constructor } = handler;
1827
+ if (instance.using || constructor.using) {
1828
+ for (const command of file.commands) {
1829
+ if (withinSizeRange(localUri, command, constructor.REGEXP_SIZERANGE) && !data.aborted) {
1830
+ try {
1831
+ if (instance.threadable) {
1832
+ if (this.openThread(instance, data, this.getProcessTimeout(handler))) {
1833
+ (instance.using ? instance.using(data, command) : constructor.using.call(this, instance, data, command))
1834
+ .then(() => this.closeThread(instance, data))
1835
+ .catch(err => {
1836
+ this.closeThread(instance, data);
1837
+ errorAsset(instance, err, 2048 /* LOG_TYPE.IMAGE */);
1838
+ });
1839
+ }
1840
+ }
1841
+ else if (!this.aborted) {
1842
+ this.addProcessTimeout(instance, file, this.getProcessTimeout(handler));
1843
+ await (instance.using ? instance.using(data, command) : constructor.using.call(this, instance, data, command));
1844
+ }
1845
+ }
1846
+ catch (err) {
1847
+ errorAsset(instance, err, 2048 /* LOG_TYPE.IMAGE */);
1848
+ }
1849
+ }
1850
+ }
1851
+ }
1852
+ }
1853
+ }
1854
+ }
1855
+ else if (file.document) {
1856
+ for (const handler of this.Document) {
1857
+ const { instance, constructor } = handler;
1858
+ if ((instance.using || constructor.using) && this.hasDocument(instance, file.document) && !data.aborted) {
1859
+ try {
1860
+ if (instance.threadable) {
1861
+ if (this.openThread(instance, data, this.getProcessTimeout(handler))) {
1862
+ (instance.using ? instance.using(data) : constructor.using.call(this, instance, file))
1863
+ .then(() => this.closeThread(instance, data))
1864
+ .catch(err => {
1865
+ this.closeThread(instance, data);
1866
+ errorAsset(instance, err);
1867
+ });
1868
+ }
1869
+ }
1870
+ else if (!this.aborted) {
1871
+ this.addProcessTimeout(instance, file, this.getProcessTimeout(handler));
1872
+ await (instance.using ? instance.using(data) : constructor.using.call(this, instance, file));
1873
+ }
1874
+ }
1875
+ catch (err) {
1876
+ errorAsset(instance, err);
1877
+ }
1878
+ }
1879
+ }
1880
+ }
1881
+ }
1882
+ this.closeThread(null, data, () => {
1883
+ if (!file.invalid) {
1884
+ this.add(localUri, parent);
1885
+ }
1886
+ else if (localUri && (0, types_1.isEmpty)(file.bundleId)) {
1887
+ this.deleteFile(localUri, { emptyDir: true });
1888
+ }
1889
+ });
1890
+ }
1891
+ openThread(instance, data, timeout = 0) {
1892
+ if (this.aborted || data.aborted) {
1893
+ return false;
1894
+ }
1895
+ core_1.AbortComponent.attach(data, instance.signal);
1896
+ if (timeout > 0) {
1897
+ this.addProcessTimeout(instance, data.file, timeout);
1898
+ }
1899
+ this.performAsyncTask();
1900
+ ++data.threadCount;
1901
+ return true;
1902
+ }
1903
+ closeThread(instance, data, callback) {
1904
+ if (data.aborted) {
1905
+ return false;
1906
+ }
1907
+ if (instance) {
1908
+ core_1.AbortComponent.detach(data, instance.signal);
1909
+ this.removeProcessTimeout(instance, data.file);
1910
+ }
1911
+ if (typeof callback === 'function') {
1912
+ data.queuedTasks.push(callback);
1913
+ }
1914
+ else {
1915
+ this.removeAsyncTask();
1916
+ }
1917
+ if (--data.threadCount === 0) {
1918
+ const index = this.processing.findIndex(item => item === data);
1919
+ if (index !== -1) {
1920
+ this.processing.splice(index, 1);
1921
+ }
1922
+ data.queuedTasks.forEach(task => {
1923
+ try {
1924
+ task();
1925
+ }
1926
+ catch (err) {
1927
+ this.writeFail(["Unable to perform task" /* ERR_MESSAGE.PERFORM_TASK */, path.basename(this.getLocalUri(data))], err);
1928
+ }
1929
+ this.removeAsyncTask();
1930
+ });
1931
+ this.performFinalize();
1932
+ return true;
1933
+ }
1934
+ return false;
1935
+ }
1936
+ addProcessTimeout(instance, file, timeout) {
1937
+ if (timeout > 0) {
1938
+ const processModule = file.processModule || (file.processModule = {});
1939
+ const current = processModule[instance.moduleName];
1940
+ if (current) {
1941
+ current.timeout += timeout;
1942
+ ++current.threadCount;
1943
+ }
1944
+ else {
1945
+ processModule[instance.moduleName] = { threadCount: 1, startTime: Date.now(), timeout };
1946
+ }
1947
+ }
1948
+ }
1949
+ removeProcessTimeout(instance, file) {
1950
+ const processModule = file.processModule;
1951
+ if (processModule) {
1952
+ const current = processModule[instance.moduleName];
1953
+ if (current && --current.threadCount === 0) {
1954
+ delete processModule[instance.moduleName];
1955
+ }
1956
+ }
1957
+ }
1958
+ getProcessTimeout(handler) {
1959
+ const moduleName = handler.instance.moduleName;
1960
+ return this[kProcessTimeout][moduleName] ?? PROCESS_TIMEOUT[moduleName] ?? (handler.constructor.PROCESS_TIMEOUT || 0);
1961
+ }
1962
+ clearProcessTimeout() {
1963
+ const timerMain = this[KTimerMain];
1964
+ if (timerMain) {
1965
+ clearInterval(timerMain);
1966
+ this[KTimerMain] = null;
1967
+ }
1968
+ }
1969
+ addDownload(value, type = 0, encoding) {
1970
+ if (typeof type === 'string') {
1971
+ encoding = type;
1972
+ type = 0;
1973
+ }
1974
+ let result = 0;
1975
+ if (typeof value === 'number') {
1976
+ result = value;
1977
+ }
1978
+ else if (typeof value === 'string') {
1979
+ if ((result = (0, lib_v4_1.byteLength)(value, encoding)) === 0) {
1980
+ return 0;
1981
+ }
1982
+ }
1983
+ else if (Buffer.isBuffer(value)) {
1984
+ result = value.length;
1985
+ }
1986
+ else {
1987
+ return 0;
1988
+ }
1989
+ const stat = this[kDownloadStats][type];
1990
+ stat[0] += result;
1991
+ stat[1]++;
1992
+ return result;
1993
+ }
1994
+ getDownload(type = 0) {
1995
+ return this[kDownloadStats][type];
1996
+ }
1997
+ fetchObject(uri, options) {
1998
+ if (!(0, types_1.isObject)(options)) {
1999
+ options = { format: options };
2000
+ }
2001
+ options.format || (options.format = 'json');
2002
+ return this.fetchBuffer(uri, options).then(data => typeof data === 'object' ? data : null).catch(() => null);
2003
+ }
2004
+ fetchBuffer(uri, options) {
2005
+ if (options) {
2006
+ options.format = undefined;
2007
+ }
2008
+ return this.Request.get(uri, options).then(buffer => {
2009
+ let encoding, pipeTo;
2010
+ if (options) {
2011
+ ({ encoding, pipeTo } = options);
2012
+ }
2013
+ if (buffer) {
2014
+ this.addDownload(Buffer.byteLength(buffer, encoding));
2015
+ }
2016
+ else if ((0, types_1.isString)(pipeTo) && core_1.Host.isPath(pipeTo, true)) {
2017
+ this.addDownload(pipeTo);
2018
+ }
2019
+ return buffer;
2020
+ });
2021
+ }
2022
+ fetchFiles(uri, options) {
2023
+ if (!(0, types_1.isObject)(options)) {
2024
+ options = { pathname: options };
2025
+ }
2026
+ options.pathname || (options.pathname = this.baseDirectory);
2027
+ return this.Request.aria2c(uri, options);
2028
+ }
2029
+ start(emptyDir) {
2030
+ const listener = (resolve) => {
2031
+ const callback = (files, errors, status) => {
2032
+ if (!this.restarting) {
2033
+ this.removeListener('end', callback);
2034
+ resolve({ files, errors, status, aborted: this.aborted });
2035
+ }
2036
+ };
2037
+ return callback;
2038
+ };
2039
+ if (this.aborted) {
2040
+ const pending = this._pendingResult;
2041
+ if (pending) {
2042
+ queueMicrotask(() => abortedHost.call(this));
2043
+ this._pendingResult = null;
2044
+ return pending;
2045
+ }
2046
+ return new Promise(resolve => {
2047
+ this.on('end', listener(resolve));
2048
+ queueMicrotask(() => {
2049
+ if (!abortedHost.call(this)) {
2050
+ this.restarting = false;
2051
+ this.emit('end', [], collectErrors.call(this), this.collectLog());
2052
+ this.done = true;
2053
+ }
2054
+ });
2055
+ });
2056
+ }
2057
+ switch (this.finalizeState) {
2058
+ case 0 /* FINALIZE_STATE.READY */:
2059
+ if (this.delayed === 0 && !this.cleared) {
2060
+ break;
2061
+ }
2062
+ case 1 /* FINALIZE_STATE.COMMIT */:
2063
+ case 3 /* FINALIZE_STATE.RESTART */:
2064
+ case 5 /* FINALIZE_STATE.RESTARTED */:
2065
+ case 4 /* FINALIZE_STATE.QUEUED */:
2066
+ if (this._pendingResult) {
2067
+ return this._pendingResult;
2068
+ }
2069
+ this.finalizeState = 0 /* FINALIZE_STATE.READY */;
2070
+ case 2 /* FINALIZE_STATE.END */:
2071
+ resetAssets.call(this);
2072
+ break;
2073
+ }
2074
+ return this._pendingResult || (this._pendingResult = new Promise((resolve, reject) => {
2075
+ this.on('end', listener(resolve));
2076
+ try {
2077
+ this.processAssets(emptyDir);
2078
+ }
2079
+ catch (err) {
2080
+ this.done = true;
2081
+ reject(err);
2082
+ }
2083
+ }));
2084
+ }
2085
+ processAssets(emptyDir, targeted) {
2086
+ if (this.aborted) {
2087
+ abortedHost.call(this);
2088
+ return;
2089
+ }
2090
+ if (this.finalizeState === 5 /* FINALIZE_STATE.RESTARTED */) {
2091
+ this.restarting = false;
2092
+ }
2093
+ else if (this._pendingResult) {
2094
+ return;
2095
+ }
2096
+ if (!this.canWrite(this.baseDirectory, { ownPermissionOnly: true })) {
2097
+ this.writeFail("Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, new Error(this.baseDirectory), 8192 /* LOG_TYPE.PERMISSION */);
2098
+ this.cleared = true;
2099
+ if (this.queued) {
2100
+ this.joinQueue({ reject: true });
2101
+ }
2102
+ return;
2103
+ }
2104
+ switch (this.finalizeState) {
2105
+ case 0 /* FINALIZE_STATE.READY */:
2106
+ if (this.delayed === 0 && !this.cleared) {
2107
+ break;
2108
+ }
2109
+ case 1 /* FINALIZE_STATE.COMMIT */:
2110
+ case 3 /* FINALIZE_STATE.RESTART */:
2111
+ case 4 /* FINALIZE_STATE.QUEUED */:
2112
+ return;
2113
+ case 2 /* FINALIZE_STATE.END */:
2114
+ resetAssets.call(this);
2115
+ break;
2116
+ }
2117
+ if (this.queued) {
2118
+ const length = arguments.length;
2119
+ const args = new Array(length);
2120
+ for (let i = 0; i < length; ++i) {
2121
+ args[i] = arguments[i];
2122
+ }
2123
+ if (this.joinQueue({ args })) {
2124
+ this.finalizeState = 4 /* FINALIZE_STATE.QUEUED */;
2125
+ return;
2126
+ }
2127
+ }
2128
+ if (targeted) {
2129
+ this.using(true, ...targeted);
2130
+ }
2131
+ this.clearProcessTimeout();
2132
+ this[KTimerMain] = setInterval(() => {
2133
+ const { processing, processTimeout, finalizeState } = this;
2134
+ if (finalizeState === 4 /* FINALIZE_STATE.QUEUED */) {
2135
+ return;
2136
+ }
2137
+ const currentTime = Date.now();
2138
+ let aborted;
2139
+ for (let i = 0; i < processing.length; ++i) {
2140
+ const data = processing[i];
2141
+ const file = data.file;
2142
+ const processModule = file.processModule;
2143
+ let expired = processTimeout > 0 && currentTime - data.startTime >= processTimeout, moduleName;
2144
+ if (processModule && !expired) {
2145
+ for (const name in processModule) {
2146
+ const { startTime, timeout } = processModule[name];
2147
+ if (timeout > 0 && currentTime - startTime >= timeout) {
2148
+ moduleName = name;
2149
+ expired = true;
2150
+ break;
2151
+ }
2152
+ }
2153
+ }
2154
+ if (expired || data.aborted) {
2155
+ let threadCount = data.threadCount + data.queuedTasks.length;
2156
+ while (threadCount-- > 0) {
2157
+ this.removeAsyncTask();
2158
+ }
2159
+ file.invalid = true;
2160
+ const localUri = file.localUri;
2161
+ if (expired) {
2162
+ data.abort();
2163
+ if (localUri) {
2164
+ this.deleteFile(localUri, { id: file.id, emptyDir: true, all: true });
2165
+ }
2166
+ }
2167
+ (moduleName && this.find(moduleName) || this).formatFail(16384 /* LOG_TYPE.TIMEOUT */, "FAIL!" /* ERR_MESSAGE.FAIL */, ["Unable to process file" /* ERR_MESSAGE.PROCESS_FILE */, moduleName || 'main'], (0, types_1.errorValue)(expired ? "Timeout was exceeded" /* ERR_MESSAGE.TIMEOUT */ : "Aborted" /* ERR_MESSAGE.ABORTED */, localUri), { queue: false, startTime: data.startTime });
2168
+ processing.splice(i--, 1);
2169
+ aborted = true;
2170
+ }
2171
+ }
2172
+ if (this.processing.length === 0 && this.aborted) {
2173
+ this.performFinalize(true);
2174
+ }
2175
+ else if (aborted) {
2176
+ this.performFinalize();
2177
+ }
2178
+ }, 100);
2179
+ const hasIncremental = (value) => value === 'etag' || value === 'exists';
2180
+ const { assets, cacheToDisk, cacheToMemory, fetchedAssets, Watch: watch } = this;
2181
+ const initial = this[kRecursionLimit] === RECURSION_LIMIT;
2182
+ const downloadble = new Map();
2183
+ const completed = Object.create(null);
2184
+ const processing = Object.create(null);
2185
+ const downloading = Object.create(null);
2186
+ const appending = {};
2187
+ const bundling = {};
2188
+ const originCount = {};
2189
+ const emptied = [this.baseDirectory];
2190
+ const incremental = this.config.incremental;
2191
+ const cacheable = initial && !this.archiving;
2192
+ const cacheOpen = cacheable && hasIncremental(incremental);
2193
+ const cacheEtag = cacheable && incremental === 'etag';
2194
+ if (cacheOpen) {
2195
+ this[kIncremental] = incremental;
2196
+ }
2197
+ else if (!initial) {
2198
+ this[kIncremental] = 'none';
2199
+ }
2200
+ const targeting = this._usingObjects.size > 0;
2201
+ const isCacheable = (file) => file.initialValue?.cacheable !== false;
2202
+ const hasEtag = (file) => {
2203
+ if (!cacheable || !(0, types_1.existsFlag)(file.flags)) {
2204
+ return false;
2205
+ }
2206
+ switch (file.incremental) {
2207
+ case false:
2208
+ case 'none':
2209
+ case 'exists':
2210
+ return false;
2211
+ case 'etag':
2212
+ return true;
2213
+ default:
2214
+ return cacheEtag;
2215
+ }
2216
+ };
2217
+ const applyHeaders = (file, headers, lastModified, mainEtag) => {
2218
+ let contentLength = headers['content-length'];
2219
+ if ((contentLength = parseInt(contentLength)) > 0) {
2220
+ file.contentLength = contentLength;
2221
+ }
2222
+ else {
2223
+ contentLength = 0;
2224
+ }
2225
+ const etag = headers.etag;
2226
+ if (etag) {
2227
+ if (mainEtag) {
2228
+ CACHE_ETAG[file.uri] = etag;
2229
+ }
2230
+ return file.etag = etag;
2231
+ }
2232
+ if (lastModified && watch) {
2233
+ return file.lastModified = headers['last-modified'];
2234
+ }
2235
+ };
2236
+ const checkQueue = (file, localUri, pathname, content) => {
2237
+ var _m;
2238
+ if (!createFolder(file, pathname)) {
2239
+ return true;
2240
+ }
2241
+ const { bundleId, bundleIndex = -1 } = file;
2242
+ if (!(0, types_1.isEmpty)(bundleId) && bundleIndex >= 0) {
2243
+ const items = appending[localUri] || (appending[localUri] = []);
2244
+ bundling[_m = file.uri] || (bundling[_m] = []);
2245
+ if (bundleIndex > 0) {
2246
+ items[bundleIndex - 1] = file;
2247
+ const url = file.url;
2248
+ if (file.fetchType === 1 /* FETCH_TYPE.HTTP */ && (cacheToDisk.has(url) || cacheToMemory.has(url))) {
2249
+ const parent = assets.find(item => item.bundleIndex === 0 && item.bundleId === bundleId);
2250
+ if (parent) {
2251
+ (parent.bundleQueue || (parent.bundleQueue = [])).push(new Promise(resolve => {
2252
+ this.Request.open(url, { method: 'HEAD', httpVersion: 1 })
2253
+ .on('response', res => {
2254
+ if (res.statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
2255
+ applyHeaders(file, res.headers);
2256
+ }
2257
+ resolve(file);
2258
+ })
2259
+ .on('error', () => resolve(file))
2260
+ .on('timeout', () => resolve(file));
2261
+ }));
2262
+ }
2263
+ }
2264
+ return true;
2265
+ }
2266
+ }
2267
+ else if (!content && file.filename) {
2268
+ const previous = completed[localUri];
2269
+ if (previous) {
2270
+ if (file.uri === previous.uri) {
2271
+ file.etag = previous.etag;
2272
+ file.lastModified = previous.lastModified;
2273
+ }
2274
+ this.transformAsset(new FileThread(this, file, 1));
2275
+ return true;
2276
+ }
2277
+ const queue = processing[localUri];
2278
+ if (queue) {
2279
+ queue.push(file);
2280
+ return true;
2281
+ }
2282
+ processing[localUri] = [file];
2283
+ }
2284
+ return false;
2285
+ };
2286
+ const copyDownload = (file, queued) => {
2287
+ const uriMap = new Map();
2288
+ for (const item of queued) {
2289
+ const destUri = item.localUri;
2290
+ let items = uriMap.get(destUri);
2291
+ if (!items) {
2292
+ const pathname = path.dirname(destUri);
2293
+ if (!core_1.Host.createDir(pathname)) {
2294
+ item.invalid = true;
2295
+ continue;
2296
+ }
2297
+ uriMap.set(destUri, items = []);
2298
+ }
2299
+ item.etag = file.etag;
2300
+ item.lastModified = file.lastModified;
2301
+ items.push(item);
2302
+ }
2303
+ const buffer = file.sourceUTF8 || file.buffer;
2304
+ for (const [destUri, items] of uriMap) {
2305
+ try {
2306
+ if (buffer) {
2307
+ fs.writeFileSync(destUri, buffer);
2308
+ }
2309
+ else {
2310
+ fs.copyFileSync(file.localUri, destUri);
2311
+ }
2312
+ for (const queue of items) {
2313
+ this.performAsyncTask();
2314
+ this.transformAsset(new FileThread(this, queue, 1));
2315
+ }
2316
+ }
2317
+ catch (err) {
2318
+ items.forEach(queue => queue.invalid = true);
2319
+ this.writeFail([buffer ? "Unable to write buffer" /* ERR_MESSAGE.WRITE_BUFFER */ : "Unable to copy file" /* ERR_MESSAGE.COPY_FILE */, path.basename(file.localUri)], err, 32 /* LOG_TYPE.FILE */);
2320
+ }
2321
+ }
2322
+ };
2323
+ const processQueue = async (file, localUri) => {
2324
+ completed[localUri] = file;
2325
+ if (!(0, types_1.isEmpty)(file.bundleId) && file.bundleIndex === 0) {
2326
+ this.setAssetContent(file, this.getUTF8String(file, localUri));
2327
+ let success = true, error, checkEtag = !file.trailingContent && hasEtag(file);
2328
+ if (file.bundleQueue) {
2329
+ error = await Promise.all(file.bundleQueue).then(() => null).catch((err) => err);
2330
+ delete file.bundleQueue;
2331
+ }
2332
+ const items = appending[localUri];
2333
+ if (items) {
2334
+ if (error) {
2335
+ items.forEach(queue => queue.invalid = true);
2336
+ success = false;
2337
+ }
2338
+ else {
2339
+ const tasks = [];
2340
+ for (const queue of items) {
2341
+ const encoding = queue.encoding || (queue.encoding = 'utf-8');
2342
+ const { uri, fetchType: type } = queue;
2343
+ let tempFile;
2344
+ if (checkEtag && queue.trailingContent) {
2345
+ checkEtag = false;
2346
+ }
2347
+ const verifyBundle = (value, etag) => {
2348
+ if (!queue.invalid) {
2349
+ if (value instanceof Buffer) {
2350
+ value = value.toString(encoding);
2351
+ }
2352
+ const url = queue.url;
2353
+ if (etag && cacheToMemory.has(url)) {
2354
+ cacheToMemory.add(url, encodeURIComponent(etag), value, {
2355
+ encoding,
2356
+ contentLength: queue.contentLength,
2357
+ toDisk: !tempFile && isCacheable(queue) ? queue.filename || queue.localUri && path.basename(queue.localUri) : ''
2358
+ });
2359
+ }
2360
+ this.setAssetContent(queue, value, { localUri, bundleIndex: queue.bundleIndex, bundleReplace: queue.bundleReplace });
2361
+ }
2362
+ };
2363
+ if (queue.content) {
2364
+ verifyBundle(queue.content);
2365
+ checkEtag = false;
2366
+ }
2367
+ else if (uri) {
2368
+ if (type === 1 /* FETCH_TYPE.HTTP */ || type === 2 /* FETCH_TYPE.UNIX_SOCKET */) {
2369
+ const url = queue.url;
2370
+ const options = {
2371
+ url,
2372
+ encoding,
2373
+ statusMessage: uri + ` (${queue.bundleIndex})`
2374
+ };
2375
+ let etag, pipeTo;
2376
+ if (type === 2 /* FETCH_TYPE.UNIX_SOCKET */) {
2377
+ options.socketPath = queue.socketPath;
2378
+ options.httpVersion = 1;
2379
+ }
2380
+ else {
2381
+ if (etag = queue.etag) {
2382
+ const valid = incremental !== false || file.incremental === true;
2383
+ const cached = valid && MEMORY.CACHE[uri];
2384
+ const etagDir = encodeURIComponent(etag);
2385
+ if (cached) {
2386
+ if (etagDir === cached[5]) {
2387
+ const source = cached[1];
2388
+ verifyBundle(typeof source === 'string' ? source : source.toString(encoding));
2389
+ this.addDownload(Buffer.byteLength(source, encoding), types_1.DOWNLOAD_TYPE.CACHE);
2390
+ continue;
2391
+ }
2392
+ cacheToMemory.clear(uri);
2393
+ }
2394
+ if (cacheToDisk.has(url) && isCacheable(queue)) {
2395
+ const baseDir = path.join(this.getCacheDir(url), etagDir);
2396
+ pipeTo = path.join(baseDir, path.basename(localUri));
2397
+ try {
2398
+ if (valid && (0, lib_v4_1.hasSize)(pipeTo)) {
2399
+ const buffer = fs.readFileSync(pipeTo, { encoding });
2400
+ verifyBundle(buffer, etag);
2401
+ this.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
2402
+ continue;
2403
+ }
2404
+ if (!fs.existsSync(baseDir)) {
2405
+ fs.mkdirSync(baseDir);
2406
+ }
2407
+ tempFile = path.join(baseDir, (0, types_1.generateUUID)());
2408
+ options.pipeTo = tempFile;
2409
+ }
2410
+ catch {
2411
+ pipeTo = undefined;
2412
+ }
2413
+ }
2414
+ }
2415
+ if ((originCount[url.origin] || 0) <= 1) {
2416
+ options.httpVersion = 1;
2417
+ }
2418
+ options.connected = (headers) => {
2419
+ etag = applyHeaders(queue, headers, true);
2420
+ return true;
2421
+ };
2422
+ }
2423
+ tasks.push(this.fetchBuffer(url, options)
2424
+ .then(data => {
2425
+ if (data) {
2426
+ verifyBundle(data, etag);
2427
+ }
2428
+ else {
2429
+ queue.invalid = true;
2430
+ }
2431
+ const downloaded = bundling[uri];
2432
+ if ((0, types_1.isArray)(downloaded)) {
2433
+ if (data) {
2434
+ if (typeof data === 'string') {
2435
+ queue.sourceUTF8 = data;
2436
+ }
2437
+ else {
2438
+ queue.buffer = data;
2439
+ }
2440
+ copyDownload(queue, downloaded);
2441
+ }
2442
+ else {
2443
+ downloaded.forEach(item => item.invalid = true);
2444
+ }
2445
+ }
2446
+ if (tempFile && (!pipeTo || core_1.Host.isPath(pipeTo) || !core_1.Host.renameFile(tempFile, pipeTo, false))) {
2447
+ queueMicrotask(() => fs.unlink(tempFile, () => { }));
2448
+ }
2449
+ })
2450
+ .catch(() => {
2451
+ queue.invalid = true;
2452
+ if (tempFile) {
2453
+ queueMicrotask(() => fs.unlink(tempFile, () => { }));
2454
+ }
2455
+ }));
2456
+ }
2457
+ else if (type) {
2458
+ const mimeType = queue.mimeType || file.mimeType;
2459
+ const pathname = this.getTempDir({ uuidDir: true });
2460
+ if (!pathname || !mimeType) {
2461
+ queue.invalid = true;
2462
+ tasks.push(Promise.reject(!pathname ? new Error("Unable to create temp directory" /* ERR_MESSAGE.TEMP_DIRECTORY */) : (0, types_1.errorValue)("MIME not found" /* ERR_MESSAGE.NOTFOUND_MIME */, uri)));
2463
+ break;
2464
+ }
2465
+ tasks.push(this.fetchFiles(queue.url || uri, { pathname, binOpts: queue.binOpts || file.binOpts })
2466
+ .then(result => {
2467
+ if (result.length) {
2468
+ verifyBundle(bundleTorrent.call(this, result, mimeType, encoding));
2469
+ }
2470
+ else {
2471
+ queue.invalid = true;
2472
+ }
2473
+ queueMicrotask(() => core_1.Host.removeDir(pathname));
2474
+ })
2475
+ .catch(() => {
2476
+ queue.invalid = true;
2477
+ queueMicrotask(() => core_1.Host.removeDir(pathname));
2478
+ }));
2479
+ }
2480
+ else if (this.canRead(uri)) {
2481
+ tasks.push(fs.promises.readFile(uri, encoding)
2482
+ .then(data => {
2483
+ verifyBundle(data);
2484
+ this.addDownload(Buffer.byteLength(data, encoding), types_1.DOWNLOAD_TYPE.DISK);
2485
+ })
2486
+ .catch(() => {
2487
+ queue.invalid = true;
2488
+ }));
2489
+ }
2490
+ else {
2491
+ checkEtag = false;
2492
+ errorPermission(file);
2493
+ }
2494
+ }
2495
+ }
2496
+ if (tasks.length) {
2497
+ success = await Promise.all(tasks)
2498
+ .then(() => true)
2499
+ .catch(err => {
2500
+ this.writeFail(["Unable to download file" /* ERR_MESSAGE.DOWNLOAD_FILE */, 'bundle: ' + path.basename(localUri)], err, 1024 /* LOG_TYPE.HTTP */);
2501
+ return false;
2502
+ });
2503
+ }
2504
+ else if (checkEtag && core_1.Host.isPath(localUri)) {
2505
+ this.completeAsyncTask();
2506
+ appending[localUri] = undefined;
2507
+ return;
2508
+ }
2509
+ }
2510
+ }
2511
+ if (success) {
2512
+ if (!fetchedAssets.includes(file)) {
2513
+ fetchedAssets.push(file);
2514
+ }
2515
+ this.transformAsset(new FileThread(this, file, 1));
2516
+ }
2517
+ else {
2518
+ file.invalid = true;
2519
+ delete file.buffer;
2520
+ delete file.sourceUTF8;
2521
+ this.completeAsyncTask(error);
2522
+ queueMicrotask(() => this.deleteFile(localUri, { emptyDir: true }));
2523
+ }
2524
+ appending[localUri] = undefined;
2525
+ return;
2526
+ }
2527
+ const uri = file.uri;
2528
+ const processed = processing[localUri];
2529
+ const downloaded = downloading[uri];
2530
+ if ((0, types_1.isArray)(downloaded)) {
2531
+ copyDownload(file, downloaded);
2532
+ }
2533
+ if (processed) {
2534
+ for (const item of processed) {
2535
+ if (item !== file) {
2536
+ if (item.uri === file.uri) {
2537
+ item.etag = file.etag;
2538
+ item.lastModified = file.lastModified;
2539
+ }
2540
+ this.performAsyncTask();
2541
+ }
2542
+ this.transformAsset(new FileThread(this, item, 1));
2543
+ }
2544
+ processing[localUri] = undefined;
2545
+ }
2546
+ else {
2547
+ this.transformAsset(new FileThread(this, file, 1));
2548
+ }
2549
+ downloading[uri] = undefined;
2550
+ };
2551
+ const clearQueue = (data, attr) => {
2552
+ if (attr && data[attr]) {
2553
+ data[attr].forEach(item => item.invalid = true);
2554
+ data[attr] = undefined;
2555
+ }
2556
+ };
2557
+ const errorRequest = (file, err, preceding) => {
2558
+ const { uri, localUri } = file;
2559
+ clearQueue(processing, localUri);
2560
+ clearQueue(downloading, uri);
2561
+ clearQueue(appending, localUri);
2562
+ file.invalid = true;
2563
+ if (!preceding) {
2564
+ this.completeAsyncTask();
2565
+ }
2566
+ this.writeFail(["Unable to download file" /* ERR_MESSAGE.DOWNLOAD_FILE */, uri], err, err instanceof Error && err.message.startsWith("Timeout was exceeded" /* ERR_MESSAGE.TIMEOUT */) ? 16384 /* LOG_TYPE.TIMEOUT */ : 1024 /* LOG_TYPE.HTTP */);
2567
+ };
2568
+ const errorPermission = (file) => {
2569
+ this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, file.uri], (0, types_1.errorValue)('Operation not permitted', file.uri || "Unknown" /* ERR_MESSAGE.UNKNOWN */), 8192 /* LOG_TYPE.PERMISSION */);
2570
+ file.invalid = true;
2571
+ };
2572
+ const createFolder = (file, pathname) => {
2573
+ if (!emptied.includes(pathname)) {
2574
+ if (emptyDir && core_1.Host.removeDir(pathname, true)) {
2575
+ emptied.push(pathname);
2576
+ }
2577
+ else if (core_1.Host.createDir(pathname)) {
2578
+ emptied.push(pathname);
2579
+ }
2580
+ else {
2581
+ file.invalid = true;
2582
+ this.writeFail("Unable to create directory" /* ERR_MESSAGE.CREATE_DIRECTORY */, (0, types_1.errorValue)('Path not found', pathname));
2583
+ return false;
2584
+ }
2585
+ }
2586
+ return true;
2587
+ };
2588
+ const fileReceived = (item, localUri, err, fetched, binary) => {
2589
+ if (err) {
2590
+ item.invalid = true;
2591
+ this.completeAsyncTask(err, localUri);
2592
+ return;
2593
+ }
2594
+ if (fetched) {
2595
+ fetchedAssets.push(item);
2596
+ }
2597
+ else {
2598
+ this.copiedAssets.push(item);
2599
+ }
2600
+ if (binary) {
2601
+ this.transformAsset(new FileThread(this, item, 1));
2602
+ }
2603
+ else {
2604
+ processQueue(item, localUri);
2605
+ }
2606
+ };
2607
+ const imported = assets.filter(item => item.imported && (0, types_1.isArray)(item.imported));
2608
+ for (let item of assets) {
2609
+ if (item.invalid || (0, types_1.ignoreFlag)(item.flags)) {
2610
+ continue;
2611
+ }
2612
+ if (!item.filename) {
2613
+ if (!(item.uri && core_1.Host.isFile(item.uri, 'torrent'))) {
2614
+ item.invalid = true;
2615
+ continue;
2616
+ }
2617
+ item.filename = '';
2618
+ }
2619
+ if (targeting && !this.contains(item, (other) => (0, asset_1.isEqual)(item, other))) {
2620
+ this.setLocalUri(item);
2621
+ item.invalid = true;
2622
+ continue;
2623
+ }
2624
+ let download = this.setLocalUri(item);
2625
+ const localUri = download.localUri;
2626
+ if (!localUri) {
2627
+ item.invalid = true;
2628
+ continue;
2629
+ }
2630
+ const type = item.incremental;
2631
+ let valid = cacheOpen;
2632
+ if (valid) {
2633
+ if (type === false || type === 'none') {
2634
+ valid = false;
2635
+ }
2636
+ }
2637
+ else if (hasIncremental(type)) {
2638
+ if (cacheable) {
2639
+ valid = true;
2640
+ }
2641
+ else {
2642
+ item.incremental = undefined;
2643
+ }
2644
+ }
2645
+ if (valid && item.filename) {
2646
+ let uri = item.uri, cached;
2647
+ const etag = (cacheEtag && type !== 'exists' || type === 'etag') && !!uri;
2648
+ if (etag && imported.some(file => file.imported.includes(uri))) {
2649
+ item.incremental = 'none';
2650
+ }
2651
+ else if (!(0, types_1.mainFlag)(item.flags)) {
2652
+ const { bundleId, bundleIndex = -1 } = item;
2653
+ const setBuffer = (target) => {
2654
+ if (!etag && (uri = target.uri) && (cached = MEMORY.CACHE[uri])) {
2655
+ target.etag = cached[5];
2656
+ target.contentLength = cached[3];
2657
+ return true;
2658
+ }
2659
+ return false;
2660
+ };
2661
+ if ((!etag || item.fetchType === 1 /* FETCH_TYPE.HTTP */ && ((0, types_1.isEmpty)(bundleId) || bundleIndex <= 0)) && (!watch || !item.watch || setBuffer(item))) {
2662
+ let childBundle, childDownload;
2663
+ if (!(0, types_1.isEmpty)(bundleId) && bundleIndex > 0) {
2664
+ const target = assets.find(parent => parent.bundleId === bundleId && parent.bundleIndex === 0);
2665
+ if (target) {
2666
+ if ((0, types_1.existsFlag)(target.flags)) {
2667
+ setBuffer(item);
2668
+ item.invalid = true;
2669
+ }
2670
+ else if (target.localUri) {
2671
+ downloadble.set(item, download);
2672
+ }
2673
+ else {
2674
+ childDownload = download;
2675
+ download = this.setLocalUri(target);
2676
+ if (download.localUri) {
2677
+ childBundle = item;
2678
+ item = target;
2679
+ cached = undefined;
2680
+ }
2681
+ else {
2682
+ item.invalid = true;
2683
+ }
2684
+ }
2685
+ }
2686
+ else {
2687
+ item.invalid = true;
2688
+ }
2689
+ if (!childBundle) {
2690
+ continue;
2691
+ }
2692
+ }
2693
+ if (!cached) {
2694
+ setBuffer(item);
2695
+ }
2696
+ if (core_1.Host.isPath(localUri)) {
2697
+ item.flags |= 128 /* ASSET_FLAG.EXISTS */;
2698
+ if (!etag || item.fetchType !== 1 /* FETCH_TYPE.HTTP */) {
2699
+ if (!(0, types_1.isEmpty)(bundleId) && bundleIndex === 0) {
2700
+ assets.filter(child => child.bundleId === bundleId && child.bundleIndex > 0).forEach(child => {
2701
+ setBuffer(child);
2702
+ child.invalid = true;
2703
+ });
2704
+ }
2705
+ continue;
2706
+ }
2707
+ }
2708
+ else if (childBundle) {
2709
+ downloadble.set(childBundle, childDownload);
2710
+ }
2711
+ else if (cached) {
2712
+ try {
2713
+ const buffer = cached[1];
2714
+ fs.writeFileSync(localUri, buffer);
2715
+ if (item.willChange && Buffer.isBuffer(buffer)) {
2716
+ item.buffer = buffer;
2717
+ }
2718
+ this.performAsyncTask();
2719
+ fileReceived(item, localUri, null, true);
2720
+ continue;
2721
+ }
2722
+ catch {
2723
+ }
2724
+ }
2725
+ }
2726
+ }
2727
+ else if (core_1.Host.isPath(localUri)) {
2728
+ try {
2729
+ const buffer = fs.readFileSync(localUri);
2730
+ if (!etag) {
2731
+ (0, asset_1.setInitialValue)(item, false);
2732
+ item.initialValue.buffer = buffer;
2733
+ }
2734
+ else if (uri && CACHE_ETAG[uri]) {
2735
+ (0, asset_1.setInitialValue)(item, false);
2736
+ item.initialValue.buffer = buffer;
2737
+ item.initialValue.etag = CACHE_ETAG[uri];
2738
+ }
2739
+ }
2740
+ catch {
2741
+ }
2742
+ }
2743
+ }
2744
+ downloadble.set(item, download);
2745
+ }
2746
+ if (downloadble.size > 1 && this.Request.httpVersion !== 1) {
2747
+ for (const { url } of downloadble.keys()) {
2748
+ if (url?.protocol === 'https:') {
2749
+ originCount[url.origin] = (originCount[url.origin] || 0) + 1;
2750
+ }
2751
+ }
2752
+ }
2753
+ for (const [item, download] of downloadble) {
2754
+ if (this.aborted) {
2755
+ break;
2756
+ }
2757
+ const { pathname, localUri } = download;
2758
+ let uri;
2759
+ if (item.content) {
2760
+ if (!checkQueue(item, localUri, pathname, true)) {
2761
+ item.sourceUTF8 = item.content;
2762
+ this.performAsyncTask();
2763
+ fs.writeFile(localUri, item.content, item.encoding || (item.encoding = 'utf-8'), err => fileReceived(item, localUri, err));
2764
+ }
2765
+ }
2766
+ else if (item.dataView) {
2767
+ if (createFolder(item, pathname)) {
2768
+ this.performAsyncTask();
2769
+ const dataView = item.dataView;
2770
+ fs.writeFile(localUri, dataView, err => {
2771
+ if (!err) {
2772
+ item.buffer = Buffer.isBuffer(dataView) ? dataView : Buffer.from(dataView.buffer);
2773
+ }
2774
+ fileReceived(item, localUri, err, false, true);
2775
+ });
2776
+ }
2777
+ }
2778
+ else if (item.base64) {
2779
+ if (createFolder(item, pathname)) {
2780
+ this.performAsyncTask();
2781
+ fs.writeFile(localUri, item.base64, 'base64', err => fileReceived(item, localUri, err, false, true));
2782
+ }
2783
+ }
2784
+ else if (uri = item.uri) {
2785
+ const checkDest = (src) => this.archiving || !(0, lib_v4_1.hasSameStat)(src, localUri);
2786
+ const type = item.fetchType;
2787
+ const bundleMain = !(0, types_1.isEmpty)(item.bundleId) && item.bundleIndex === 0;
2788
+ let isHttp;
2789
+ if ((isHttp = type === 1 /* FETCH_TYPE.HTTP */) || type === 2 /* FETCH_TYPE.UNIX_SOCKET */) {
2790
+ const url = item.url;
2791
+ const checkEtag = hasEtag(item);
2792
+ if ((0, types_1.isEmpty)(item.bundleId) && bundling[uri]) {
2793
+ bundling[uri].push(item);
2794
+ }
2795
+ else if (checkEtag || !checkQueue(item, localUri, pathname)) {
2796
+ if (!isHttp && !checkDest(uri)) {
2797
+ fileReceived(item, localUri);
2798
+ }
2799
+ else if (!checkEtag && downloading[uri]) {
2800
+ downloading[uri].push(item);
2801
+ }
2802
+ else if (!isHttp && !this.canRead(uri)) {
2803
+ errorPermission(item);
2804
+ }
2805
+ else {
2806
+ if (!checkEtag) {
2807
+ downloading[uri] = [];
2808
+ }
2809
+ let cacheDir, cacheBuffer, mainEtag, encoding = item.encoding, client = null;
2810
+ if (isHttp) {
2811
+ cacheDir = cacheToDisk.has(url) && isCacheable(item);
2812
+ cacheBuffer = cacheToMemory.has(url);
2813
+ mainEtag = (0, types_1.mainFlag)(item.flags) && (cacheEtag || item.incremental === 'etag');
2814
+ }
2815
+ const closeResponse = () => client?.destroy();
2816
+ const downloadUri = (request, etagDir) => {
2817
+ if (checkEtag) {
2818
+ item.flags &= ~128 /* ASSET_FLAG.EXISTS */;
2819
+ }
2820
+ closeResponse();
2821
+ const location = request.url.toString();
2822
+ request.encoding = encoding;
2823
+ request.pipeTo = localUri;
2824
+ request.statusMessage = location + (bundleMain ? ' (0)' : '');
2825
+ if (isHttp) {
2826
+ request.method = 'GET';
2827
+ request.httpVersion = (originCount[request.url.origin] || 0) <= 1 ? 1 : undefined;
2828
+ request.connected = headers => {
2829
+ applyHeaders(item, headers, true, mainEtag);
2830
+ return item.willChange || !!etagDir && (cacheDir || !item.contentLength || cacheToMemory.within(item.contentLength));
2831
+ };
2832
+ }
2833
+ else {
2834
+ request.socketPath = item.socketPath;
2835
+ request.httpVersion = 1;
2836
+ }
2837
+ this.fetchBuffer(request.url, request)
2838
+ .then(data => {
2839
+ if (typeof data === 'string') {
2840
+ item.sourceUTF8 = data;
2841
+ }
2842
+ else if (data) {
2843
+ item.buffer = data;
2844
+ }
2845
+ fileReceived(item, localUri, null, isHttp);
2846
+ if (etagDir) {
2847
+ queueMicrotask(() => {
2848
+ if (cacheBuffer && data) {
2849
+ cacheToMemory.add(location, etagDir, data, { encoding, contentLength: item.contentLength, toDisk: !cacheDir && isCacheable(item) ? path.basename(localUri) : '' });
2850
+ }
2851
+ if (cacheDir) {
2852
+ cacheToDisk.add(location, etagDir, localUri, { buffer: data, contentLength: item.contentLength });
2853
+ }
2854
+ });
2855
+ }
2856
+ })
2857
+ .catch(err => errorRequest(item, err));
2858
+ };
2859
+ this.performAsyncTask();
2860
+ const request = this.Request;
2861
+ if (cacheDir || cacheBuffer || mainEtag) {
2862
+ let redirects = 0;
2863
+ (function checkHeaders(href) {
2864
+ try {
2865
+ const target = request.opts(href, { method: 'HEAD', httpVersion: 1 });
2866
+ (client = request.open(href, target))
2867
+ .on('response', res => {
2868
+ const statusCode = res.statusCode;
2869
+ if (statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
2870
+ const etag = applyHeaders(item, res.headers, false, mainEtag);
2871
+ let tempDir, etagDir;
2872
+ if (etag) {
2873
+ if (cacheDir) {
2874
+ tempDir = this.getCacheDir(href);
2875
+ }
2876
+ etagDir = encodeURIComponent(etag);
2877
+ if (incremental !== false || item.incremental === true) {
2878
+ const location = href.toString();
2879
+ const cached = MEMORY.CACHE[location];
2880
+ let buffer;
2881
+ if (cached) {
2882
+ if (etagDir === cached[5] && (!encoding || encoding === cached[2])) {
2883
+ if (checkEtag) {
2884
+ this.completeAsyncTask(null, localUri);
2885
+ closeResponse();
2886
+ return;
2887
+ }
2888
+ buffer = cached[1];
2889
+ encoding = cached[2];
2890
+ item.encoding = encoding;
2891
+ cached[0] = Date.now();
2892
+ }
2893
+ else {
2894
+ cacheToMemory.clear(location);
2895
+ }
2896
+ }
2897
+ try {
2898
+ const setBuffer = () => {
2899
+ if (typeof buffer === 'string') {
2900
+ item.sourceUTF8 = buffer;
2901
+ }
2902
+ else if (buffer) {
2903
+ item.buffer = buffer;
2904
+ }
2905
+ };
2906
+ let pipeAs;
2907
+ if (tempDir && (0, lib_v4_1.hasSize)(pipeAs = path.join(tempDir, etagDir, path.basename(localUri)))) {
2908
+ if (!checkEtag) {
2909
+ if (cacheBuffer && !buffer) {
2910
+ buffer = fs.readFileSync(pipeAs, encoding);
2911
+ if (cacheToMemory.within(item.contentLength = Buffer.byteLength(buffer, encoding))) {
2912
+ cacheToMemory.add(location, etagDir, buffer, { encoding, contentLength: item.contentLength, tempFile: pipeAs });
2913
+ }
2914
+ }
2915
+ if (checkDest(pipeAs)) {
2916
+ if (buffer) {
2917
+ fs.writeFileSync(localUri, buffer);
2918
+ this.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
2919
+ }
2920
+ else {
2921
+ fs.copyFileSync(pipeAs, localUri);
2922
+ this.addDownload(pipeAs, types_1.DOWNLOAD_TYPE.CACHE);
2923
+ }
2924
+ }
2925
+ if (item.willChange) {
2926
+ setBuffer();
2927
+ }
2928
+ fileReceived(item, localUri, null, true);
2929
+ }
2930
+ else {
2931
+ this.completeAsyncTask(null, localUri);
2932
+ }
2933
+ closeResponse();
2934
+ return;
2935
+ }
2936
+ if (buffer) {
2937
+ setBuffer();
2938
+ fs.writeFileSync(localUri, buffer);
2939
+ this.addDownload(Buffer.byteLength(buffer, encoding), types_1.DOWNLOAD_TYPE.CACHE);
2940
+ if (checkEtag) {
2941
+ item.flags &= ~128 /* ASSET_FLAG.EXISTS */;
2942
+ }
2943
+ fileReceived(item, localUri, null, true);
2944
+ closeResponse();
2945
+ if (pipeAs) {
2946
+ fs.writeFile(pipeAs, buffer, () => { });
2947
+ }
2948
+ return;
2949
+ }
2950
+ }
2951
+ catch {
2952
+ }
2953
+ }
2954
+ }
2955
+ downloadUri(target, etagDir);
2956
+ }
2957
+ else if (statusCode < 400 /* HTTP_STATUS.BAD_REQUEST */) {
2958
+ closeResponse();
2959
+ const location = res.headers.location;
2960
+ if (location && ++redirects <= HTTP_CLIENT.redirectLimit) {
2961
+ try {
2962
+ checkHeaders.call(this, new URL(request_1.default.fromURL(href, location)));
2963
+ return;
2964
+ }
2965
+ catch {
2966
+ }
2967
+ }
2968
+ errorRequest(item, (0, types_1.errorMessage)(statusCode, 'Exceeded redirect limit', url.toString()));
2969
+ }
2970
+ else {
2971
+ downloadUri(target);
2972
+ }
2973
+ })
2974
+ .on('error', err => {
2975
+ if (!client.destroyed) {
2976
+ if ((0, util_1.checkRetryable)(err)) {
2977
+ downloadUri(target);
2978
+ }
2979
+ else {
2980
+ errorRequest(item, err);
2981
+ }
2982
+ }
2983
+ })
2984
+ .on('timeout', () => {
2985
+ if (!client.destroyed) {
2986
+ downloadUri(target);
2987
+ }
2988
+ });
2989
+ }
2990
+ catch {
2991
+ downloadUri(request.opts(href));
2992
+ }
2993
+ }).bind(this)(url);
2994
+ }
2995
+ else {
2996
+ downloadUri(request.opts(url));
2997
+ }
2998
+ }
2999
+ }
3000
+ }
3001
+ else if (type) {
3002
+ if (bundleMain && !item.mimeType) {
3003
+ errorRequest(item, (0, types_1.errorValue)("MIME not found" /* ERR_MESSAGE.NOTFOUND_MIME */, uri), true);
3004
+ }
3005
+ else if (!checkQueue(item, localUri, pathname, false)) {
3006
+ if (downloading[uri]) {
3007
+ downloading[uri].push(item);
3008
+ continue;
3009
+ }
3010
+ downloading[uri] = [];
3011
+ this.performAsyncTask();
3012
+ this.fetchFiles(item.url || uri, { pathname, binOpts: item.binOpts })
3013
+ .then(result => {
3014
+ if (result.length === 0) {
3015
+ errorRequest(item, (0, types_1.errorValue)('No files were successfully downloaded', uri));
3016
+ }
3017
+ else if (bundleMain) {
3018
+ const encoding = item.encoding || (item.encoding = 'utf-8');
3019
+ fs.writeFile(localUri, bundleTorrent.call(this, result, item.mimeType, encoding), encoding, err => {
3020
+ if (!err) {
3021
+ fetchedAssets.push(item);
3022
+ processQueue(item, localUri);
3023
+ }
3024
+ else {
3025
+ errorRequest(item, err);
3026
+ }
3027
+ });
3028
+ }
3029
+ else {
3030
+ const ext = item.filename && path.extname(item.filename);
3031
+ let found;
3032
+ for (const file of result) {
3033
+ if (!found && ext === path.extname(file).toLowerCase()) {
3034
+ try {
3035
+ if (file !== localUri && !core_1.Host.renameFile(file, localUri)) {
3036
+ this.filesToRemove.add(file);
3037
+ }
3038
+ found = true;
3039
+ }
3040
+ catch (err) {
3041
+ this.writeFail(["Unable to rename file" /* ERR_MESSAGE.RENAME_FILE */, item.filename], err, 32 /* LOG_TYPE.FILE */);
3042
+ }
3043
+ }
3044
+ else {
3045
+ this.add(file, item, types_1.FILE_TYPE.TORRENT);
3046
+ }
3047
+ }
3048
+ if (found) {
3049
+ fetchedAssets.push(item);
3050
+ processQueue(item, localUri);
3051
+ }
3052
+ else {
3053
+ item.filename = '';
3054
+ item.localUri = '';
3055
+ item.mimeType = '';
3056
+ clearQueue(processing, localUri);
3057
+ clearQueue(downloading, uri);
3058
+ this.completeAsyncTask();
3059
+ }
3060
+ }
3061
+ })
3062
+ .catch(err => errorRequest(item, err));
3063
+ }
3064
+ }
3065
+ else if (!this.canRead(uri)) {
3066
+ errorPermission(item);
3067
+ }
3068
+ else if (!checkQueue(item, localUri, pathname)) {
3069
+ this.performAsyncTask();
3070
+ if (checkDest(uri)) {
3071
+ fs.copyFile(uri, localUri, err => {
3072
+ if (!err) {
3073
+ this.addDownload(localUri, types_1.DOWNLOAD_TYPE.DISK);
3074
+ }
3075
+ fileReceived(item, localUri, err);
3076
+ });
3077
+ }
3078
+ else {
3079
+ fileReceived(item, localUri);
3080
+ }
3081
+ }
3082
+ }
3083
+ else {
3084
+ item.invalid = true;
3085
+ }
3086
+ }
3087
+ this.cleared = true;
3088
+ }
3089
+ async finalizeCompress(assets) {
3090
+ const compress = this.Compress;
3091
+ if (!(compress && assets.length)) {
3092
+ return;
3093
+ }
3094
+ const tasks = [];
3095
+ for (const item of assets) {
3096
+ if (image_1.default.isBinary(item.mimeType)) {
3097
+ const localUri = item.localUri;
3098
+ const files = [localUri];
3099
+ if (item.transforms) {
3100
+ files.push(...item.transforms);
3101
+ }
3102
+ const format = item.mimeType.split('/').pop();
3103
+ for (const file of files) {
3104
+ if (this.has(file)) {
3105
+ const output = item.compress.filter(({ condition }) => !condition || withinSizeRange(file, condition));
3106
+ if (output.length) {
3107
+ const found = output.filter(value => value.format === format);
3108
+ for (const config of found.length ? found : output) {
3109
+ const options = { ...config };
3110
+ options.timeout = this[kProcessTimeout].compress ?? PROCESS_TIMEOUT.compress;
3111
+ options.proxyUrl = (uri) => {
3112
+ const proxy = this.Request.proxyOf(uri);
3113
+ return proxy ? proxy.host.href : '';
3114
+ };
3115
+ tasks.push(compress.tryImage(item.buffer && files.length === 1 ? item.buffer : file, file, options)
3116
+ .then(result => {
3117
+ if (result instanceof Buffer && file === localUri) {
3118
+ item.buffer = result;
3119
+ }
3120
+ })
3121
+ .catch(err => this.writeFail(["Unable to compress file" /* ERR_MESSAGE.COMPRESS_FILE */, path.basename(file)], err, { type: 8 /* LOG_TYPE.COMPRESS */, startTime: options.startTime })));
3122
+ }
3123
+ }
3124
+ }
3125
+ }
3126
+ }
3127
+ }
3128
+ if (tasks.length) {
3129
+ return Promise.all(tasks);
3130
+ }
3131
+ }
3132
+ async finalizeDocument() {
3133
+ for (const { instance, constructor } of this.Document) {
3134
+ if (constructor.finalize && instance.assets.length) {
3135
+ await constructor.finalize.call(this, instance).catch(err => rejectModule.call(instance, err, 4 /* LOG_TYPE.PROCESS */));
3136
+ if (this.aborted) {
3137
+ break;
3138
+ }
3139
+ }
3140
+ }
3141
+ }
3142
+ async finalizeTask(assets) {
3143
+ if (assets.length) {
3144
+ for (const { instance, constructor } of this.Task) {
3145
+ const items = assets.filter(item => item.tasks.find(data => data.handler === instance.moduleName));
3146
+ if (items.length) {
3147
+ await (constructor.using || constructor.finalize).call(this, instance, items).catch(err => rejectModule.call(instance, err, 4 /* LOG_TYPE.PROCESS */));
3148
+ if (this.aborted) {
3149
+ break;
3150
+ }
3151
+ }
3152
+ }
3153
+ }
3154
+ }
3155
+ async finalizeCloud() {
3156
+ if (this.Cloud) {
3157
+ return cloud_1.default.finalize.call(this, this.Cloud).catch(err => rejectModule.call(this.Cloud, err, 64 /* LOG_TYPE.CLOUD */));
3158
+ }
3159
+ }
3160
+ async finalizeCleanup() {
3161
+ if (this.Compress) {
3162
+ const tasks = [];
3163
+ this.assets.forEach(item => item.compress && !ignoreAsset(item, true) && tasks.push(this.compressFile(item, false)));
3164
+ if (tasks.length) {
3165
+ await Promise.allSettled(tasks);
3166
+ }
3167
+ }
3168
+ if (this.emptyDir.size) {
3169
+ for (const value of Array.from(this.emptyDir).reverse()) {
3170
+ try {
3171
+ fs.rmdirSync(value);
3172
+ }
3173
+ catch {
3174
+ }
3175
+ }
3176
+ }
3177
+ for (const { instance, constructor } of this.Document) {
3178
+ if (constructor.cleanup && instance.assets.length) {
3179
+ await constructor.cleanup.call(this, instance).catch(err => rejectModule.call(instance, err, 4 /* LOG_TYPE.PROCESS */));
3180
+ }
3181
+ }
3182
+ }
3183
+ async finalize() {
3184
+ if (this.aborted) {
3185
+ return Promise.reject((0, types_1.createAbortError)());
3186
+ }
3187
+ if (LOG_TIMEELAPSED) {
3188
+ this.writeTimeElapsed('READY', 'Finalizing assets...', this.startTime, { ...core_1.Host.LOG_STYLE_WARN, showCpu: true });
3189
+ }
3190
+ const startTime = process.hrtime();
3191
+ const filesToRemove = this.filesToRemove;
3192
+ const removeFiles = () => {
3193
+ if (filesToRemove.size) {
3194
+ filesToRemove.forEach(value => this.deleteFile(value, { emptyDir: true }));
3195
+ filesToRemove.clear();
3196
+ }
3197
+ };
3198
+ for (const [file, output] of this.filesToCompare) {
3199
+ const localUri = file.localUri;
3200
+ let minFile = localUri, minSize = (0, lib_v4_1.getSize)(minFile);
3201
+ for (const other of output) {
3202
+ const size = (0, lib_v4_1.getSize)(other);
3203
+ if (minSize === 0 || size > 0 && size < minSize) {
3204
+ filesToRemove.add(minFile);
3205
+ minFile = other;
3206
+ minSize = size;
3207
+ }
3208
+ else {
3209
+ filesToRemove.add(other);
3210
+ }
3211
+ }
3212
+ if (minFile !== localUri) {
3213
+ this.replace(file, minFile);
3214
+ }
3215
+ }
3216
+ removeFiles();
3217
+ await this.finalizeCompress(this.assets.filter(item => item.compress && !ignoreAsset(item))).catch(err => rejectModule.call(this, err, 8 /* LOG_TYPE.COMPRESS */));
3218
+ if (this.aborted) {
3219
+ return Promise.reject((0, types_1.createAbortError)());
3220
+ }
3221
+ await this.finalizeDocument().catch(err => rejectModule.call(this, err, 4 /* LOG_TYPE.PROCESS */));
3222
+ if (this.aborted) {
3223
+ return Promise.reject((0, types_1.createAbortError)());
3224
+ }
3225
+ for (const item of this.assets) {
3226
+ if (item.sourceUTF8 && !ignoreAsset(item)) {
3227
+ try {
3228
+ fs.writeFileSync(item.localUri, item.sourceUTF8, item.encoding || (item.encoding = 'utf-8'));
3229
+ }
3230
+ catch (err) {
3231
+ this.writeFail(["Unable to write file" /* ERR_MESSAGE.WRITE_FILE */, path.basename(item.localUri)], err, { type: 32 /* LOG_TYPE.FILE */, startTime });
3232
+ }
3233
+ }
3234
+ }
3235
+ removeFiles();
3236
+ 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 /* LOG_TYPE.PROCESS */));
3237
+ if (this.aborted) {
3238
+ return Promise.reject((0, types_1.createAbortError)());
3239
+ }
3240
+ removeFiles();
3241
+ await this.finalizeCloud().catch(err => rejectModule.call(this, err, 64 /* LOG_TYPE.CLOUD */));
3242
+ if (this.aborted) {
3243
+ return Promise.reject((0, types_1.createAbortError)());
3244
+ }
3245
+ removeFiles();
3246
+ await this.finalizeCleanup().catch(err => rejectModule.call(this, err, 1 /* LOG_TYPE.SYSTEM */));
3247
+ removeFiles();
3248
+ if (LOG_TIMEELAPSED) {
3249
+ const [h, d, c] = this[kDownloadStats];
3250
+ const errorCount = this.errorCount;
3251
+ const message = [];
3252
+ if (errorCount) {
3253
+ message.push(`ERROR ${errorCount}`);
3254
+ }
3255
+ let [size, count] = h;
3256
+ if (count) {
3257
+ message.push('HTTP ' + (count > 1 ? count + '/' : '') + (0, types_1.formatSize)(size));
3258
+ }
3259
+ [size, count] = d;
3260
+ if (count) {
3261
+ message.push('DISK ' + (count > 1 ? count + '/' : '') + (0, types_1.formatSize)(size));
3262
+ }
3263
+ [size, count] = c;
3264
+ if (count) {
3265
+ message.push('CACHE ' + (count > 1 ? count + '/' : '') + (0, types_1.formatSize)(size));
3266
+ }
3267
+ if (MEMORY.SIZE > 0) {
3268
+ const bufferCount = Object.keys(MEMORY.CACHE).length;
3269
+ message.push('BUFFER ' + (bufferCount > 1 ? bufferCount + '/' : '') + (0, types_1.formatSize)(MEMORY.SIZE));
3270
+ }
3271
+ this.writeTimeElapsed('CLOSE', ['No further modifications', message.join(' | ')], startTime, { ...core_1.Host.LOG_STYLE_WARN });
3272
+ }
3273
+ this.Watch?.start(this.assets);
3274
+ }
3275
+ close() {
3276
+ this.Request.close();
3277
+ }
3278
+ set restarting(value) {
3279
+ this.finalizeState = (this[kRestarting] = value) ? 3 /* FINALIZE_STATE.RESTART */ : 0 /* FINALIZE_STATE.READY */;
3280
+ }
3281
+ get restarting() {
3282
+ return this[kRestarting];
3283
+ }
3284
+ get baseDirectory() {
3285
+ return this[kBaseDirectory];
3286
+ }
3287
+ get assets() {
3288
+ return this._assets;
3289
+ }
3290
+ get incremental() {
3291
+ return this[kIncremental];
3292
+ }
3293
+ get delayed() {
3294
+ return this[kDelayed];
3295
+ }
3296
+ set cleared(value) {
3297
+ this[kCleared] = value;
3298
+ if (value) {
3299
+ this.performFinalize();
3300
+ }
3301
+ }
3302
+ get cleared() {
3303
+ return this[kCleared];
3304
+ }
3305
+ get errorCount() {
3306
+ return Array.from(this.modules).reduce((a, b) => a + b.errors.length, this.errors.length);
3307
+ }
3308
+ }
3309
+ exports.default = FileManager;
3310
+
3311
+ if (exports.default) {
3312
+ module.exports = exports.default;
3313
+ module.exports.default = exports.default;
3314
+ }