@e-mc/module 0.8.0 → 0.8.2

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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ### @e-mc/module
2
2
 
3
+ https://e-mc.readthedocs.io
4
+
3
5
  ### LICENSE
4
6
 
5
7
  BSD 3-Clause
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");
@@ -40,7 +41,8 @@ const SETTINGS = {
40
41
  format: {
41
42
  title: {
42
43
  width: 6,
43
- justify: 'right'
44
+ justify: 'right',
45
+ as: {}
44
46
  },
45
47
  value: {
46
48
  width: 71,
@@ -48,7 +50,8 @@ const SETTINGS = {
48
50
  },
49
51
  hint: {
50
52
  width: 32,
51
- unit: 'auto'
53
+ unit: 'auto',
54
+ as: {}
52
55
  },
53
56
  meter: {
54
57
  width: Infinity,
@@ -118,6 +121,14 @@ const VALUES = {
118
121
  ["broadcast.out" /* KEY_NAME.BROADCAST_OUT */]: null,
119
122
  ["logger.level" /* KEY_NAME.LOGGER_LEVEL */]: -1
120
123
  };
124
+ const MEMORY_CACHE_DISK = {
125
+ enabled: false,
126
+ min_size: Infinity,
127
+ max_size: 0,
128
+ expires: Infinity,
129
+ include: null,
130
+ exclude: null
131
+ };
121
132
  const REGEXP_TORRENT = /^(?:magnet:\?xt=|(?:https?|s?ftp):\/\/[^/][^\n]*?\.(?:torrent|metalink|meta4)(?:\?[^\n]*)?$)/i;
122
133
  let LOG_NEWLINE = true;
123
134
  let LOG_EMPTYLINE = false;
@@ -303,14 +314,35 @@ function tryRemoveDir(value, empty, recursive) {
303
314
  }
304
315
  return failed;
305
316
  }
317
+ function tryIncrementDir(value, increment) {
318
+ const baseDir = trimDir(value);
319
+ let i = 0, outErr;
320
+ do {
321
+ try {
322
+ if (tryCreateDir(value)) {
323
+ return [value, i];
324
+ }
325
+ }
326
+ catch (err) {
327
+ if (increment === 0) {
328
+ outErr = err;
329
+ }
330
+ }
331
+ value = baseDir + '_' + ++i;
332
+ } while (increment-- > 0);
333
+ return [outErr, -1];
334
+ }
306
335
  function errorObject(message) {
336
+ if (message instanceof Error) {
337
+ return message;
338
+ }
307
339
  switch (typeof message) {
308
340
  case 'string':
309
341
  return new Error(message);
310
342
  case 'number':
311
343
  return (0, types_1.errorMessage)("Error code" /* ERR_MESSAGE.ERROR_CODE */, message.toString());
312
344
  default:
313
- return message instanceof Error ? message : new Error(Module.asString(message) || "Unknown" /* ERR_MESSAGE.UNKNOWN */);
345
+ return new Error(Module.asString(message) || "Unknown" /* ERR_MESSAGE.UNKNOWN */);
314
346
  }
315
347
  }
316
348
  function isFailed(options) {
@@ -322,7 +354,7 @@ function isFailed(options) {
322
354
  }
323
355
  return false;
324
356
  }
325
- function getErrorCause(err, out, visited) {
357
+ function recurseCause(err, out, visited) {
326
358
  let message;
327
359
  if (visited) {
328
360
  message = SETTINGS.stack_trace && err.stack || err.message;
@@ -338,7 +370,7 @@ function getErrorCause(err, out, visited) {
338
370
  out.push(message);
339
371
  }
340
372
  if (!visited.has(cause)) {
341
- getErrorCause(cause, out, visited);
373
+ recurseCause(cause, out, visited);
342
374
  }
343
375
  return;
344
376
  }
@@ -352,7 +384,7 @@ function getErrorCause(err, out, visited) {
352
384
  }
353
385
  function getErrorMessage(err) {
354
386
  const cause = [];
355
- getErrorCause(err, cause);
387
+ recurseCause(err, cause);
356
388
  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
389
  }
358
390
  function writeLine(value) {
@@ -360,9 +392,6 @@ function writeLine(value) {
360
392
  LOG_NEWLINE = true;
361
393
  LOG_EMPTYLINE = false;
362
394
  }
363
- function errorPermission(value) {
364
- return (0, types_1.errorValue)("Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, value);
365
- }
366
395
  function parseFileArgs(options = {}, callback) {
367
396
  let promises;
368
397
  if (typeof options === 'boolean') {
@@ -409,16 +438,40 @@ function getTimeStamp(options, include) {
409
438
  }
410
439
  function getCacheItem(map, key) {
411
440
  const item = map.get(key);
412
- if (item) {
413
- item[0] = Date.now();
414
- return item[1];
441
+ if (!item) {
442
+ return;
443
+ }
444
+ const current = Date.now();
445
+ if (item[0] + MEMORY_CACHE_DISK.expires >= current) {
446
+ --CACHE_TOTAL;
447
+ map.delete(key);
448
+ return;
415
449
  }
450
+ item[0] = current;
451
+ return item[1];
416
452
  }
417
- function addCacheItem(map, key, data) {
418
- if (!map.has(key)) {
419
- ++CACHE_TOTAL;
453
+ function addCacheItem(map, key, data, cache) {
454
+ const length = Buffer.byteLength(data);
455
+ if (length < MEMORY_CACHE_DISK.min_size || length > MEMORY_CACHE_DISK.max_size) {
456
+ return;
457
+ }
458
+ key = Module.toPosix(key, true);
459
+ if (!cache) {
460
+ if (MEMORY_CACHE_DISK.include) {
461
+ if (!MEMORY_CACHE_DISK.include.some(value => pm.isMatch(key, value, { nocase: PLATFORM_WIN32, matchBase: value.startsWith('*') }))) {
462
+ return;
463
+ }
464
+ }
465
+ else {
466
+ cache = true;
467
+ }
468
+ }
469
+ if (!(cache && MEMORY_CACHE_DISK.exclude?.some(value => pm.isMatch(key, value, { nocase: PLATFORM_WIN32, matchBase: value.startsWith('*') })))) {
470
+ if (!map.has(key)) {
471
+ ++CACHE_TOTAL;
472
+ }
473
+ map.set(key, [Date.now(), data]);
420
474
  }
421
- map.set(key, [Date.now(), data]);
422
475
  }
423
476
  function checkFunction(value) {
424
477
  if (typeof value === 'function') {
@@ -430,9 +483,7 @@ function checkFunction(value) {
430
483
  function encryptMessage(data, cipher, algorithm) {
431
484
  var _h;
432
485
  if (cipher?.key && cipher.iv) {
433
- if (!algorithm) {
434
- algorithm = cipher.algorithm || 'aes-256-gcm';
435
- }
486
+ algorithm || (algorithm = cipher.algorithm || 'aes-256-gcm');
436
487
  const result = (0, types_1.encryptUTF8)(algorithm, cipher.key, cipher.iv, data);
437
488
  if (result) {
438
489
  VALUES[_h = "process.cipher.algorithm" /* KEY_NAME.PROCESS_CIPHER_ALGORITHM */] || (VALUES[_h] = algorithm);
@@ -506,9 +557,7 @@ function hasFileSystem(type, value, options, ignoreExists, overwrite) {
506
557
  return result;
507
558
  }
508
559
  function applyLogId(options) {
509
- if (options.sessionId === undefined) {
510
- options.sessionId = this.sessionId;
511
- }
560
+ options.sessionId ?? (options.sessionId = this.sessionId);
512
561
  let value = options.broadcastId;
513
562
  if (value === undefined) {
514
563
  if (value = this.broadcastId) {
@@ -538,36 +587,20 @@ function formatPercent(value, precision = 3) {
538
587
  }
539
588
  return (value * 100).toPrecision(precision) + '%';
540
589
  }
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
590
  const hideAbort = (err) => err.name === 'AbortError' && SETTINGS.abort === false;
560
591
  const asFile = (value) => value instanceof URL ? value.protocol === 'file:' ? url.fileURLToPath(value) : '' : value;
561
592
  const wrapQuote = (value) => '"' + value.replace(/"/g, '\\"') + '"';
562
593
  const isFunction = (value) => typeof value === 'function';
563
594
  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
595
  const sanitizePath = (value) => (0, types_1.isString)(value) ? path.resolve(value.trim()) : '';
566
596
  const ensureDir = (value) => value.endsWith(path.sep) ? value : value + path.sep;
567
597
  const trimDir = (value) => value.endsWith(path.sep) ? value.substring(0, value.length - 1) : value;
568
598
  const getExtension = (value) => path.extname(value).toLowerCase().substring(1);
569
599
  const hasString = (item, value) => (0, types_1.isString)(value) && (item === value || Array.isArray(item) && item.includes(value));
570
600
  const getCpuTimes = () => os.cpus().reduce((a, b) => a + b.times.user + b.times.sys, 0) * 1000 /* TIME.S */;
601
+ const autoMemoryCache = () => MEMORY_CACHE_DISK.enabled && MEMORY_CACHE_DISK.max_size > 0;
602
+ const errorDirectory = (value) => (0, types_1.errorValue)("Path is not a directory" /* ERR_MESSAGE.NOT_DIRECTORY */, value);
603
+ const errorPermission = (value) => (0, types_1.errorValue)("Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, value);
571
604
  class Module extends EventEmitter {
572
605
  constructor() {
573
606
  super(...arguments);
@@ -590,7 +623,7 @@ class Module extends EventEmitter {
590
623
  this[_f] = new AbortController();
591
624
  this[_g] = null;
592
625
  }
593
- static get VERSION() { return "0.8.0" /* INTERNAL.VERSION */; }
626
+ static get VERSION() { return "0.8.2" /* INTERNAL.VERSION */; }
594
627
  static get LOG_TYPE() { return types_1.LOG_TYPE; }
595
628
  static get STATUS_TYPE() { return types_1.STATUS_TYPE; }
596
629
  static get MAX_TIMEOUT() { return 2147483647; }
@@ -618,6 +651,8 @@ class Module extends EventEmitter {
618
651
  }
619
652
  case "temp.dir" /* KEY_NAME.TEMP_DIR */:
620
653
  return VALUES[key] !== "tmp" /* INTERNAL.TEMP_DIR */;
654
+ case "memory.settings.cache_disk" /* KEY_NAME.MEMORY_SETTINGS_CACHE_DISK */:
655
+ return MEMORY_CACHE_DISK.enabled;
621
656
  case "node.require.npm" /* KEY_NAME.NODE_REQUIRE_NPM */:
622
657
  case "node.require.inline" /* KEY_NAME.NODE_REQUIRE_INLINE */:
623
658
  case "node.process.cpu_usage" /* KEY_NAME.NODE_PROCESS_CPUUSAGE */:
@@ -867,10 +902,11 @@ class Module extends EventEmitter {
867
902
  }
868
903
  }
869
904
  }
870
- title = titleIndent !== -1 ? ' '.repeat(titleIndent || (formatTitle.width + 3)) : (0, types_1.isString)(title) ? alignColumn(title.toUpperCase(), formatTitle.width, titleJustify, 1) : '';
871
- if (hint) {
905
+ title = titleIndent !== -1 ? ' '.repeat(titleIndent || (formatTitle.width + 3)) : (0, types_1.isString)(title) ? (title = title.toUpperCase(), alignColumn(formatTitle.as[title] || title, formatTitle.width, titleJustify, 1)) : '';
906
+ if ((0, types_1.isString)(hint)) {
872
907
  const formatHint = format.hint;
873
908
  let { hintColor, hintBgColor, hintBold } = options, hintWidth = formatHint.width;
909
+ hint = formatHint.as[hint] || hint;
874
910
  valueWidth -= Math.min(hint.length, hintWidth) + 2;
875
911
  if (hint.length > hintWidth && value.length + 1 < valueWidth) {
876
912
  const offset = Math.min(valueWidth - (value.length + 1), hint.length - hintWidth);
@@ -1145,11 +1181,15 @@ class Module extends EventEmitter {
1145
1181
  }
1146
1182
  }
1147
1183
  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);
1184
+ const { algorithm, digest, chunkSize = 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */ } = options;
1185
+ const hash = crypto.createHash(algorithm || "sha256" /* HASH_OUTPUT.ALGORITHM */);
1150
1186
  try {
1187
+ let minStreamSize = options.minStreamSize || 0;
1188
+ if ((0, types_1.isString)(minStreamSize)) {
1189
+ minStreamSize = (0, types_1.formatSize)(minStreamSize);
1190
+ }
1151
1191
  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);
1192
+ return hash.update(fs.readFileSync(value)).digest(digest || "hex" /* HASH_OUTPUT.DIGEST */);
1153
1193
  }
1154
1194
  }
1155
1195
  catch (err) {
@@ -1157,7 +1197,7 @@ class Module extends EventEmitter {
1157
1197
  throw err;
1158
1198
  }
1159
1199
  }
1160
- const readable = fs.createReadStream(value);
1200
+ const readable = fs.createReadStream(value, { signal: options.signal });
1161
1201
  const chunks = [];
1162
1202
  let length = 0;
1163
1203
  for await (const chunk of readable) {
@@ -1173,7 +1213,7 @@ class Module extends EventEmitter {
1173
1213
  if (chunks.length) {
1174
1214
  hash.update(Buffer.concat(chunks));
1175
1215
  }
1176
- return hash.digest(digest);
1216
+ return hash.digest(digest || "hex" /* HASH_OUTPUT.DIGEST */);
1177
1217
  }
1178
1218
  static toPosix(value, filename, normalize) {
1179
1219
  if (typeof filename === 'boolean') {
@@ -1574,21 +1614,64 @@ class Module extends EventEmitter {
1574
1614
  }
1575
1615
  return false;
1576
1616
  }
1617
+ static async streamFile(src, cache, options) {
1618
+ if ((0, types_1.isObject)(cache)) {
1619
+ options = cache;
1620
+ }
1621
+ let minStreamSize = 0, encoding, signal;
1622
+ if (options) {
1623
+ ({ minStreamSize = 0, encoding, signal, cache } = options);
1624
+ }
1625
+ return new Promise(async (resolve) => {
1626
+ if ((0, types_1.isString)(minStreamSize)) {
1627
+ minStreamSize = (0, types_1.formatSize)(minStreamSize);
1628
+ }
1629
+ const fileSize = fs.statSync(src).size;
1630
+ let data;
1631
+ if (fileSize >= minStreamSize || fileSize >= 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */) {
1632
+ const readable = fs.createReadStream(src, { signal });
1633
+ const chunks = [];
1634
+ for await (const chunk of readable) {
1635
+ chunks.push(Buffer.from(chunk));
1636
+ }
1637
+ data = Buffer.concat(chunks);
1638
+ if (encoding) {
1639
+ data = data.toString(encoding);
1640
+ }
1641
+ }
1642
+ else {
1643
+ data = fs.readFileSync(src, encoding);
1644
+ }
1645
+ if (cache || cache !== false && autoMemoryCache()) {
1646
+ addCacheItem(encoding ? CACHE_READTEXT : CACHE_READBUFFER, src, data, cache);
1647
+ }
1648
+ resolve(data);
1649
+ });
1650
+ }
1577
1651
  static readText(value, encoding, cache) {
1652
+ let minStreamSize, options;
1578
1653
  if (typeof encoding === 'boolean') {
1579
1654
  cache = encoding;
1580
1655
  encoding = undefined;
1581
1656
  }
1657
+ else if ((0, types_1.isObject)(encoding)) {
1658
+ options = encoding;
1659
+ ({ minStreamSize, encoding, cache } = options);
1660
+ }
1582
1661
  const src = sanitizePath(asFile(value));
1583
1662
  if (src && this.isPath(src, true)) {
1584
1663
  let result;
1585
1664
  if (cache && (result = getCacheItem(CACHE_READTEXT, src))) {
1586
- return result;
1665
+ return (minStreamSize !== undefined ? Promise.resolve(result) : result);
1666
+ }
1667
+ encoding = (0, types_1.getEncoding)(encoding);
1668
+ if (minStreamSize !== undefined) {
1669
+ return this.streamFile(src, options);
1587
1670
  }
1588
1671
  try {
1589
- result = fs.readFileSync(value, (0, types_1.getEncoding)(encoding));
1590
- if (cache && result) {
1591
- addCacheItem(CACHE_READTEXT, src, result);
1672
+ result = fs.readFileSync(value, encoding);
1673
+ if (result && (cache || cache !== false && autoMemoryCache())) {
1674
+ addCacheItem(CACHE_READTEXT, src, result, cache);
1592
1675
  }
1593
1676
  return result;
1594
1677
  }
@@ -1596,19 +1679,27 @@ class Module extends EventEmitter {
1596
1679
  this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(src)], err, 32 /* LOG_VALUE.FILE */);
1597
1680
  }
1598
1681
  }
1599
- return '';
1682
+ return (minStreamSize !== undefined ? Promise.resolve('') : '');
1600
1683
  }
1601
1684
  static readBuffer(value, cache) {
1685
+ let minStreamSize, options;
1686
+ if ((0, types_1.isObject)(cache)) {
1687
+ options = cache;
1688
+ ({ minStreamSize, cache } = options);
1689
+ }
1602
1690
  const src = sanitizePath(asFile(value));
1603
1691
  if (src && this.isPath(src, true)) {
1604
1692
  let result;
1605
1693
  if (cache && (result = getCacheItem(CACHE_READBUFFER, src))) {
1606
- return result;
1694
+ return (minStreamSize !== undefined ? Promise.resolve(result) : result);
1695
+ }
1696
+ if (minStreamSize !== undefined) {
1697
+ return this.streamFile(src, options);
1607
1698
  }
1608
1699
  try {
1609
1700
  result = fs.readFileSync(value);
1610
- if (cache && result) {
1611
- addCacheItem(CACHE_READBUFFER, src, result);
1701
+ if (result && (cache || cache !== false && autoMemoryCache())) {
1702
+ addCacheItem(CACHE_READBUFFER, src, result, cache);
1612
1703
  }
1613
1704
  return result;
1614
1705
  }
@@ -1616,7 +1707,7 @@ class Module extends EventEmitter {
1616
1707
  this.writeFail(["Unable to read file" /* ERR_MESSAGE.READ_FILE */, path.basename(src)], err, 32 /* LOG_VALUE.FILE */);
1617
1708
  }
1618
1709
  }
1619
- return null;
1710
+ return (minStreamSize !== undefined ? Promise.resolve(null) : null);
1620
1711
  }
1621
1712
  static async resolveMime(data) {
1622
1713
  return typeof data === 'string' ? filetype.fromFile(data) : filetype.fromBuffer(data);
@@ -1989,9 +2080,15 @@ class Module extends EventEmitter {
1989
2080
  }
1990
2081
  else if (percent > 0) {
1991
2082
  const stored = [];
2083
+ const current = Date.now();
1992
2084
  for (const map of [CACHE_READTEXT, CACHE_READBUFFER, CACHE_READCJS]) {
1993
2085
  for (const [key, value] of map) {
1994
- stored.push([map, key, value[0]]);
2086
+ if (value[0] + MEMORY_CACHE_DISK.expires >= current) {
2087
+ map.delete(key);
2088
+ }
2089
+ else {
2090
+ stored.push([map, key, value[0]]);
2091
+ }
1995
2092
  }
1996
2093
  }
1997
2094
  stored.sort((a, b) => a[2] - b[2]);
@@ -2081,11 +2178,44 @@ class Module extends EventEmitter {
2081
2178
  VALUES[_h = "process.password" /* KEY_NAME.PROCESS_PASSWORD */] || (VALUES[_h] = encryptMessage(pwd, cipher));
2082
2179
  }
2083
2180
  }
2084
- if (memory && (0, types_1.isPlainObject)(memory.settings)) {
2085
- const users = memory.settings.users;
2181
+ if ((0, types_1.isPlainObject)(memory?.settings)) {
2182
+ const { users, cache_disk } = memory.settings;
2086
2183
  if (typeof users === 'boolean' || Array.isArray(users)) {
2087
2184
  VALUES["memory.settings.users" /* KEY_NAME.MEMORY_SETTINGS_USERS */] = users;
2088
2185
  }
2186
+ if ((0, types_1.isPlainObject)(cache_disk)) {
2187
+ let { enabled, min_size, max_size, expires, include, exclude } = cache_disk;
2188
+ MEMORY_CACHE_DISK.enabled = enabled === true;
2189
+ if (min_size !== undefined) {
2190
+ if ((0, types_1.isString)(min_size)) {
2191
+ min_size = (0, types_1.formatSize)(min_size);
2192
+ }
2193
+ else if (min_size > 0) {
2194
+ min_size *= 1024;
2195
+ }
2196
+ MEMORY_CACHE_DISK.min_size = min_size > 0 ? min_size : Infinity;
2197
+ }
2198
+ if (max_size !== undefined) {
2199
+ if ((0, types_1.isString)(max_size)) {
2200
+ max_size = (0, types_1.formatSize)(max_size);
2201
+ }
2202
+ else if (max_size > 0) {
2203
+ max_size *= 1024;
2204
+ }
2205
+ MEMORY_CACHE_DISK.max_size = max_size > 0 ? max_size : 0;
2206
+ }
2207
+ if (expires !== undefined && (expires = (0, types_1.parseExpires)(expires)) > 0) {
2208
+ MEMORY_CACHE_DISK.expires = expires;
2209
+ }
2210
+ MEMORY_CACHE_DISK.include = null;
2211
+ MEMORY_CACHE_DISK.exclude = null;
2212
+ if ((0, types_1.isArray)(include)) {
2213
+ MEMORY_CACHE_DISK.include = include.map(value => this.toPosix(value, true));
2214
+ }
2215
+ else if ((0, types_1.isArray)(exclude)) {
2216
+ MEMORY_CACHE_DISK.exclude = exclude.map(value => this.toPosix(value, true));
2217
+ }
2218
+ }
2089
2219
  }
2090
2220
  if ((0, types_1.isPlainObject)(logger)) {
2091
2221
  const { enabled, level, production, broadcast, stack_trace } = logger;
@@ -2105,44 +2235,53 @@ class Module extends EventEmitter {
2105
2235
  switch (attr) {
2106
2236
  case 'format': {
2107
2237
  const format = logger.format;
2108
- if ((0, types_1.isPlainObject)(format)) {
2109
- for (const section in format) {
2110
- const stored = SETTINGS.format[section];
2111
- const target = format[section];
2112
- if (stored && (0, types_1.isPlainObject)(target)) {
2113
- for (let name in target) {
2114
- const value = target[name];
2115
- switch (name) {
2116
- case 'bg_color':
2117
- name = 'bgColor';
2118
- break;
2119
- case 'bg_alt_color':
2120
- name = 'bgAltColor';
2121
- break;
2238
+ for (const section in format) {
2239
+ const stored = SETTINGS.format[section];
2240
+ const target = format[section];
2241
+ if (stored && (0, types_1.isPlainObject)(target)) {
2242
+ for (let name in target) {
2243
+ const value = target[name];
2244
+ switch (name) {
2245
+ case 'bg_color':
2246
+ name = 'bgColor';
2247
+ break;
2248
+ case 'bg_alt_color':
2249
+ name = 'bgAltColor';
2250
+ break;
2251
+ }
2252
+ switch (name) {
2253
+ case 'width': {
2254
+ const width = parseInt(value);
2255
+ if (width > 0) {
2256
+ stored[name] = width;
2257
+ }
2258
+ break;
2122
2259
  }
2123
- switch (name) {
2124
- case 'width': {
2125
- const width = parseInt(value);
2126
- if (width > 0) {
2127
- stored[name] = width;
2128
- }
2129
- break;
2260
+ case 'bold':
2261
+ if (typeof value === 'boolean') {
2262
+ stored[name] = value;
2130
2263
  }
2131
- case 'bold':
2132
- if (typeof value === 'boolean') {
2133
- stored[name] = value;
2134
- }
2135
- break;
2136
- case 'color':
2137
- case 'bgColor':
2138
- case 'bgAltColor':
2139
- case 'justify':
2140
- case 'unit':
2141
- if (typeof value === 'string') {
2142
- stored[name] = value;
2264
+ break;
2265
+ case 'color':
2266
+ case 'bgColor':
2267
+ case 'bgAltColor':
2268
+ case 'justify':
2269
+ case 'unit':
2270
+ if (typeof value === 'string') {
2271
+ stored[name] = value;
2272
+ }
2273
+ break;
2274
+ case 'as':
2275
+ if ((section === 'title' || section === 'hint') && (0, types_1.isPlainObject)(value)) {
2276
+ const data = {};
2277
+ for (const as in value) {
2278
+ if (typeof value[as] === 'string') {
2279
+ data[section === 'title' ? as.toUpperCase() : as] = value[as];
2280
+ }
2143
2281
  }
2144
- break;
2145
- }
2282
+ Object.assign(stored[name], data);
2283
+ }
2284
+ break;
2146
2285
  }
2147
2286
  }
2148
2287
  }
@@ -2151,12 +2290,10 @@ class Module extends EventEmitter {
2151
2290
  }
2152
2291
  case 'meter': {
2153
2292
  const meter = logger.meter;
2154
- if ((0, types_1.isPlainObject)(meter)) {
2155
- for (const name in meter) {
2156
- const increment = +meter[name];
2157
- if (increment > 0) {
2158
- SETTINGS.meter[name] = increment;
2159
- }
2293
+ for (const name in meter) {
2294
+ const increment = +meter[name];
2295
+ if (increment > 0) {
2296
+ SETTINGS.meter[name] = increment;
2160
2297
  }
2161
2298
  }
2162
2299
  break;
@@ -2227,7 +2364,7 @@ class Module extends EventEmitter {
2227
2364
  Error.stackTraceLimit = +stack_trace;
2228
2365
  }
2229
2366
  }
2230
- if (error) {
2367
+ if ((0, types_1.isPlainObject)(error)) {
2231
2368
  if (error.out) {
2232
2369
  VALUES["error.out" /* KEY_NAME.ERROR_OUT */] = this.parseFunction(error.out, { external: true, absolute: true });
2233
2370
  }
@@ -2235,7 +2372,7 @@ class Module extends EventEmitter {
2235
2372
  VALUES["error.fatal" /* KEY_NAME.ERROR_FATAL */] = error.fatal;
2236
2373
  }
2237
2374
  }
2238
- if (permission && Array.isArray(permission.process_exec)) {
2375
+ if (Array.isArray(permission?.process_exec)) {
2239
2376
  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
2377
  if (typeof exec === 'string') {
2241
2378
  return exec.trim();
@@ -2248,12 +2385,11 @@ class Module extends EventEmitter {
2248
2385
  });
2249
2386
  }
2250
2387
  {
2251
- let dir = settings.temp_dir, write;
2388
+ let dir = settings.temp_dir, write, modified;
2252
2389
  if ((0, types_1.isPlainObject)(temp)) {
2253
2390
  dir || (dir = temp.dir);
2254
2391
  write = temp.write;
2255
2392
  }
2256
- let modified;
2257
2393
  if ((0, types_1.isString)(dir) && path.isAbsolute(dir = path.normalize(dir).replace(/[\\/]$/, ''))) {
2258
2394
  if (withinDir(dir, PROCESS_CWD)) {
2259
2395
  dir = dir.substring(ensureDir(PROCESS_CWD).length);
@@ -2402,12 +2538,12 @@ class Module extends EventEmitter {
2402
2538
  let promises, outSrc;
2403
2539
  [options, promises, callback] = parseFileArgs(options, callback);
2404
2540
  if (outSrc = hasFileSystem.call(this, 0 /* FILE_SYSTEM.READ */, src, options)) {
2405
- const { requireExt, cache } = options;
2541
+ let { requireExt, minStreamSize, cache } = options;
2406
2542
  const encoding = options.encoding && (0, types_1.getEncoding)(options.encoding);
2407
2543
  const setCache = (data, cjs) => {
2408
2544
  if (data) {
2409
- if (cache) {
2410
- addCacheItem(cjs ? CACHE_READCJS : encoding ? CACHE_READTEXT : CACHE_READBUFFER, outSrc, data);
2545
+ if (cache || cache !== false && autoMemoryCache()) {
2546
+ addCacheItem(cjs ? CACHE_READCJS : encoding ? CACHE_READTEXT : CACHE_READBUFFER, outSrc, data, cache);
2411
2547
  }
2412
2548
  this.emit('file:read', outSrc, data, options);
2413
2549
  }
@@ -2430,6 +2566,31 @@ class Module extends EventEmitter {
2430
2566
  if (cache) {
2431
2567
  result || (result = (encoding ? getCacheItem(CACHE_READTEXT, outSrc) : getCacheItem(CACHE_READBUFFER, outSrc)));
2432
2568
  }
2569
+ try {
2570
+ if ((0, types_1.isString)(minStreamSize)) {
2571
+ minStreamSize = (0, types_1.formatSize)(minStreamSize);
2572
+ }
2573
+ if (typeof minStreamSize === 'number' || promises && fs.statSync(outSrc).size >= 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */) {
2574
+ if (result) {
2575
+ return Promise.resolve(result);
2576
+ }
2577
+ if (promises || fs.statSync(outSrc).size >= Math.min(minStreamSize || Infinity, 2097152000 /* HASH_OUTPUT.CHUNK_SIZE */)) {
2578
+ return new Promise(async (resolve) => {
2579
+ const readable = fs.createReadStream(outSrc, { signal: this.signal });
2580
+ const chunks = [];
2581
+ for await (const chunk of readable) {
2582
+ chunks.push(Buffer.from(chunk));
2583
+ }
2584
+ const data = Buffer.concat(chunks);
2585
+ resolve((encoding ? data.toString(encoding) : data));
2586
+ });
2587
+ }
2588
+ promises = true;
2589
+ }
2590
+ }
2591
+ catch {
2592
+ promises = true;
2593
+ }
2433
2594
  if (promises) {
2434
2595
  if (result) {
2435
2596
  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.2",
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.2",
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
  }