@e-mc/module 0.8.0 → 0.8.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/LICENSE CHANGED
@@ -1,11 +1,11 @@
1
- Copyright 2023 An Pham
2
-
3
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
-
5
- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
-
7
- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
-
9
- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
-
1
+ Copyright 2023 An Pham
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
11
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { ModuleConstructor } from '../types/lib';
2
-
3
- declare const Module: ModuleConstructor;
4
-
1
+ import type { ModuleConstructor } from '../types/lib';
2
+
3
+ declare const Module: ModuleConstructor;
4
+
5
5
  export = Module;
package/index.js CHANGED
@@ -9,6 +9,7 @@ const crypto = require("crypto");
9
9
  const url = require("url");
10
10
  const filetype = require("file-type");
11
11
  const mime = require("mime-types");
12
+ const pm = require("picomatch");
12
13
  const chalk = require("chalk");
13
14
  const stripansi = require("strip-ansi");
14
15
  const EventEmitter = require("events");
@@ -118,6 +119,14 @@ const VALUES = {
118
119
  ["broadcast.out" /* KEY_NAME.BROADCAST_OUT */]: null,
119
120
  ["logger.level" /* KEY_NAME.LOGGER_LEVEL */]: -1
120
121
  };
122
+ const MEMORY_CACHE_DISK = {
123
+ enabled: false,
124
+ min_size: Infinity,
125
+ max_size: 0,
126
+ expires: Infinity,
127
+ include: null,
128
+ exclude: null
129
+ };
121
130
  const REGEXP_TORRENT = /^(?:magnet:\?xt=|(?:https?|s?ftp):\/\/[^/][^\n]*?\.(?:torrent|metalink|meta4)(?:\?[^\n]*)?$)/i;
122
131
  let LOG_NEWLINE = true;
123
132
  let LOG_EMPTYLINE = false;
@@ -303,14 +312,35 @@ function tryRemoveDir(value, empty, recursive) {
303
312
  }
304
313
  return failed;
305
314
  }
315
+ function tryIncrementDir(value, increment) {
316
+ const baseDir = trimDir(value);
317
+ let i = 0, outErr;
318
+ do {
319
+ try {
320
+ if (tryCreateDir(value)) {
321
+ return [value, i];
322
+ }
323
+ }
324
+ catch (err) {
325
+ if (increment === 0) {
326
+ outErr = err;
327
+ }
328
+ }
329
+ value = baseDir + '_' + ++i;
330
+ } while (increment-- > 0);
331
+ return [outErr, -1];
332
+ }
306
333
  function errorObject(message) {
334
+ if (message instanceof Error) {
335
+ return message;
336
+ }
307
337
  switch (typeof message) {
308
338
  case 'string':
309
339
  return new Error(message);
310
340
  case 'number':
311
341
  return (0, types_1.errorMessage)("Error code" /* ERR_MESSAGE.ERROR_CODE */, message.toString());
312
342
  default:
313
- return message instanceof Error ? message : new Error(Module.asString(message) || "Unknown" /* ERR_MESSAGE.UNKNOWN */);
343
+ return new Error(Module.asString(message) || "Unknown" /* ERR_MESSAGE.UNKNOWN */);
314
344
  }
315
345
  }
316
346
  function isFailed(options) {
@@ -322,7 +352,7 @@ function isFailed(options) {
322
352
  }
323
353
  return false;
324
354
  }
