@e-mc/document 0.13.10 → 0.14.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/README.md +22 -21
- package/asset.js +4 -2
- package/index.js +371 -193
- package/package.json +5 -8
- package/parse/dom.js +41 -42
- package/parse/index.js +54 -52
- package/transform/index.js +23 -22
- package/util.d.ts +2 -1
- package/util.js +40 -36
package/index.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const mod = require('node:module');
|
|
6
|
+
const pm = require('picomatch');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const { pathToFileURL } = require('node:url');
|
|
9
|
+
const { toUSVString } = require('node:util');
|
|
10
|
+
const { load } = require('js-yaml');
|
|
11
|
+
const { IMPORT_MAP, asExt, asFunction, cloneObject, coerceObject, createAbortError, errorMessage, errorValue, escapePattern, formatSize, getEncoding, hasGlob, hashKey, importESM, incrementUUID, isArray, isEmpty, isError, isFunction, isObject, isPlainObject, isString, manageGlobalObject, parseExpires, requireESM, supported } = require('@e-mc/types');
|
|
12
|
+
const { Client } = require('@e-mc/core');
|
|
13
|
+
const Db = require('@e-mc/db');
|
|
14
|
+
const { SourceMap, TransformSeries } = require('@e-mc/document/transform');
|
|
15
|
+
const { XmlWriter } = require('@e-mc/document/parse');
|
|
16
|
+
const { PATTERN_PARENTHESIS, appendSuffix, concatString, getHashData, getIndent, getModuleName, getNewline, spliceString } = require('@e-mc/document/util');
|
|
14
17
|
const kDocument = Symbol.for('document:constructor');
|
|
18
|
+
const SUPPORTED_GLOB = supported(22);
|
|
19
|
+
const SUPPORTED_PACKAGEJSON = supported(23, 2) || supported(22, 14, true);
|
|
20
|
+
const REGEXP_PACKAGEURI = /^(?:npm:)?((?:@[a-z\d-*~][a-z\d-*._~]*\/)?[a-z\d-~][a-z\d-._~]*\/.+)$/;
|
|
15
21
|
const CACHE_PACKAGE = new Map();
|
|
16
22
|
const CACHE_CONFIG = new Map();
|
|
17
23
|
const CACHE_TEMPLATE = new Map();
|
|
@@ -26,8 +32,8 @@ function initCache() {
|
|
|
26
32
|
CACHE_ETAG = Object.create(null);
|
|
27
33
|
CACHE_CODE = Object.create(null);
|
|
28
34
|
CACHE_HASH = Object.create(null);
|
|
29
|
-
CACHE_PICOMATCH = Object.create(null);
|
|
30
35
|
CACHE_EXTERNAL = Object.create(null);
|
|
36
|
+
CACHE_PICOMATCH = Object.create(null);
|
|
31
37
|
}
|
|
32
38
|
function deleteTransform(map, key, timeout) {
|
|
33
39
|
if (timeout) {
|
|
@@ -38,7 +44,7 @@ function deleteTransform(map, key, timeout) {
|
|
|
38
44
|
}
|
|
39
45
|
function getSourceMappingURL(value, css) {
|
|
40
46
|
if (value.includes(' ')) {
|
|
41
|
-
value = encodeURIComponent(
|
|
47
|
+
value = encodeURIComponent(toUSVString(value));
|
|
42
48
|
}
|
|
43
49
|
return css ? `\n/*# sourceMappingURL=${value} */\n` : `\n//# sourceMappingURL=${value}\n`;
|
|
44
50
|
}
|
|
@@ -47,21 +53,26 @@ function normalizeDir(value, check) {
|
|
|
47
53
|
if (check) {
|
|
48
54
|
value = toPosix(value).toLowerCase();
|
|
49
55
|
}
|
|
50
|
-
return value.
|
|
56
|
+
return value.at(-1) === sep ? value : value + sep;
|
|
57
|
+
}
|
|
58
|
+
function joinSpecifier(baseDir, specifier) {
|
|
59
|
+
const result = path.join(baseDir, specifier);
|
|
60
|
+
return Client.PLATFORM_WIN32 ? result.toLowerCase() : result;
|
|
51
61
|
}
|
|
52
62
|
function cloneConfigItems(items) {
|
|
53
63
|
const [a, b, c] = items;
|
|
54
|
-
return [a, (typeof b === 'object' ?
|
|
64
|
+
return [a, (typeof b === 'object' ? cloneObject(b, true) : b), typeof c === 'object' ? cloneObject(c, true) : c];
|
|
55
65
|
}
|
|
56
66
|
const isExcluded = (type, name, config, cacheData) => !(config?.hasType(type, name) || cacheData?.override === true);
|
|
57
67
|
const wrapCount = (value) => chalk.grey('(') + value + chalk.grey(')');
|
|
68
|
+
const validateExports = (value) => typeof value === 'string' && value.startsWith('./') && !/\/\.{1,2}\//.test(value);
|
|
58
69
|
const fixHint = (warningCount, errorCount, value) => warningCount > 0 || errorCount > 0 ? ':' + value : '';
|
|
59
70
|
const compareValue = (value) => value.replace(/["'()]/g, '').trim();
|
|
60
|
-
const toPath = (uri, hostname) => path.resolve(hostname[1], uri.
|
|
71
|
+
const toPath = (uri, hostname) => path.resolve(hostname[1], uri.slice(normalizeDir(hostname[0]).length).split('?')[0]);
|
|
61
72
|
const toBase64 = (value) => 'data:application/json;base64,' + Buffer.from(value).toString('base64');
|
|
62
|
-
const toPosix = (value) =>
|
|
73
|
+
const toPosix = (value) => Client.PLATFORM_WIN32 ? value.trim().replace(/(?:^\\|\\+)/g, '/') : value;
|
|
63
74
|
const joinString = (name, ...values) => (name ? name + ': ' : '') + values.reduce((a, b) => b ? a + (a ? ' -> ' : '') + b : a, '');
|
|
64
|
-
const truncateString = (value, width) => value.length > width ? value.
|
|
75
|
+
const truncateString = (value, width) => value.length > width ? value.slice(0, width - 3) + '...' : value.padStart(width);
|
|
65
76
|
class TransformCache {
|
|
66
77
|
config;
|
|
67
78
|
cacheData;
|
|
@@ -79,9 +90,9 @@ class TransformCache {
|
|
|
79
90
|
}
|
|
80
91
|
set(type, data) {
|
|
81
92
|
let pathname;
|
|
82
|
-
if (typeof this.cacheDir === 'string' &&
|
|
93
|
+
if (typeof this.cacheDir === 'string' && Client.createDir(pathname = path.join(this.cacheDir, 'transform', type))) {
|
|
83
94
|
try {
|
|
84
|
-
fs.writeFileSync(pathname = path.join(pathname,
|
|
95
|
+
fs.writeFileSync(pathname = path.join(pathname, incrementUUID()), JSON.stringify(data));
|
|
85
96
|
return pathname;
|
|
86
97
|
}
|
|
87
98
|
catch {
|
|
@@ -183,7 +194,7 @@ class TransformConfig {
|
|
|
183
194
|
algorithm = options;
|
|
184
195
|
enabled = true;
|
|
185
196
|
}
|
|
186
|
-
else if (
|
|
197
|
+
else if (options) {
|
|
187
198
|
({ enabled = true, algorithm, etag, expires, renew, limit, include, exclude } = options);
|
|
188
199
|
}
|
|
189
200
|
if (!enabled) {
|
|
@@ -207,32 +218,28 @@ class TransformConfig {
|
|
|
207
218
|
if (typeof etag === 'boolean') {
|
|
208
219
|
this.etag = etag;
|
|
209
220
|
}
|
|
210
|
-
if (expires && (expires =
|
|
211
|
-
this.expires = Math.min(expires,
|
|
221
|
+
if (expires && (expires = parseExpires(expires)) >= 0) {
|
|
222
|
+
this.expires = Math.min(expires, Client.MAX_TIMEOUT);
|
|
212
223
|
}
|
|
213
224
|
if (renew) {
|
|
214
225
|
this.renew = true;
|
|
215
226
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
this.include[type] = item;
|
|
224
|
-
}
|
|
227
|
+
for (const type in include) {
|
|
228
|
+
const item = include[type];
|
|
229
|
+
if (item === '*') {
|
|
230
|
+
this.include[type] = true;
|
|
231
|
+
}
|
|
232
|
+
else if (isArray(item)) {
|
|
233
|
+
this.include[type] = item;
|
|
225
234
|
}
|
|
226
235
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
this.exclude[type] = item;
|
|
235
|
-
}
|
|
236
|
+
for (const type in exclude) {
|
|
237
|
+
const item = exclude[type];
|
|
238
|
+
if (item === '*') {
|
|
239
|
+
this.exclude[type] = true;
|
|
240
|
+
}
|
|
241
|
+
else if (isArray(item)) {
|
|
242
|
+
this.exclude[type] = item;
|
|
236
243
|
}
|
|
237
244
|
}
|
|
238
245
|
if (limit !== undefined) {
|
|
@@ -241,7 +248,7 @@ class TransformConfig {
|
|
|
241
248
|
if (parseFloat(limit) === 0) {
|
|
242
249
|
value = 0;
|
|
243
250
|
}
|
|
244
|
-
else if ((value =
|
|
251
|
+
else if ((value = formatSize(limit)) === 0) {
|
|
245
252
|
return;
|
|
246
253
|
}
|
|
247
254
|
}
|
|
@@ -299,7 +306,7 @@ class TransformConfig {
|
|
|
299
306
|
}
|
|
300
307
|
useHash(cache, code) {
|
|
301
308
|
let key;
|
|
302
|
-
if (this.withinLimit(code, cache.encoding) && (key =
|
|
309
|
+
if (this.withinLimit(code, cache.encoding) && (key = Client.asHash(code, this.algorithm, { encoding: cache.encoding }))) {
|
|
303
310
|
const hashMap = CACHE_HASH[this.moduleName] ||= new Map();
|
|
304
311
|
const stored = hashMap.get(key);
|
|
305
312
|
let result;
|
|
@@ -335,7 +342,7 @@ class TransformConfig {
|
|
|
335
342
|
return limit === Infinity || limit > 0 && Buffer.byteLength(code, encoding) <= limit;
|
|
336
343
|
}
|
|
337
344
|
}
|
|
338
|
-
class Document extends
|
|
345
|
+
class Document extends Client {
|
|
339
346
|
static [kDocument] = true;
|
|
340
347
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
341
348
|
if (limit > 0 && CACHE_TOTAL < limit) {
|
|
@@ -384,14 +391,11 @@ class Document extends core_1.Client {
|
|
|
384
391
|
static async finalize(instance) {
|
|
385
392
|
for (const ext of instance.extensions) {
|
|
386
393
|
if (instance.aborted) {
|
|
387
|
-
return
|
|
394
|
+
return createAbortError(true);
|
|
388
395
|
}
|
|
389
396
|
try {
|
|
390
397
|
const args = [instance];
|
|
391
|
-
if (
|
|
392
|
-
args.push(__dirname);
|
|
393
|
-
}
|
|
394
|
-
else if (core_1.Client.enabled("node.require.inline")) {
|
|
398
|
+
if (!isFunction(ext, true) && Client.enabled("node.require.inline")) {
|
|
395
399
|
args.push(require);
|
|
396
400
|
}
|
|
397
401
|
await ext.apply(this, args);
|
|
@@ -429,16 +433,16 @@ class Document extends core_1.Client {
|
|
|
429
433
|
sourceMappingURL += '.map';
|
|
430
434
|
}
|
|
431
435
|
if (hash) {
|
|
432
|
-
const [algorithm, length] =
|
|
436
|
+
const [algorithm, length] = getHashData(hash);
|
|
433
437
|
if (algorithm) {
|
|
434
438
|
const value = this.asHash(output, algorithm);
|
|
435
439
|
if (value) {
|
|
436
|
-
sourceMappingURL =
|
|
440
|
+
sourceMappingURL = appendSuffix(sourceMappingURL, length ? value.slice(0, length) : value);
|
|
437
441
|
}
|
|
438
442
|
}
|
|
439
443
|
}
|
|
440
444
|
}
|
|
441
|
-
let code = data.code.replace(
|
|
445
|
+
let code = data.code.replace(SourceMap.SOURCE_MAPPING_URL, (...capture) => {
|
|
442
446
|
flags |= 1;
|
|
443
447
|
if (capture[2] && capture[5]) {
|
|
444
448
|
css = true;
|
|
@@ -469,10 +473,19 @@ class Document extends core_1.Client {
|
|
|
469
473
|
}
|
|
470
474
|
}
|
|
471
475
|
static createSourceMap(code, uri, remove) {
|
|
472
|
-
return new
|
|
476
|
+
return new SourceMap(code, uri, remove);
|
|
473
477
|
}
|
|
474
|
-
static updateGradle(source, namespaces,
|
|
475
|
-
|
|
478
|
+
static updateGradle(source, namespaces, values, options) {
|
|
479
|
+
let value;
|
|
480
|
+
if (Array.isArray(values)) {
|
|
481
|
+
values = values.slice(0);
|
|
482
|
+
value = values.pop().trim();
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
value = values.trim();
|
|
486
|
+
values = [];
|
|
487
|
+
}
|
|
488
|
+
const local = /^([\w.]+)(?:\((.+)\)|\s*(=)?\s*(".+"|'.+'|\(.+\)||\[.+\]|\S+))$/s.exec(value);
|
|
476
489
|
if (!local) {
|
|
477
490
|
return source;
|
|
478
491
|
}
|
|
@@ -485,28 +498,44 @@ class Document extends core_1.Client {
|
|
|
485
498
|
}
|
|
486
499
|
const replacement = addendum ? value + ' ' + addendum : value;
|
|
487
500
|
const length = namespaces.length;
|
|
488
|
-
let ident, lastIndex = 0, i = 0;
|
|
501
|
+
let ident, lastMatch = null, lastIndex = 0, i = 0;
|
|
489
502
|
while (i < length) {
|
|
490
|
-
const
|
|
503
|
+
const item = namespaces[i];
|
|
504
|
+
const pattern = new RegExp(`([\\t ]*)${item instanceof RegExp ? item.source : escapePattern(item)}\\s*\\{[ \\t]*(?:\\r?\\n)*`);
|
|
491
505
|
pattern.lastIndex = lastIndex;
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
506
|
+
if (lastMatch = pattern.exec(source)) {
|
|
507
|
+
if (i > 0 && !ident && lastMatch[1]) {
|
|
508
|
+
ident = lastMatch[1];
|
|
509
|
+
}
|
|
510
|
+
lastIndex = lastMatch.index + lastMatch[0].length;
|
|
495
511
|
}
|
|
496
|
-
|
|
497
|
-
|
|
512
|
+
else {
|
|
513
|
+
break;
|
|
498
514
|
}
|
|
499
|
-
lastIndex = match.index + match[0].length;
|
|
500
515
|
++i;
|
|
501
516
|
}
|
|
502
|
-
const newline =
|
|
503
|
-
ident ||=
|
|
504
|
-
if (
|
|
505
|
-
|
|
517
|
+
const newline = getNewline(source);
|
|
518
|
+
ident ||= getIndent(source);
|
|
519
|
+
if (lastMatch) {
|
|
520
|
+
if (lastMatch[2]) {
|
|
521
|
+
let block = lastMatch[0];
|
|
522
|
+
for (let j = 0; j < values.length; ++j) {
|
|
523
|
+
const group = lastMatch[j + 2];
|
|
524
|
+
if (group) {
|
|
525
|
+
block = block.replace(group, values[j]);
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
return source;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
source = spliceString(source, lastMatch.index, lastMatch.index + lastMatch[0].length, block);
|
|
532
|
+
lastIndex = lastMatch.index + block.length;
|
|
533
|
+
}
|
|
534
|
+
const pattern = new RegExp(`\\b(${escapePattern(local[1])}` + (local[2] ? `\\(${PATTERN_PARENTHESIS}\\)` : '\\b' + (local[3] ? '\\s*=\\s*' : '\\s*') + `("[^"]+"|'[^']+'|\\(${PATTERN_PARENTHESIS}\\)|\\S+)?`) + ')' + (addendum ? '[^\\r\\n]*' : '[^\\w\\r\\n]*'), 'g');
|
|
506
535
|
pattern.lastIndex = lastIndex;
|
|
507
|
-
let match;
|
|
536
|
+
let match, found = false;
|
|
508
537
|
while (match = pattern.exec(source)) {
|
|
509
|
-
const preceding = source.
|
|
538
|
+
const preceding = source.slice(lastIndex, match.index);
|
|
510
539
|
let opening = 0, closing = 0;
|
|
511
540
|
for (let j = 0, q = preceding.length; j < q; ++j) {
|
|
512
541
|
switch (preceding[j]) {
|
|
@@ -519,15 +548,16 @@ class Document extends core_1.Client {
|
|
|
519
548
|
}
|
|
520
549
|
}
|
|
521
550
|
if (opening === closing) {
|
|
551
|
+
found = true;
|
|
522
552
|
if (!multiple || local[2] && local[1].includes('.') || match[2] && local[4] && compareValue(match[2]) === compareValue(local[4])) {
|
|
523
|
-
return upgrade && match[1] !== value ?
|
|
553
|
+
return upgrade && match[1] !== value ? XmlWriter.replaceMatch(match, source, replacement, pattern) : source;
|
|
524
554
|
}
|
|
525
555
|
lastIndex = match.index + match[0].length;
|
|
526
556
|
}
|
|
527
557
|
}
|
|
528
|
-
return
|
|
558
|
+
return found && updateOnly ? source : spliceString(source, lastIndex, lastIndex, ident.repeat(length) + replacement + newline);
|
|
529
559
|
}
|
|
530
|
-
if (updateOnly) {
|
|
560
|
+
if (updateOnly || namespaces.some(item => item instanceof RegExp)) {
|
|
531
561
|
return source;
|
|
532
562
|
}
|
|
533
563
|
const j = i;
|
|
@@ -540,7 +570,7 @@ class Document extends core_1.Client {
|
|
|
540
570
|
trailing += ident.repeat(i) + '}' + newline;
|
|
541
571
|
}
|
|
542
572
|
const content = leading + ident.repeat(length) + replacement + newline + trailing;
|
|
543
|
-
return lastIndex > 0 ?
|
|
573
|
+
return lastIndex > 0 ? spliceString(source, lastIndex, lastIndex, content) : source.trimEnd() + newline + newline + content;
|
|
544
574
|
}
|
|
545
575
|
static generateLintTable(messages, options) {
|
|
546
576
|
const { leadingText, trailingText, pathname, filename, ruleWidth = 30, messageWidth = 60 } = options;
|
|
@@ -615,6 +645,7 @@ class Document extends core_1.Client {
|
|
|
615
645
|
_transformConfig = null;
|
|
616
646
|
_mimeMap = null;
|
|
617
647
|
_imports = null;
|
|
648
|
+
_packageJSON = { exports: false };
|
|
618
649
|
constructor(data) {
|
|
619
650
|
super(data);
|
|
620
651
|
const transform = this.settingsOf('transform', 'cache');
|
|
@@ -624,13 +655,27 @@ class Document extends core_1.Client {
|
|
|
624
655
|
}
|
|
625
656
|
restart() { }
|
|
626
657
|
init(assets, config) {
|
|
627
|
-
let ignoreModules, ignoreExtensions;
|
|
658
|
+
let baseUrl, ignoreModules, ignoreExtensions;
|
|
628
659
|
if (config) {
|
|
629
|
-
let baseUrl;
|
|
630
660
|
({ baseUrl, ignoreModules, ignoreExtensions } = config);
|
|
631
661
|
const users = this.getUserSettings();
|
|
632
|
-
|
|
633
|
-
|
|
662
|
+
let package_json = this.settings.package_json;
|
|
663
|
+
if (users) {
|
|
664
|
+
if (Array.isArray(users.extensions)) {
|
|
665
|
+
this._extensions = users.extensions.slice(0);
|
|
666
|
+
}
|
|
667
|
+
if (users.package_json) {
|
|
668
|
+
package_json = users.package_json;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
let jsonExports = package_json?.exports;
|
|
672
|
+
if (jsonExports) {
|
|
673
|
+
if (typeof jsonExports !== 'string') {
|
|
674
|
+
this._packageJSON.exports = true;
|
|
675
|
+
}
|
|
676
|
+
else if (Client.isDir(jsonExports = path.resolve(jsonExports))) {
|
|
677
|
+
this._packageJSON.exports = jsonExports;
|
|
678
|
+
}
|
|
634
679
|
}
|
|
635
680
|
if (baseUrl) {
|
|
636
681
|
let pages = this.settings.pages;
|
|
@@ -646,11 +691,11 @@ class Document extends core_1.Client {
|
|
|
646
691
|
const items = [];
|
|
647
692
|
for (const pattern in pages) {
|
|
648
693
|
const item = pages[pattern];
|
|
649
|
-
if (
|
|
694
|
+
if (isObject(item)) {
|
|
650
695
|
if (pattern === baseUrl) {
|
|
651
696
|
items.push(item);
|
|
652
697
|
}
|
|
653
|
-
else if (
|
|
698
|
+
else if (hasGlob(pattern)) {
|
|
654
699
|
const isMatch = CACHE_PICOMATCH[pattern] ||= pm(pattern, { matchBase: true });
|
|
655
700
|
if (isMatch(baseUrl)) {
|
|
656
701
|
items.push(item);
|
|
@@ -669,7 +714,7 @@ class Document extends core_1.Client {
|
|
|
669
714
|
if (mimeMap) {
|
|
670
715
|
for (const item of assets) {
|
|
671
716
|
const merge = item.mimeType && mimeMap[item.mimeType];
|
|
672
|
-
if (
|
|
717
|
+
if (isObject(merge)) {
|
|
673
718
|
Object.assign(item, merge);
|
|
674
719
|
}
|
|
675
720
|
}
|
|
@@ -685,12 +730,12 @@ class Document extends core_1.Client {
|
|
|
685
730
|
let instance = null;
|
|
686
731
|
if (handler && handler !== "@e-mc/db") {
|
|
687
732
|
try {
|
|
688
|
-
const Module =
|
|
689
|
-
if (
|
|
733
|
+
const Module = requireESM(handler);
|
|
734
|
+
if (Client.constructorOf(Module, 'clientdb')) {
|
|
690
735
|
instance = new Module(db, database);
|
|
691
736
|
}
|
|
692
737
|
else {
|
|
693
|
-
throw
|
|
738
|
+
throw errorMessage(this.moduleName, "Not a Db constructor", handler);
|
|
694
739
|
}
|
|
695
740
|
}
|
|
696
741
|
catch (err) {
|
|
@@ -698,7 +743,7 @@ class Document extends core_1.Client {
|
|
|
698
743
|
}
|
|
699
744
|
}
|
|
700
745
|
else {
|
|
701
|
-
instance = new
|
|
746
|
+
instance = new Db(db, database);
|
|
702
747
|
}
|
|
703
748
|
if (instance) {
|
|
704
749
|
const host = this.host;
|
|
@@ -721,11 +766,11 @@ class Document extends core_1.Client {
|
|
|
721
766
|
}
|
|
722
767
|
else {
|
|
723
768
|
const extensions = this._extensions;
|
|
724
|
-
if (
|
|
769
|
+
if (isArray(extensions)) {
|
|
725
770
|
if (typeof ignoreExtensions === 'string') {
|
|
726
771
|
this._extensions = extensions.filter(value => value !== ignoreExtensions);
|
|
727
772
|
}
|
|
728
|
-
else if (
|
|
773
|
+
else if (isArray(ignoreExtensions)) {
|
|
729
774
|
this._extensions = extensions.filter(value => !ignoreExtensions.includes(value));
|
|
730
775
|
}
|
|
731
776
|
}
|
|
@@ -734,10 +779,10 @@ class Document extends core_1.Client {
|
|
|
734
779
|
return this;
|
|
735
780
|
}
|
|
736
781
|
abort(name, reason) {
|
|
737
|
-
if (this.aborted ||
|
|
782
|
+
if (this.aborted || isString(name) && this.settingsOf(name, 'abort') !== true) {
|
|
738
783
|
return;
|
|
739
784
|
}
|
|
740
|
-
if (name
|
|
785
|
+
if (isError(name)) {
|
|
741
786
|
reason ||= name;
|
|
742
787
|
}
|
|
743
788
|
super.abort(reason);
|
|
@@ -807,7 +852,7 @@ class Document extends core_1.Client {
|
|
|
807
852
|
}
|
|
808
853
|
this.#addConfigError("\"output\" can only be a plain object");
|
|
809
854
|
}
|
|
810
|
-
else if (
|
|
855
|
+
else if (isPlainObject(result)) {
|
|
811
856
|
return this.#getConfigObject(data, name, result, false);
|
|
812
857
|
}
|
|
813
858
|
else if (path.isAbsolute(value)) {
|
|
@@ -854,28 +899,28 @@ class Document extends core_1.Client {
|
|
|
854
899
|
let result, pkgName;
|
|
855
900
|
try {
|
|
856
901
|
if (value.startsWith('npm:')) {
|
|
857
|
-
if (!
|
|
902
|
+
if (!Client.enabled("node.require.npm")) {
|
|
858
903
|
return null;
|
|
859
904
|
}
|
|
860
|
-
pkgName = value.
|
|
861
|
-
result = options?.default ?
|
|
905
|
+
pkgName = value.slice(4);
|
|
906
|
+
result = options?.default ? requireESM(pkgName, options.url) : require(pkgName);
|
|
862
907
|
if (typeof result === 'function') {
|
|
863
|
-
return Object.defineProperty(result, "__cjs__", { value: true });
|
|
908
|
+
return Object.defineProperty(result, "__cjs__", { value: true, writable: false, enumerable: false });
|
|
864
909
|
}
|
|
865
910
|
return result;
|
|
866
911
|
}
|
|
867
|
-
const source = this.readFile(value, { ownPermissionOnly: true, absolutePath: this.hasEval('absolute'), requireExt: true, encoding:
|
|
912
|
+
const source = this.readFile(value, { ownPermissionOnly: true, absolutePath: this.hasEval('absolute'), requireExt: true, encoding: getEncoding(encoding), cache }) || value;
|
|
868
913
|
if (typeof source !== 'string') {
|
|
869
914
|
result = source;
|
|
870
915
|
}
|
|
871
|
-
else if (!(result =
|
|
916
|
+
else if (!(result = asFunction(source))) {
|
|
872
917
|
try {
|
|
873
|
-
result = this.tryParse(source,
|
|
918
|
+
result = this.tryParse(source, asExt(value));
|
|
874
919
|
}
|
|
875
920
|
catch {
|
|
876
921
|
}
|
|
877
922
|
}
|
|
878
|
-
if (
|
|
923
|
+
if (isObject(result) || isFunction(result, true) || typeof result === 'function' && this.hasEval('function')) {
|
|
879
924
|
return result;
|
|
880
925
|
}
|
|
881
926
|
}
|
|
@@ -905,11 +950,11 @@ class Document extends core_1.Client {
|
|
|
905
950
|
}
|
|
906
951
|
findSourceScope(uri, imports) {
|
|
907
952
|
const scopes = imports.scopes;
|
|
908
|
-
if (
|
|
953
|
+
if (isPlainObject(scopes)) {
|
|
909
954
|
const qualified = [];
|
|
910
955
|
for (const qualifier in scopes) {
|
|
911
956
|
const item = scopes[qualifier];
|
|
912
|
-
if (uri.includes(qualifier) &&
|
|
957
|
+
if (uri.includes(qualifier) && isPlainObject(item)) {
|
|
913
958
|
qualified.push([qualifier, item]);
|
|
914
959
|
}
|
|
915
960
|
}
|
|
@@ -918,23 +963,23 @@ class Document extends core_1.Client {
|
|
|
918
963
|
return [];
|
|
919
964
|
}
|
|
920
965
|
findSourceRoot(uri, imports = this.imports) {
|
|
921
|
-
if (!
|
|
966
|
+
if (!isPlainObject(imports)) {
|
|
922
967
|
return;
|
|
923
968
|
}
|
|
924
|
-
const importsStrict = this.
|
|
925
|
-
const scopes = (importsStrict ? this.findSourceScope(uri, imports) : []).concat([imports]);
|
|
926
|
-
const
|
|
927
|
-
|
|
969
|
+
const importsStrict = this.isImportsStrict();
|
|
970
|
+
const scopes = (importsStrict ? this.findSourceScope(uri, imports) : []).concat([isPlainObject(imports.imports) ? imports.imports : imports]);
|
|
971
|
+
const integrity = isPlainObject(imports.integrity) ? imports.integrity : undefined;
|
|
972
|
+
const protocol = Client.isURL(uri);
|
|
973
|
+
let result = '', target;
|
|
928
974
|
for (const scope of scopes) {
|
|
929
975
|
for (const url in scope) {
|
|
930
|
-
if (uri === url &&
|
|
931
|
-
if (importsStrict) {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
976
|
+
if (uri === url && isString(target = scope[url])) {
|
|
977
|
+
if (!importsStrict) {
|
|
978
|
+
return target;
|
|
979
|
+
}
|
|
980
|
+
if (Client.isPath(target) && !(protocol ? url : toPosix(url)).endsWith('/') && this.#checkIntegrity(integrity, url, target)) {
|
|
981
|
+
return toPosix(target);
|
|
936
982
|
}
|
|
937
|
-
return result;
|
|
938
983
|
}
|
|
939
984
|
}
|
|
940
985
|
}
|
|
@@ -944,11 +989,11 @@ class Document extends core_1.Client {
|
|
|
944
989
|
for (const scope of scopes) {
|
|
945
990
|
for (const url in scope) {
|
|
946
991
|
const local = protocol ? url : toPosix(url);
|
|
947
|
-
if (local.endsWith('/') && remote.startsWith(local) && (
|
|
992
|
+
if (local.endsWith('/') && remote.startsWith(local) && isString(target = scope[url]) && target.endsWith('/')) {
|
|
948
993
|
if (protocol) {
|
|
949
|
-
found.push([url,
|
|
994
|
+
found.push([url, target]);
|
|
950
995
|
}
|
|
951
|
-
else if (
|
|
996
|
+
else if (Client.isPath(result = path.join(target, remote.slice(local.length))) && this.#checkIntegrity(integrity, url, target)) {
|
|
952
997
|
return toPosix(result);
|
|
953
998
|
}
|
|
954
999
|
}
|
|
@@ -959,13 +1004,13 @@ class Document extends core_1.Client {
|
|
|
959
1004
|
for (const scope of scopes) {
|
|
960
1005
|
for (const url in scope) {
|
|
961
1006
|
const local = normalizeDir(url);
|
|
962
|
-
if ((normalizeDir(uri) === local ||
|
|
963
|
-
return
|
|
1007
|
+
if ((normalizeDir(uri) === local || Client.PLATFORM_WIN32 && normalizeDir(uri, true) === local.toLowerCase()) && isString(target = scope[url])) {
|
|
1008
|
+
return target;
|
|
964
1009
|
}
|
|
965
1010
|
}
|
|
966
1011
|
for (const url in scope) {
|
|
967
|
-
if (uri.startsWith(normalizeDir(url)) &&
|
|
968
|
-
found.push([url,
|
|
1012
|
+
if (uri.startsWith(normalizeDir(url)) && isString(target = scope[url])) {
|
|
1013
|
+
found.push([url, target]);
|
|
969
1014
|
}
|
|
970
1015
|
}
|
|
971
1016
|
}
|
|
@@ -974,7 +1019,7 @@ class Document extends core_1.Client {
|
|
|
974
1019
|
found.sort((a, b) => b[0].length - a[0].length);
|
|
975
1020
|
if (importsStrict) {
|
|
976
1021
|
for (const url of found) {
|
|
977
|
-
if (
|
|
1022
|
+
if (Client.isPath(result = toPath(uri, url)) && this.#checkIntegrity(integrity, url[1], result)) {
|
|
978
1023
|
break;
|
|
979
1024
|
}
|
|
980
1025
|
result = '';
|
|
@@ -987,6 +1032,9 @@ class Document extends core_1.Client {
|
|
|
987
1032
|
return toPosix(result);
|
|
988
1033
|
}
|
|
989
1034
|
}
|
|
1035
|
+
if (!protocol && this._packageJSON.exports) {
|
|
1036
|
+
return this.resolvePackageJSONExports(uri);
|
|
1037
|
+
}
|
|
990
1038
|
}
|
|
991
1039
|
locateSourceFiles(file, code, bundleContent) {
|
|
992
1040
|
return (imports = this.imports) => {
|
|
@@ -998,31 +1046,31 @@ class Document extends core_1.Client {
|
|
|
998
1046
|
}
|
|
999
1047
|
else if (Object.keys(imports).length > 0) {
|
|
1000
1048
|
const bundleId = file.bundleId;
|
|
1001
|
-
const assets = !
|
|
1049
|
+
const assets = !isEmpty(bundleId) ? this.assets.filter(item => item.bundleId === bundleId).sort((a, b) => a.bundleIndex - b.bundleIndex) : [file];
|
|
1002
1050
|
if (!Array.isArray(bundleContent) || bundleContent.length !== assets.length - 1) {
|
|
1003
1051
|
bundleContent = undefined;
|
|
1004
1052
|
}
|
|
1005
1053
|
for (const item of assets) {
|
|
1006
1054
|
const localFile = !item.exported && item.uri ? this.findSourceRoot(item.uri, imports) : undefined;
|
|
1007
|
-
if (localFile &&
|
|
1055
|
+
if (localFile && Client.isPath(localFile) && !item.trailingContent) {
|
|
1008
1056
|
sourceFile.push([localFile]);
|
|
1009
1057
|
}
|
|
1010
1058
|
else {
|
|
1059
|
+
const localUri = item.localUri;
|
|
1011
1060
|
let source;
|
|
1012
|
-
if (item.bundleIndex === 0) {
|
|
1013
|
-
const localUri = item.localUri;
|
|
1061
|
+
if (item.bundleIndex === 0 && localUri) {
|
|
1014
1062
|
try {
|
|
1015
1063
|
source = fs.readFileSync(localUri, file.encoding ||= 'utf8');
|
|
1016
|
-
if (this.resolveUri &&
|
|
1064
|
+
if (this.resolveUri && isArray(file.trailingContent)) {
|
|
1017
1065
|
let trailing;
|
|
1018
|
-
[source, trailing] = this.resolveUri(file, source,
|
|
1066
|
+
[source, trailing] = this.resolveUri(file, source, concatString(file.trailingContent));
|
|
1019
1067
|
if (trailing) {
|
|
1020
1068
|
source += trailing;
|
|
1021
1069
|
}
|
|
1022
1070
|
}
|
|
1023
1071
|
}
|
|
1024
1072
|
catch (err) {
|
|
1025
|
-
this.writeFail(["Unable to read file",
|
|
1073
|
+
this.writeFail(["Unable to read file", path.basename(localUri)], err, 32);
|
|
1026
1074
|
}
|
|
1027
1075
|
}
|
|
1028
1076
|
else if (bundleContent) {
|
|
@@ -1059,31 +1107,136 @@ class Document extends core_1.Client {
|
|
|
1059
1107
|
}
|
|
1060
1108
|
};
|
|
1061
1109
|
}
|
|
1110
|
+
resolvePackageJSONExports(uri, base) {
|
|
1111
|
+
if (uri.startsWith('./')) {
|
|
1112
|
+
const cwd = [base && (base = Client.resolveFile(base)) && path.resolve(base) || this.host?.baseDirectory];
|
|
1113
|
+
if (SUPPORTED_PACKAGEJSON && cwd[0]) {
|
|
1114
|
+
try {
|
|
1115
|
+
const pathname = mod.findPackageJSON(pathToFileURL(cwd[0]));
|
|
1116
|
+
if (pathname) {
|
|
1117
|
+
cwd[0] = pathname;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
catch {
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
if (!base) {
|
|
1124
|
+
cwd.push(process.cwd());
|
|
1125
|
+
}
|
|
1126
|
+
for (let i = 0; i < cwd.length; ++i) {
|
|
1127
|
+
const baseDir = cwd[i];
|
|
1128
|
+
if (baseDir) {
|
|
1129
|
+
try {
|
|
1130
|
+
const pathname = path.join(baseDir, 'package.json');
|
|
1131
|
+
if (fs.existsSync(pathname)) {
|
|
1132
|
+
const packageJSON = (i === 0 ? JSON.parse(fs.readFileSync(pathname, 'utf8')) : require(pathname));
|
|
1133
|
+
if (isPlainObject(packageJSON?.exports)) {
|
|
1134
|
+
const packageExports = packageJSON.exports;
|
|
1135
|
+
let value = packageExports[uri];
|
|
1136
|
+
if (value === null) {
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
if (validateExports(value) && Client.isFile(value = path.join(baseDir, value))) {
|
|
1140
|
+
return value;
|
|
1141
|
+
}
|
|
1142
|
+
const subDir = [];
|
|
1143
|
+
const globDir = [];
|
|
1144
|
+
for (const specifier in packageExports) {
|
|
1145
|
+
const target = packageExports[specifier];
|
|
1146
|
+
let items;
|
|
1147
|
+
if (validateExports(target)) {
|
|
1148
|
+
items = [target];
|
|
1149
|
+
}
|
|
1150
|
+
else if (isArray(items)) {
|
|
1151
|
+
items = items.filter(item => validateExports(item));
|
|
1152
|
+
}
|
|
1153
|
+
if (isArray(items) && validateExports(specifier)) {
|
|
1154
|
+
if (specifier.at(-1) === '/') {
|
|
1155
|
+
subDir.push([specifier, items]);
|
|
1156
|
+
}
|
|
1157
|
+
else if (SUPPORTED_GLOB && specifier.endsWith('/*')) {
|
|
1158
|
+
globDir.push([specifier.slice(0, -1), items.map(item => item.replaceAll('/*/', '/**/'))]);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
uri = joinSpecifier(baseDir, uri);
|
|
1163
|
+
for (let [specifier, items] of subDir.sort((a, b) => b.length - a.length)) {
|
|
1164
|
+
if (uri.startsWith(specifier = joinSpecifier(baseDir, specifier))) {
|
|
1165
|
+
for (const target of items) {
|
|
1166
|
+
const result = path.join(baseDir, target, uri.slice(specifier.length));
|
|
1167
|
+
if (Client.isFile(result)) {
|
|
1168
|
+
return result;
|
|
1169
|
+
}
|
|
1170
|
+
if (this.isImportsStrict()) {
|
|
1171
|
+
break;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
for (let [specifier, items] of globDir.sort((a, b) => b.length - a.length)) {
|
|
1177
|
+
if (uri.startsWith(specifier = joinSpecifier(baseDir, specifier))) {
|
|
1178
|
+
for (const target of items) {
|
|
1179
|
+
try {
|
|
1180
|
+
const files = fs.globSync(target);
|
|
1181
|
+
if (files.length > 0) {
|
|
1182
|
+
const filename = uri.slice(specifier.length - 1);
|
|
1183
|
+
const result = files.filter(entry => entry.endsWith(filename) && Client.isFile(entry)).sort((a, b) => a.length - b.length).at(0);
|
|
1184
|
+
if (result) {
|
|
1185
|
+
return result;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
else if (this.isImportsStrict()) {
|
|
1189
|
+
break;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
catch {
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
catch {
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
else if (!uri.startsWith('..') && !path.isAbsolute(uri)) {
|
|
1206
|
+
let baseUrl = this._packageJSON.exports;
|
|
1207
|
+
if (typeof baseUrl === 'string' && Client.isFile(baseUrl = path.join(baseUrl, uri))) {
|
|
1208
|
+
return baseUrl;
|
|
1209
|
+
}
|
|
1210
|
+
const match = REGEXP_PACKAGEURI.exec(uri);
|
|
1211
|
+
if (match) {
|
|
1212
|
+
try {
|
|
1213
|
+
return require.resolve(match[1]);
|
|
1214
|
+
}
|
|
1215
|
+
catch {
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1062
1220
|
tryParse(source, format, options) {
|
|
1063
1221
|
try {
|
|
1064
1222
|
switch (format.toLowerCase()) {
|
|
1065
1223
|
case 'yml':
|
|
1066
1224
|
case 'yaml':
|
|
1067
|
-
return
|
|
1225
|
+
return load(source, options);
|
|
1068
1226
|
case 'json5':
|
|
1069
1227
|
return require('json5').parse(source);
|
|
1070
1228
|
case 'xml':
|
|
1071
1229
|
return new (require('fast-xml-parser').XMLParser)(options).parse(source);
|
|
1072
1230
|
case 'toml':
|
|
1073
|
-
|
|
1074
|
-
return require('smol-toml').parse(source, options);
|
|
1075
|
-
}
|
|
1076
|
-
catch {
|
|
1077
|
-
return require('toml').parse(source);
|
|
1078
|
-
}
|
|
1231
|
+
return require('toml').parse(source);
|
|
1079
1232
|
default:
|
|
1080
1233
|
return JSON.parse(source);
|
|
1081
1234
|
}
|
|
1082
1235
|
}
|
|
1083
1236
|
catch (err) {
|
|
1084
|
-
const name =
|
|
1237
|
+
const name = getModuleName(err);
|
|
1085
1238
|
if (name) {
|
|
1086
|
-
this.checkPackage(err,
|
|
1239
|
+
this.checkPackage(err, getModuleName(err), "Unknown");
|
|
1087
1240
|
}
|
|
1088
1241
|
throw err;
|
|
1089
1242
|
}
|
|
@@ -1096,7 +1249,7 @@ class Document extends core_1.Client {
|
|
|
1096
1249
|
}
|
|
1097
1250
|
settingsOf(name, option) {
|
|
1098
1251
|
const options = this.settings.options?.[name];
|
|
1099
|
-
if (
|
|
1252
|
+
if (isObject(options)) {
|
|
1100
1253
|
return options[option];
|
|
1101
1254
|
}
|
|
1102
1255
|
}
|
|
@@ -1105,12 +1258,12 @@ class Document extends core_1.Client {
|
|
|
1105
1258
|
if (typeof viewEngine === 'string') {
|
|
1106
1259
|
target = this.settings.view_engine?.[viewEngine];
|
|
1107
1260
|
const userConfig = this.getUserSettings()?.view_engine?.[viewEngine];
|
|
1108
|
-
if ((
|
|
1261
|
+
if (isObject(userConfig)) {
|
|
1109
1262
|
if (CACHE_VIEWENGINE.has(userConfig)) {
|
|
1110
1263
|
target = CACHE_VIEWENGINE.get(userConfig);
|
|
1111
1264
|
}
|
|
1112
|
-
else if ((
|
|
1113
|
-
target =
|
|
1265
|
+
else if (isObject(target)) {
|
|
1266
|
+
target = cloneObject(userConfig, { target: { ...target }, deep: true, preserve: true, structured: true });
|
|
1114
1267
|
CACHE_VIEWENGINE.set(userConfig, target);
|
|
1115
1268
|
}
|
|
1116
1269
|
else {
|
|
@@ -1122,13 +1275,13 @@ class Document extends core_1.Client {
|
|
|
1122
1275
|
else {
|
|
1123
1276
|
target = viewEngine;
|
|
1124
1277
|
}
|
|
1125
|
-
if (!((
|
|
1278
|
+
if (!(isObject(target) && isString(target.name))) {
|
|
1126
1279
|
this.abort('view_engine');
|
|
1127
1280
|
const from = typeof viewEngine === 'string' ? viewEngine : this.moduleName;
|
|
1128
|
-
this.writeFail(["Unable to load configuration", from],
|
|
1281
|
+
this.writeFail(["Unable to load configuration", from], errorMessage('view-engine', from, "Unknown"));
|
|
1129
1282
|
return null;
|
|
1130
1283
|
}
|
|
1131
|
-
if (!target.outputEmpty && !
|
|
1284
|
+
if (!target.outputEmpty && !isArray(data)) {
|
|
1132
1285
|
return '';
|
|
1133
1286
|
}
|
|
1134
1287
|
try {
|
|
@@ -1137,15 +1290,15 @@ class Document extends core_1.Client {
|
|
|
1137
1290
|
context = require(target.name);
|
|
1138
1291
|
}
|
|
1139
1292
|
catch {
|
|
1140
|
-
context = await
|
|
1293
|
+
context = await importESM(target.name);
|
|
1141
1294
|
}
|
|
1142
1295
|
const { compile, output } = target.options || {};
|
|
1143
1296
|
if (this.settingsOf('view_engine', 'coerce') === true) {
|
|
1144
1297
|
if (compile) {
|
|
1145
|
-
|
|
1298
|
+
coerceObject(compile, stored);
|
|
1146
1299
|
}
|
|
1147
1300
|
if (output) {
|
|
1148
|
-
|
|
1301
|
+
coerceObject(output, stored);
|
|
1149
1302
|
}
|
|
1150
1303
|
}
|
|
1151
1304
|
let cache = CACHE_TEMPLATE.get(target.name);
|
|
@@ -1154,8 +1307,8 @@ class Document extends core_1.Client {
|
|
|
1154
1307
|
CACHE_TEMPLATE.set(target.name, cache);
|
|
1155
1308
|
}
|
|
1156
1309
|
const username = this.host?.username || '';
|
|
1157
|
-
const cacheKey = (username ? username + ':' : '') +
|
|
1158
|
-
let result = '', valid = false, expires = typeof target.expires === 'string' ?
|
|
1310
|
+
const cacheKey = (username ? username + ':' : '') + hashKey(template + (compile ? Client.asString(compile) : ''));
|
|
1311
|
+
let result = '', valid = false, expires = typeof target.expires === 'string' ? parseExpires(target.expires) : target.expires, render;
|
|
1159
1312
|
if (expires !== 0) {
|
|
1160
1313
|
render = cache.get(cacheKey);
|
|
1161
1314
|
}
|
|
@@ -1163,7 +1316,7 @@ class Document extends core_1.Client {
|
|
|
1163
1316
|
cache.delete(cacheKey);
|
|
1164
1317
|
}
|
|
1165
1318
|
if (!render) {
|
|
1166
|
-
if (
|
|
1319
|
+
if (isArray(compile)) {
|
|
1167
1320
|
render = typeof context.compileSync === 'function' ? context.compileSync(template, ...compile) : await context.compile(template, ...compile);
|
|
1168
1321
|
}
|
|
1169
1322
|
else {
|
|
@@ -1172,7 +1325,7 @@ class Document extends core_1.Client {
|
|
|
1172
1325
|
if (expires !== 0) {
|
|
1173
1326
|
cache.set(cacheKey, render);
|
|
1174
1327
|
if (this.hasPermission('memory')) {
|
|
1175
|
-
expires = typeof expires === 'number' && expires !== Infinity ? Math.min(expires,
|
|
1328
|
+
expires = typeof expires === 'number' && expires !== Infinity ? Math.min(expires, Client.MAX_TIMEOUT) : 0;
|
|
1176
1329
|
}
|
|
1177
1330
|
else {
|
|
1178
1331
|
expires = 60000;
|
|
@@ -1192,14 +1345,14 @@ class Document extends core_1.Client {
|
|
|
1192
1345
|
const singleRow = !!target.singleRow;
|
|
1193
1346
|
for (let i = 0, j = 0; i < data.length; ++i) {
|
|
1194
1347
|
let row = data[i];
|
|
1195
|
-
if (
|
|
1348
|
+
if (isPlainObject(row)) {
|
|
1196
1349
|
row.__index__ ??= ++j;
|
|
1197
1350
|
if (output) {
|
|
1198
1351
|
row = { ...output, ...row };
|
|
1199
1352
|
}
|
|
1200
1353
|
}
|
|
1201
|
-
else if (!
|
|
1202
|
-
this.addLog(3, joinString('view engine', target.name,
|
|
1354
|
+
else if (!isObject(row)) {
|
|
1355
|
+
this.addLog(3, joinString('view engine', target.name, Client.asString(row) || "Unknown"), { source: `row #${i + 1}` });
|
|
1203
1356
|
continue;
|
|
1204
1357
|
}
|
|
1205
1358
|
if (!singleRow) {
|
|
@@ -1220,7 +1373,7 @@ class Document extends core_1.Client {
|
|
|
1220
1373
|
async transform(type, code, format, options = {}) {
|
|
1221
1374
|
let transform = this.settings.transform;
|
|
1222
1375
|
const data = transform?.[type];
|
|
1223
|
-
if (!
|
|
1376
|
+
if (!isObject(data)) {
|
|
1224
1377
|
return;
|
|
1225
1378
|
}
|
|
1226
1379
|
if (typeof format === 'string') {
|
|
@@ -1234,9 +1387,9 @@ class Document extends core_1.Client {
|
|
|
1234
1387
|
const cacheDir = this.hasPermission('memory.user') || this.cacheDir || this.hasPermission('memory');
|
|
1235
1388
|
if (cacheDir && !CACHE_EXTERNAL[excludeKey = this.moduleName + '_' + type + '_' + format] && config.valid(type, format)) {
|
|
1236
1389
|
const uri = cacheData.uri;
|
|
1237
|
-
const encoding =
|
|
1238
|
-
const hashOpts =
|
|
1239
|
-
cache = new TransformCache(config, cacheData, cacheDir, encoding, (username ? username + ':' : '') + type + '_' + format + '_' + encoding + (hashOpts ? '_' +
|
|
1390
|
+
const encoding = getEncoding(cacheData.encoding);
|
|
1391
|
+
const hashOpts = Client.asString(options.external) + Client.asString(options.metadata);
|
|
1392
|
+
cache = new TransformCache(config, cacheData, cacheDir, encoding, (username ? username + ':' : '') + type + '_' + format + '_' + encoding + (hashOpts ? '_' + hashKey(hashOpts) : ''));
|
|
1240
1393
|
let result, cacheName;
|
|
1241
1394
|
if (config.etag && cacheData.etag && uri) {
|
|
1242
1395
|
[result, cacheName] = config.useETag(cache, cacheData.etag, uri);
|
|
@@ -1251,18 +1404,18 @@ class Document extends core_1.Client {
|
|
|
1251
1404
|
}
|
|
1252
1405
|
if (result) {
|
|
1253
1406
|
result.log?.forEach(log => this.addLog(log));
|
|
1254
|
-
this.formatMessage(4, type, [joinString(cacheName, format.filter(value => value).join(' | '), options.filename), 'cache'], uri, { ...
|
|
1407
|
+
this.formatMessage(4, type, [joinString(cacheName, format.filter(value => value).join(' | '), options.filename), 'cache'], uri, { ...Client.LOG_STYLE_NOTICE, hintBold: true });
|
|
1255
1408
|
return result;
|
|
1256
1409
|
}
|
|
1257
1410
|
}
|
|
1258
1411
|
options.cacheData = undefined;
|
|
1259
1412
|
}
|
|
1260
1413
|
const imports = transform.imports ||= {};
|
|
1261
|
-
const series = new
|
|
1414
|
+
const series = new TransformSeries(type, code, options);
|
|
1262
1415
|
series.init(this, __dirname);
|
|
1263
1416
|
let valid = false, excluded = false, userData, userImports, ignoreCache = false, storedLog, sourceFiles;
|
|
1264
|
-
if (username &&
|
|
1265
|
-
if (
|
|
1417
|
+
if (username && isObject(transform = this.getUserSettings()?.transform)) {
|
|
1418
|
+
if (isObject(transform[type])) {
|
|
1266
1419
|
userData = transform[type];
|
|
1267
1420
|
}
|
|
1268
1421
|
userImports = transform.imports;
|
|
@@ -1282,7 +1435,7 @@ class Document extends core_1.Client {
|
|
|
1282
1435
|
if (!plugin || a === plugin) {
|
|
1283
1436
|
if (b) {
|
|
1284
1437
|
if (baseConfig) {
|
|
1285
|
-
|
|
1438
|
+
cloneObject(b, { target: baseConfig, deep: true, preserve: true });
|
|
1286
1439
|
}
|
|
1287
1440
|
else {
|
|
1288
1441
|
baseConfig = b;
|
|
@@ -1290,7 +1443,7 @@ class Document extends core_1.Client {
|
|
|
1290
1443
|
}
|
|
1291
1444
|
if (c) {
|
|
1292
1445
|
if (outputConfig) {
|
|
1293
|
-
|
|
1446
|
+
cloneObject(c, { target: outputConfig, deep: true, preserve: true });
|
|
1294
1447
|
}
|
|
1295
1448
|
else {
|
|
1296
1449
|
outputConfig = c;
|
|
@@ -1317,10 +1470,10 @@ class Document extends core_1.Client {
|
|
|
1317
1470
|
}
|
|
1318
1471
|
const out = series.out;
|
|
1319
1472
|
let bypassLog = false, failed = false;
|
|
1320
|
-
if (typeof value !== 'string' ||
|
|
1473
|
+
if (typeof value !== 'string' || isArray(out.sourceFiles) && (this.hasPermission('fs') || process.permission) && out.sourceFiles.some(item => !this.canRead(item, { ownPermissionOnly: true }))) {
|
|
1321
1474
|
failed = true;
|
|
1322
1475
|
ignoreCache = true;
|
|
1323
|
-
this.writeFail(["Unable to transform document", plugin],
|
|
1476
|
+
this.writeFail(["Unable to transform document", plugin], errorMessage(plugin, name, typeof value === 'string' ? "Unsupported access" : "Empty"), { type: 4, startTime });
|
|
1324
1477
|
}
|
|
1325
1478
|
else if (source !== value) {
|
|
1326
1479
|
series.code = value;
|
|
@@ -1328,16 +1481,16 @@ class Document extends core_1.Client {
|
|
|
1328
1481
|
if (out.ignoreCache && isExcluded(type, name, config, cacheData)) {
|
|
1329
1482
|
ignoreCache = true;
|
|
1330
1483
|
}
|
|
1331
|
-
if (
|
|
1484
|
+
if (isArray(out.sourceFiles)) {
|
|
1332
1485
|
sourceFiles = sourceFiles ? sourceFiles.concat(out.sourceFiles.filter(item => !sourceFiles.includes(item))) : out.sourceFiles.slice(0);
|
|
1333
1486
|
}
|
|
1334
1487
|
}
|
|
1335
|
-
if (
|
|
1488
|
+
if (isArray(out.logAppend)) {
|
|
1336
1489
|
out.logAppend.forEach(log => this.addLog(log));
|
|
1337
1490
|
storedLog = (storedLog || []).concat(out.logAppend);
|
|
1338
1491
|
bypassLog = true;
|
|
1339
1492
|
}
|
|
1340
|
-
if (
|
|
1493
|
+
if (isArray(out.logQueued)) {
|
|
1341
1494
|
out.logQueued.forEach(log => this.writeLog(log, true));
|
|
1342
1495
|
storedLog = (storedLog || []).concat(out.logQueued);
|
|
1343
1496
|
bypassLog = true;
|
|
@@ -1354,17 +1507,17 @@ class Document extends core_1.Client {
|
|
|
1354
1507
|
context = require(plugin);
|
|
1355
1508
|
}
|
|
1356
1509
|
catch {
|
|
1357
|
-
context = await
|
|
1510
|
+
context = await importESM(plugin);
|
|
1358
1511
|
}
|
|
1359
1512
|
series.packageName = plugin;
|
|
1360
1513
|
if (typeof baseConfig === 'function') {
|
|
1361
1514
|
series.baseConfig = outputConfig;
|
|
1362
|
-
if (
|
|
1515
|
+
if (isFunction(baseConfig, true)) {
|
|
1363
1516
|
next(await baseConfig(context, source, series));
|
|
1364
1517
|
}
|
|
1365
1518
|
else {
|
|
1366
|
-
const thisArg =
|
|
1367
|
-
const inlineArg =
|
|
1519
|
+
const thisArg = Client.enabled("node.process.inline") ? process : null;
|
|
1520
|
+
const inlineArg = Client.enabled("node.require.inline");
|
|
1368
1521
|
const args = [context, source, series];
|
|
1369
1522
|
if (baseConfig.toString().startsWith('async')) {
|
|
1370
1523
|
if (inlineArg) {
|
|
@@ -1387,7 +1540,7 @@ class Document extends core_1.Client {
|
|
|
1387
1540
|
let transformer = CACHE_PACKAGE.get(target + username);
|
|
1388
1541
|
if (!transformer) {
|
|
1389
1542
|
try {
|
|
1390
|
-
let pkg = this.resolveDir('package', plugin + '.js') || this.resolveDir('package', plugin + '.cjs') || this.resolveDir('package', plugin + '.mjs') || userImports?.[plugin] || imports[plugin] ||
|
|
1543
|
+
let pkg = this.resolveDir('package', plugin + '.js') || this.resolveDir('package', plugin + '.cjs') || this.resolveDir('package', plugin + '.mjs') || userImports?.[plugin] || imports[plugin] || IMPORT_MAP[plugin];
|
|
1391
1544
|
if (pkg) {
|
|
1392
1545
|
const match = /^(@?\S+)[@:](\d+(?:\.\d+(?:[.-]\S+)?)?|[a-z]+)$/.exec(pkg);
|
|
1393
1546
|
if (match) {
|
|
@@ -1396,7 +1549,7 @@ class Document extends core_1.Client {
|
|
|
1396
1549
|
}
|
|
1397
1550
|
const ext = path.extname(pkg);
|
|
1398
1551
|
if (ext === '.mjs') {
|
|
1399
|
-
transformer = await
|
|
1552
|
+
transformer = await importESM(pkg, false, true);
|
|
1400
1553
|
}
|
|
1401
1554
|
else if (ext === '.cjs') {
|
|
1402
1555
|
transformer = require(pkg);
|
|
@@ -1406,7 +1559,7 @@ class Document extends core_1.Client {
|
|
|
1406
1559
|
transformer = require(pkg);
|
|
1407
1560
|
}
|
|
1408
1561
|
catch {
|
|
1409
|
-
transformer = await
|
|
1562
|
+
transformer = await importESM(pkg, false, true);
|
|
1410
1563
|
}
|
|
1411
1564
|
}
|
|
1412
1565
|
}
|
|
@@ -1414,11 +1567,11 @@ class Document extends core_1.Client {
|
|
|
1414
1567
|
transformer = context;
|
|
1415
1568
|
context = null;
|
|
1416
1569
|
}
|
|
1417
|
-
if (
|
|
1418
|
-
transformer = typeof transformer[name] === 'function' ? transformer[name] : typeof transformer[name.
|
|
1570
|
+
if (isObject(transformer)) {
|
|
1571
|
+
transformer = typeof transformer[name] === 'function' ? transformer[name] : typeof transformer[name.replace(/-/g, '_')] === 'function' ? transformer[name.replace(/-/g, '_')] : transformer.default;
|
|
1419
1572
|
}
|
|
1420
1573
|
if (typeof transformer !== 'function') {
|
|
1421
|
-
throw
|
|
1574
|
+
throw errorMessage(plugin, "Invalid function", pkg || name);
|
|
1422
1575
|
}
|
|
1423
1576
|
if (pkg) {
|
|
1424
1577
|
CACHE_PACKAGE.set(target + username, transformer);
|
|
@@ -1436,7 +1589,7 @@ class Document extends core_1.Client {
|
|
|
1436
1589
|
}
|
|
1437
1590
|
catch (err) {
|
|
1438
1591
|
abortTransform();
|
|
1439
|
-
this.checkPackage(err,
|
|
1592
|
+
this.checkPackage(err, getModuleName(err), ["Unable to transform document", target], { type: 4, startTime });
|
|
1440
1593
|
if (i < length - 1) {
|
|
1441
1594
|
series.reset();
|
|
1442
1595
|
}
|
|
@@ -1445,10 +1598,10 @@ class Document extends core_1.Client {
|
|
|
1445
1598
|
else if (name) {
|
|
1446
1599
|
abortTransform();
|
|
1447
1600
|
if (plugin) {
|
|
1448
|
-
this.writeFail("Unable to load configuration",
|
|
1601
|
+
this.writeFail("Unable to load configuration", errorMessage(plugin, name, "Invalid config"), 4);
|
|
1449
1602
|
}
|
|
1450
1603
|
else {
|
|
1451
|
-
this.writeFail("Format method was not found",
|
|
1604
|
+
this.writeFail("Format method was not found", errorValue(name, "Unknown"), 4);
|
|
1452
1605
|
}
|
|
1453
1606
|
}
|
|
1454
1607
|
}
|
|
@@ -1468,7 +1621,7 @@ class Document extends core_1.Client {
|
|
|
1468
1621
|
if (sourceMap.map && sourceMap.code === output.code) {
|
|
1469
1622
|
output.map = sourceMap.map;
|
|
1470
1623
|
}
|
|
1471
|
-
if (
|
|
1624
|
+
if (isArray(series.supplementChunks)) {
|
|
1472
1625
|
output.chunks = series.supplementChunks.map(item => ({ code: item.code, map: output.map && item.sourceMap?.map, entryPoint: item.entryPoint, filename: item.filename }));
|
|
1473
1626
|
}
|
|
1474
1627
|
if (sourceFiles) {
|
|
@@ -1479,11 +1632,31 @@ class Document extends core_1.Client {
|
|
|
1479
1632
|
}
|
|
1480
1633
|
return output;
|
|
1481
1634
|
}
|
|
1635
|
+
isImportsStrict() {
|
|
1636
|
+
return !!(this.getUserSettings()?.imports_strict ?? this.settings.imports_strict);
|
|
1637
|
+
}
|
|
1638
|
+
#checkIntegrity(metadata, url, localUri) {
|
|
1639
|
+
const integrity = metadata?.[url];
|
|
1640
|
+
if (!isString(integrity)) {
|
|
1641
|
+
return true;
|
|
1642
|
+
}
|
|
1643
|
+
try {
|
|
1644
|
+
const match = /^(sha(?:256|384|512))-(.+)$/i.exec(integrity);
|
|
1645
|
+
if (match && hashKey(fs.readFileSync(localUri), match[1], 'base64') === match[2]) {
|
|
1646
|
+
return true;
|
|
1647
|
+
}
|
|
1648
|
+
this.addLog(3, joinString('checksum', url, integrity), 'imports', path.basename(localUri));
|
|
1649
|
+
}
|
|
1650
|
+
catch (err) {
|
|
1651
|
+
this.writeFail(["Unable to read file", path.basename(localUri)], err, 32);
|
|
1652
|
+
}
|
|
1653
|
+
return false;
|
|
1654
|
+
}
|
|
1482
1655
|
#getConfigObject(data, name, target, cache) {
|
|
1483
1656
|
if (this.settingsOf('transform', 'coerce') === true) {
|
|
1484
|
-
|
|
1657
|
+
coerceObject(target, cache);
|
|
1485
1658
|
}
|
|
1486
|
-
return
|
|
1659
|
+
return cloneObject(data[name] = target, true);
|
|
1487
1660
|
}
|
|
1488
1661
|
#addConfigError(...message) {
|
|
1489
1662
|
this.addLog(2, joinString('config', ...message));
|
|
@@ -1515,17 +1688,17 @@ class Document extends core_1.Client {
|
|
|
1515
1688
|
return [];
|
|
1516
1689
|
}
|
|
1517
1690
|
set imports(value) {
|
|
1518
|
-
if (
|
|
1519
|
-
this._imports
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1691
|
+
if (isPlainObject(value)) {
|
|
1692
|
+
if (this._imports) {
|
|
1693
|
+
this._imports = Object.assign(this._imports, value);
|
|
1694
|
+
}
|
|
1695
|
+
else {
|
|
1696
|
+
const imports = this.getUserSettings()?.imports || this.module.imports;
|
|
1697
|
+
this._imports = Object.assign({}, isPlainObject(imports) ? imports : undefined, value);
|
|
1698
|
+
}
|
|
1525
1699
|
}
|
|
1526
1700
|
else {
|
|
1527
|
-
|
|
1528
|
-
this._imports = Object.assign(this._imports || {}, (0, types_1.isPlainObject)(imports) ? imports : undefined, value);
|
|
1701
|
+
this._imports = null;
|
|
1529
1702
|
}
|
|
1530
1703
|
}
|
|
1531
1704
|
get imports() {
|
|
@@ -1539,4 +1712,9 @@ class Document extends core_1.Client {
|
|
|
1539
1712
|
}
|
|
1540
1713
|
}
|
|
1541
1714
|
initCache();
|
|
1715
|
+
manageGlobalObject(CACHE_PACKAGE);
|
|
1716
|
+
manageGlobalObject(CACHE_VIEWENGINE);
|
|
1717
|
+
manageGlobalObject(CACHE_EXTERNAL);
|
|
1718
|
+
manageGlobalObject(CACHE_PICOMATCH);
|
|
1719
|
+
|
|
1542
1720
|
module.exports = Document;
|