325
- function getErrorCause(err, out, visited) {
355
+ function recurseCause(err, out, visited) {
326
356
  let message;
327
357
  if (visited) {
328
358
  message = SETTINGS.stack_trace && err.stack || err.message;
@@ -338,7 +368,7 @@ function getErrorCause(err, out, visited) {
338
368
  out.push(message);
339
369
  }
340
370
  if (!visited.has(cause)) {
341
- getErrorCause(cause, out, visited);
371
+ recurseCause(cause, out, visited);
342
372
  }
343
373
  return;
344
374
  }
@@ -352,7 +382,7 @@ function getErrorCause(err, out, visited) {
352
382
  }
353
383
  function getErrorMessage(err) {
354
384
  const cause = [];
355
- getErrorCause(err, cause);
385
+ recurseCause(err, cause);
356
386
  return (SETTINGS.stack_trace && err.stack || err.message || err.toString() || "Unknown" /* ERR_MESSAGE.UNKNOWN */) + (cause.length ? cause.map((value, index) => `\n\nCause #${cause.length - index}: ` + value).join('') : '');
357
387
  }
358
388
  function writeLine(value) {
@@ -360,9 +390,6 @@ function writeLine(value) {
360
390
  LOG_NEWLINE = true;
361
391
  LOG_EMPTYLINE = false;
362
392
  }
363
- function errorPermission(value) {
364
- return (0, types_1.errorValue)("Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, value);
365
- }
366
393
  function parseFileArgs(options = {}, callback) {
367
394
  let promises;
368
395
  if (typeof options === 'boolean') {
@@ -409,16 +436,40 @@ function getTimeStamp(options, include) {
409
436
  }
410
437
  function getCacheItem(map, key) {
411
438
  const item = map.get(key);
412
- if (item) {
413
- item[0] = Date.now();
414
- return item[1];
439
+ if (!item) {
440
+ return;
415
441
  }
442
+ const current = Date.now();
443
+ if (item[0] + MEMORY_CACHE_DISK.expires >= current) {
444
+ --CACHE_TOTAL;
445
+ map.delete(key);
446
+ return;
447
+ }
448
+ item[0] = current;
449
+ return item[1];
416
450
  }
417
- function addCacheItem(map, key, data) {
418
- if (!map.has(key)) {
419
- ++CACHE_TOTAL;
451
+ function addCacheItem(map, key, data, cache) {
452
+ const length = Buffer.byteLength(data);
453
+ if (length < MEMORY_CACHE_DISK.min_size || length > MEMORY_CACHE_DISK.max_size) {
454
+ return;
455
+ }
456
+ key = Module.toPosix(key, true);
457
+ if (!cache) {
458
+ if (MEMORY_CACHE_DISK.include) {
459
+ if (!MEMORY_CACHE_DISK.include.some(value => pm.isMatch(key, value, { nocase: PLATFORM_WIN32, matchBase: value.startsWith('*') }))) {
460
+ return;
461
+ }
462
+ }
463
+ else {
464
+ cache = true;
465
+ }
466
+ }
467
+ if (!(cache && MEMORY_CACHE_DISK.exclude?.some(value => pm.isMatch(key, value, { nocase: PLATFORM_WIN32, matchBase: value.startsWith('*') })))) {
468
+ if (!map.has(key)) {
469
+ ++CACHE_TOTAL;
470
+ }
471
+ map.set(key, [Date.now(), data]);
420
472
  }
421
- map.set(key, [Date.now(), data]);
422
473
  }
423
474
  function checkFunction(value) {
424
475
  if (typeof value === 'function') {
@@ -430,9 +481,7 @@ function checkFunction(value) {
430
481
  function encryptMessage(data, cipher, algorithm) {
431
482
  var _h;
432
483
  if (cipher?.key && cipher.iv) {
433
- if (!algorithm) {
434
- algorithm = cipher.algorithm || 'aes-256-gcm';
435
- }
484
+ algorithm || (algorithm = cipher.algorithm || 'aes-256-gcm');
436
485
  const result = (0, types_1.encryptUTF8)(algorithm, cipher.key, cipher.iv, data);
437
486
  if (result) {
438
487
  VALUES[_h = "process.cipher.algorithm" /* KEY_NAME.PROCESS_CIPHER_ALGORITHM */] || (VALUES[_h] = algorithm);
@@ -506,9 +555,7 @@ function hasFileSystem(type, value, options, ignoreExists, overwrite) {
506
555
  return result;
507
556
  }
508
557
  function applyLogId(options) {
509
- if (options.sessionId === undefined) {
510
- options.sessionId = this.sessionId;
511
- }
558
+ options.sessionId ?? (options.sessionId = this.sessionId);
512
559
  let value = options.broadcastId;
513
560
  if (value === undefined) {
514
561
  if (value = this.broadcastId) {
@@ -538,36 +585,20 @@ function formatPercent(value, precision = 3) {
538
585
  }
539
586
  return (value * 100).toPrecision(precision) + '%';
540
587
  }
541
- function tryIncrementDir(value, increment) {
542
- const baseDir = trimDir(value);
543
- let i = 0, outErr;
544
- do {
545
- try {
546
- if (tryCreateDir(value)) {
547
- return [value, i];
548
- }
549
- }
550
- catch (err) {
551
- if (increment === 0) {
552
- outErr = err;
553
- }
554
- }
555
- value = baseDir + '_' + ++i;
556
- } while (increment-- > 0);
557
- return [outErr, -1];
558
- }
559
588
  const hideAbort = (err) => err.name === 'AbortError' && SETTINGS.abort === false;
560
589
  const asFile = (value) => value instanceof URL ? value.protocol === 'file:' ? url.fileURLToPath(value) : '' : value;
561
590
  const wrapQuote = (value) => '"' + value.replace(/"/g, '\\"') + '"';
562
591
  const isFunction = (value) => typeof value === 'function';
563
592
  const isFileURL = (value) => /^file:\/\//i.test(value);
564
- const errorDirectory = (value) => (0, types_1.errorValue)("Path is not a directory" /* ERR_MESSAGE.NOT_DIRECTORY */, value);
565
593
  const sanitizePath = (value) => (0, types_1.isString)(value) ? path.resolve(value.trim()) : '';
566
594
  const ensureDir = (value) => value.endsWith(path.sep) ? value : value + path.sep;
567
595
  const trimDir = (value) => value.endsWith(path.sep) ? value.substring(0, value.length - 1) : value;
568
596
  const getExtension = (value) => path.extname(value).toLowerCase().substring(1);
569
597
  const hasString = (item, value) => (0, types_1.isString)(value) && (item === value || Array.isArray(item) && item.includes(value));
570
598
  const getCpuTimes = () => os.cpus().reduce((a, b) => a + b.times.user + b.times.sys, 0) * 1000 /* TIME.S */;
599
+ const autoMemoryCache = () => MEMORY_CACHE_DISK.enabled && MEMORY_CACHE_DISK.max_size > 0;
600
+ const errorDirectory = (value) => (0, types_1.errorValue)("Path is not a directory" /* ERR_MESSAGE.NOT_DIRECTORY */, value);
601
+ const errorPermission = (value) => (0, types_1.errorValue)("Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, value);
571
602
  class Module extends EventEmitter {
572
603
  constructor() {
573
604
  super(...arguments);
@@ -590,7 +621,7 @@ class Module extends EventEmitter {
590
621
  this[_f] = new AbortController();
591
622
  this[_g] = null;
592
623
  }
593
- static get VERSION() { return "0.8.0" /* INTERNAL.VERSION */; }
624
+ static get VERSION() { return "0.8.1" /* INTERNAL.VERSION */; }
594
625
  static get LOG_TYPE() { return types_1.LOG_TYPE; }
595
626
  static get STATUS_TYPE() { return types_1.STATUS_TYPE; }
596
627
  static get MAX_TIMEOUT() { return 2147483647; }
@@ -618,6 +649,8 @@ class Module extends EventEmitter {
618
649
  }
619
650
  case "temp.dir" /* KEY_NAME.TEMP_DIR */:
620
651
  return VALUES[key] !== "tmp" /* INTERNAL.TEMP_DIR */;
652
+ case "memory.settings.cache_disk" /* KEY_NAME.MEMORY_SETTINGS_CACHE_DISK */:
653
+ return MEMORY_CACHE_DISK.enabled;
621
654
  case "node.require.npm" /* KEY_NAME.NODE_REQUIRE_NPM */:
622
655
  case "node.require.inline" /* KEY_NAME.NODE_REQUIRE_INLINE */:
623
656
  case "node.process.cpu_usage" /* KEY_NAME.NODE_PROCESS_CPUUSAGE */:
@@ -1145,11 +1178,15 @@ class Module extends EventEmitter {
1145
1178
  }
1146
1179
  }
1147
1180
  static async readHash(value, options = {}) {
1148
- const { algorithm = "sha256" /* HASH_OUTPUT.ALGORITHM */, digest = "hex" /* HASH_OUTPUT.DIGEST */, minStreamSize = 0, chunkSize = 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */ } = options;
1149
- const hash = crypto.createHash(algorithm);
1181
+ const { algorithm, digest, chunkSize = 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */ } = options;
1182
+ const hash = crypto.createHash(algorithm || "sha256" /* HASH_OUTPUT.ALGORITHM */);
1150
1183
  try {
1184
+ let minStreamSize = options.minStreamSize || 0;
1185
+ if ((0, types_1.isString)(minStreamSize)) {
1186
+ minStreamSize = (0, types_1.formatSize)(minStreamSize);
1187
+ }
1151
1188
  if (fs.statSync(value).size <= Math.min(minStreamSize > 0 ? minStreamSize : Infinity, 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */)) {
1152
- return hash.update(fs.readFileSync(value)).digest(digest);
1189
+ return hash.update(fs.readFileSync(value)).digest(digest || "hex" /* HASH_OUTPUT.DIGEST */);
1153
1190
  }
1154
1191
  }
1155
1192
  catch (err) {
@@ -1157,7 +1194,7 @@ class Module extends EventEmitter {
1157
1194
  throw err;
1158
1195
  }
1159
1196
  }
1160
- const readable = fs.createReadStream(value);
1197
+ const readable = fs.createReadStream(value, { signal: options.signal });
1161
1198
  const chunks = [];
1162
1199
  let length = 0;
1163
1200
  for await (const chunk of readable) {
@@ -1173,7 +1210,7 @@ class Module extends EventEmitter {
1173
1210
  if (chunks.length) {
1174
1211
  hash.update(Buffer.concat(chunks));
1175
1212
  }
1176
- return hash.digest(digest);
1213
+ return hash.digest(digest || "hex" /* HASH_OUTPUT.DIGEST */);
1177
1214
  }
1178
1215
  static toPosix(value, filename, normalize) {
1179
1216
  if (typeof filename === 'boolean') {
@@ -1574,21 +1611,64 @@ class Module extends EventEmitter {
1574
1611
  }
1575
1612
  return false;
1576
1613
  }
1614
+ static async streamFile(src, cache, options) {
1615
+ if ((0, types_1.isObject)(cache)) {
1616
+ options = cache;
1617
+ }
1618
+ let minStreamSize = 0, encoding, signal;
1619
+ if (options) {
1620
+ ({ minStreamSize = 0, encoding, signal, cache } = options);
1621
+ }
1622
+ return new Promise(async (resolve) => {
1623
+ if ((0, types_1.isString)(minStreamSize)) {
1624
+ minStreamSize = (0, types_1.formatSize)(minStreamSize);
1625
+ }
1626
+ const fileSize = fs.statSync(src).size;
1627
+ let data;
1628
+ if (fileSize >= minStreamSize || fileSize >= 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */) {
1629
+ const readable = fs.createReadStream(src, { signal });
1630
+ const chunks = [];
1631
+ for await (const chunk of readable) {
1632
+ chunks.push(Buffer.from(chunk));
1633
+ }
1634
+ data = Buffer.concat(chunks);
1635
+ if (encoding) {
1636
+ data = data.toString(encoding);
1637
+ }
1638
+ }
1639
+ else {
1640
+ data = fs.readFileSync(src, encoding);
1641
+ }
1642
+ if (cache || cache !== false && autoMemoryCache()) {
1643
+ addCacheItem(encoding ? CACHE_READTEXT : CACHE_READBUFFER, src, data, cache);
1644
+ }
1645
+ resolve(data);
1646
+ });
1647
+ }
1577
1648
  static readText(value, encoding, cache) {
1649
+ let minStreamSize, options;
1578
1650
  if (typeof encoding === 'boolean') {
1579
1651
  cache = encoding;
1580
1652
  encoding = undefined;
1581
1653
  }
1654
+ else if ((0, types_1.isObject)(encoding)) {
1655
+ options = encoding;
1656
+ ({ minStreamSize, encoding, cache } = options);
1657
+ }
1582
1658
  const src = sanitizePath(asFile(value));
1583
1659
  if (src && this.isPath(src, true)) {
1584
1660
  let result;
1585
1661
  if (cache && (result = getCacheItem(CACHE_READTEXT, src))) {
1586
- return result;
1662
+ return (minStreamSize !== undefined ? Promise.resolve(result) : result);
1663
+ }
1664
+ encoding = (0, types_1.getEncoding)(encoding);
1665
+ if (minStreamSize !== undefined) {
1666
+ return this.streamFile(src, options);
1587
1667
  }
1588
1668
  try {
1589
- result = fs.readFileSync(value, (0, types_1.getEncoding)(encoding));
1590
- if (cache && result) {
1591
- addCacheItem(CACHE_READTEXT, src, result);
1669
+ result = fs.readFileSync(value, encoding);
1670
+ if (result && (cache || cache !== false && autoMemoryCache())) {
1671
+ addCacheItem(CACHE_READTEXT, src, result, cache);
1592
1672
  }
1593
1673
  return result;
1594
1674
  }
@@ -1596,19 +1676,27 @@ class Module extends EventEmitter {
1596
1676
  this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(src)], err, 32 /* LOG_VALUE.FILE */);
1597
1677
  }
1598
1678
  }
1599
- return '';
1679
+ return (minStreamSize !== undefined ? Promise.resolve('') : '');
1600
1680
  }
1601
1681
  static readBuffer(value, cache) {
1682
+ let minStreamSize, options;
1683
+ if ((0, types_1.isObject)(cache)) {
1684
+ options = cache;
1685
+ ({ minStreamSize, cache } = options);
1686
+ }
1602
1687
  const src = sanitizePath(asFile(value));
1603
1688
  if (src && this.isPath(src, true)) {
1604
1689
  let result;
1605
1690
  if (cache && (result = getCacheItem(CACHE_READBUFFER, src))) {
1606
- return result;
1691
+ return (minStreamSize !== undefined ? Promise.resolve(result) : result);
1692
+ }
1693
+ if (minStreamSize !== undefined) {
1694
+ return this.streamFile(src, options);
1607
1695
  }
1608
1696
  try {
1609
1697
  result = fs.readFileSync(value);
1610
- if (cache && result) {
1611
- addCacheItem(CACHE_READBUFFER, src, result);
1698
+ if (result && (cache || cache !== false && autoMemoryCache())) {
1699
+ addCacheItem(CACHE_READBUFFER, src, result, cache);
1612
1700
  }
1613
1701
  return result;
1614
1702
  }
@@ -1616,7 +1704,7 @@ class Module extends EventEmitter {
1616
1704
  this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(src)], err, 32 /* LOG_VALUE.FILE */);
1617
1705
  }
1618
1706
  }
1619
- return null;
1707
+ return (minStreamSize !== undefined ? Promise.resolve(null) : null);
1620
1708
  }
1621
1709
  static async resolveMime(data) {
1622
1710
  return typeof data === 'string' ? filetype.fromFile(data) : filetype.fromBuffer(data);
@@ -1989,9 +2077,15 @@ class Module extends EventEmitter {
1989
2077
  }
1990
2078
  else if (percent > 0) {
1991
2079
  const stored = [];
2080
+ const current = Date.now();
1992
2081
  for (const map of [CACHE_READTEXT, CACHE_READBUFFER, CACHE_READCJS]) {
1993
2082
  for (const [key, value] of map) {
1994
- stored.push([map, key, value[0]]);
2083
+ if (value[0] + MEMORY_CACHE_DISK.expires >= current) {
2084
+ map.delete(key);
2085
+ }
2086
+ else {
2087
+ stored.push([map, key, value[0]]);
2088
+ }
1995
2089
  }
1996
2090
  }
1997
2091
  stored.sort((a, b) => a[2] - b[2]);
@@ -2081,11 +2175,44 @@ class Module extends EventEmitter {
2081
2175
  VALUES[_h = "process.password" /* KEY_NAME.PROCESS_PASSWORD */] || (VALUES[_h] = encryptMessage(pwd, cipher));
2082
2176
  }
2083
2177
  }
2084
- if (memory && (0, types_1.isPlainObject)(memory.settings)) {
2085
- const users = memory.settings.users;
2178
+ if ((0, types_1.isPlainObject)(memory?.settings)) {
2179
+ const { users, cache_disk } = memory.settings;
2086
2180
  if (typeof users === 'boolean' || Array.isArray(users)) {
2087
2181
  VALUES["memory.settings.users" /* KEY_NAME.MEMORY_SETTINGS_USERS */] = users;
2088
2182
  }
2183
+ if ((0, types_1.isPlainObject)(cache_disk)) {
2184
+ let { enabled, min_size, max_size, expires, include, exclude } = cache_disk;
2185
+ MEMORY_CACHE_DISK.enabled = enabled === true;
2186
+ if (min_size !== undefined) {
2187
+ if ((0, types_1.isString)(min_size)) {
2188
+ min_size = (0, types_1.formatSize)(min_size);
2189
+ }
2190
+ else if (min_size > 0) {
2191
+ min_size *= 1024;
2192
+ }
2193
+ MEMORY_CACHE_DISK.min_size = min_size > 0 ? min_size : Infinity;
2194
+ }
2195
+ if (max_size !== undefined) {
2196
+ if ((0, types_1.isString)(max_size)) {
2197
+ max_size = (0, types_1.formatSize)(max_size);
2198
+ }
2199
+ else if (max_size > 0) {
2200
+ max_size *= 1024;
2201
+ }
2202
+ MEMORY_CACHE_DISK.max_size = max_size > 0 ? max_size : 0;
2203
+ }
2204
+ if (expires !== undefined && (expires = (0, types_1.parseExpires)(expires)) > 0) {
2205
+ MEMORY_CACHE_DISK.expires = expires;
2206
+ }
2207
+ MEMORY_CACHE_DISK.include = null;
2208
+ MEMORY_CACHE_DISK.exclude = null;
2209
+ if ((0, types_1.isArray)(include)) {
2210
+ MEMORY_CACHE_DISK.include = include.map(value => this.toPosix(value, true));
2211
+ }
2212
+ else if ((0, types_1.isArray)(exclude)) {
2213
+ MEMORY_CACHE_DISK.exclude = exclude.map(value => this.toPosix(value, true));
2214
+ }
2215
+ }
2089
2216
  }
2090
2217
  if ((0, types_1.isPlainObject)(logger)) {
2091
2218
  const { enabled, level, production, broadcast, stack_trace } = logger;
@@ -2227,7 +2354,7 @@ class Module extends EventEmitter {
2227
2354
  Error.stackTraceLimit = +stack_trace;
2228
2355
  }
2229
2356
  }
2230
- if (error) {
2357
+ if ((0, types_1.isPlainObject)(error)) {
2231
2358
  if (error.out) {
2232
2359
  VALUES["error.out" /* KEY_NAME.ERROR_OUT */] = this.parseFunction(error.out, { external: true, absolute: true });
2233
2360
  }
@@ -2235,7 +2362,7 @@ class Module extends EventEmitter {
2235
2362
  VALUES["error.fatal" /* KEY_NAME.ERROR_FATAL */] = error.fatal;
2236
2363
  }
2237
2364
  }
2238
- if (permission && Array.isArray(permission.process_exec)) {
2365
+ if (Array.isArray(permission?.process_exec)) {
2239
2366
  VALUES["permission.process_exec" /* KEY_NAME.PERMISSION_PROCESS_EXEC */] = permission.process_exec.filter(item => typeof item === 'string' || (0, types_1.isObject)(item) && typeof item.command === 'string').map(exec => {
2240
2367
  if (typeof exec === 'string') {
2241
2368
  return exec.trim();
@@ -2248,12 +2375,11 @@ class Module extends EventEmitter {
2248
2375
  });
2249
2376
  }
2250
2377
  {
2251
- let dir = settings.temp_dir, write;
2378
+ let dir = settings.temp_dir, write, modified;
2252
2379
  if ((0, types_1.isPlainObject)(temp)) {
2253
2380
  dir || (dir = temp.dir);
2254
2381
  write = temp.write;
2255
2382
  }
2256
- let modified;
2257
2383
  if ((0, types_1.isString)(dir) && path.isAbsolute(dir = path.normalize(dir).replace(/[\\/]$/, ''))) {
2258
2384
  if (withinDir(dir, PROCESS_CWD)) {
2259
2385
  dir = dir.substring(ensureDir(PROCESS_CWD).length);
@@ -2402,12 +2528,12 @@ class Module extends EventEmitter {
2402
2528
  let promises, outSrc;
2403
2529
  [options, promises, callback] = parseFileArgs(options, callback);
2404
2530
  if (outSrc = hasFileSystem.call(this, 0 /* FILE_SYSTEM.READ */, src, options)) {
2405
- const { requireExt, cache } = options;
2531
+ let { requireExt, minStreamSize, cache } = options;
2406
2532
  const encoding = options.encoding && (0, types_1.getEncoding)(options.encoding);
2407
2533
  const setCache = (data, cjs) => {
2408
2534
  if (data) {
2409
- if (cache) {
2410
- addCacheItem(cjs ? CACHE_READCJS : encoding ? CACHE_READTEXT : CACHE_READBUFFER, outSrc, data);
2535
+ if (cache || cache !== false && autoMemoryCache()) {
2536
+ addCacheItem(cjs ? CACHE_READCJS : encoding ? CACHE_READTEXT : CACHE_READBUFFER, outSrc, data, cache);
2411
2537
  }
2412
2538
  this.emit('file:read', outSrc, data, options);
2413
2539
  }
@@ -2430,6 +2556,31 @@ class Module extends EventEmitter {
2430
2556
  if (cache) {
2431
2557
  result || (result = (encoding ? getCacheItem(CACHE_READTEXT, outSrc) : getCacheItem(CACHE_READBUFFER, outSrc)));
2432
2558
  }
2559
+ try {
2560
+ if ((0, types_1.isString)(minStreamSize)) {
2561
+ minStreamSize = (0, types_1.formatSize)(minStreamSize);
2562
+ }
2563
+ if (typeof minStreamSize === 'number' || promises && fs.statSync(outSrc).size >= 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */) {
2564
+ if (result) {
2565
+ return Promise.resolve(result);
2566
+ }
2567
+ if (promises || fs.statSync(outSrc).size >= Math.min(minStreamSize || Infinity, 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */)) {
2568
+ return new Promise(async (resolve) => {
2569
+ const readable = fs.createReadStream(outSrc, { signal: this.signal });
2570
+ const chunks = [];
2571
+ for await (const chunk of readable) {
2572
+ chunks.push(Buffer.from(chunk));
2573
+ }
2574
+ const data = Buffer.concat(chunks);
2575
+ resolve((encoding ? data.toString(encoding) : data));
2576
+ });
2577
+ }
2578
+ promises = true;
2579
+ }
2580
+ }
2581
+ catch {
2582
+ promises = true;
2583
+ }
2433
2584
  if (promises) {
2434
2585
  if (result) {
2435
2586
  return Promise.resolve(result);
package/lib-v4.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { IModuleLibV4 } from '../types/lib/compat-v4';
2
-
3
- declare const LibV4: IModuleLibV4;
4
-
1
+ import type { IModuleLibV4 } from '../types/lib/compat-v4';
2
+
3
+ declare const LibV4: IModuleLibV4;
4
+
5
5
  export = LibV4;
package/lib-v4.js CHANGED
@@ -97,7 +97,7 @@ function isPathUNC(value) {
97
97
  return index_1.default.isPath(value, 'unc');
98
98
  }
99
99
  exports.isPathUNC = isPathUNC;
100
- function readFileSafe(value, encoding, cache) {
100
+ async function readFileSafe(value, encoding, cache) {
101
101
  return encoding === 'buffer' ? index_1.default.readBuffer(value, cache) : index_1.default.readText(value, encoding, cache);
102
102
  }
103
103
  exports.readFileSafe = readFileSafe;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/module",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Module base class for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,12 +20,13 @@
20
20
  "license": "BSD 3-Clause",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/types": "0.8.0",
23
+ "@e-mc/types": "0.8.1",
24
24
  "abort-controller": "^3.0.0",
25
25
  "chalk": "4.1.2",
26
26
  "event-target-shim": "^5.0.1",
27
27
  "file-type": "16.5.4",
28
28
  "mime-types": "^2.1.35",
29
+ "picomatch": "^3.0.1",
29
30
  "strip-ansi": "6.0.1"
30
31
  }
31
32
  }