@jsenv/core 38.3.11 → 38.4.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 +17 -18
- package/dist/babel_helpers/AsyncGenerator/AsyncGenerator.js +3 -3
- package/dist/babel_helpers/AwaitValue/AwaitValue.js +2 -2
- package/dist/babel_helpers/{overloadYield/overloadYield.js → OverloadYield/OverloadYield.js} +1 -1
- package/dist/babel_helpers/applyDecoratedDescriptor/applyDecoratedDescriptor.js +23 -14
- package/dist/babel_helpers/applyDecs/applyDecs.js +32 -21
- package/dist/babel_helpers/applyDecs2203/applyDecs2203.js +549 -549
- package/dist/babel_helpers/applyDecs2203R/applyDecs2203R.js +27 -15
- package/dist/babel_helpers/applyDecs2301/applyDecs2301.js +29 -18
- package/dist/babel_helpers/applyDecs2305/applyDecs2305.js +362 -541
- package/dist/babel_helpers/arrayLikeToArray/arrayLikeToArray.js +4 -4
- package/dist/babel_helpers/arrayWithHoles/arrayWithHoles.js +2 -2
- package/dist/babel_helpers/arrayWithoutHoles/arrayWithoutHoles.js +3 -3
- package/dist/babel_helpers/assertThisInitialized/assertThisInitialized.js +5 -3
- package/dist/babel_helpers/asyncGeneratorDelegate/asyncGeneratorDelegate.js +2 -2
- package/dist/babel_helpers/asyncIterator/asyncIterator.js +1 -1
- package/dist/babel_helpers/asyncToGenerator/asyncToGenerator.js +17 -17
- package/dist/babel_helpers/awaitAsyncGenerator/awaitAsyncGenerator.js +2 -2
- package/dist/babel_helpers/callSuper/callSuper.js +25 -0
- package/dist/babel_helpers/checkInRHS/checkInRHS.js +10 -8
- package/dist/babel_helpers/classApplyDescriptorDestructureSet/classApplyDescriptorDestructureSet.js +9 -6
- package/dist/babel_helpers/classApplyDescriptorGet/classApplyDescriptorGet.js +2 -2
- package/dist/babel_helpers/classApplyDescriptorSet/classApplyDescriptorSet.js +3 -3
- package/dist/babel_helpers/classCallCheck/classCallCheck.js +1 -1
- package/dist/babel_helpers/classCheckPrivateStaticAccess/classCheckPrivateStaticAccess.js +5 -2
- package/dist/babel_helpers/classCheckPrivateStaticFieldDescriptor/classCheckPrivateStaticFieldDescriptor.js +7 -2
- package/dist/babel_helpers/classExtractFieldDescriptor/classExtractFieldDescriptor.js +9 -3
- package/dist/babel_helpers/classNameTDZError/classNameTDZError.js +3 -1
- package/dist/babel_helpers/classPrivateFieldDestructureSet/classPrivateFieldDestructureSet.js +4 -4
- package/dist/babel_helpers/classPrivateFieldGet/classPrivateFieldGet.js +4 -4
- package/dist/babel_helpers/classPrivateFieldLooseBase/classPrivateFieldLooseBase.js +2 -2
- package/dist/babel_helpers/classPrivateFieldLooseKey/classPrivateFieldLooseKey.js +2 -2
- package/dist/babel_helpers/classPrivateFieldSet/classPrivateFieldSet.js +5 -5
- package/dist/babel_helpers/classPrivateMethodGet/classPrivateMethodGet.js +2 -2
- package/dist/babel_helpers/classPrivateMethodSet/classPrivateMethodSet.js +1 -1
- package/dist/babel_helpers/classStaticPrivateFieldSpecGet/classStaticPrivateFieldSpecGet.js +11 -7
- package/dist/babel_helpers/classStaticPrivateFieldSpecSet/classStaticPrivateFieldSpecSet.js +7 -7
- package/dist/babel_helpers/classStaticPrivateMethodGet/classStaticPrivateMethodGet.js +8 -4
- package/dist/babel_helpers/classStaticPrivateMethodSet/classStaticPrivateMethodSet.js +1 -1
- package/dist/babel_helpers/construct/construct.js +18 -14
- package/dist/babel_helpers/createClass/createClass.js +1 -1
- package/dist/babel_helpers/createForOfIteratorHelper/createForOfIteratorHelper.js +21 -20
- package/dist/babel_helpers/createForOfIteratorHelperLoose/createForOfIteratorHelperLoose.js +10 -9
- package/dist/babel_helpers/createRawReactElement/createRawReactElement.js +11 -11
- package/dist/babel_helpers/createSuper/createSuper.js +11 -11
- package/dist/babel_helpers/decorate/decorate.js +255 -170
- package/dist/babel_helpers/defaults/defaults.js +5 -5
- package/dist/babel_helpers/defineAccessor/defineAccessor.js +1 -1
- package/dist/babel_helpers/defineEnumerableProperties/defineEnumerableProperties.js +11 -11
- package/dist/babel_helpers/defineProperty/defineProperty.js +4 -4
- package/dist/babel_helpers/dispose/dispose.js +39 -39
- package/dist/babel_helpers/extends/extends.js +4 -4
- package/dist/babel_helpers/get/get.js +2 -2
- package/dist/babel_helpers/getPrototypeOf/getPrototypeOf.js +1 -1
- package/dist/babel_helpers/identity/identity.js +1 -1
- package/dist/babel_helpers/importDeferProxy/importDeferProxy.js +27 -27
- package/dist/babel_helpers/inherits/inherits.js +4 -4
- package/dist/babel_helpers/inheritsLoose/inheritsLoose.js +4 -4
- package/dist/babel_helpers/initializerDefineProperty/initializerDefineProperty.js +5 -3
- package/dist/babel_helpers/initializerWarningHelper/initializerWarningHelper.js +1 -1
- package/dist/babel_helpers/instanceof/instanceof.js +7 -3
- package/dist/babel_helpers/interopRequireDefault/interopRequireDefault.js +1 -1
- package/dist/babel_helpers/interopRequireWildcard/interopRequireWildcard.js +3 -1
- package/dist/babel_helpers/isNativeFunction/isNativeFunction.js +1 -1
- package/dist/babel_helpers/isNativeReflectConstruct/isNativeReflectConstruct.js +12 -14
- package/dist/babel_helpers/iterableToArray/iterableToArray.js +1 -1
- package/dist/babel_helpers/iterableToArrayLimit/iterableToArrayLimit.js +1 -1
- package/dist/babel_helpers/iterableToArrayLimitLoose/iterableToArrayLimitLoose.js +1 -1
- package/dist/babel_helpers/jsx/jsx.js +1 -1
- package/dist/babel_helpers/maybeArrayLike/maybeArrayLike.js +4 -4
- package/dist/babel_helpers/newArrowCheck/newArrowCheck.js +1 -1
- package/dist/babel_helpers/nonIterableRest/nonIterableRest.js +2 -2
- package/dist/babel_helpers/nonIterableSpread/nonIterableSpread.js +2 -2
- package/dist/babel_helpers/nullishReceiverError/nullishReceiverError.js +1 -1
- package/dist/babel_helpers/objectDestructuringEmpty/objectDestructuringEmpty.js +1 -1
- package/dist/babel_helpers/objectSpread/objectSpread.js +8 -8
- package/dist/babel_helpers/objectSpread2/objectSpread2.js +5 -3
- package/dist/babel_helpers/objectWithoutProperties/objectWithoutProperties.js +12 -12
- package/dist/babel_helpers/objectWithoutPropertiesLoose/objectWithoutPropertiesLoose.js +10 -10
- package/dist/babel_helpers/possibleConstructorReturn/possibleConstructorReturn.js +7 -5
- package/dist/babel_helpers/readOnlyError/readOnlyError.js +1 -1
- package/dist/babel_helpers/regeneratorRuntime/regeneratorRuntime.js +1 -1
- package/dist/babel_helpers/set/set.js +22 -19
- package/dist/babel_helpers/setFunctionName/setFunctionName.js +18 -0
- package/dist/babel_helpers/setPrototypeOf/setPrototypeOf.js +7 -6
- package/dist/babel_helpers/skipFirstGeneratorNext/skipFirstGeneratorNext.js +4 -4
- package/dist/babel_helpers/slicedToArray/slicedToArray.js +5 -5
- package/dist/babel_helpers/slicedToArrayLoose/slicedToArrayLoose.js +5 -5
- package/dist/babel_helpers/superPropBase/superPropBase.js +4 -4
- package/dist/babel_helpers/taggedTemplateLiteral/taggedTemplateLiteral.js +2 -2
- package/dist/babel_helpers/taggedTemplateLiteralLoose/taggedTemplateLiteralLoose.js +3 -3
- package/dist/babel_helpers/tdz/tdz.js +1 -1
- package/dist/babel_helpers/temporalRef/temporalRef.js +3 -3
- package/dist/babel_helpers/toArray/toArray.js +5 -5
- package/dist/babel_helpers/toConsumableArray/toConsumableArray.js +5 -5
- package/dist/babel_helpers/toPrimitive/toPrimitive.js +11 -7
- package/dist/babel_helpers/toPropertyKey/toPropertyKey.js +8 -4
- package/dist/babel_helpers/typeof/typeof.js +6 -5
- package/dist/babel_helpers/unsupportedIterableToArray/unsupportedIterableToArray.js +7 -7
- package/dist/babel_helpers/using/using.js +20 -20
- package/dist/babel_helpers/wrapAsyncGenerator/wrapAsyncGenerator.js +3 -3
- package/dist/babel_helpers/wrapNativeSuper/wrapNativeSuper.js +12 -12
- package/dist/babel_helpers/wrapRegExp/wrapRegExp.js +5 -3
- package/dist/babel_helpers/writeOnlyError/writeOnlyError.js +1 -1
- package/dist/js/ribbon.js +1 -1
- package/dist/js/ws.js +234 -146
- package/dist/jsenv_core.js +1365 -1211
- package/package.json +26 -22
- package/src/build/build.js +22 -14
- package/src/dev/start_dev_server.js +8 -21
- package/src/kitchen/errors.js +29 -24
- package/src/kitchen/kitchen.js +1 -1
- package/src/kitchen/url_graph/references.js +8 -0
- package/src/kitchen/url_graph/url_graph_report.js +5 -3
- package/src/plugins/plugins.js +2 -2
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +17 -7
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +10 -12
- package/src/plugins/ribbon/client/ribbon.js +1 -1
package/dist/jsenv_core.js
CHANGED
|
@@ -13,119 +13,19 @@ import http from "node:http";
|
|
|
13
13
|
import { Readable, Stream, Writable } from "node:stream";
|
|
14
14
|
import { Http2ServerResponse } from "node:http2";
|
|
15
15
|
import { lookup } from "node:dns";
|
|
16
|
-
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtml, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition, getUrlForContentInsideHtml, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, setHtmlNodeText, removeHtmlNode, parseCssUrls,
|
|
16
|
+
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtml, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, parseJsUrls, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition, getUrlForContentInsideHtml, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, setHtmlNodeText, removeHtmlNode, parseCssUrls, getUrlForContentInsideJs, analyzeLinkNode, findHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
|
|
17
17
|
import { sourcemapConverter, createMagicSource, composeTwoSourcemaps, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import { systemJsClientFileUrlDefault, convertJsModuleToJsClassic } from "@jsenv/js-module-fallback";
|
|
20
20
|
import { RUNTIME_COMPAT } from "@jsenv/runtime-compat";
|
|
21
21
|
import { jsenvPluginSupervisor } from "@jsenv/plugin-supervisor";
|
|
22
22
|
|
|
23
|
-
const assertUrlLike = (value, name = "url") => {
|
|
24
|
-
if (typeof value !== "string") {
|
|
25
|
-
throw new TypeError(`${name} must be a url string, got ${value}`);
|
|
26
|
-
}
|
|
27
|
-
if (isWindowsPathnameSpecifier(value)) {
|
|
28
|
-
throw new TypeError(
|
|
29
|
-
`${name} must be a url but looks like a windows pathname, got ${value}`,
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
if (!hasScheme$1(value)) {
|
|
33
|
-
throw new TypeError(
|
|
34
|
-
`${name} must be a url and no scheme found, got ${value}`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const isPlainObject = (value) => {
|
|
40
|
-
if (value === null) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
if (typeof value === "object") {
|
|
44
|
-
if (Array.isArray(value)) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const isWindowsPathnameSpecifier = (specifier) => {
|
|
53
|
-
const firstChar = specifier[0];
|
|
54
|
-
if (!/[a-zA-Z]/.test(firstChar)) return false;
|
|
55
|
-
const secondChar = specifier[1];
|
|
56
|
-
if (secondChar !== ":") return false;
|
|
57
|
-
const thirdChar = specifier[2];
|
|
58
|
-
return thirdChar === "/" || thirdChar === "\\";
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const hasScheme$1 = (specifier) => /^[a-zA-Z]+:/.test(specifier);
|
|
62
|
-
|
|
63
|
-
const resolveAssociations = (associations, baseUrl) => {
|
|
64
|
-
if (baseUrl && typeof baseUrl.href === "string") baseUrl = baseUrl.href;
|
|
65
|
-
assertUrlLike(baseUrl, "baseUrl");
|
|
66
|
-
const associationsResolved = {};
|
|
67
|
-
Object.keys(associations).forEach((key) => {
|
|
68
|
-
const value = associations[key];
|
|
69
|
-
if (typeof value === "object" && value !== null) {
|
|
70
|
-
const valueMapResolved = {};
|
|
71
|
-
Object.keys(value).forEach((pattern) => {
|
|
72
|
-
const valueAssociated = value[pattern];
|
|
73
|
-
const patternResolved = normalizeUrlPattern(pattern, baseUrl);
|
|
74
|
-
valueMapResolved[patternResolved] = valueAssociated;
|
|
75
|
-
});
|
|
76
|
-
associationsResolved[key] = valueMapResolved;
|
|
77
|
-
} else {
|
|
78
|
-
associationsResolved[key] = value;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
return associationsResolved;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const normalizeUrlPattern = (urlPattern, baseUrl) => {
|
|
85
|
-
try {
|
|
86
|
-
return String(new URL(urlPattern, baseUrl));
|
|
87
|
-
} catch (e) {
|
|
88
|
-
// it's not really an url, no need to perform url resolution nor encoding
|
|
89
|
-
return urlPattern;
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const asFlatAssociations = (associations) => {
|
|
94
|
-
if (!isPlainObject(associations)) {
|
|
95
|
-
throw new TypeError(
|
|
96
|
-
`associations must be a plain object, got ${associations}`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
const flatAssociations = {};
|
|
100
|
-
Object.keys(associations).forEach((associationName) => {
|
|
101
|
-
const associationValue = associations[associationName];
|
|
102
|
-
if (isPlainObject(associationValue)) {
|
|
103
|
-
Object.keys(associationValue).forEach((pattern) => {
|
|
104
|
-
const patternValue = associationValue[pattern];
|
|
105
|
-
const previousValue = flatAssociations[pattern];
|
|
106
|
-
if (isPlainObject(previousValue)) {
|
|
107
|
-
flatAssociations[pattern] = {
|
|
108
|
-
...previousValue,
|
|
109
|
-
[associationName]: patternValue,
|
|
110
|
-
};
|
|
111
|
-
} else {
|
|
112
|
-
flatAssociations[pattern] = {
|
|
113
|
-
[associationName]: patternValue,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
return flatAssociations;
|
|
120
|
-
};
|
|
121
|
-
|
|
122
23
|
/*
|
|
123
24
|
* Link to things doing pattern matching:
|
|
124
25
|
* https://git-scm.com/docs/gitignore
|
|
125
26
|
* https://github.com/kaelzhang/node-ignore
|
|
126
27
|
*/
|
|
127
28
|
|
|
128
|
-
|
|
129
29
|
/** @module jsenv_url_meta **/
|
|
130
30
|
/**
|
|
131
31
|
* An object representing the result of applying a pattern to an url
|
|
@@ -143,21 +43,18 @@ const asFlatAssociations = (associations) => {
|
|
|
143
43
|
* @param {string} applyPatternMatchingParams.url a string representing an url
|
|
144
44
|
* @return {MatchResult}
|
|
145
45
|
*/
|
|
146
|
-
const
|
|
147
|
-
assertUrlLike(pattern, "pattern");
|
|
148
|
-
if (url && typeof url.href === "string") url = url.href;
|
|
149
|
-
assertUrlLike(url, "url");
|
|
46
|
+
const applyPattern = ({ url, pattern }) => {
|
|
150
47
|
const { matched, patternIndex, index, groups } = applyMatching(pattern, url);
|
|
151
48
|
const matchGroups = [];
|
|
152
49
|
let groupIndex = 0;
|
|
153
|
-
|
|
50
|
+
for (const group of groups) {
|
|
154
51
|
if (group.name) {
|
|
155
52
|
matchGroups[group.name] = group.string;
|
|
156
53
|
} else {
|
|
157
54
|
matchGroups[groupIndex] = group.string;
|
|
158
55
|
groupIndex++;
|
|
159
56
|
}
|
|
160
|
-
}
|
|
57
|
+
}
|
|
161
58
|
return {
|
|
162
59
|
matched,
|
|
163
60
|
patternIndex,
|
|
@@ -392,54 +289,100 @@ const skipUntilMatch = ({ pattern, string, canSkipSlash }) => {
|
|
|
392
289
|
return tryToMatch();
|
|
393
290
|
};
|
|
394
291
|
|
|
292
|
+
const applyPatternMatching = ({ url, pattern }) => {
|
|
293
|
+
assertUrlLike(pattern, "pattern");
|
|
294
|
+
if (url && typeof url.href === "string") url = url.href;
|
|
295
|
+
assertUrlLike(url, "url");
|
|
296
|
+
return applyPattern({ url, pattern });
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const resolveAssociations = (associations, baseUrl) => {
|
|
300
|
+
if (baseUrl && typeof baseUrl.href === "string") baseUrl = baseUrl.href;
|
|
301
|
+
assertUrlLike(baseUrl, "baseUrl");
|
|
302
|
+
|
|
303
|
+
const associationsResolved = {};
|
|
304
|
+
for (const key of Object.keys(associations)) {
|
|
305
|
+
const value = associations[key];
|
|
306
|
+
if (typeof value === "object" && value !== null) {
|
|
307
|
+
const valueMapResolved = {};
|
|
308
|
+
for (const pattern of Object.keys(value)) {
|
|
309
|
+
const valueAssociated = value[pattern];
|
|
310
|
+
let patternResolved;
|
|
311
|
+
try {
|
|
312
|
+
patternResolved = String(new URL(pattern, baseUrl));
|
|
313
|
+
} catch (e) {
|
|
314
|
+
// it's not really an url, no need to perform url resolution nor encoding
|
|
315
|
+
patternResolved = pattern;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
valueMapResolved[patternResolved] = valueAssociated;
|
|
319
|
+
}
|
|
320
|
+
associationsResolved[key] = valueMapResolved;
|
|
321
|
+
} else {
|
|
322
|
+
associationsResolved[key] = value;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return associationsResolved;
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const asFlatAssociations = (associations) => {
|
|
329
|
+
if (!isPlainObject(associations)) {
|
|
330
|
+
throw new TypeError(
|
|
331
|
+
`associations must be a plain object, got ${associations}`,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
const flatAssociations = {};
|
|
335
|
+
for (const associationName of Object.keys(associations)) {
|
|
336
|
+
const associationValue = associations[associationName];
|
|
337
|
+
if (!isPlainObject(associationValue)) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
for (const pattern of Object.keys(associationValue)) {
|
|
341
|
+
const patternValue = associationValue[pattern];
|
|
342
|
+
const previousValue = flatAssociations[pattern];
|
|
343
|
+
if (isPlainObject(previousValue)) {
|
|
344
|
+
flatAssociations[pattern] = {
|
|
345
|
+
...previousValue,
|
|
346
|
+
[associationName]: patternValue,
|
|
347
|
+
};
|
|
348
|
+
} else {
|
|
349
|
+
flatAssociations[pattern] = {
|
|
350
|
+
[associationName]: patternValue,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return flatAssociations;
|
|
356
|
+
};
|
|
357
|
+
|
|
395
358
|
const applyAssociations = ({ url, associations }) => {
|
|
396
359
|
if (url && typeof url.href === "string") url = url.href;
|
|
397
360
|
assertUrlLike(url);
|
|
398
361
|
const flatAssociations = asFlatAssociations(associations);
|
|
399
|
-
|
|
362
|
+
let associatedValue = {};
|
|
363
|
+
for (const pattern of Object.keys(flatAssociations)) {
|
|
400
364
|
const { matched } = applyPatternMatching({
|
|
401
365
|
pattern,
|
|
402
366
|
url,
|
|
403
367
|
});
|
|
404
368
|
if (matched) {
|
|
405
369
|
const value = flatAssociations[pattern];
|
|
406
|
-
|
|
407
|
-
return {
|
|
408
|
-
...previousValue,
|
|
409
|
-
...value,
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
return value;
|
|
370
|
+
associatedValue = deepAssign(associatedValue, value);
|
|
413
371
|
}
|
|
414
|
-
|
|
415
|
-
|
|
372
|
+
}
|
|
373
|
+
return associatedValue;
|
|
416
374
|
};
|
|
417
375
|
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const aliasMatchResult = applyPatternMatching({
|
|
422
|
-
pattern: key,
|
|
423
|
-
url,
|
|
424
|
-
});
|
|
425
|
-
if (aliasMatchResult.matched) {
|
|
426
|
-
aliasFullMatchResult = aliasMatchResult;
|
|
427
|
-
return true;
|
|
428
|
-
}
|
|
429
|
-
return false;
|
|
430
|
-
});
|
|
431
|
-
if (!aliasMatchingKey) {
|
|
432
|
-
return url;
|
|
376
|
+
const deepAssign = (firstValue, secondValue) => {
|
|
377
|
+
if (!isPlainObject(firstValue) || !isPlainObject(secondValue)) {
|
|
378
|
+
return secondValue;
|
|
433
379
|
}
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}`;
|
|
441
|
-
}, "");
|
|
442
|
-
return newUrl;
|
|
380
|
+
for (const key of Object.keys(secondValue)) {
|
|
381
|
+
const leftValue = firstValue[key];
|
|
382
|
+
const rightValue = secondValue[key];
|
|
383
|
+
firstValue[key] = deepAssign(leftValue, rightValue);
|
|
384
|
+
}
|
|
385
|
+
return firstValue;
|
|
443
386
|
};
|
|
444
387
|
|
|
445
388
|
const urlChildMayMatch = ({ url, associations, predicate }) => {
|
|
@@ -459,7 +402,7 @@ const urlChildMayMatch = ({ url, associations, predicate }) => {
|
|
|
459
402
|
// for partial match, any meta satisfying predicate will be valid because
|
|
460
403
|
// we don't know for sure if pattern will still match for a file inside pathname
|
|
461
404
|
const partialMatchMetaArray = [];
|
|
462
|
-
Object.keys(flatAssociations)
|
|
405
|
+
for (const pattern of Object.keys(flatAssociations)) {
|
|
463
406
|
const value = flatAssociations[pattern];
|
|
464
407
|
const matchResult = applyPatternMatching({
|
|
465
408
|
pattern,
|
|
@@ -478,7 +421,7 @@ const urlChildMayMatch = ({ url, associations, predicate }) => {
|
|
|
478
421
|
} else if (someFullMatch === false && matchResult.urlIndex >= url.length) {
|
|
479
422
|
partialMatchMetaArray.push(value);
|
|
480
423
|
}
|
|
481
|
-
}
|
|
424
|
+
}
|
|
482
425
|
if (someFullMatch) {
|
|
483
426
|
return Boolean(predicate(fullMatchMeta));
|
|
484
427
|
}
|
|
@@ -487,12 +430,111 @@ const urlChildMayMatch = ({ url, associations, predicate }) => {
|
|
|
487
430
|
);
|
|
488
431
|
};
|
|
489
432
|
|
|
433
|
+
const applyAliases = ({ url, aliases }) => {
|
|
434
|
+
let aliasFullMatchResult;
|
|
435
|
+
const aliasMatchingKey = Object.keys(aliases).find((key) => {
|
|
436
|
+
const aliasMatchResult = applyPatternMatching({
|
|
437
|
+
pattern: key,
|
|
438
|
+
url,
|
|
439
|
+
});
|
|
440
|
+
if (aliasMatchResult.matched) {
|
|
441
|
+
aliasFullMatchResult = aliasMatchResult;
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
return false;
|
|
445
|
+
});
|
|
446
|
+
if (!aliasMatchingKey) {
|
|
447
|
+
return url;
|
|
448
|
+
}
|
|
449
|
+
const { matchGroups } = aliasFullMatchResult;
|
|
450
|
+
const alias = aliases[aliasMatchingKey];
|
|
451
|
+
const parts = alias.split("*");
|
|
452
|
+
let newUrl = "";
|
|
453
|
+
let index = 0;
|
|
454
|
+
for (const part of parts) {
|
|
455
|
+
newUrl += `${part}`;
|
|
456
|
+
if (index < parts.length - 1) {
|
|
457
|
+
newUrl += matchGroups[index];
|
|
458
|
+
}
|
|
459
|
+
index++;
|
|
460
|
+
}
|
|
461
|
+
return newUrl;
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
const matches = (url, patterns) => {
|
|
465
|
+
return Boolean(
|
|
466
|
+
applyAssociations({
|
|
467
|
+
url,
|
|
468
|
+
associations: {
|
|
469
|
+
yes: patterns,
|
|
470
|
+
},
|
|
471
|
+
}).yes,
|
|
472
|
+
);
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// const assertSpecifierMetaMap = (value, checkComposition = true) => {
|
|
476
|
+
// if (!isPlainObject(value)) {
|
|
477
|
+
// throw new TypeError(
|
|
478
|
+
// `specifierMetaMap must be a plain object, got ${value}`,
|
|
479
|
+
// );
|
|
480
|
+
// }
|
|
481
|
+
// if (checkComposition) {
|
|
482
|
+
// const plainObject = value;
|
|
483
|
+
// Object.keys(plainObject).forEach((key) => {
|
|
484
|
+
// assertUrlLike(key, "specifierMetaMap key");
|
|
485
|
+
// const value = plainObject[key];
|
|
486
|
+
// if (value !== null && !isPlainObject(value)) {
|
|
487
|
+
// throw new TypeError(
|
|
488
|
+
// `specifierMetaMap value must be a plain object or null, got ${value} under key ${key}`,
|
|
489
|
+
// );
|
|
490
|
+
// }
|
|
491
|
+
// });
|
|
492
|
+
// }
|
|
493
|
+
// };
|
|
494
|
+
const assertUrlLike = (value, name = "url") => {
|
|
495
|
+
if (typeof value !== "string") {
|
|
496
|
+
throw new TypeError(`${name} must be a url string, got ${value}`);
|
|
497
|
+
}
|
|
498
|
+
if (isWindowsPathnameSpecifier(value)) {
|
|
499
|
+
throw new TypeError(
|
|
500
|
+
`${name} must be a url but looks like a windows pathname, got ${value}`,
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
if (!hasScheme$1(value)) {
|
|
504
|
+
throw new TypeError(
|
|
505
|
+
`${name} must be a url and no scheme found, got ${value}`,
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
const isPlainObject = (value) => {
|
|
510
|
+
if (value === null) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
if (typeof value === "object") {
|
|
514
|
+
if (Array.isArray(value)) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
return false;
|
|
520
|
+
};
|
|
521
|
+
const isWindowsPathnameSpecifier = (specifier) => {
|
|
522
|
+
const firstChar = specifier[0];
|
|
523
|
+
if (!/[a-zA-Z]/.test(firstChar)) return false;
|
|
524
|
+
const secondChar = specifier[1];
|
|
525
|
+
if (secondChar !== ":") return false;
|
|
526
|
+
const thirdChar = specifier[2];
|
|
527
|
+
return thirdChar === "/" || thirdChar === "\\";
|
|
528
|
+
};
|
|
529
|
+
const hasScheme$1 = (specifier) => /^[a-zA-Z]+:/.test(specifier);
|
|
530
|
+
|
|
490
531
|
const URL_META = {
|
|
491
532
|
resolveAssociations,
|
|
492
533
|
applyAssociations,
|
|
493
|
-
urlChildMayMatch,
|
|
494
|
-
applyPatternMatching,
|
|
495
534
|
applyAliases,
|
|
535
|
+
applyPatternMatching,
|
|
536
|
+
urlChildMayMatch,
|
|
537
|
+
matches,
|
|
496
538
|
};
|
|
497
539
|
|
|
498
540
|
/*
|
|
@@ -546,132 +588,111 @@ const DATA_URL = {
|
|
|
546
588
|
},
|
|
547
589
|
};
|
|
548
590
|
|
|
549
|
-
|
|
550
|
-
// https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/css-syntax-error.js#L43
|
|
551
|
-
// https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/terminal-highlight.js#L50
|
|
552
|
-
// https://github.com/babel/babel/blob/eea156b2cb8deecfcf82d52aa1b71ba4995c7d68/packages/babel-code-frame/src/index.js#L1
|
|
553
|
-
|
|
591
|
+
const formatDefault = (v) => v;
|
|
554
592
|
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
numberOfSurroundingLinesToShow,
|
|
560
|
-
lineMaxLength,
|
|
561
|
-
color,
|
|
562
|
-
} = {},
|
|
563
|
-
) => {
|
|
564
|
-
let string = url;
|
|
593
|
+
const inspectFileContent = ({
|
|
594
|
+
content,
|
|
595
|
+
line,
|
|
596
|
+
column,
|
|
565
597
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if (!showCodeFrame || typeof line !== "number" || !content) {
|
|
574
|
-
return string;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
const sourceLoc = showSourceLocation({
|
|
578
|
-
content,
|
|
579
|
-
line,
|
|
580
|
-
column,
|
|
581
|
-
numberOfSurroundingLinesToShow,
|
|
582
|
-
lineMaxLength,
|
|
583
|
-
color,
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
return `${string}
|
|
587
|
-
${sourceLoc}`;
|
|
588
|
-
};
|
|
589
|
-
|
|
590
|
-
const showSourceLocation = ({
|
|
591
|
-
content,
|
|
592
|
-
line,
|
|
593
|
-
column,
|
|
594
|
-
numberOfSurroundingLinesToShow = 1,
|
|
595
|
-
lineMaxLength = 120,
|
|
598
|
+
linesAbove = 3,
|
|
599
|
+
linesBelow = 0,
|
|
600
|
+
lineMaxWidth = 120,
|
|
601
|
+
lineNumbersOnTheLeft = true,
|
|
602
|
+
lineMarker = true,
|
|
603
|
+
columnMarker = true,
|
|
604
|
+
format = formatDefault,
|
|
596
605
|
} = {}) => {
|
|
597
|
-
|
|
598
|
-
let aside = (string) => string;
|
|
599
|
-
// if (color) {
|
|
600
|
-
// mark = (string) => ANSI.color(string, ANSI.RED)
|
|
601
|
-
// aside = (string) => ANSI.color(string, ANSI.GREY)
|
|
602
|
-
// }
|
|
603
|
-
|
|
604
|
-
const lines = content.split(/\r?\n/);
|
|
606
|
+
const lineStrings = content.split(/\r?\n/);
|
|
605
607
|
if (line === 0) line = 1;
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
}
|
|
610
|
-
lineRange = moveLineRangeUp(lineRange, numberOfSurroundingLinesToShow);
|
|
611
|
-
lineRange = moveLineRangeDown(lineRange, numberOfSurroundingLinesToShow);
|
|
612
|
-
lineRange = lineRangeWithinLines(lineRange, lines);
|
|
613
|
-
const linesToShow = lines.slice(lineRange.start, lineRange.end);
|
|
614
|
-
const endLineNumber = lineRange.end;
|
|
615
|
-
const lineNumberMaxWidth = String(endLineNumber).length;
|
|
616
|
-
|
|
608
|
+
if (column === undefined) {
|
|
609
|
+
columnMarker = false;
|
|
610
|
+
column = 1;
|
|
611
|
+
}
|
|
617
612
|
if (column === 0) column = 1;
|
|
618
613
|
|
|
619
|
-
|
|
620
|
-
if (
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
614
|
+
let lineStartIndex = line - 1 - linesAbove;
|
|
615
|
+
if (lineStartIndex < 0) {
|
|
616
|
+
lineStartIndex = 0;
|
|
617
|
+
}
|
|
618
|
+
let lineEndIndex = line - 1 + linesBelow;
|
|
619
|
+
if (lineEndIndex > lineStrings.length - 1) {
|
|
620
|
+
lineEndIndex = lineStrings.length - 1;
|
|
621
|
+
}
|
|
622
|
+
if (columnMarker) {
|
|
623
|
+
// human reader deduce the line when there is a column marker
|
|
624
|
+
lineMarker = false;
|
|
625
|
+
}
|
|
626
|
+
if (line - 1 === lineEndIndex) {
|
|
627
|
+
lineMarker = false; // useless because last line
|
|
628
|
+
}
|
|
629
|
+
let lineIndex = lineStartIndex;
|
|
630
|
+
|
|
631
|
+
let columnsBefore;
|
|
632
|
+
let columnsAfter;
|
|
633
|
+
if (column > lineMaxWidth) {
|
|
634
|
+
columnsBefore = column - Math.ceil(lineMaxWidth / 2);
|
|
635
|
+
columnsAfter = column + Math.floor(lineMaxWidth / 2);
|
|
626
636
|
} else {
|
|
627
|
-
|
|
628
|
-
|
|
637
|
+
columnsBefore = 0;
|
|
638
|
+
columnsAfter = lineMaxWidth;
|
|
629
639
|
}
|
|
640
|
+
let columnMarkerIndex = column - 1 - columnsBefore;
|
|
630
641
|
|
|
631
|
-
|
|
632
|
-
|
|
642
|
+
let source = "";
|
|
643
|
+
while (lineIndex <= lineEndIndex) {
|
|
644
|
+
const lineString = lineStrings[lineIndex];
|
|
645
|
+
const lineNumber = lineIndex + 1;
|
|
646
|
+
const isLastLine = lineIndex === lineEndIndex;
|
|
633
647
|
const isMainLine = lineNumber === line;
|
|
634
|
-
|
|
635
|
-
const lineNumberWidth = String(lineNumber).length;
|
|
636
|
-
// ensure if line moves from 7,8,9 to 10 the display is still great
|
|
637
|
-
const lineNumberRightSpacing = " ".repeat(
|
|
638
|
-
lineNumberMaxWidth - lineNumberWidth,
|
|
639
|
-
);
|
|
640
|
-
const asideSource = `${lineNumber}${lineNumberRightSpacing} |`;
|
|
641
|
-
const lineFormatted = `${aside(asideSource)} ${lineSourceTruncated}`;
|
|
642
|
-
if (isMainLine) {
|
|
643
|
-
if (column === undefined) {
|
|
644
|
-
return `${mark(">")} ${lineFormatted}`;
|
|
645
|
-
}
|
|
646
|
-
const spacing = stringToSpaces(
|
|
647
|
-
`${asideSource} ${lineSourceTruncated.slice(
|
|
648
|
-
0,
|
|
649
|
-
column - columnRange.start - 1,
|
|
650
|
-
)}`,
|
|
651
|
-
);
|
|
652
|
-
return `${mark(">")} ${lineFormatted}
|
|
653
|
-
${spacing}${mark("^")}`;
|
|
654
|
-
}
|
|
655
|
-
return ` ${lineFormatted}`;
|
|
656
|
-
}).join(`
|
|
657
|
-
`);
|
|
658
|
-
};
|
|
648
|
+
lineIndex++;
|
|
659
649
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
650
|
+
{
|
|
651
|
+
if (lineMarker) {
|
|
652
|
+
if (isMainLine) {
|
|
653
|
+
source += `${format(">", "marker_line")} `;
|
|
654
|
+
} else {
|
|
655
|
+
source += " ";
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (lineNumbersOnTheLeft) {
|
|
659
|
+
// fill with spaces to ensure if line moves from 7,8,9 to 10 the display is still great
|
|
660
|
+
const asideSource = `${fillLeft(lineNumber, lineEndIndex + 1)} |`;
|
|
661
|
+
source += `${format(asideSource, "line_number_aside")} `;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
{
|
|
665
|
+
source += truncateLine(lineString, {
|
|
666
|
+
start: columnsBefore,
|
|
667
|
+
end: columnsAfter,
|
|
668
|
+
prefix: "…",
|
|
669
|
+
suffix: "…",
|
|
670
|
+
format,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
{
|
|
674
|
+
if (columnMarker && isMainLine) {
|
|
675
|
+
source += `\n`;
|
|
676
|
+
if (lineMarker) {
|
|
677
|
+
source += " ";
|
|
678
|
+
}
|
|
679
|
+
if (lineNumbersOnTheLeft) {
|
|
680
|
+
const asideSpaces = `${fillLeft(lineNumber, lineEndIndex + 1)} | `
|
|
681
|
+
.length;
|
|
682
|
+
source += " ".repeat(asideSpaces);
|
|
683
|
+
}
|
|
684
|
+
source += " ".repeat(columnMarkerIndex);
|
|
685
|
+
source += format("^", "marker_column");
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (!isLastLine) {
|
|
689
|
+
source += "\n";
|
|
690
|
+
}
|
|
671
691
|
}
|
|
692
|
+
return source;
|
|
693
|
+
};
|
|
672
694
|
|
|
673
|
-
|
|
674
|
-
const suffix = "…";
|
|
695
|
+
const truncateLine = (line, { start, end, prefix, suffix, format }) => {
|
|
675
696
|
const lastIndex = line.length;
|
|
676
697
|
|
|
677
698
|
if (line.length === 0) {
|
|
@@ -690,53 +711,360 @@ const applyColumnRange = ({ start, end }, line) => {
|
|
|
690
711
|
if (start >= lastIndex || from === to) {
|
|
691
712
|
return "";
|
|
692
713
|
}
|
|
693
|
-
|
|
694
714
|
let result = "";
|
|
695
715
|
while (from < to) {
|
|
696
|
-
result += line[from];
|
|
716
|
+
result += format(line[from], "char");
|
|
697
717
|
from++;
|
|
698
718
|
}
|
|
699
|
-
|
|
700
719
|
if (result.length === 0) {
|
|
701
720
|
return "";
|
|
702
721
|
}
|
|
703
722
|
if (startTruncated && endTruncated) {
|
|
704
|
-
return `${prefix}${result}${
|
|
723
|
+
return `${format(prefix, "marker_overflow_left")}${result}${format(
|
|
724
|
+
suffix,
|
|
725
|
+
"marker_overflow_right",
|
|
726
|
+
)}`;
|
|
705
727
|
}
|
|
706
728
|
if (startTruncated) {
|
|
707
|
-
return `${prefix}${result}`;
|
|
729
|
+
return `${format(prefix, "marker_overflow_left")}${result}`;
|
|
708
730
|
}
|
|
709
731
|
if (endTruncated) {
|
|
710
|
-
return `${result}${suffix}`;
|
|
732
|
+
return `${result}${format(suffix, "marker_overflow_right")}`;
|
|
711
733
|
}
|
|
712
734
|
return result;
|
|
713
735
|
};
|
|
714
736
|
|
|
715
|
-
const
|
|
737
|
+
const fillLeft = (value, biggestValue, char = " ") => {
|
|
738
|
+
const width = String(value).length;
|
|
739
|
+
const biggestWidth = String(biggestValue).length;
|
|
740
|
+
let missingWidth = biggestWidth - width;
|
|
741
|
+
let padded = "";
|
|
742
|
+
while (missingWidth--) {
|
|
743
|
+
padded += char;
|
|
744
|
+
}
|
|
745
|
+
padded += value;
|
|
746
|
+
return padded;
|
|
747
|
+
};
|
|
716
748
|
|
|
717
|
-
|
|
749
|
+
const getPrecision = (number) => {
|
|
750
|
+
if (Math.floor(number) === number) return 0;
|
|
751
|
+
const [, decimals] = number.toString().split(".");
|
|
752
|
+
return decimals.length || 0;
|
|
753
|
+
};
|
|
718
754
|
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
755
|
+
const setRoundedPrecision = (
|
|
756
|
+
number,
|
|
757
|
+
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
758
|
+
) => {
|
|
759
|
+
return setDecimalsPrecision(number, {
|
|
760
|
+
decimals,
|
|
761
|
+
decimalsWhenSmall,
|
|
762
|
+
transform: Math.round,
|
|
763
|
+
});
|
|
724
764
|
};
|
|
725
765
|
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
766
|
+
const setPrecision = (
|
|
767
|
+
number,
|
|
768
|
+
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
769
|
+
) => {
|
|
770
|
+
return setDecimalsPrecision(number, {
|
|
771
|
+
decimals,
|
|
772
|
+
decimalsWhenSmall,
|
|
773
|
+
transform: parseInt,
|
|
774
|
+
});
|
|
731
775
|
};
|
|
732
776
|
|
|
733
|
-
const
|
|
777
|
+
const setDecimalsPrecision = (
|
|
778
|
+
number,
|
|
779
|
+
{
|
|
780
|
+
transform,
|
|
781
|
+
decimals, // max decimals for number in [-Infinity, -1[]1, Infinity]
|
|
782
|
+
decimalsWhenSmall, // max decimals for number in [-1,1]
|
|
783
|
+
} = {},
|
|
784
|
+
) => {
|
|
785
|
+
if (number === 0) {
|
|
786
|
+
return 0;
|
|
787
|
+
}
|
|
788
|
+
let numberCandidate = Math.abs(number);
|
|
789
|
+
if (numberCandidate < 1) {
|
|
790
|
+
const integerGoal = Math.pow(10, decimalsWhenSmall - 1);
|
|
791
|
+
let i = 1;
|
|
792
|
+
while (numberCandidate < integerGoal) {
|
|
793
|
+
numberCandidate *= 10;
|
|
794
|
+
i *= 10;
|
|
795
|
+
}
|
|
796
|
+
const asInteger = transform(numberCandidate);
|
|
797
|
+
const asFloat = asInteger / i;
|
|
798
|
+
return number < 0 ? -asFloat : asFloat;
|
|
799
|
+
}
|
|
800
|
+
const coef = Math.pow(10, decimals);
|
|
801
|
+
const numberMultiplied = (number + Number.EPSILON) * coef;
|
|
802
|
+
const asInteger = transform(numberMultiplied);
|
|
803
|
+
const asFloat = asInteger / coef;
|
|
804
|
+
return number < 0 ? -asFloat : asFloat;
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
// https://www.codingem.com/javascript-how-to-limit-decimal-places/
|
|
808
|
+
// export const roundNumber = (number, maxDecimals) => {
|
|
809
|
+
// const decimalsExp = Math.pow(10, maxDecimals)
|
|
810
|
+
// const numberRoundInt = Math.round(decimalsExp * (number + Number.EPSILON))
|
|
811
|
+
// const numberRoundFloat = numberRoundInt / decimalsExp
|
|
812
|
+
// return numberRoundFloat
|
|
813
|
+
// }
|
|
814
|
+
|
|
815
|
+
// export const setPrecision = (number, precision) => {
|
|
816
|
+
// if (Math.floor(number) === number) return number
|
|
817
|
+
// const [int, decimals] = number.toString().split(".")
|
|
818
|
+
// if (precision <= 0) return int
|
|
819
|
+
// const numberTruncated = `${int}.${decimals.slice(0, precision)}`
|
|
820
|
+
// return numberTruncated
|
|
821
|
+
// }
|
|
822
|
+
|
|
823
|
+
const unitShort = {
|
|
824
|
+
year: "y",
|
|
825
|
+
month: "m",
|
|
826
|
+
week: "w",
|
|
827
|
+
day: "d",
|
|
828
|
+
hour: "h",
|
|
829
|
+
minute: "m",
|
|
830
|
+
second: "s",
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
const inspectDuration = (
|
|
834
|
+
ms,
|
|
835
|
+
{ short, rounded = true, decimals } = {},
|
|
836
|
+
) => {
|
|
837
|
+
// ignore ms below meaningfulMs so that:
|
|
838
|
+
// inspectDuration(0.5) -> "0 second"
|
|
839
|
+
// inspectDuration(1.1) -> "0.001 second" (and not "0.0011 second")
|
|
840
|
+
// This tool is meant to be read by humans and it would be barely readable to see
|
|
841
|
+
// "0.0001 second" (stands for 0.1 millisecond)
|
|
842
|
+
// yes we could return "0.1 millisecond" but we choosed consistency over precision
|
|
843
|
+
// so that the prefered unit is "second" (and does not become millisecond when ms is super small)
|
|
844
|
+
if (ms < 1) {
|
|
845
|
+
return short ? "0s" : "0 second";
|
|
846
|
+
}
|
|
847
|
+
const { primary, remaining } = parseMs(ms);
|
|
848
|
+
if (!remaining) {
|
|
849
|
+
return inspectDurationUnit(primary, {
|
|
850
|
+
decimals:
|
|
851
|
+
decimals === undefined ? (primary.name === "second" ? 1 : 0) : decimals,
|
|
852
|
+
short,
|
|
853
|
+
rounded,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
return `${inspectDurationUnit(primary, {
|
|
857
|
+
decimals: decimals === undefined ? 0 : decimals,
|
|
858
|
+
short,
|
|
859
|
+
rounded,
|
|
860
|
+
})} and ${inspectDurationUnit(remaining, {
|
|
861
|
+
decimals: decimals === undefined ? 0 : decimals,
|
|
862
|
+
short,
|
|
863
|
+
rounded,
|
|
864
|
+
})}`;
|
|
865
|
+
};
|
|
866
|
+
const inspectDurationUnit = (unit, { decimals, short, rounded }) => {
|
|
867
|
+
const count = rounded
|
|
868
|
+
? setRoundedPrecision(unit.count, { decimals })
|
|
869
|
+
: setPrecision(unit.count, { decimals });
|
|
870
|
+
let name = unit.name;
|
|
871
|
+
if (short) {
|
|
872
|
+
name = unitShort[name];
|
|
873
|
+
return `${count}${name}`;
|
|
874
|
+
}
|
|
875
|
+
if (count <= 1) {
|
|
876
|
+
return `${count} ${name}`;
|
|
877
|
+
}
|
|
878
|
+
return `${count} ${name}s`;
|
|
879
|
+
};
|
|
880
|
+
const MS_PER_UNITS = {
|
|
881
|
+
year: 31_557_600_000,
|
|
882
|
+
month: 2_629_000_000,
|
|
883
|
+
week: 604_800_000,
|
|
884
|
+
day: 86_400_000,
|
|
885
|
+
hour: 3_600_000,
|
|
886
|
+
minute: 60_000,
|
|
887
|
+
second: 1000,
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
const parseMs = (ms) => {
|
|
891
|
+
const unitNames = Object.keys(MS_PER_UNITS);
|
|
892
|
+
const smallestUnitName = unitNames[unitNames.length - 1];
|
|
893
|
+
let firstUnitName = smallestUnitName;
|
|
894
|
+
let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
|
|
895
|
+
const firstUnitIndex = unitNames.findIndex((unitName) => {
|
|
896
|
+
if (unitName === smallestUnitName) {
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
899
|
+
const msPerUnit = MS_PER_UNITS[unitName];
|
|
900
|
+
const unitCount = Math.floor(ms / msPerUnit);
|
|
901
|
+
if (unitCount) {
|
|
902
|
+
firstUnitName = unitName;
|
|
903
|
+
firstUnitCount = unitCount;
|
|
904
|
+
return true;
|
|
905
|
+
}
|
|
906
|
+
return false;
|
|
907
|
+
});
|
|
908
|
+
if (firstUnitName === smallestUnitName) {
|
|
909
|
+
return {
|
|
910
|
+
primary: {
|
|
911
|
+
name: firstUnitName,
|
|
912
|
+
count: firstUnitCount,
|
|
913
|
+
},
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
|
|
917
|
+
const remainingUnitName = unitNames[firstUnitIndex + 1];
|
|
918
|
+
const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
|
|
919
|
+
// - 1 year and 1 second is too much information
|
|
920
|
+
// so we don't check the remaining units
|
|
921
|
+
// - 1 year and 0.0001 week is awful
|
|
922
|
+
// hence the if below
|
|
923
|
+
if (Math.round(remainingUnitCount) < 1) {
|
|
924
|
+
return {
|
|
925
|
+
primary: {
|
|
926
|
+
name: firstUnitName,
|
|
927
|
+
count: firstUnitCount,
|
|
928
|
+
},
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
// - 1 year and 1 month is great
|
|
734
932
|
return {
|
|
735
|
-
|
|
736
|
-
|
|
933
|
+
primary: {
|
|
934
|
+
name: firstUnitName,
|
|
935
|
+
count: firstUnitCount,
|
|
936
|
+
},
|
|
937
|
+
remaining: {
|
|
938
|
+
name: remainingUnitName,
|
|
939
|
+
count: remainingUnitCount,
|
|
940
|
+
},
|
|
737
941
|
};
|
|
738
942
|
};
|
|
739
943
|
|
|
944
|
+
const inspectFileSize = (numberOfBytes, { decimals, short } = {}) => {
|
|
945
|
+
return inspectBytes(numberOfBytes, { decimals, short });
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
const inspectBytes = (
|
|
949
|
+
number,
|
|
950
|
+
{ fixedDecimals = false, decimals, short } = {},
|
|
951
|
+
) => {
|
|
952
|
+
if (number === 0) {
|
|
953
|
+
return `0 B`;
|
|
954
|
+
}
|
|
955
|
+
const exponent = Math.min(
|
|
956
|
+
Math.floor(Math.log10(number) / 3),
|
|
957
|
+
BYTE_UNITS.length - 1,
|
|
958
|
+
);
|
|
959
|
+
const unitNumber = number / Math.pow(1000, exponent);
|
|
960
|
+
const unitName = BYTE_UNITS[exponent];
|
|
961
|
+
if (decimals === undefined) {
|
|
962
|
+
if (unitNumber < 100) {
|
|
963
|
+
decimals = 1;
|
|
964
|
+
} else {
|
|
965
|
+
decimals = 0;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
const unitNumberRounded = setRoundedPrecision(unitNumber, {
|
|
969
|
+
decimals,
|
|
970
|
+
decimalsWhenSmall: 1,
|
|
971
|
+
});
|
|
972
|
+
const value = fixedDecimals
|
|
973
|
+
? unitNumberRounded.toFixed(decimals)
|
|
974
|
+
: unitNumberRounded;
|
|
975
|
+
if (short) {
|
|
976
|
+
return `${value}${unitName}`;
|
|
977
|
+
}
|
|
978
|
+
return `${value} ${unitName}`;
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
const BYTE_UNITS = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
982
|
+
|
|
983
|
+
const distributePercentages = (
|
|
984
|
+
namedNumbers,
|
|
985
|
+
{ maxPrecisionHint = 2 } = {},
|
|
986
|
+
) => {
|
|
987
|
+
const numberNames = Object.keys(namedNumbers);
|
|
988
|
+
if (numberNames.length === 0) {
|
|
989
|
+
return {};
|
|
990
|
+
}
|
|
991
|
+
if (numberNames.length === 1) {
|
|
992
|
+
const firstNumberName = numberNames[0];
|
|
993
|
+
return { [firstNumberName]: "100 %" };
|
|
994
|
+
}
|
|
995
|
+
const numbers = numberNames.map((name) => namedNumbers[name]);
|
|
996
|
+
const total = numbers.reduce((sum, value) => sum + value, 0);
|
|
997
|
+
const ratios = numbers.map((number) => number / total);
|
|
998
|
+
const percentages = {};
|
|
999
|
+
ratios.pop();
|
|
1000
|
+
ratios.forEach((ratio, index) => {
|
|
1001
|
+
const percentage = ratio * 100;
|
|
1002
|
+
percentages[numberNames[index]] = percentage;
|
|
1003
|
+
});
|
|
1004
|
+
const lowestPercentage = (1 / Math.pow(10, maxPrecisionHint)) * 100;
|
|
1005
|
+
let precision = 0;
|
|
1006
|
+
Object.keys(percentages).forEach((name) => {
|
|
1007
|
+
const percentage = percentages[name];
|
|
1008
|
+
if (percentage < lowestPercentage) {
|
|
1009
|
+
// check the amout of meaningful decimals
|
|
1010
|
+
// and that what we will use
|
|
1011
|
+
const percentageRounded = setRoundedPrecision(percentage);
|
|
1012
|
+
const percentagePrecision = getPrecision(percentageRounded);
|
|
1013
|
+
if (percentagePrecision > precision) {
|
|
1014
|
+
precision = percentagePrecision;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
let remainingPercentage = 100;
|
|
1019
|
+
|
|
1020
|
+
Object.keys(percentages).forEach((name) => {
|
|
1021
|
+
const percentage = percentages[name];
|
|
1022
|
+
const percentageAllocated = setRoundedPrecision(percentage, {
|
|
1023
|
+
decimals: precision,
|
|
1024
|
+
});
|
|
1025
|
+
remainingPercentage -= percentageAllocated;
|
|
1026
|
+
percentages[name] = percentageAllocated;
|
|
1027
|
+
});
|
|
1028
|
+
const lastName = numberNames[numberNames.length - 1];
|
|
1029
|
+
percentages[lastName] = setRoundedPrecision(remainingPercentage, {
|
|
1030
|
+
decimals: precision,
|
|
1031
|
+
});
|
|
1032
|
+
return percentages;
|
|
1033
|
+
};
|
|
1034
|
+
|
|
1035
|
+
// consider switching to https://babeljs.io/docs/en/babel-code-frame
|
|
1036
|
+
// https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/css-syntax-error.js#L43
|
|
1037
|
+
// https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/terminal-highlight.js#L50
|
|
1038
|
+
// https://github.com/babel/babel/blob/eea156b2cb8deecfcf82d52aa1b71ba4995c7d68/packages/babel-code-frame/src/index.js#L1
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
const stringifyUrlSite = (
|
|
1042
|
+
{ url, line, column, content },
|
|
1043
|
+
{ showCodeFrame = true, ...params } = {},
|
|
1044
|
+
) => {
|
|
1045
|
+
let string = url;
|
|
1046
|
+
|
|
1047
|
+
if (typeof line === "number") {
|
|
1048
|
+
string += `:${line}`;
|
|
1049
|
+
if (typeof column === "number") {
|
|
1050
|
+
string += `:${column}`;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
if (!showCodeFrame || typeof line !== "number" || !content) {
|
|
1055
|
+
return string;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
const sourceLoc = inspectFileContent({
|
|
1059
|
+
content,
|
|
1060
|
+
line,
|
|
1061
|
+
column,
|
|
1062
|
+
params,
|
|
1063
|
+
});
|
|
1064
|
+
return `${string}
|
|
1065
|
+
${sourceLoc}`;
|
|
1066
|
+
};
|
|
1067
|
+
|
|
740
1068
|
const urlToScheme$1 = (url) => {
|
|
741
1069
|
const urlString = String(url);
|
|
742
1070
|
const colonIndex = urlString.indexOf(":");
|
|
@@ -1761,6 +2089,18 @@ const createOperation = () => {
|
|
|
1761
2089
|
});
|
|
1762
2090
|
};
|
|
1763
2091
|
|
|
2092
|
+
const wait = (ms) => {
|
|
2093
|
+
return new Promise((resolve) => {
|
|
2094
|
+
const timeoutId = setTimeout(() => {
|
|
2095
|
+
removeAbortCallback();
|
|
2096
|
+
resolve();
|
|
2097
|
+
}, ms);
|
|
2098
|
+
const removeAbortCallback = addAbortCallback(() => {
|
|
2099
|
+
clearTimeout(timeoutId);
|
|
2100
|
+
});
|
|
2101
|
+
});
|
|
2102
|
+
};
|
|
2103
|
+
|
|
1764
2104
|
const withSignal = async (asyncCallback) => {
|
|
1765
2105
|
const abortController = new AbortController();
|
|
1766
2106
|
const signal = abortController.signal;
|
|
@@ -1797,6 +2137,12 @@ const createOperation = () => {
|
|
|
1797
2137
|
}
|
|
1798
2138
|
};
|
|
1799
2139
|
|
|
2140
|
+
const fork = () => {
|
|
2141
|
+
const forkedOperation = createOperation();
|
|
2142
|
+
forkedOperation.addAbortSignal(operationSignal);
|
|
2143
|
+
return forkedOperation;
|
|
2144
|
+
};
|
|
2145
|
+
|
|
1800
2146
|
return {
|
|
1801
2147
|
// We could almost hide the operationSignal
|
|
1802
2148
|
// But it can be handy for 2 things:
|
|
@@ -1808,7 +2154,9 @@ const createOperation = () => {
|
|
|
1808
2154
|
addAbortCallback,
|
|
1809
2155
|
addAbortSignal,
|
|
1810
2156
|
addAbortSource,
|
|
2157
|
+
fork,
|
|
1811
2158
|
timeout,
|
|
2159
|
+
wait,
|
|
1812
2160
|
withSignal,
|
|
1813
2161
|
withSignalSync,
|
|
1814
2162
|
addEndCallback,
|
|
@@ -2389,65 +2737,258 @@ const removeDirectory = async (
|
|
|
2389
2737
|
);
|
|
2390
2738
|
};
|
|
2391
2739
|
|
|
2392
|
-
const visitFile = async (fileUrl) => {
|
|
2393
|
-
await removeNonDirectory(fileUrl, { maxRetries, retryDelay });
|
|
2394
|
-
};
|
|
2740
|
+
const visitFile = async (fileUrl) => {
|
|
2741
|
+
await removeNonDirectory(fileUrl, { maxRetries, retryDelay });
|
|
2742
|
+
};
|
|
2743
|
+
|
|
2744
|
+
const visitSymbolicLink = async (symbolicLinkUrl) => {
|
|
2745
|
+
await removeNonDirectory(symbolicLinkUrl, { maxRetries, retryDelay });
|
|
2746
|
+
};
|
|
2747
|
+
|
|
2748
|
+
try {
|
|
2749
|
+
if (onlyContent) {
|
|
2750
|
+
await removeDirectoryContent(rootDirectoryUrl);
|
|
2751
|
+
} else {
|
|
2752
|
+
await visitDirectory(rootDirectoryUrl);
|
|
2753
|
+
}
|
|
2754
|
+
} finally {
|
|
2755
|
+
await removeDirectoryOperation.end();
|
|
2756
|
+
}
|
|
2757
|
+
};
|
|
2758
|
+
|
|
2759
|
+
const removeDirectoryNaive = (
|
|
2760
|
+
directoryPath,
|
|
2761
|
+
{ handleNotEmptyError = null, handlePermissionError = null } = {},
|
|
2762
|
+
) => {
|
|
2763
|
+
return new Promise((resolve, reject) => {
|
|
2764
|
+
rmdir(directoryPath, (error, lstatObject) => {
|
|
2765
|
+
if (error) {
|
|
2766
|
+
if (handlePermissionError && error.code === "EPERM") {
|
|
2767
|
+
resolve(handlePermissionError(error));
|
|
2768
|
+
} else if (error.code === "ENOENT") {
|
|
2769
|
+
resolve();
|
|
2770
|
+
} else if (
|
|
2771
|
+
handleNotEmptyError &&
|
|
2772
|
+
// linux os
|
|
2773
|
+
(error.code === "ENOTEMPTY" ||
|
|
2774
|
+
// SunOS
|
|
2775
|
+
error.code === "EEXIST")
|
|
2776
|
+
) {
|
|
2777
|
+
resolve(handleNotEmptyError(error));
|
|
2778
|
+
} else {
|
|
2779
|
+
reject(error);
|
|
2780
|
+
}
|
|
2781
|
+
} else {
|
|
2782
|
+
resolve(lstatObject);
|
|
2783
|
+
}
|
|
2784
|
+
});
|
|
2785
|
+
});
|
|
2786
|
+
};
|
|
2787
|
+
|
|
2788
|
+
process.platform === "win32";
|
|
2789
|
+
|
|
2790
|
+
/*
|
|
2791
|
+
* - stats object documentation on Node.js
|
|
2792
|
+
* https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
|
|
2793
|
+
*/
|
|
2794
|
+
|
|
2795
|
+
|
|
2796
|
+
process.platform === "win32";
|
|
2797
|
+
|
|
2798
|
+
process.platform === "win32";
|
|
2799
|
+
|
|
2800
|
+
const mediaTypeInfos = {
|
|
2801
|
+
"application/json": {
|
|
2802
|
+
extensions: ["json", "map"],
|
|
2803
|
+
isTextual: true,
|
|
2804
|
+
},
|
|
2805
|
+
"application/importmap+json": {
|
|
2806
|
+
extensions: ["importmap"],
|
|
2807
|
+
isTextual: true,
|
|
2808
|
+
},
|
|
2809
|
+
"application/manifest+json": {
|
|
2810
|
+
extensions: ["webmanifest"],
|
|
2811
|
+
isTextual: true,
|
|
2812
|
+
},
|
|
2813
|
+
"application/octet-stream": {},
|
|
2814
|
+
"application/pdf": {
|
|
2815
|
+
extensions: ["pdf"],
|
|
2816
|
+
},
|
|
2817
|
+
"application/xml": {
|
|
2818
|
+
extensions: ["xml"],
|
|
2819
|
+
isTextual: true,
|
|
2820
|
+
},
|
|
2821
|
+
"application/x-gzip": {
|
|
2822
|
+
extensions: ["gz"],
|
|
2823
|
+
},
|
|
2824
|
+
"application/wasm": {
|
|
2825
|
+
extensions: ["wasm"],
|
|
2826
|
+
},
|
|
2827
|
+
"application/zip": {
|
|
2828
|
+
extensions: ["zip"],
|
|
2829
|
+
},
|
|
2830
|
+
"audio/basic": {
|
|
2831
|
+
extensions: ["au", "snd"],
|
|
2832
|
+
},
|
|
2833
|
+
"audio/mpeg": {
|
|
2834
|
+
extensions: ["mpga", "mp2", "mp2a", "mp3", "m2a", "m3a"],
|
|
2835
|
+
},
|
|
2836
|
+
"audio/midi": {
|
|
2837
|
+
extensions: ["midi", "mid", "kar", "rmi"],
|
|
2838
|
+
},
|
|
2839
|
+
"audio/mp4": {
|
|
2840
|
+
extensions: ["m4a", "mp4a"],
|
|
2841
|
+
},
|
|
2842
|
+
"audio/ogg": {
|
|
2843
|
+
extensions: ["oga", "ogg", "spx"],
|
|
2844
|
+
},
|
|
2845
|
+
"audio/webm": {
|
|
2846
|
+
extensions: ["weba"],
|
|
2847
|
+
},
|
|
2848
|
+
"audio/x-wav": {
|
|
2849
|
+
extensions: ["wav"],
|
|
2850
|
+
},
|
|
2851
|
+
"font/ttf": {
|
|
2852
|
+
extensions: ["ttf"],
|
|
2853
|
+
},
|
|
2854
|
+
"font/woff": {
|
|
2855
|
+
extensions: ["woff"],
|
|
2856
|
+
},
|
|
2857
|
+
"font/woff2": {
|
|
2858
|
+
extensions: ["woff2"],
|
|
2859
|
+
},
|
|
2860
|
+
"image/png": {
|
|
2861
|
+
extensions: ["png"],
|
|
2862
|
+
},
|
|
2863
|
+
"image/gif": {
|
|
2864
|
+
extensions: ["gif"],
|
|
2865
|
+
},
|
|
2866
|
+
"image/jpeg": {
|
|
2867
|
+
extensions: ["jpg"],
|
|
2868
|
+
},
|
|
2869
|
+
"image/svg+xml": {
|
|
2870
|
+
extensions: ["svg", "svgz"],
|
|
2871
|
+
isTextual: true,
|
|
2872
|
+
},
|
|
2873
|
+
"text/plain": {
|
|
2874
|
+
extensions: ["txt"],
|
|
2875
|
+
isTextual: true,
|
|
2876
|
+
},
|
|
2877
|
+
"text/html": {
|
|
2878
|
+
extensions: ["html"],
|
|
2879
|
+
isTextual: true,
|
|
2880
|
+
},
|
|
2881
|
+
"text/css": {
|
|
2882
|
+
extensions: ["css"],
|
|
2883
|
+
isTextual: true,
|
|
2884
|
+
},
|
|
2885
|
+
"text/javascript": {
|
|
2886
|
+
extensions: ["js", "cjs", "mjs", "ts", "jsx", "tsx"],
|
|
2887
|
+
isTextual: true,
|
|
2888
|
+
},
|
|
2889
|
+
"text/x-sass": {
|
|
2890
|
+
extensions: ["sass"],
|
|
2891
|
+
isTextual: true,
|
|
2892
|
+
},
|
|
2893
|
+
"text/x-scss": {
|
|
2894
|
+
extensions: ["scss"],
|
|
2895
|
+
isTextual: true,
|
|
2896
|
+
},
|
|
2897
|
+
"text/cache-manifest": {
|
|
2898
|
+
extensions: ["appcache"],
|
|
2899
|
+
},
|
|
2900
|
+
"video/mp4": {
|
|
2901
|
+
extensions: ["mp4", "mp4v", "mpg4"],
|
|
2902
|
+
},
|
|
2903
|
+
"video/mpeg": {
|
|
2904
|
+
extensions: ["mpeg", "mpg", "mpe", "m1v", "m2v"],
|
|
2905
|
+
},
|
|
2906
|
+
"video/ogg": {
|
|
2907
|
+
extensions: ["ogv"],
|
|
2908
|
+
},
|
|
2909
|
+
"video/webm": {
|
|
2910
|
+
extensions: ["webm"],
|
|
2911
|
+
},
|
|
2912
|
+
};
|
|
2913
|
+
|
|
2914
|
+
const CONTENT_TYPE = {
|
|
2915
|
+
parse: (string) => {
|
|
2916
|
+
const [mediaType, charset] = string.split(";");
|
|
2917
|
+
return { mediaType: normalizeMediaType(mediaType), charset };
|
|
2918
|
+
},
|
|
2395
2919
|
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2920
|
+
stringify: ({ mediaType, charset }) => {
|
|
2921
|
+
if (charset) {
|
|
2922
|
+
return `${mediaType};${charset}`;
|
|
2923
|
+
}
|
|
2924
|
+
return mediaType;
|
|
2925
|
+
},
|
|
2399
2926
|
|
|
2400
|
-
|
|
2401
|
-
if (
|
|
2402
|
-
|
|
2403
|
-
} else {
|
|
2404
|
-
await visitDirectory(rootDirectoryUrl);
|
|
2927
|
+
asMediaType: (value) => {
|
|
2928
|
+
if (typeof value === "string") {
|
|
2929
|
+
return CONTENT_TYPE.parse(value).mediaType;
|
|
2405
2930
|
}
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2931
|
+
if (typeof value === "object") {
|
|
2932
|
+
return value.mediaType;
|
|
2933
|
+
}
|
|
2934
|
+
return null;
|
|
2935
|
+
},
|
|
2410
2936
|
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
if (handlePermissionError && error.code === "EPERM") {
|
|
2419
|
-
resolve(handlePermissionError(error));
|
|
2420
|
-
} else if (error.code === "ENOENT") {
|
|
2421
|
-
resolve();
|
|
2422
|
-
} else if (
|
|
2423
|
-
handleNotEmptyError &&
|
|
2424
|
-
// linux os
|
|
2425
|
-
(error.code === "ENOTEMPTY" ||
|
|
2426
|
-
// SunOS
|
|
2427
|
-
error.code === "EEXIST")
|
|
2428
|
-
) {
|
|
2429
|
-
resolve(handleNotEmptyError(error));
|
|
2430
|
-
} else {
|
|
2431
|
-
reject(error);
|
|
2432
|
-
}
|
|
2433
|
-
} else {
|
|
2434
|
-
resolve(lstatObject);
|
|
2435
|
-
}
|
|
2436
|
-
});
|
|
2437
|
-
});
|
|
2438
|
-
};
|
|
2937
|
+
isJson: (value) => {
|
|
2938
|
+
const mediaType = CONTENT_TYPE.asMediaType(value);
|
|
2939
|
+
return (
|
|
2940
|
+
mediaType === "application/json" ||
|
|
2941
|
+
/^application\/\w+\+json$/.test(mediaType)
|
|
2942
|
+
);
|
|
2943
|
+
},
|
|
2439
2944
|
|
|
2440
|
-
|
|
2945
|
+
isTextual: (value) => {
|
|
2946
|
+
const mediaType = CONTENT_TYPE.asMediaType(value);
|
|
2947
|
+
if (mediaType.startsWith("text/")) {
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
const mediaTypeInfo = mediaTypeInfos[mediaType];
|
|
2951
|
+
if (mediaTypeInfo && mediaTypeInfo.isTextual) {
|
|
2952
|
+
return true;
|
|
2953
|
+
}
|
|
2954
|
+
// catch things like application/manifest+json, application/importmap+json
|
|
2955
|
+
if (/^application\/\w+\+json$/.test(mediaType)) {
|
|
2956
|
+
return true;
|
|
2957
|
+
}
|
|
2958
|
+
return false;
|
|
2959
|
+
},
|
|
2441
2960
|
|
|
2442
|
-
|
|
2443
|
-
* - stats object documentation on Node.js
|
|
2444
|
-
* https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
|
|
2445
|
-
*/
|
|
2961
|
+
isBinary: (value) => !CONTENT_TYPE.isTextual(value),
|
|
2446
2962
|
|
|
2963
|
+
asFileExtension: (value) => {
|
|
2964
|
+
const mediaType = CONTENT_TYPE.asMediaType(value);
|
|
2965
|
+
const mediaTypeInfo = mediaTypeInfos[mediaType];
|
|
2966
|
+
return mediaTypeInfo ? `.${mediaTypeInfo.extensions[0]}` : "";
|
|
2967
|
+
},
|
|
2447
2968
|
|
|
2448
|
-
|
|
2969
|
+
fromUrlExtension: (url) => {
|
|
2970
|
+
const { pathname } = new URL(url);
|
|
2971
|
+
const extensionWithDot = extname(pathname);
|
|
2972
|
+
if (!extensionWithDot || extensionWithDot === ".") {
|
|
2973
|
+
return "application/octet-stream";
|
|
2974
|
+
}
|
|
2975
|
+
const extension = extensionWithDot.slice(1);
|
|
2976
|
+
const mediaTypeFound = Object.keys(mediaTypeInfos).find((mediaType) => {
|
|
2977
|
+
const mediaTypeInfo = mediaTypeInfos[mediaType];
|
|
2978
|
+
return (
|
|
2979
|
+
mediaTypeInfo.extensions && mediaTypeInfo.extensions.includes(extension)
|
|
2980
|
+
);
|
|
2981
|
+
});
|
|
2982
|
+
return mediaTypeFound || "application/octet-stream";
|
|
2983
|
+
},
|
|
2984
|
+
};
|
|
2449
2985
|
|
|
2450
|
-
|
|
2986
|
+
const normalizeMediaType = (value) => {
|
|
2987
|
+
if (value === "application/javascript") {
|
|
2988
|
+
return "text/javascript";
|
|
2989
|
+
}
|
|
2990
|
+
return value;
|
|
2991
|
+
};
|
|
2451
2992
|
|
|
2452
2993
|
const ensureEmptyDirectory = async (source) => {
|
|
2453
2994
|
const stats = await readEntryStat(source, {
|
|
@@ -3216,355 +3757,122 @@ function createSupportsColor(stream, options = {}) {
|
|
|
3216
3757
|
});
|
|
3217
3758
|
|
|
3218
3759
|
const processSupportsBasicColor = createSupportsColor(process.stdout).hasBasic;
|
|
3219
|
-
let canUseColors = processSupportsBasicColor;
|
|
3220
|
-
|
|
3221
|
-
// GitHub workflow does support ANSI but "supports-color" returns false
|
|
3222
|
-
// because stream.isTTY returns false, see https://github.com/actions/runner/issues/241
|
|
3223
|
-
if (process.env.GITHUB_WORKFLOW) {
|
|
3224
|
-
// Check on FORCE_COLOR is to ensure it is prio over GitHub workflow check
|
|
3225
|
-
if (process.env.FORCE_COLOR !== "false") {
|
|
3226
|
-
// in unit test we use process.env.FORCE_COLOR = 'false' to fake
|
|
3227
|
-
// that colors are not supported. Let it have priority
|
|
3228
|
-
canUseColors = true;
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
|
|
3232
3760
|
// https://github.com/Marak/colors.js/blob/master/lib/styles.js
|
|
3233
|
-
|
|
3234
|
-
const GREEN = "\x1b[32m";
|
|
3235
|
-
const YELLOW = "\x1b[33m";
|
|
3236
|
-
const BLUE = "\x1b[34m";
|
|
3237
|
-
const MAGENTA = "\x1b[35m";
|
|
3238
|
-
const GREY = "\x1b[90m";
|
|
3761
|
+
// https://stackoverflow.com/a/75985833/2634179
|
|
3239
3762
|
const RESET = "\x1b[0m";
|
|
3240
3763
|
|
|
3241
|
-
const setANSIColor = canUseColors
|
|
3242
|
-
? (text, ANSI_COLOR) => `${ANSI_COLOR}${text}${RESET}`
|
|
3243
|
-
: (text) => text;
|
|
3244
|
-
|
|
3245
3764
|
const ANSI = {
|
|
3246
|
-
supported:
|
|
3247
|
-
|
|
3248
|
-
RED,
|
|
3249
|
-
GREEN,
|
|
3250
|
-
YELLOW,
|
|
3251
|
-
BLUE,
|
|
3252
|
-
MAGENTA,
|
|
3253
|
-
GREY,
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
};
|
|
3258
|
-
|
|
3259
|
-
function isUnicodeSupported() {
|
|
3260
|
-
if (process$1.platform !== 'win32') {
|
|
3261
|
-
return process$1.env.TERM !== 'linux'; // Linux console (kernel)
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3264
|
-
return Boolean(process$1.env.WT_SESSION) // Windows Terminal
|
|
3265
|
-
|| Boolean(process$1.env.TERMINUS_SUBLIME) // Terminus (<0.2.27)
|
|
3266
|
-
|| process$1.env.ConEmuTask === '{cmd::Cmder}' // ConEmu and cmder
|
|
3267
|
-
|| process$1.env.TERM_PROGRAM === 'Terminus-Sublime'
|
|
3268
|
-
|| process$1.env.TERM_PROGRAM === 'vscode'
|
|
3269
|
-
|| process$1.env.TERM === 'xterm-256color'
|
|
3270
|
-
|| process$1.env.TERM === 'alacritty'
|
|
3271
|
-
|| process$1.env.TERMINAL_EMULATOR === 'JetBrains-JediTerm';
|
|
3272
|
-
}
|
|
3273
|
-
|
|
3274
|
-
// see also https://github.com/sindresorhus/figures
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
const canUseUnicode = isUnicodeSupported();
|
|
3278
|
-
|
|
3279
|
-
const COMMAND_RAW = canUseUnicode ? `❯` : `>`;
|
|
3280
|
-
const OK_RAW = canUseUnicode ? `✔` : `√`;
|
|
3281
|
-
const FAILURE_RAW = canUseUnicode ? `✖` : `×`;
|
|
3282
|
-
const DEBUG_RAW = canUseUnicode ? `◆` : `♦`;
|
|
3283
|
-
const INFO_RAW = canUseUnicode ? `ℹ` : `i`;
|
|
3284
|
-
const WARNING_RAW = canUseUnicode ? `⚠` : `‼`;
|
|
3285
|
-
const CIRCLE_CROSS_RAW = canUseUnicode ? `ⓧ` : `(×)`;
|
|
3286
|
-
|
|
3287
|
-
const COMMAND = ANSI.color(COMMAND_RAW, ANSI.GREY); // ANSI_MAGENTA)
|
|
3288
|
-
const OK = ANSI.color(OK_RAW, ANSI.GREEN);
|
|
3289
|
-
const FAILURE = ANSI.color(FAILURE_RAW, ANSI.RED);
|
|
3290
|
-
const DEBUG = ANSI.color(DEBUG_RAW, ANSI.GREY);
|
|
3291
|
-
const INFO = ANSI.color(INFO_RAW, ANSI.BLUE);
|
|
3292
|
-
const WARNING = ANSI.color(WARNING_RAW, ANSI.YELLOW);
|
|
3293
|
-
const CIRCLE_CROSS = ANSI.color(CIRCLE_CROSS_RAW, ANSI.RED);
|
|
3294
|
-
|
|
3295
|
-
const UNICODE = {
|
|
3296
|
-
COMMAND,
|
|
3297
|
-
OK,
|
|
3298
|
-
FAILURE,
|
|
3299
|
-
DEBUG,
|
|
3300
|
-
INFO,
|
|
3301
|
-
WARNING,
|
|
3302
|
-
CIRCLE_CROSS,
|
|
3303
|
-
|
|
3304
|
-
COMMAND_RAW,
|
|
3305
|
-
OK_RAW,
|
|
3306
|
-
FAILURE_RAW,
|
|
3307
|
-
DEBUG_RAW,
|
|
3308
|
-
INFO_RAW,
|
|
3309
|
-
WARNING_RAW,
|
|
3310
|
-
CIRCLE_CROSS_RAW,
|
|
3311
|
-
|
|
3312
|
-
supported: canUseUnicode,
|
|
3313
|
-
};
|
|
3314
|
-
|
|
3315
|
-
const createDetailedMessage$1 = (message, details = {}) => {
|
|
3316
|
-
let string = `${message}`;
|
|
3317
|
-
|
|
3318
|
-
Object.keys(details).forEach((key) => {
|
|
3319
|
-
const value = details[key];
|
|
3320
|
-
string += `
|
|
3321
|
-
--- ${key} ---
|
|
3322
|
-
${
|
|
3323
|
-
Array.isArray(value)
|
|
3324
|
-
? value.join(`
|
|
3325
|
-
`)
|
|
3326
|
-
: value
|
|
3327
|
-
}`;
|
|
3328
|
-
});
|
|
3329
|
-
|
|
3330
|
-
return string;
|
|
3331
|
-
};
|
|
3332
|
-
|
|
3333
|
-
const getPrecision = (number) => {
|
|
3334
|
-
if (Math.floor(number) === number) return 0;
|
|
3335
|
-
const [, decimals] = number.toString().split(".");
|
|
3336
|
-
return decimals.length || 0;
|
|
3337
|
-
};
|
|
3338
|
-
|
|
3339
|
-
const setRoundedPrecision = (
|
|
3340
|
-
number,
|
|
3341
|
-
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
3342
|
-
) => {
|
|
3343
|
-
return setDecimalsPrecision(number, {
|
|
3344
|
-
decimals,
|
|
3345
|
-
decimalsWhenSmall,
|
|
3346
|
-
transform: Math.round,
|
|
3347
|
-
});
|
|
3348
|
-
};
|
|
3765
|
+
supported: processSupportsBasicColor,
|
|
3766
|
+
|
|
3767
|
+
RED: "\x1b[31m",
|
|
3768
|
+
GREEN: "\x1b[32m",
|
|
3769
|
+
YELLOW: "\x1b[33m",
|
|
3770
|
+
BLUE: "\x1b[34m",
|
|
3771
|
+
MAGENTA: "\x1b[35m",
|
|
3772
|
+
GREY: "\x1b[90m",
|
|
3773
|
+
color: (text, ANSI_COLOR) => {
|
|
3774
|
+
return ANSI.supported ? `${ANSI_COLOR}${text}${RESET}` : text;
|
|
3775
|
+
},
|
|
3349
3776
|
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
decimals, // max decimals for number in [-Infinity, -1[]1, Infinity]
|
|
3355
|
-
decimalsWhenSmall, // max decimals for number in [-1,1]
|
|
3356
|
-
} = {},
|
|
3357
|
-
) => {
|
|
3358
|
-
if (number === 0) {
|
|
3359
|
-
return 0;
|
|
3360
|
-
}
|
|
3361
|
-
let numberCandidate = Math.abs(number);
|
|
3362
|
-
if (numberCandidate < 1) {
|
|
3363
|
-
const integerGoal = Math.pow(10, decimalsWhenSmall - 1);
|
|
3364
|
-
let i = 1;
|
|
3365
|
-
while (numberCandidate < integerGoal) {
|
|
3366
|
-
numberCandidate *= 10;
|
|
3367
|
-
i *= 10;
|
|
3368
|
-
}
|
|
3369
|
-
const asInteger = transform(numberCandidate);
|
|
3370
|
-
const asFloat = asInteger / i;
|
|
3371
|
-
return number < 0 ? -asFloat : asFloat;
|
|
3372
|
-
}
|
|
3373
|
-
const coef = Math.pow(10, decimals);
|
|
3374
|
-
const numberMultiplied = (number + Number.EPSILON) * coef;
|
|
3375
|
-
const asInteger = transform(numberMultiplied);
|
|
3376
|
-
const asFloat = asInteger / coef;
|
|
3377
|
-
return number < 0 ? -asFloat : asFloat;
|
|
3777
|
+
BOLD: "\x1b[1m",
|
|
3778
|
+
effect: (text, ANSI_EFFECT) => {
|
|
3779
|
+
return ANSI.supported ? `${ANSI_EFFECT}${text}${RESET}` : text;
|
|
3780
|
+
},
|
|
3378
3781
|
};
|
|
3379
3782
|
|
|
3380
|
-
//
|
|
3381
|
-
//
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
//
|
|
3385
|
-
//
|
|
3386
|
-
//
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
// if (precision <= 0) return int
|
|
3392
|
-
// const numberTruncated = `${int}.${decimals.slice(0, precision)}`
|
|
3393
|
-
// return numberTruncated
|
|
3394
|
-
// }
|
|
3395
|
-
|
|
3396
|
-
const msAsDuration = (ms) => {
|
|
3397
|
-
// ignore ms below meaningfulMs so that:
|
|
3398
|
-
// msAsDuration(0.5) -> "0 second"
|
|
3399
|
-
// msAsDuration(1.1) -> "0.001 second" (and not "0.0011 second")
|
|
3400
|
-
// This tool is meant to be read by humans and it would be barely readable to see
|
|
3401
|
-
// "0.0001 second" (stands for 0.1 millisecond)
|
|
3402
|
-
// yes we could return "0.1 millisecond" but we choosed consistency over precision
|
|
3403
|
-
// so that the prefered unit is "second" (and does not become millisecond when ms is super small)
|
|
3404
|
-
if (ms < 1) {
|
|
3405
|
-
return "0 second";
|
|
3406
|
-
}
|
|
3407
|
-
const { primary, remaining } = parseMs(ms);
|
|
3408
|
-
if (!remaining) {
|
|
3409
|
-
return formatDurationUnit(primary, primary.name === "second" ? 1 : 0);
|
|
3410
|
-
}
|
|
3411
|
-
return `${formatDurationUnit(primary, 0)} and ${formatDurationUnit(
|
|
3412
|
-
remaining,
|
|
3413
|
-
0,
|
|
3414
|
-
)}`;
|
|
3415
|
-
};
|
|
3783
|
+
// GitHub workflow does support ANSI but "supports-color" returns false
|
|
3784
|
+
// because stream.isTTY returns false, see https://github.com/actions/runner/issues/241
|
|
3785
|
+
if (
|
|
3786
|
+
process.env.GITHUB_WORKFLOW &&
|
|
3787
|
+
// Check on FORCE_COLOR is to ensure it is prio over GitHub workflow check
|
|
3788
|
+
// in unit test we use process.env.FORCE_COLOR = 'false' to fake
|
|
3789
|
+
// that colors are not supported. Let it have priority
|
|
3790
|
+
process.env.FORCE_COLOR !== "false"
|
|
3791
|
+
) {
|
|
3792
|
+
ANSI.supported = true;
|
|
3793
|
+
}
|
|
3416
3794
|
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
if (count <= 1) {
|
|
3422
|
-
return `${count} ${unit.name}`;
|
|
3423
|
-
}
|
|
3424
|
-
return `${count} ${unit.name}s`;
|
|
3425
|
-
};
|
|
3795
|
+
function isUnicodeSupported() {
|
|
3796
|
+
if (process$1.platform !== 'win32') {
|
|
3797
|
+
return process$1.env.TERM !== 'linux'; // Linux console (kernel)
|
|
3798
|
+
}
|
|
3426
3799
|
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
}
|
|
3800
|
+
return Boolean(process$1.env.WT_SESSION) // Windows Terminal
|
|
3801
|
+
|| Boolean(process$1.env.TERMINUS_SUBLIME) // Terminus (<0.2.27)
|
|
3802
|
+
|| process$1.env.ConEmuTask === '{cmd::Cmder}' // ConEmu and cmder
|
|
3803
|
+
|| process$1.env.TERM_PROGRAM === 'Terminus-Sublime'
|
|
3804
|
+
|| process$1.env.TERM_PROGRAM === 'vscode'
|
|
3805
|
+
|| process$1.env.TERM === 'xterm-256color'
|
|
3806
|
+
|| process$1.env.TERM === 'alacritty'
|
|
3807
|
+
|| process$1.env.TERMINAL_EMULATOR === 'JetBrains-JediTerm';
|
|
3808
|
+
}
|
|
3436
3809
|
|
|
3437
|
-
|
|
3438
|
-
const unitNames = Object.keys(MS_PER_UNITS);
|
|
3439
|
-
const smallestUnitName = unitNames[unitNames.length - 1];
|
|
3440
|
-
let firstUnitName = smallestUnitName;
|
|
3441
|
-
let firstUnitCount = ms / MS_PER_UNITS[smallestUnitName];
|
|
3442
|
-
const firstUnitIndex = unitNames.findIndex((unitName) => {
|
|
3443
|
-
if (unitName === smallestUnitName) {
|
|
3444
|
-
return false;
|
|
3445
|
-
}
|
|
3446
|
-
const msPerUnit = MS_PER_UNITS[unitName];
|
|
3447
|
-
const unitCount = Math.floor(ms / msPerUnit);
|
|
3448
|
-
if (unitCount) {
|
|
3449
|
-
firstUnitName = unitName;
|
|
3450
|
-
firstUnitCount = unitCount;
|
|
3451
|
-
return true;
|
|
3452
|
-
}
|
|
3453
|
-
return false;
|
|
3454
|
-
});
|
|
3455
|
-
if (firstUnitName === smallestUnitName) {
|
|
3456
|
-
return {
|
|
3457
|
-
primary: {
|
|
3458
|
-
name: firstUnitName,
|
|
3459
|
-
count: firstUnitCount,
|
|
3460
|
-
},
|
|
3461
|
-
};
|
|
3462
|
-
}
|
|
3463
|
-
const remainingMs = ms - firstUnitCount * MS_PER_UNITS[firstUnitName];
|
|
3464
|
-
const remainingUnitName = unitNames[firstUnitIndex + 1];
|
|
3465
|
-
const remainingUnitCount = remainingMs / MS_PER_UNITS[remainingUnitName];
|
|
3466
|
-
// - 1 year and 1 second is too much information
|
|
3467
|
-
// so we don't check the remaining units
|
|
3468
|
-
// - 1 year and 0.0001 week is awful
|
|
3469
|
-
// hence the if below
|
|
3470
|
-
if (Math.round(remainingUnitCount) < 1) {
|
|
3471
|
-
return {
|
|
3472
|
-
primary: {
|
|
3473
|
-
name: firstUnitName,
|
|
3474
|
-
count: firstUnitCount,
|
|
3475
|
-
},
|
|
3476
|
-
};
|
|
3477
|
-
}
|
|
3478
|
-
// - 1 year and 1 month is great
|
|
3479
|
-
return {
|
|
3480
|
-
primary: {
|
|
3481
|
-
name: firstUnitName,
|
|
3482
|
-
count: firstUnitCount,
|
|
3483
|
-
},
|
|
3484
|
-
remaining: {
|
|
3485
|
-
name: remainingUnitName,
|
|
3486
|
-
count: remainingUnitCount,
|
|
3487
|
-
},
|
|
3488
|
-
};
|
|
3489
|
-
};
|
|
3810
|
+
// see also https://github.com/sindresorhus/figures
|
|
3490
3811
|
|
|
3491
|
-
const byteAsFileSize = (numberOfBytes) => {
|
|
3492
|
-
return formatBytes(numberOfBytes);
|
|
3493
|
-
};
|
|
3494
3812
|
|
|
3495
|
-
const
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
}
|
|
3510
|
-
|
|
3511
|
-
return
|
|
3512
|
-
}
|
|
3513
|
-
|
|
3813
|
+
const UNICODE = {
|
|
3814
|
+
supported: isUnicodeSupported(),
|
|
3815
|
+
|
|
3816
|
+
get COMMAND_RAW() {
|
|
3817
|
+
return UNICODE.supported ? `❯` : `>`;
|
|
3818
|
+
},
|
|
3819
|
+
get OK_RAW() {
|
|
3820
|
+
return UNICODE.supported ? `✔` : `√`;
|
|
3821
|
+
},
|
|
3822
|
+
get FAILURE_RAW() {
|
|
3823
|
+
return UNICODE.supported ? `✖` : `×`;
|
|
3824
|
+
},
|
|
3825
|
+
get DEBUG_RAW() {
|
|
3826
|
+
return UNICODE.supported ? `◆` : `♦`;
|
|
3827
|
+
},
|
|
3828
|
+
get INFO_RAW() {
|
|
3829
|
+
return UNICODE.supported ? `ℹ` : `i`;
|
|
3830
|
+
},
|
|
3831
|
+
get WARNING_RAW() {
|
|
3832
|
+
return UNICODE.supported ? `⚠` : `‼`;
|
|
3833
|
+
},
|
|
3834
|
+
get CIRCLE_CROSS_RAW() {
|
|
3835
|
+
return UNICODE.supported ? `ⓧ` : `(×)`;
|
|
3836
|
+
},
|
|
3837
|
+
get COMMAND() {
|
|
3838
|
+
return ANSI.color(UNICODE.COMMAND_RAW, ANSI.GREY); // ANSI_MAGENTA)
|
|
3839
|
+
},
|
|
3840
|
+
get OK() {
|
|
3841
|
+
return ANSI.color(UNICODE.OK_RAW, ANSI.GREEN);
|
|
3842
|
+
},
|
|
3843
|
+
get FAILURE() {
|
|
3844
|
+
return ANSI.color(UNICODE.FAILURE_RAW, ANSI.RED);
|
|
3845
|
+
},
|
|
3846
|
+
get DEBUG() {
|
|
3847
|
+
return ANSI.color(UNICODE.DEBUG_RAW, ANSI.GREY);
|
|
3848
|
+
},
|
|
3849
|
+
get INFO() {
|
|
3850
|
+
return ANSI.color(UNICODE.INFO_RAW, ANSI.BLUE);
|
|
3851
|
+
},
|
|
3852
|
+
get WARNING() {
|
|
3853
|
+
return ANSI.color(UNICODE.WARNING_RAW, ANSI.YELLOW);
|
|
3854
|
+
},
|
|
3855
|
+
get CIRCLE_CROSS() {
|
|
3856
|
+
return ANSI.color(UNICODE.CIRCLE_CROSS_RAW, ANSI.RED);
|
|
3857
|
+
},
|
|
3514
3858
|
};
|
|
3515
3859
|
|
|
3516
|
-
const
|
|
3860
|
+
const createDetailedMessage$1 = (message, details = {}) => {
|
|
3861
|
+
let string = `${message}`;
|
|
3517
3862
|
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
return { [firstNumberName]: "100 %" };
|
|
3529
|
-
}
|
|
3530
|
-
const numbers = numberNames.map((name) => namedNumbers[name]);
|
|
3531
|
-
const total = numbers.reduce((sum, value) => sum + value, 0);
|
|
3532
|
-
const ratios = numbers.map((number) => number / total);
|
|
3533
|
-
const percentages = {};
|
|
3534
|
-
ratios.pop();
|
|
3535
|
-
ratios.forEach((ratio, index) => {
|
|
3536
|
-
const percentage = ratio * 100;
|
|
3537
|
-
percentages[numberNames[index]] = percentage;
|
|
3538
|
-
});
|
|
3539
|
-
const lowestPercentage = (1 / Math.pow(10, maxPrecisionHint)) * 100;
|
|
3540
|
-
let precision = 0;
|
|
3541
|
-
Object.keys(percentages).forEach((name) => {
|
|
3542
|
-
const percentage = percentages[name];
|
|
3543
|
-
if (percentage < lowestPercentage) {
|
|
3544
|
-
// check the amout of meaningful decimals
|
|
3545
|
-
// and that what we will use
|
|
3546
|
-
const percentageRounded = setRoundedPrecision(percentage);
|
|
3547
|
-
const percentagePrecision = getPrecision(percentageRounded);
|
|
3548
|
-
if (percentagePrecision > precision) {
|
|
3549
|
-
precision = percentagePrecision;
|
|
3550
|
-
}
|
|
3551
|
-
}
|
|
3863
|
+
Object.keys(details).forEach((key) => {
|
|
3864
|
+
const value = details[key];
|
|
3865
|
+
string += `
|
|
3866
|
+
--- ${key} ---
|
|
3867
|
+
${
|
|
3868
|
+
Array.isArray(value)
|
|
3869
|
+
? value.join(`
|
|
3870
|
+
`)
|
|
3871
|
+
: value
|
|
3872
|
+
}`;
|
|
3552
3873
|
});
|
|
3553
|
-
let remainingPercentage = 100;
|
|
3554
3874
|
|
|
3555
|
-
|
|
3556
|
-
const percentage = percentages[name];
|
|
3557
|
-
const percentageAllocated = setRoundedPrecision(percentage, {
|
|
3558
|
-
decimals: precision,
|
|
3559
|
-
});
|
|
3560
|
-
remainingPercentage -= percentageAllocated;
|
|
3561
|
-
percentages[name] = percentageAllocated;
|
|
3562
|
-
});
|
|
3563
|
-
const lastName = numberNames[numberNames.length - 1];
|
|
3564
|
-
percentages[lastName] = setRoundedPrecision(remainingPercentage, {
|
|
3565
|
-
decimals: precision,
|
|
3566
|
-
});
|
|
3567
|
-
return percentages;
|
|
3875
|
+
return string;
|
|
3568
3876
|
};
|
|
3569
3877
|
|
|
3570
3878
|
const ESC = '\u001B[';
|
|
@@ -3732,58 +4040,28 @@ ansiEscapes.iTerm = {
|
|
|
3732
4040
|
},
|
|
3733
4041
|
};
|
|
3734
4042
|
|
|
3735
|
-
/*
|
|
3736
|
-
*
|
|
3737
|
-
*/
|
|
3738
|
-
|
|
3739
|
-
// maybe https://github.com/gajus/output-interceptor/tree/v3.0.0 ?
|
|
3740
|
-
// the problem with listening data on stdout
|
|
3741
|
-
// is that node.js will later throw error if stream gets closed
|
|
3742
|
-
// while something listening data on it
|
|
3743
|
-
const spyStreamOutput = (stream) => {
|
|
3744
|
-
const originalWrite = stream.write;
|
|
3745
|
-
|
|
3746
|
-
let output = "";
|
|
3747
|
-
let installed = true;
|
|
3748
|
-
|
|
3749
|
-
stream.write = function (...args /* chunk, encoding, callback */) {
|
|
3750
|
-
output += args;
|
|
3751
|
-
return originalWrite.call(stream, ...args);
|
|
3752
|
-
};
|
|
3753
|
-
|
|
3754
|
-
const uninstall = () => {
|
|
3755
|
-
if (!installed) {
|
|
3756
|
-
return;
|
|
3757
|
-
}
|
|
3758
|
-
stream.write = originalWrite;
|
|
3759
|
-
installed = false;
|
|
3760
|
-
};
|
|
3761
|
-
|
|
3762
|
-
return () => {
|
|
3763
|
-
uninstall();
|
|
3764
|
-
return output;
|
|
3765
|
-
};
|
|
3766
|
-
};
|
|
3767
|
-
|
|
3768
4043
|
/*
|
|
3769
4044
|
* see also https://github.com/vadimdemedes/ink
|
|
3770
4045
|
*/
|
|
3771
4046
|
|
|
3772
4047
|
|
|
3773
|
-
const
|
|
4048
|
+
const createDynamicLog = ({
|
|
3774
4049
|
stream = process.stdout,
|
|
3775
|
-
|
|
4050
|
+
clearTerminalAllowed,
|
|
4051
|
+
onVerticalOverflow = () => {},
|
|
4052
|
+
onWriteFromOutside = () => {},
|
|
3776
4053
|
} = {}) => {
|
|
3777
4054
|
const { columns = 80, rows = 24 } = stream;
|
|
3778
|
-
|
|
3779
|
-
const log = {
|
|
4055
|
+
const dynamicLog = {
|
|
3780
4056
|
destroyed: false,
|
|
3781
|
-
onVerticalOverflow
|
|
4057
|
+
onVerticalOverflow,
|
|
4058
|
+
onWriteFromOutside,
|
|
3782
4059
|
};
|
|
3783
4060
|
|
|
3784
4061
|
let lastOutput = "";
|
|
4062
|
+
let lastOutputFromOutside = "";
|
|
3785
4063
|
let clearAttemptResult;
|
|
3786
|
-
let
|
|
4064
|
+
let writing = false;
|
|
3787
4065
|
|
|
3788
4066
|
const getErasePreviousOutput = () => {
|
|
3789
4067
|
// nothing to clear
|
|
@@ -3796,19 +4074,27 @@ const createLog = ({
|
|
|
3796
4074
|
|
|
3797
4075
|
const logLines = lastOutput.split(/\r\n|\r|\n/);
|
|
3798
4076
|
let visualLineCount = 0;
|
|
3799
|
-
|
|
4077
|
+
for (const logLine of logLines) {
|
|
3800
4078
|
const width = stringWidth(logLine);
|
|
3801
|
-
|
|
3802
|
-
|
|
4079
|
+
if (width === 0) {
|
|
4080
|
+
visualLineCount++;
|
|
4081
|
+
} else {
|
|
4082
|
+
visualLineCount += Math.ceil(width / columns);
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
3803
4085
|
|
|
3804
4086
|
if (visualLineCount > rows) {
|
|
4087
|
+
if (clearTerminalAllowed) {
|
|
4088
|
+
clearAttemptResult = true;
|
|
4089
|
+
return ansiEscapes.clearTerminal;
|
|
4090
|
+
}
|
|
3805
4091
|
// the whole log cannot be cleared because it's vertically to long
|
|
3806
4092
|
// (longer than terminal height)
|
|
3807
4093
|
// readline.moveCursor cannot move cursor higher than screen height
|
|
3808
4094
|
// it means we would only clear the visible part of the log
|
|
3809
4095
|
// better keep the log untouched
|
|
3810
4096
|
clearAttemptResult = false;
|
|
3811
|
-
|
|
4097
|
+
dynamicLog.onVerticalOverflow();
|
|
3812
4098
|
return "";
|
|
3813
4099
|
}
|
|
3814
4100
|
|
|
@@ -3816,95 +4102,129 @@ const createLog = ({
|
|
|
3816
4102
|
return ansiEscapes.eraseLines(visualLineCount);
|
|
3817
4103
|
};
|
|
3818
4104
|
|
|
3819
|
-
const
|
|
3820
|
-
if (
|
|
3821
|
-
|
|
3822
|
-
const stderrSpy = spyStreamOutput(process.stderr);
|
|
3823
|
-
return () => {
|
|
3824
|
-
return stdoutSpy() + stderrSpy();
|
|
3825
|
-
};
|
|
4105
|
+
const update = (string) => {
|
|
4106
|
+
if (dynamicLog.destroyed) {
|
|
4107
|
+
throw new Error("Cannot write log after destroy");
|
|
3826
4108
|
}
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
4109
|
+
let stringToWrite = string;
|
|
4110
|
+
if (lastOutput) {
|
|
4111
|
+
if (lastOutputFromOutside) {
|
|
4112
|
+
// We don't want to clear logs written by other code,
|
|
4113
|
+
// it makes output unreadable and might erase precious information
|
|
4114
|
+
// To detect this we put a spy on the stream.
|
|
4115
|
+
// The spy is required only if we actually wrote something in the stream
|
|
4116
|
+
// something else than this code has written in the stream
|
|
4117
|
+
// so we just write without clearing (append instead of replacing)
|
|
4118
|
+
lastOutputFromOutside = "";
|
|
4119
|
+
} else {
|
|
4120
|
+
stringToWrite = `${getErasePreviousOutput()}${string}`;
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
writing = true;
|
|
4124
|
+
stream.write(stringToWrite);
|
|
3833
4125
|
lastOutput = string;
|
|
4126
|
+
writing = false;
|
|
3834
4127
|
clearAttemptResult = undefined;
|
|
4128
|
+
};
|
|
4129
|
+
|
|
4130
|
+
const clearDuringFunctionCall = (callback) => {
|
|
4131
|
+
// 1. Erase the current log
|
|
4132
|
+
// 2. Call callback (expected to write something on stdout)
|
|
4133
|
+
// 3. Restore the current log
|
|
4134
|
+
// During step 2. we expect a "write from outside" so we uninstall
|
|
4135
|
+
// the stream spy during function call
|
|
4136
|
+
const currentOutput = lastOutput;
|
|
4137
|
+
update("");
|
|
4138
|
+
|
|
4139
|
+
writing = true;
|
|
4140
|
+
callback();
|
|
4141
|
+
writing = false;
|
|
3835
4142
|
|
|
3836
|
-
|
|
3837
|
-
// it makes output unreadable and might erase precious information
|
|
3838
|
-
// To detect this we put a spy on the stream.
|
|
3839
|
-
// The spy is required only if we actually wrote something in the stream
|
|
3840
|
-
// otherwise tryToClear() won't do a thing so spy is useless
|
|
3841
|
-
streamOutputSpy = string ? spyStream() : noopStreamSpy;
|
|
4143
|
+
update(currentOutput);
|
|
3842
4144
|
};
|
|
3843
4145
|
|
|
3844
|
-
const
|
|
3845
|
-
if (log.destroyed) {
|
|
3846
|
-
throw new Error("Cannot write log after destroy");
|
|
3847
|
-
}
|
|
4146
|
+
const writeFromOutsideEffect = (value) => {
|
|
3848
4147
|
if (!lastOutput) {
|
|
3849
|
-
|
|
4148
|
+
// we don't care if the log never wrote anything
|
|
4149
|
+
// or if last update() wrote an empty string
|
|
3850
4150
|
return;
|
|
3851
4151
|
}
|
|
3852
|
-
if (
|
|
3853
|
-
|
|
3854
|
-
// so we just write without clearing (append instead of replacing)
|
|
3855
|
-
doWrite(string);
|
|
3856
|
-
} else {
|
|
3857
|
-
doWrite(`${getErasePreviousOutput()}${string}`);
|
|
4152
|
+
if (writing) {
|
|
4153
|
+
return;
|
|
3858
4154
|
}
|
|
4155
|
+
lastOutputFromOutside = value;
|
|
4156
|
+
dynamicLog.onWriteFromOutside(value);
|
|
3859
4157
|
};
|
|
3860
4158
|
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
const
|
|
3864
|
-
|
|
3865
|
-
|
|
4159
|
+
let removeStreamSpy;
|
|
4160
|
+
if (stream === process.stdout) {
|
|
4161
|
+
const removeStdoutSpy = spyStreamOutput(
|
|
4162
|
+
process.stdout,
|
|
4163
|
+
writeFromOutsideEffect,
|
|
4164
|
+
);
|
|
4165
|
+
const removeStderrSpy = spyStreamOutput(
|
|
4166
|
+
process.stderr,
|
|
4167
|
+
writeFromOutsideEffect,
|
|
4168
|
+
);
|
|
4169
|
+
removeStreamSpy = () => {
|
|
4170
|
+
removeStdoutSpy();
|
|
4171
|
+
removeStderrSpy();
|
|
4172
|
+
};
|
|
4173
|
+
} else {
|
|
4174
|
+
removeStreamSpy = spyStreamOutput(stream, writeFromOutsideEffect);
|
|
4175
|
+
}
|
|
3866
4176
|
|
|
3867
4177
|
const destroy = () => {
|
|
3868
|
-
|
|
3869
|
-
if (
|
|
3870
|
-
|
|
3871
|
-
|
|
4178
|
+
dynamicLog.destroyed = true;
|
|
4179
|
+
if (removeStreamSpy) {
|
|
4180
|
+
removeStreamSpy();
|
|
4181
|
+
removeStreamSpy = null;
|
|
3872
4182
|
lastOutput = "";
|
|
4183
|
+
lastOutputFromOutside = "";
|
|
3873
4184
|
}
|
|
3874
4185
|
};
|
|
3875
4186
|
|
|
3876
|
-
Object.assign(
|
|
3877
|
-
|
|
3878
|
-
dynamicWrite,
|
|
4187
|
+
Object.assign(dynamicLog, {
|
|
4188
|
+
update,
|
|
3879
4189
|
destroy,
|
|
3880
4190
|
stream,
|
|
4191
|
+
clearDuringFunctionCall,
|
|
3881
4192
|
});
|
|
3882
|
-
return
|
|
4193
|
+
return dynamicLog;
|
|
3883
4194
|
};
|
|
3884
4195
|
|
|
3885
|
-
|
|
4196
|
+
// maybe https://github.com/gajus/output-interceptor/tree/v3.0.0 ?
|
|
4197
|
+
// the problem with listening data on stdout
|
|
4198
|
+
// is that node.js will later throw error if stream gets closed
|
|
4199
|
+
// while something listening data on it
|
|
4200
|
+
const spyStreamOutput = (stream, callback) => {
|
|
4201
|
+
const originalWrite = stream.write;
|
|
4202
|
+
|
|
4203
|
+
let output = "";
|
|
4204
|
+
let installed = true;
|
|
4205
|
+
|
|
4206
|
+
stream.write = function (...args /* chunk, encoding, callback */) {
|
|
4207
|
+
output += args;
|
|
4208
|
+
callback(output);
|
|
4209
|
+
return originalWrite.call(stream, ...args);
|
|
4210
|
+
};
|
|
4211
|
+
|
|
4212
|
+
const uninstall = () => {
|
|
4213
|
+
if (!installed) {
|
|
4214
|
+
return;
|
|
4215
|
+
}
|
|
4216
|
+
stream.write = originalWrite;
|
|
4217
|
+
installed = false;
|
|
4218
|
+
};
|
|
3886
4219
|
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
return `
|
|
3892
|
-
${string}`;
|
|
3893
|
-
}
|
|
3894
|
-
if (newLine === "after") {
|
|
3895
|
-
return `${string}
|
|
3896
|
-
`;
|
|
3897
|
-
}
|
|
3898
|
-
if (newLine === "around") {
|
|
3899
|
-
return `
|
|
3900
|
-
${string}
|
|
3901
|
-
`;
|
|
3902
|
-
}
|
|
3903
|
-
return string;
|
|
4220
|
+
return () => {
|
|
4221
|
+
uninstall();
|
|
4222
|
+
return output;
|
|
4223
|
+
};
|
|
3904
4224
|
};
|
|
3905
4225
|
|
|
3906
4226
|
const startSpinner = ({
|
|
3907
|
-
|
|
4227
|
+
dynamicLog,
|
|
3908
4228
|
frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
|
|
3909
4229
|
fps = 20,
|
|
3910
4230
|
keepProcessAlive = false,
|
|
@@ -3912,7 +4232,7 @@ const startSpinner = ({
|
|
|
3912
4232
|
stopOnVerticalOverflow = true,
|
|
3913
4233
|
render = () => "",
|
|
3914
4234
|
effect = () => {},
|
|
3915
|
-
animated =
|
|
4235
|
+
animated = dynamicLog.stream.isTTY,
|
|
3916
4236
|
}) => {
|
|
3917
4237
|
let frameIndex = 0;
|
|
3918
4238
|
let interval;
|
|
@@ -3923,7 +4243,9 @@ const startSpinner = ({
|
|
|
3923
4243
|
};
|
|
3924
4244
|
|
|
3925
4245
|
const update = (message) => {
|
|
3926
|
-
spinner.message = running
|
|
4246
|
+
spinner.message = running
|
|
4247
|
+
? `${frames[frameIndex]} ${message}\n`
|
|
4248
|
+
: `${message}\n`;
|
|
3927
4249
|
return spinner.message;
|
|
3928
4250
|
};
|
|
3929
4251
|
spinner.update = update;
|
|
@@ -3932,23 +4254,17 @@ const startSpinner = ({
|
|
|
3932
4254
|
if (animated && ANSI.supported) {
|
|
3933
4255
|
running = true;
|
|
3934
4256
|
cleanup = effect();
|
|
3935
|
-
|
|
4257
|
+
dynamicLog.update(update(render()));
|
|
3936
4258
|
|
|
3937
4259
|
interval = setInterval(() => {
|
|
3938
4260
|
frameIndex = frameIndex === frames.length - 1 ? 0 : frameIndex + 1;
|
|
3939
|
-
|
|
3940
|
-
if (outputFromOutside && stopOnWriteFromOutside) {
|
|
3941
|
-
stop();
|
|
3942
|
-
return "";
|
|
3943
|
-
}
|
|
3944
|
-
return update(render());
|
|
3945
|
-
});
|
|
4261
|
+
dynamicLog.update(update(render()));
|
|
3946
4262
|
}, 1000 / fps);
|
|
3947
4263
|
if (!keepProcessAlive) {
|
|
3948
4264
|
interval.unref();
|
|
3949
4265
|
}
|
|
3950
4266
|
} else {
|
|
3951
|
-
|
|
4267
|
+
dynamicLog.update(update(render()));
|
|
3952
4268
|
}
|
|
3953
4269
|
|
|
3954
4270
|
const stop = (message) => {
|
|
@@ -3961,15 +4277,18 @@ const startSpinner = ({
|
|
|
3961
4277
|
cleanup();
|
|
3962
4278
|
cleanup = null;
|
|
3963
4279
|
}
|
|
3964
|
-
if (
|
|
3965
|
-
|
|
3966
|
-
|
|
4280
|
+
if (dynamicLog && message) {
|
|
4281
|
+
dynamicLog.update(update(message));
|
|
4282
|
+
dynamicLog = null;
|
|
3967
4283
|
}
|
|
3968
4284
|
};
|
|
3969
4285
|
spinner.stop = stop;
|
|
3970
4286
|
|
|
3971
4287
|
if (stopOnVerticalOverflow) {
|
|
3972
|
-
|
|
4288
|
+
dynamicLog.onVerticalOverflow = stop;
|
|
4289
|
+
}
|
|
4290
|
+
if (stopOnWriteFromOutside) {
|
|
4291
|
+
dynamicLog.onWriteFromOutside = stop;
|
|
3973
4292
|
}
|
|
3974
4293
|
|
|
3975
4294
|
return spinner;
|
|
@@ -3988,10 +4307,10 @@ const createTaskLog = (
|
|
|
3988
4307
|
};
|
|
3989
4308
|
}
|
|
3990
4309
|
const startMs = Date.now();
|
|
3991
|
-
const
|
|
4310
|
+
const dynamicLog = createDynamicLog();
|
|
3992
4311
|
let message = label;
|
|
3993
4312
|
const taskSpinner = startSpinner({
|
|
3994
|
-
|
|
4313
|
+
dynamicLog,
|
|
3995
4314
|
render: () => message,
|
|
3996
4315
|
stopOnWriteFromOutside,
|
|
3997
4316
|
animated,
|
|
@@ -4003,7 +4322,7 @@ const createTaskLog = (
|
|
|
4003
4322
|
done: () => {
|
|
4004
4323
|
const msEllapsed = Date.now() - startMs;
|
|
4005
4324
|
taskSpinner.stop(
|
|
4006
|
-
`${UNICODE.OK} ${label} (done in ${
|
|
4325
|
+
`${UNICODE.OK} ${label} (done in ${inspectDuration(msEllapsed)})`,
|
|
4007
4326
|
);
|
|
4008
4327
|
},
|
|
4009
4328
|
happen: (message) => {
|
|
@@ -6004,7 +6323,7 @@ const startServer = async ({
|
|
|
6004
6323
|
let status = "starting";
|
|
6005
6324
|
let nodeServer;
|
|
6006
6325
|
const startServerOperation = Abort.startOperation();
|
|
6007
|
-
const
|
|
6326
|
+
const stopCallbackSet = new Set();
|
|
6008
6327
|
const serverOrigins = {
|
|
6009
6328
|
local: "", // favors hostname when possible
|
|
6010
6329
|
};
|
|
@@ -6128,10 +6447,10 @@ const startServer = async ({
|
|
|
6128
6447
|
// (otherwise an AbortError is thrown to the code calling "startServer")
|
|
6129
6448
|
// we can proceed to create a stop function to stop it gacefully
|
|
6130
6449
|
// and add a request handler
|
|
6131
|
-
|
|
6450
|
+
stopCallbackSet.add(({ reason }) => {
|
|
6132
6451
|
logger.info(`${serverName} stopping server (reason: ${reason})`);
|
|
6133
6452
|
});
|
|
6134
|
-
|
|
6453
|
+
stopCallbackSet.add(async () => {
|
|
6135
6454
|
await stopListening(nodeServer);
|
|
6136
6455
|
});
|
|
6137
6456
|
let stoppedResolve;
|
|
@@ -6140,7 +6459,12 @@ const startServer = async ({
|
|
|
6140
6459
|
});
|
|
6141
6460
|
const stop = memoize(async (reason = STOP_REASON_NOT_SPECIFIED) => {
|
|
6142
6461
|
status = "stopping";
|
|
6143
|
-
|
|
6462
|
+
const promises = [];
|
|
6463
|
+
for (const stopCallback of stopCallbackSet) {
|
|
6464
|
+
promises.push(stopCallback({ reason }));
|
|
6465
|
+
}
|
|
6466
|
+
stopCallbackSet.clear();
|
|
6467
|
+
await Promise.all(promises);
|
|
6144
6468
|
serviceController.callHooks("serverStopped", { reason });
|
|
6145
6469
|
status = "stopped";
|
|
6146
6470
|
stoppedResolve(reason);
|
|
@@ -6152,7 +6476,7 @@ const startServer = async ({
|
|
|
6152
6476
|
stop(PROCESS_TEARDOWN_EVENTS_MAP[winner.name]);
|
|
6153
6477
|
},
|
|
6154
6478
|
);
|
|
6155
|
-
|
|
6479
|
+
stopCallbackSet.add(cancelProcessTeardownRace);
|
|
6156
6480
|
|
|
6157
6481
|
const onError = (error) => {
|
|
6158
6482
|
if (status === "stopping" && error.code === "ECONNRESET") {
|
|
@@ -6167,19 +6491,19 @@ const startServer = async ({
|
|
|
6167
6491
|
nodeServer,
|
|
6168
6492
|
onError,
|
|
6169
6493
|
);
|
|
6170
|
-
|
|
6494
|
+
stopCallbackSet.add(removeConnectionErrorListener);
|
|
6171
6495
|
|
|
6172
6496
|
const connectionsTracker = trackServerPendingConnections(nodeServer, {
|
|
6173
6497
|
http2,
|
|
6174
6498
|
});
|
|
6175
6499
|
// opened connection must be shutdown before the close event is emitted
|
|
6176
|
-
|
|
6500
|
+
stopCallbackSet.add(connectionsTracker.stop);
|
|
6177
6501
|
|
|
6178
6502
|
const pendingRequestsTracker = trackServerPendingRequests(nodeServer, {
|
|
6179
6503
|
http2,
|
|
6180
6504
|
});
|
|
6181
6505
|
// ensure pending requests got a response from the server
|
|
6182
|
-
|
|
6506
|
+
stopCallbackSet.add((reason) => {
|
|
6183
6507
|
pendingRequestsTracker.stop({
|
|
6184
6508
|
status: reason === STOP_REASON_INTERNAL_ERROR ? 500 : 503,
|
|
6185
6509
|
reason,
|
|
@@ -6219,13 +6543,13 @@ const startServer = async ({
|
|
|
6219
6543
|
};
|
|
6220
6544
|
});
|
|
6221
6545
|
receiveRequestOperation.addAbortSource((abort) => {
|
|
6222
|
-
return
|
|
6546
|
+
return stopCallbackSet.add(abort);
|
|
6223
6547
|
});
|
|
6224
6548
|
|
|
6225
6549
|
const sendResponseOperation = Abort.startOperation();
|
|
6226
6550
|
sendResponseOperation.addAbortSignal(receiveRequestOperation.signal);
|
|
6227
6551
|
sendResponseOperation.addAbortSource((abort) => {
|
|
6228
|
-
return
|
|
6552
|
+
return stopCallbackSet.add(abort);
|
|
6229
6553
|
});
|
|
6230
6554
|
|
|
6231
6555
|
const request = fromNodeRequest(nodeRequest, {
|
|
@@ -6778,7 +7102,7 @@ const startServer = async ({
|
|
|
6778
7102
|
};
|
|
6779
7103
|
const removeRequestListener = listenRequest(nodeServer, requestCallback);
|
|
6780
7104
|
// ensure we don't try to handle new requests while server is stopping
|
|
6781
|
-
|
|
7105
|
+
stopCallbackSet.add(removeRequestListener);
|
|
6782
7106
|
}
|
|
6783
7107
|
|
|
6784
7108
|
{
|
|
@@ -6795,325 +7119,139 @@ const startServer = async ({
|
|
|
6795
7119
|
const { WebSocketServer } = await import("./js/ws.js");
|
|
6796
7120
|
let websocketServer = new WebSocketServer({ noServer: true });
|
|
6797
7121
|
const websocketOrigin = https
|
|
6798
|
-
? `wss://${hostname}:${port}`
|
|
6799
|
-
: `ws://${hostname}:${port}`;
|
|
6800
|
-
server.websocketOrigin = websocketOrigin;
|
|
6801
|
-
const upgradeCallback = (nodeRequest, socket, head) => {
|
|
6802
|
-
websocketServer.handleUpgrade(
|
|
6803
|
-
nodeRequest,
|
|
6804
|
-
socket,
|
|
6805
|
-
head,
|
|
6806
|
-
async (websocket) => {
|
|
6807
|
-
websocketClients.add(websocket);
|
|
6808
|
-
websocket.once("close", () => {
|
|
6809
|
-
websocketClients.delete(websocket);
|
|
6810
|
-
});
|
|
6811
|
-
const request = fromNodeRequest(nodeRequest, {
|
|
6812
|
-
serverOrigin: websocketOrigin,
|
|
6813
|
-
signal: new AbortController().signal,
|
|
6814
|
-
requestBodyLifetime,
|
|
6815
|
-
});
|
|
6816
|
-
serviceController.callAsyncHooksUntil(
|
|
6817
|
-
"handleWebsocket",
|
|
6818
|
-
websocket,
|
|
6819
|
-
{
|
|
6820
|
-
request,
|
|
6821
|
-
},
|
|
6822
|
-
);
|
|
6823
|
-
},
|
|
6824
|
-
);
|
|
6825
|
-
};
|
|
6826
|
-
|
|
6827
|
-
// see server-polyglot.js, upgrade must be listened on https server when used
|
|
6828
|
-
const facadeServer = nodeServer._tlsServer || nodeServer;
|
|
6829
|
-
const removeUpgradeCallback = listenEvent(
|
|
6830
|
-
facadeServer,
|
|
6831
|
-
"upgrade",
|
|
6832
|
-
upgradeCallback,
|
|
6833
|
-
);
|
|
6834
|
-
stopCallbackList.add(removeUpgradeCallback);
|
|
6835
|
-
stopCallbackList.add(() => {
|
|
6836
|
-
websocketClients.forEach((websocketClient) => {
|
|
6837
|
-
websocketClient.close();
|
|
6838
|
-
});
|
|
6839
|
-
websocketClients.clear();
|
|
6840
|
-
websocketServer.close();
|
|
6841
|
-
websocketServer = null;
|
|
6842
|
-
});
|
|
6843
|
-
}
|
|
6844
|
-
}
|
|
6845
|
-
|
|
6846
|
-
if (startLog) {
|
|
6847
|
-
if (serverOrigins.network) {
|
|
6848
|
-
logger.info(
|
|
6849
|
-
`${serverName} started at ${serverOrigins.local} (${serverOrigins.network})`,
|
|
6850
|
-
);
|
|
6851
|
-
} else {
|
|
6852
|
-
logger.info(`${serverName} started at ${serverOrigins.local}`);
|
|
6853
|
-
}
|
|
6854
|
-
}
|
|
6855
|
-
|
|
6856
|
-
Object.assign(server, {
|
|
6857
|
-
getStatus: () => status,
|
|
6858
|
-
port,
|
|
6859
|
-
hostname,
|
|
6860
|
-
origin: serverOrigin,
|
|
6861
|
-
origins: serverOrigins,
|
|
6862
|
-
nodeServer,
|
|
6863
|
-
stop,
|
|
6864
|
-
stoppedPromise,
|
|
6865
|
-
addEffect: (callback) => {
|
|
6866
|
-
const cleanup = callback();
|
|
6867
|
-
if (typeof cleanup === "function") {
|
|
6868
|
-
stopCallbackList.add(cleanup);
|
|
6869
|
-
}
|
|
6870
|
-
},
|
|
6871
|
-
});
|
|
6872
|
-
return server;
|
|
6873
|
-
};
|
|
6874
|
-
|
|
6875
|
-
const createNodeServer = async ({
|
|
6876
|
-
https,
|
|
6877
|
-
redirectHttpToHttps,
|
|
6878
|
-
allowHttpRequestOnHttps,
|
|
6879
|
-
http2,
|
|
6880
|
-
http1Allowed,
|
|
6881
|
-
}) => {
|
|
6882
|
-
if (https) {
|
|
6883
|
-
const { certificate, privateKey } = https;
|
|
6884
|
-
if (redirectHttpToHttps || allowHttpRequestOnHttps) {
|
|
6885
|
-
return createPolyglotServer({
|
|
6886
|
-
certificate,
|
|
6887
|
-
privateKey,
|
|
6888
|
-
http2,
|
|
6889
|
-
http1Allowed,
|
|
6890
|
-
});
|
|
6891
|
-
}
|
|
6892
|
-
const { createServer } = await import("node:https");
|
|
6893
|
-
return createServer({
|
|
6894
|
-
cert: certificate,
|
|
6895
|
-
key: privateKey,
|
|
6896
|
-
});
|
|
6897
|
-
}
|
|
6898
|
-
const { createServer } = await import("node:http");
|
|
6899
|
-
return createServer();
|
|
6900
|
-
};
|
|
6901
|
-
|
|
6902
|
-
const testCanPushStream = (http2Stream) => {
|
|
6903
|
-
if (!http2Stream.pushAllowed) {
|
|
6904
|
-
return {
|
|
6905
|
-
can: false,
|
|
6906
|
-
reason: `stream.pushAllowed is false`,
|
|
6907
|
-
};
|
|
6908
|
-
}
|
|
6909
|
-
|
|
6910
|
-
// See https://nodejs.org/dist/latest-v16.x/docs/api/http2.html#http2sessionstate
|
|
6911
|
-
// And https://github.com/google/node-h2-auto-push/blob/67a36c04cbbd6da7b066a4e8d361c593d38853a4/src/index.ts#L100-L106
|
|
6912
|
-
const { remoteWindowSize } = http2Stream.session.state;
|
|
6913
|
-
if (remoteWindowSize === 0) {
|
|
6914
|
-
return {
|
|
6915
|
-
can: false,
|
|
6916
|
-
reason: `no more remoteWindowSize`,
|
|
6917
|
-
};
|
|
6918
|
-
}
|
|
6919
|
-
|
|
6920
|
-
return {
|
|
6921
|
-
can: true,
|
|
6922
|
-
};
|
|
6923
|
-
};
|
|
6924
|
-
|
|
6925
|
-
const PROCESS_TEARDOWN_EVENTS_MAP = {
|
|
6926
|
-
SIGHUP: STOP_REASON_PROCESS_SIGHUP,
|
|
6927
|
-
SIGTERM: STOP_REASON_PROCESS_SIGTERM,
|
|
6928
|
-
SIGINT: STOP_REASON_PROCESS_SIGINT,
|
|
6929
|
-
beforeExit: STOP_REASON_PROCESS_BEFORE_EXIT,
|
|
6930
|
-
exit: STOP_REASON_PROCESS_EXIT,
|
|
6931
|
-
};
|
|
6932
|
-
|
|
6933
|
-
const mediaTypeInfos = {
|
|
6934
|
-
"application/json": {
|
|
6935
|
-
extensions: ["json", "map"],
|
|
6936
|
-
isTextual: true,
|
|
6937
|
-
},
|
|
6938
|
-
"application/importmap+json": {
|
|
6939
|
-
extensions: ["importmap"],
|
|
6940
|
-
isTextual: true,
|
|
6941
|
-
},
|
|
6942
|
-
"application/manifest+json": {
|
|
6943
|
-
extensions: ["webmanifest"],
|
|
6944
|
-
isTextual: true,
|
|
6945
|
-
},
|
|
6946
|
-
"application/octet-stream": {},
|
|
6947
|
-
"application/pdf": {
|
|
6948
|
-
extensions: ["pdf"],
|
|
6949
|
-
},
|
|
6950
|
-
"application/xml": {
|
|
6951
|
-
extensions: ["xml"],
|
|
6952
|
-
},
|
|
6953
|
-
"application/x-gzip": {
|
|
6954
|
-
extensions: ["gz"],
|
|
6955
|
-
},
|
|
6956
|
-
"application/wasm": {
|
|
6957
|
-
extensions: ["wasm"],
|
|
6958
|
-
},
|
|
6959
|
-
"application/zip": {
|
|
6960
|
-
extensions: ["zip"],
|
|
6961
|
-
},
|
|
6962
|
-
"audio/basic": {
|
|
6963
|
-
extensions: ["au", "snd"],
|
|
6964
|
-
},
|
|
6965
|
-
"audio/mpeg": {
|
|
6966
|
-
extensions: ["mpga", "mp2", "mp2a", "mp3", "m2a", "m3a"],
|
|
6967
|
-
},
|
|
6968
|
-
"audio/midi": {
|
|
6969
|
-
extensions: ["midi", "mid", "kar", "rmi"],
|
|
6970
|
-
},
|
|
6971
|
-
"audio/mp4": {
|
|
6972
|
-
extensions: ["m4a", "mp4a"],
|
|
6973
|
-
},
|
|
6974
|
-
"audio/ogg": {
|
|
6975
|
-
extensions: ["oga", "ogg", "spx"],
|
|
6976
|
-
},
|
|
6977
|
-
"audio/webm": {
|
|
6978
|
-
extensions: ["weba"],
|
|
6979
|
-
},
|
|
6980
|
-
"audio/x-wav": {
|
|
6981
|
-
extensions: ["wav"],
|
|
6982
|
-
},
|
|
6983
|
-
"font/ttf": {
|
|
6984
|
-
extensions: ["ttf"],
|
|
6985
|
-
},
|
|
6986
|
-
"font/woff": {
|
|
6987
|
-
extensions: ["woff"],
|
|
6988
|
-
},
|
|
6989
|
-
"font/woff2": {
|
|
6990
|
-
extensions: ["woff2"],
|
|
6991
|
-
},
|
|
6992
|
-
"image/png": {
|
|
6993
|
-
extensions: ["png"],
|
|
6994
|
-
},
|
|
6995
|
-
"image/gif": {
|
|
6996
|
-
extensions: ["gif"],
|
|
6997
|
-
},
|
|
6998
|
-
"image/jpeg": {
|
|
6999
|
-
extensions: ["jpg"],
|
|
7000
|
-
},
|
|
7001
|
-
"image/svg+xml": {
|
|
7002
|
-
extensions: ["svg", "svgz"],
|
|
7003
|
-
isTextual: true,
|
|
7004
|
-
},
|
|
7005
|
-
"text/plain": {
|
|
7006
|
-
extensions: ["txt"],
|
|
7007
|
-
},
|
|
7008
|
-
"text/html": {
|
|
7009
|
-
extensions: ["html"],
|
|
7010
|
-
},
|
|
7011
|
-
"text/css": {
|
|
7012
|
-
extensions: ["css"],
|
|
7013
|
-
},
|
|
7014
|
-
"text/javascript": {
|
|
7015
|
-
extensions: ["js", "cjs", "mjs", "ts", "jsx", "tsx"],
|
|
7016
|
-
},
|
|
7017
|
-
"text/x-sass": {
|
|
7018
|
-
extensions: ["sass"],
|
|
7019
|
-
},
|
|
7020
|
-
"text/x-scss": {
|
|
7021
|
-
extensions: ["scss"],
|
|
7022
|
-
},
|
|
7023
|
-
"text/cache-manifest": {
|
|
7024
|
-
extensions: ["appcache"],
|
|
7025
|
-
},
|
|
7026
|
-
"video/mp4": {
|
|
7027
|
-
extensions: ["mp4", "mp4v", "mpg4"],
|
|
7028
|
-
},
|
|
7029
|
-
"video/mpeg": {
|
|
7030
|
-
extensions: ["mpeg", "mpg", "mpe", "m1v", "m2v"],
|
|
7031
|
-
},
|
|
7032
|
-
"video/ogg": {
|
|
7033
|
-
extensions: ["ogv"],
|
|
7034
|
-
},
|
|
7035
|
-
"video/webm": {
|
|
7036
|
-
extensions: ["webm"],
|
|
7037
|
-
},
|
|
7038
|
-
};
|
|
7039
|
-
|
|
7040
|
-
const CONTENT_TYPE = {
|
|
7041
|
-
parse: (string) => {
|
|
7042
|
-
const [mediaType, charset] = string.split(";");
|
|
7043
|
-
return { mediaType: normalizeMediaType(mediaType), charset };
|
|
7044
|
-
},
|
|
7122
|
+
? `wss://${hostname}:${port}`
|
|
7123
|
+
: `ws://${hostname}:${port}`;
|
|
7124
|
+
server.websocketOrigin = websocketOrigin;
|
|
7125
|
+
const upgradeCallback = (nodeRequest, socket, head) => {
|
|
7126
|
+
websocketServer.handleUpgrade(
|
|
7127
|
+
nodeRequest,
|
|
7128
|
+
socket,
|
|
7129
|
+
head,
|
|
7130
|
+
async (websocket) => {
|
|
7131
|
+
websocketClients.add(websocket);
|
|
7132
|
+
websocket.once("close", () => {
|
|
7133
|
+
websocketClients.delete(websocket);
|
|
7134
|
+
});
|
|
7135
|
+
const request = fromNodeRequest(nodeRequest, {
|
|
7136
|
+
serverOrigin: websocketOrigin,
|
|
7137
|
+
signal: new AbortController().signal,
|
|
7138
|
+
requestBodyLifetime,
|
|
7139
|
+
});
|
|
7140
|
+
serviceController.callAsyncHooksUntil(
|
|
7141
|
+
"handleWebsocket",
|
|
7142
|
+
websocket,
|
|
7143
|
+
{
|
|
7144
|
+
request,
|
|
7145
|
+
},
|
|
7146
|
+
);
|
|
7147
|
+
},
|
|
7148
|
+
);
|
|
7149
|
+
};
|
|
7045
7150
|
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7151
|
+
// see server-polyglot.js, upgrade must be listened on https server when used
|
|
7152
|
+
const facadeServer = nodeServer._tlsServer || nodeServer;
|
|
7153
|
+
const removeUpgradeCallback = listenEvent(
|
|
7154
|
+
facadeServer,
|
|
7155
|
+
"upgrade",
|
|
7156
|
+
upgradeCallback,
|
|
7157
|
+
);
|
|
7158
|
+
stopCallbackSet.add(removeUpgradeCallback);
|
|
7159
|
+
stopCallbackSet.add(() => {
|
|
7160
|
+
websocketClients.forEach((websocketClient) => {
|
|
7161
|
+
websocketClient.close();
|
|
7162
|
+
});
|
|
7163
|
+
websocketClients.clear();
|
|
7164
|
+
websocketServer.close();
|
|
7165
|
+
websocketServer = null;
|
|
7166
|
+
});
|
|
7049
7167
|
}
|
|
7050
|
-
|
|
7051
|
-
},
|
|
7168
|
+
}
|
|
7052
7169
|
|
|
7053
|
-
|
|
7054
|
-
if (
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7170
|
+
if (startLog) {
|
|
7171
|
+
if (serverOrigins.network) {
|
|
7172
|
+
logger.info(
|
|
7173
|
+
`${serverName} started at ${serverOrigins.local} (${serverOrigins.network})`,
|
|
7174
|
+
);
|
|
7175
|
+
} else {
|
|
7176
|
+
logger.info(`${serverName} started at ${serverOrigins.local}`);
|
|
7059
7177
|
}
|
|
7060
|
-
|
|
7061
|
-
},
|
|
7178
|
+
}
|
|
7062
7179
|
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7180
|
+
Object.assign(server, {
|
|
7181
|
+
getStatus: () => status,
|
|
7182
|
+
port,
|
|
7183
|
+
hostname,
|
|
7184
|
+
origin: serverOrigin,
|
|
7185
|
+
origins: serverOrigins,
|
|
7186
|
+
nodeServer,
|
|
7187
|
+
stop,
|
|
7188
|
+
stoppedPromise,
|
|
7189
|
+
addEffect: (callback) => {
|
|
7190
|
+
const cleanup = callback();
|
|
7191
|
+
if (typeof cleanup === "function") {
|
|
7192
|
+
stopCallbackSet.add(cleanup);
|
|
7193
|
+
}
|
|
7194
|
+
},
|
|
7195
|
+
});
|
|
7196
|
+
return server;
|
|
7197
|
+
};
|
|
7070
7198
|
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
}
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7199
|
+
const createNodeServer = async ({
|
|
7200
|
+
https,
|
|
7201
|
+
redirectHttpToHttps,
|
|
7202
|
+
allowHttpRequestOnHttps,
|
|
7203
|
+
http2,
|
|
7204
|
+
http1Allowed,
|
|
7205
|
+
}) => {
|
|
7206
|
+
if (https) {
|
|
7207
|
+
const { certificate, privateKey } = https;
|
|
7208
|
+
if (redirectHttpToHttps || allowHttpRequestOnHttps) {
|
|
7209
|
+
return createPolyglotServer({
|
|
7210
|
+
certificate,
|
|
7211
|
+
privateKey,
|
|
7212
|
+
http2,
|
|
7213
|
+
http1Allowed,
|
|
7214
|
+
});
|
|
7083
7215
|
}
|
|
7084
|
-
|
|
7085
|
-
|
|
7216
|
+
const { createServer } = await import("node:https");
|
|
7217
|
+
return createServer({
|
|
7218
|
+
cert: certificate,
|
|
7219
|
+
key: privateKey,
|
|
7220
|
+
});
|
|
7221
|
+
}
|
|
7222
|
+
const { createServer } = await import("node:http");
|
|
7223
|
+
return createServer();
|
|
7224
|
+
};
|
|
7086
7225
|
|
|
7087
|
-
|
|
7226
|
+
const testCanPushStream = (http2Stream) => {
|
|
7227
|
+
if (!http2Stream.pushAllowed) {
|
|
7228
|
+
return {
|
|
7229
|
+
can: false,
|
|
7230
|
+
reason: `stream.pushAllowed is false`,
|
|
7231
|
+
};
|
|
7232
|
+
}
|
|
7088
7233
|
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7234
|
+
// See https://nodejs.org/dist/latest-v16.x/docs/api/http2.html#http2sessionstate
|
|
7235
|
+
// And https://github.com/google/node-h2-auto-push/blob/67a36c04cbbd6da7b066a4e8d361c593d38853a4/src/index.ts#L100-L106
|
|
7236
|
+
const { remoteWindowSize } = http2Stream.session.state;
|
|
7237
|
+
if (remoteWindowSize === 0) {
|
|
7238
|
+
return {
|
|
7239
|
+
can: false,
|
|
7240
|
+
reason: `no more remoteWindowSize`,
|
|
7241
|
+
};
|
|
7242
|
+
}
|
|
7094
7243
|
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
if (!extensionWithDot || extensionWithDot === ".") {
|
|
7099
|
-
return "application/octet-stream";
|
|
7100
|
-
}
|
|
7101
|
-
const extension = extensionWithDot.slice(1);
|
|
7102
|
-
const mediaTypeFound = Object.keys(mediaTypeInfos).find((mediaType) => {
|
|
7103
|
-
const mediaTypeInfo = mediaTypeInfos[mediaType];
|
|
7104
|
-
return (
|
|
7105
|
-
mediaTypeInfo.extensions && mediaTypeInfo.extensions.includes(extension)
|
|
7106
|
-
);
|
|
7107
|
-
});
|
|
7108
|
-
return mediaTypeFound || "application/octet-stream";
|
|
7109
|
-
},
|
|
7244
|
+
return {
|
|
7245
|
+
can: true,
|
|
7246
|
+
};
|
|
7110
7247
|
};
|
|
7111
7248
|
|
|
7112
|
-
const
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7249
|
+
const PROCESS_TEARDOWN_EVENTS_MAP = {
|
|
7250
|
+
SIGHUP: STOP_REASON_PROCESS_SIGHUP,
|
|
7251
|
+
SIGTERM: STOP_REASON_PROCESS_SIGTERM,
|
|
7252
|
+
SIGINT: STOP_REASON_PROCESS_SIGINT,
|
|
7253
|
+
beforeExit: STOP_REASON_PROCESS_BEFORE_EXIT,
|
|
7254
|
+
exit: STOP_REASON_PROCESS_EXIT,
|
|
7117
7255
|
};
|
|
7118
7256
|
|
|
7119
7257
|
const isFileSystemPath = (value) => {
|
|
@@ -8701,7 +8839,10 @@ const rollupPluginJsenv = ({
|
|
|
8701
8839
|
// rollup generate specifiers only for static and dynamic imports
|
|
8702
8840
|
// other references (like new URL()) are ignored
|
|
8703
8841
|
// there is no need to remap them back
|
|
8704
|
-
if (
|
|
8842
|
+
if (
|
|
8843
|
+
reference.type === "js_import" &&
|
|
8844
|
+
reference.subtype !== "import_meta_resolve"
|
|
8845
|
+
) {
|
|
8705
8846
|
return specifierToUrlMap.get(reference.specifier);
|
|
8706
8847
|
}
|
|
8707
8848
|
return reference.specifier;
|
|
@@ -10768,34 +10909,32 @@ const jsenvPluginImportMetaResolve = ({ needJsModuleFallback }) => {
|
|
|
10768
10909
|
},
|
|
10769
10910
|
transformUrlContent: {
|
|
10770
10911
|
js_module: async (urlInfo) => {
|
|
10912
|
+
const jsUrls = parseJsUrls({
|
|
10913
|
+
js: urlInfo.content,
|
|
10914
|
+
url: urlInfo.url,
|
|
10915
|
+
isJsModule: true,
|
|
10916
|
+
});
|
|
10771
10917
|
const magicSource = createMagicSource(urlInfo.content);
|
|
10772
|
-
for (const
|
|
10773
|
-
if (
|
|
10774
|
-
|
|
10775
|
-
referenceToOther.specifier,
|
|
10776
|
-
);
|
|
10777
|
-
const specifierLength = Buffer.byteLength(
|
|
10778
|
-
referenceToOther.generatedSpecifier.slice(1, -1), // remove `"` around
|
|
10779
|
-
);
|
|
10780
|
-
const specifierLengthDiff =
|
|
10781
|
-
specifierLength - originalSpecifierLength;
|
|
10782
|
-
const { node } = referenceToOther.astInfo;
|
|
10783
|
-
const end = node.end + specifierLengthDiff;
|
|
10784
|
-
magicSource.replace({
|
|
10785
|
-
start: node.start,
|
|
10786
|
-
end,
|
|
10787
|
-
replacement: `new URL(${referenceToOther.generatedSpecifier}, import.meta.url).href`,
|
|
10788
|
-
});
|
|
10789
|
-
const currentLengthBeforeSpecifier = "import.meta.resolve(".length;
|
|
10790
|
-
const newLengthBeforeSpecifier = "new URL(".length;
|
|
10791
|
-
const lengthDiff =
|
|
10792
|
-
currentLengthBeforeSpecifier - newLengthBeforeSpecifier;
|
|
10793
|
-
referenceToOther.specifierColumn -= lengthDiff;
|
|
10794
|
-
referenceToOther.specifierStart -= lengthDiff;
|
|
10795
|
-
referenceToOther.specifierEnd =
|
|
10796
|
-
referenceToOther.specifierStart +
|
|
10797
|
-
Buffer.byteLength(referenceToOther.generatedSpecifier);
|
|
10918
|
+
for (const jsUrl of jsUrls) {
|
|
10919
|
+
if (jsUrl.subtype !== "import_meta_resolve") {
|
|
10920
|
+
continue;
|
|
10798
10921
|
}
|
|
10922
|
+
const { node } = jsUrl.astInfo;
|
|
10923
|
+
let reference;
|
|
10924
|
+
for (const referenceToOther of urlInfo.referenceToOthersSet) {
|
|
10925
|
+
if (
|
|
10926
|
+
referenceToOther.generatedSpecifier.slice(1, -1) ===
|
|
10927
|
+
jsUrl.specifier
|
|
10928
|
+
) {
|
|
10929
|
+
reference = referenceToOther;
|
|
10930
|
+
break;
|
|
10931
|
+
}
|
|
10932
|
+
}
|
|
10933
|
+
magicSource.replace({
|
|
10934
|
+
start: node.start,
|
|
10935
|
+
end: node.end,
|
|
10936
|
+
replacement: `new URL(${reference.generatedSpecifier}, import.meta.url).href`,
|
|
10937
|
+
});
|
|
10799
10938
|
}
|
|
10800
10939
|
return magicSource.toContentAndSourcemap();
|
|
10801
10940
|
},
|
|
@@ -12096,6 +12235,13 @@ const applyDependencyRemovalEffects = (reference) => {
|
|
|
12096
12235
|
|
|
12097
12236
|
const traceFromUrlSite = (urlSite) => {
|
|
12098
12237
|
return {
|
|
12238
|
+
codeFrame: urlSite.content
|
|
12239
|
+
? inspectFileContent({
|
|
12240
|
+
content: urlSite.content,
|
|
12241
|
+
line: urlSite.line,
|
|
12242
|
+
column: urlSite.column,
|
|
12243
|
+
})
|
|
12244
|
+
: "",
|
|
12099
12245
|
message: stringifyUrlSite(urlSite),
|
|
12100
12246
|
url: urlSite.url,
|
|
12101
12247
|
line: urlSite.line,
|
|
@@ -13680,15 +13826,9 @@ const createFetchUrlContentError = ({
|
|
|
13680
13826
|
fetchError.reason = reason;
|
|
13681
13827
|
fetchError.url = urlInfo.url;
|
|
13682
13828
|
if (code === "PARSE_ERROR") {
|
|
13683
|
-
fetchError.
|
|
13684
|
-
fetchError.traceLine = error.traceLine;
|
|
13685
|
-
fetchError.traceColumn = error.traceColumn;
|
|
13686
|
-
fetchError.traceMessage = error.traceMessage;
|
|
13829
|
+
fetchError.trace = error.trace;
|
|
13687
13830
|
} else {
|
|
13688
|
-
fetchError.
|
|
13689
|
-
fetchError.traceLine = urlInfo.firstReference.trace.line;
|
|
13690
|
-
fetchError.traceColumn = urlInfo.firstReference.trace.column;
|
|
13691
|
-
fetchError.traceMessage = urlInfo.firstReference.trace.message;
|
|
13831
|
+
fetchError.trace = urlInfo.firstReference.trace;
|
|
13692
13832
|
}
|
|
13693
13833
|
fetchError.asResponse = error.asResponse;
|
|
13694
13834
|
return fetchError;
|
|
@@ -13723,7 +13863,7 @@ const createFetchUrlContentError = ({
|
|
|
13723
13863
|
"code": "PARSE_ERROR",
|
|
13724
13864
|
"reason": error.reasonCode,
|
|
13725
13865
|
...(error.cause ? { "parse error message": error.cause.message } : {}),
|
|
13726
|
-
"parse error trace": error.
|
|
13866
|
+
"parse error trace": error.trace?.message,
|
|
13727
13867
|
});
|
|
13728
13868
|
}
|
|
13729
13869
|
return createFailedToFetchUrlContentError({
|
|
@@ -13762,33 +13902,43 @@ const createTransformUrlContentError = ({
|
|
|
13762
13902
|
transformError.reason = reason;
|
|
13763
13903
|
transformError.stack = error.stack;
|
|
13764
13904
|
transformError.url = urlInfo.url;
|
|
13765
|
-
transformError.
|
|
13766
|
-
transformError.traceLine = urlInfo.firstReference.trace.line;
|
|
13767
|
-
transformError.traceColumn = urlInfo.firstReference.trace.column;
|
|
13768
|
-
transformError.traceMessage = urlInfo.firstReference.trace.message;
|
|
13905
|
+
transformError.trace = urlInfo.firstReference.trace;
|
|
13769
13906
|
if (code === "PARSE_ERROR") {
|
|
13770
13907
|
transformError.reason = `parse error on ${urlInfo.type}`;
|
|
13771
13908
|
transformError.cause = error;
|
|
13772
13909
|
if (urlInfo.isInline) {
|
|
13773
|
-
transformError.
|
|
13910
|
+
transformError.trace.line =
|
|
13774
13911
|
urlInfo.firstReference.trace.line + error.line - 1;
|
|
13775
|
-
transformError.
|
|
13912
|
+
transformError.trace.column =
|
|
13776
13913
|
urlInfo.firstReference.trace.column + error.column;
|
|
13777
|
-
transformError.
|
|
13914
|
+
transformError.trace.codeFrame = inspectFileContent({
|
|
13915
|
+
line: transformError.trace.line,
|
|
13916
|
+
column: transformError.trace.column,
|
|
13917
|
+
content: urlInfo.inlineUrlSite.content,
|
|
13918
|
+
});
|
|
13919
|
+
transformError.trace.message = stringifyUrlSite({
|
|
13778
13920
|
url: urlInfo.inlineUrlSite.url,
|
|
13779
|
-
line: transformError.
|
|
13780
|
-
column: transformError.
|
|
13921
|
+
line: transformError.trace.line,
|
|
13922
|
+
column: transformError.trace.column,
|
|
13781
13923
|
content: urlInfo.inlineUrlSite.content,
|
|
13782
13924
|
});
|
|
13783
13925
|
} else {
|
|
13784
|
-
transformError.
|
|
13785
|
-
transformError.traceColumn = error.column;
|
|
13786
|
-
transformError.traceMessage = stringifyUrlSite({
|
|
13926
|
+
transformError.trace = {
|
|
13787
13927
|
url: urlInfo.url,
|
|
13788
|
-
line: error.line
|
|
13928
|
+
line: error.line,
|
|
13789
13929
|
column: error.column,
|
|
13790
|
-
|
|
13791
|
-
|
|
13930
|
+
codeFrame: inspectFileContent({
|
|
13931
|
+
line: error.line - 1,
|
|
13932
|
+
column: error.column,
|
|
13933
|
+
content: urlInfo.content,
|
|
13934
|
+
}),
|
|
13935
|
+
message: stringifyUrlSite({
|
|
13936
|
+
url: urlInfo.url,
|
|
13937
|
+
line: error.line - 1,
|
|
13938
|
+
column: error.column,
|
|
13939
|
+
content: urlInfo.content,
|
|
13940
|
+
}),
|
|
13941
|
+
};
|
|
13792
13942
|
}
|
|
13793
13943
|
}
|
|
13794
13944
|
transformError.asResponse = error.asResponse;
|
|
@@ -14453,7 +14603,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
14453
14603
|
) {
|
|
14454
14604
|
const errorInfo =
|
|
14455
14605
|
e.code === "PARSE_ERROR" && e.cause
|
|
14456
|
-
? `${e.cause.reasonCode}\n${e.
|
|
14606
|
+
? `${e.cause.reasonCode}\n${e.trace?.message}`
|
|
14457
14607
|
: e.stack;
|
|
14458
14608
|
// When something like <style> or <script> contains syntax error
|
|
14459
14609
|
// the HTML in itself it still valid
|
|
@@ -14859,7 +15009,7 @@ const determineCategory = (urlInfo) => {
|
|
|
14859
15009
|
const createRepartitionMessage = ({ html, css, js, json, other, total }) => {
|
|
14860
15010
|
const addPart = (name, { count, size, percentage }) => {
|
|
14861
15011
|
parts.push(
|
|
14862
|
-
`${ANSI.color(`${name}:`, ANSI.GREY)} ${count} (${
|
|
15012
|
+
`${ANSI.color(`${name}:`, ANSI.GREY)} ${count} (${inspectFileSize(
|
|
14863
15013
|
size,
|
|
14864
15014
|
)} / ${percentage} %)`,
|
|
14865
15015
|
);
|
|
@@ -14870,7 +15020,7 @@ const createRepartitionMessage = ({ html, css, js, json, other, total }) => {
|
|
|
14870
15020
|
// parts.push(
|
|
14871
15021
|
// `${ANSI.color(`sourcemaps:`, ANSI.GREY)} ${
|
|
14872
15022
|
// sourcemaps.count
|
|
14873
|
-
// } (${
|
|
15023
|
+
// } (${inspectFileSize(sourcemaps.size)})`,
|
|
14874
15024
|
// )
|
|
14875
15025
|
// }
|
|
14876
15026
|
if (html.count) {
|
|
@@ -16462,18 +16612,20 @@ const jsenvPluginJsReferenceAnalysis = ({ inlineContent }) => {
|
|
|
16462
16612
|
name: "jsenv:js_reference_analysis",
|
|
16463
16613
|
appliesDuring: "*",
|
|
16464
16614
|
transformUrlContent: {
|
|
16465
|
-
js_classic: (urlInfo) =>
|
|
16466
|
-
parseAndTransformJsReferences(urlInfo, {
|
|
16615
|
+
js_classic: (urlInfo) => {
|
|
16616
|
+
return parseAndTransformJsReferences(urlInfo, {
|
|
16467
16617
|
inlineContent,
|
|
16468
16618
|
canUseTemplateLiterals:
|
|
16469
16619
|
urlInfo.context.isSupportedOnCurrentClients("template_literals"),
|
|
16470
|
-
})
|
|
16471
|
-
|
|
16472
|
-
|
|
16620
|
+
});
|
|
16621
|
+
},
|
|
16622
|
+
js_module: (urlInfo) => {
|
|
16623
|
+
return parseAndTransformJsReferences(urlInfo, {
|
|
16473
16624
|
inlineContent,
|
|
16474
16625
|
canUseTemplateLiterals:
|
|
16475
16626
|
urlInfo.context.isSupportedOnCurrentClients("template_literals"),
|
|
16476
|
-
})
|
|
16627
|
+
});
|
|
16628
|
+
},
|
|
16477
16629
|
},
|
|
16478
16630
|
},
|
|
16479
16631
|
];
|
|
@@ -16602,13 +16754,9 @@ const parseAndTransformJsReferences = async (
|
|
|
16602
16754
|
if (parallelActions.length > 0) {
|
|
16603
16755
|
await Promise.all(parallelActions.map((action) => action()));
|
|
16604
16756
|
}
|
|
16605
|
-
|
|
16606
|
-
await
|
|
16607
|
-
await previous;
|
|
16608
|
-
await action();
|
|
16609
|
-
}, Promise.resolve());
|
|
16757
|
+
for (const sequentialAction of sequentialActions) {
|
|
16758
|
+
await sequentialAction();
|
|
16610
16759
|
}
|
|
16611
|
-
|
|
16612
16760
|
const { content, sourcemap } = magicSource.toContentAndSourcemap();
|
|
16613
16761
|
return { content, sourcemap };
|
|
16614
16762
|
};
|
|
@@ -18051,7 +18199,7 @@ const jsenvPluginProtocolFile = ({
|
|
|
18051
18199
|
magicExtensions = ["inherit", ".js"],
|
|
18052
18200
|
magicDirectoryIndex = true,
|
|
18053
18201
|
preserveSymlinks = false,
|
|
18054
|
-
|
|
18202
|
+
directoryReferenceEffect = "error",
|
|
18055
18203
|
}) => {
|
|
18056
18204
|
return [
|
|
18057
18205
|
{
|
|
@@ -18132,17 +18280,27 @@ const jsenvPluginProtocolFile = ({
|
|
|
18132
18280
|
}
|
|
18133
18281
|
reference.leadsToADirectory = stat && stat.isDirectory();
|
|
18134
18282
|
if (reference.leadsToADirectory) {
|
|
18135
|
-
|
|
18283
|
+
let actionForDirectory;
|
|
18284
|
+
if (
|
|
18136
18285
|
reference.type === "http_request" ||
|
|
18137
|
-
reference.type === "filesystem"
|
|
18138
|
-
|
|
18139
|
-
|
|
18140
|
-
|
|
18141
|
-
|
|
18286
|
+
reference.type === "filesystem"
|
|
18287
|
+
) {
|
|
18288
|
+
actionForDirectory = "copy";
|
|
18289
|
+
} else if (typeof directoryReferenceEffect === "string") {
|
|
18290
|
+
actionForDirectory = directoryReferenceEffect;
|
|
18291
|
+
} else if (typeof directoryReferenceEffect === "function") {
|
|
18292
|
+
actionForDirectory = directoryReferenceEffect(reference);
|
|
18293
|
+
} else {
|
|
18294
|
+
actionForDirectory = "error";
|
|
18295
|
+
}
|
|
18296
|
+
if (actionForDirectory === "error") {
|
|
18142
18297
|
const error = new Error("Reference leads to a directory");
|
|
18143
18298
|
error.code = "DIRECTORY_REFERENCE_NOT_ALLOWED";
|
|
18144
18299
|
throw error;
|
|
18145
18300
|
}
|
|
18301
|
+
if (actionForDirectory === "preserve") {
|
|
18302
|
+
return `ignore:${url}${search}${hash}`;
|
|
18303
|
+
}
|
|
18146
18304
|
}
|
|
18147
18305
|
const urlRaw = preserveSymlinks ? url : resolveSymlink(url);
|
|
18148
18306
|
const resolvedUrl = `${urlRaw}${search}${hash}`;
|
|
@@ -19898,7 +20056,7 @@ const getCorePlugins = ({
|
|
|
19898
20056
|
nodeEsmResolution = {},
|
|
19899
20057
|
magicExtensions,
|
|
19900
20058
|
magicDirectoryIndex,
|
|
19901
|
-
|
|
20059
|
+
directoryReferenceEffect,
|
|
19902
20060
|
supervisor,
|
|
19903
20061
|
injections,
|
|
19904
20062
|
transpilation = true,
|
|
@@ -19933,7 +20091,7 @@ const getCorePlugins = ({
|
|
|
19933
20091
|
- All the rest uses web standard url resolution
|
|
19934
20092
|
*/
|
|
19935
20093
|
jsenvPluginProtocolFile({
|
|
19936
|
-
|
|
20094
|
+
directoryReferenceEffect,
|
|
19937
20095
|
magicExtensions,
|
|
19938
20096
|
magicDirectoryIndex,
|
|
19939
20097
|
}),
|
|
@@ -21533,7 +21691,7 @@ const build = async ({
|
|
|
21533
21691
|
nodeEsmResolution,
|
|
21534
21692
|
magicExtensions,
|
|
21535
21693
|
magicDirectoryIndex,
|
|
21536
|
-
|
|
21694
|
+
directoryReferenceEffect,
|
|
21537
21695
|
scenarioPlaceholders,
|
|
21538
21696
|
injections,
|
|
21539
21697
|
transpilation = {},
|
|
@@ -21623,6 +21781,17 @@ const build = async ({
|
|
|
21623
21781
|
}
|
|
21624
21782
|
}
|
|
21625
21783
|
|
|
21784
|
+
if (assetsDirectory && assetsDirectory[assetsDirectory.length - 1] !== "/") {
|
|
21785
|
+
assetsDirectory = `${assetsDirectory}/`;
|
|
21786
|
+
}
|
|
21787
|
+
if (directoryToClean === undefined) {
|
|
21788
|
+
if (assetsDirectory === undefined) {
|
|
21789
|
+
directoryToClean = buildDirectoryUrl;
|
|
21790
|
+
} else {
|
|
21791
|
+
directoryToClean = new URL(assetsDirectory, buildDirectoryUrl).href;
|
|
21792
|
+
}
|
|
21793
|
+
}
|
|
21794
|
+
|
|
21626
21795
|
const operation = Abort.startOperation();
|
|
21627
21796
|
operation.addAbortSignal(signal);
|
|
21628
21797
|
if (handleSIGINT) {
|
|
@@ -21636,17 +21805,6 @@ const build = async ({
|
|
|
21636
21805
|
});
|
|
21637
21806
|
}
|
|
21638
21807
|
|
|
21639
|
-
if (assetsDirectory && assetsDirectory[assetsDirectory.length - 1] !== "/") {
|
|
21640
|
-
assetsDirectory = `${assetsDirectory}/`;
|
|
21641
|
-
}
|
|
21642
|
-
if (directoryToClean === undefined) {
|
|
21643
|
-
if (assetsDirectory === undefined) {
|
|
21644
|
-
directoryToClean = buildDirectoryUrl;
|
|
21645
|
-
} else {
|
|
21646
|
-
directoryToClean = new URL(assetsDirectory, buildDirectoryUrl).href;
|
|
21647
|
-
}
|
|
21648
|
-
}
|
|
21649
|
-
|
|
21650
21808
|
const runBuild = async ({ signal, logLevel }) => {
|
|
21651
21809
|
const logger = createLogger({ logLevel });
|
|
21652
21810
|
const createBuildTask = (label) => {
|
|
@@ -21719,7 +21877,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
21719
21877
|
nodeEsmResolution,
|
|
21720
21878
|
magicExtensions,
|
|
21721
21879
|
magicDirectoryIndex,
|
|
21722
|
-
|
|
21880
|
+
directoryReferenceEffect,
|
|
21723
21881
|
injections,
|
|
21724
21882
|
transpilation: {
|
|
21725
21883
|
babelHelpersAsImport: !explicitJsModuleConversion,
|
|
@@ -22087,7 +22245,15 @@ build ${entryPointKeys.length} entry points`);
|
|
|
22087
22245
|
};
|
|
22088
22246
|
|
|
22089
22247
|
if (!watch) {
|
|
22090
|
-
|
|
22248
|
+
try {
|
|
22249
|
+
const result = await runBuild({
|
|
22250
|
+
signal: operation.signal,
|
|
22251
|
+
logLevel,
|
|
22252
|
+
});
|
|
22253
|
+
return result;
|
|
22254
|
+
} finally {
|
|
22255
|
+
await operation.end();
|
|
22256
|
+
}
|
|
22091
22257
|
}
|
|
22092
22258
|
|
|
22093
22259
|
let resolveFirstBuild;
|
|
@@ -22326,25 +22492,13 @@ const startDevServer = async ({
|
|
|
22326
22492
|
}
|
|
22327
22493
|
|
|
22328
22494
|
const logger = createLogger({ logLevel });
|
|
22329
|
-
const operation = Abort.startOperation();
|
|
22330
|
-
operation.addAbortSignal(signal);
|
|
22331
|
-
if (handleSIGINT) {
|
|
22332
|
-
operation.addAbortSource((abort) => {
|
|
22333
|
-
return raceProcessTeardownEvents(
|
|
22334
|
-
{
|
|
22335
|
-
SIGINT: true,
|
|
22336
|
-
},
|
|
22337
|
-
abort,
|
|
22338
|
-
);
|
|
22339
|
-
});
|
|
22340
|
-
}
|
|
22341
22495
|
const startDevServerTask = createTaskLog("start dev server", {
|
|
22342
22496
|
disabled: !logger.levels.info,
|
|
22343
22497
|
});
|
|
22344
22498
|
|
|
22345
|
-
const
|
|
22499
|
+
const serverStopCallbackSet = new Set();
|
|
22346
22500
|
const serverEventsDispatcher = createServerEventsDispatcher();
|
|
22347
|
-
|
|
22501
|
+
serverStopCallbackSet.add(() => {
|
|
22348
22502
|
serverEventsDispatcher.destroy();
|
|
22349
22503
|
});
|
|
22350
22504
|
const kitchenCache = new Map();
|
|
@@ -22419,7 +22573,7 @@ const startDevServer = async ({
|
|
|
22419
22573
|
cooldownBetweenFileEvents: clientAutoreload.cooldownBetweenFileEvents,
|
|
22420
22574
|
},
|
|
22421
22575
|
);
|
|
22422
|
-
|
|
22576
|
+
serverStopCallbackSet.add(stopWatchingSourceFiles);
|
|
22423
22577
|
|
|
22424
22578
|
const getOrCreateKitchen = (request) => {
|
|
22425
22579
|
const { runtimeName, runtimeVersion } = parseUserAgentHeader(
|
|
@@ -22544,7 +22698,7 @@ const startDevServer = async ({
|
|
|
22544
22698
|
},
|
|
22545
22699
|
);
|
|
22546
22700
|
|
|
22547
|
-
|
|
22701
|
+
serverStopCallbackSet.add(() => {
|
|
22548
22702
|
kitchen.pluginController.callHooks("destroy", kitchen.context);
|
|
22549
22703
|
});
|
|
22550
22704
|
{
|
|
@@ -22708,7 +22862,7 @@ const startDevServer = async ({
|
|
|
22708
22862
|
if (urlInfo.content !== undefined) {
|
|
22709
22863
|
kitchen.context.logger.error(`Error while handling ${request.url}:
|
|
22710
22864
|
${originalError.reasonCode || originalError.code}
|
|
22711
|
-
${e.
|
|
22865
|
+
${e.trace?.message}`);
|
|
22712
22866
|
return {
|
|
22713
22867
|
url: reference.url,
|
|
22714
22868
|
status: 200,
|
|
@@ -22841,10 +22995,10 @@ ${e.traceMessage}`);
|
|
|
22841
22995
|
});
|
|
22842
22996
|
server.stoppedPromise.then((reason) => {
|
|
22843
22997
|
onStop();
|
|
22844
|
-
|
|
22998
|
+
for (const serverStopCallback of serverStopCallbackSet) {
|
|
22845
22999
|
serverStopCallback(reason);
|
|
22846
|
-
}
|
|
22847
|
-
|
|
23000
|
+
}
|
|
23001
|
+
serverStopCallbackSet.clear();
|
|
22848
23002
|
});
|
|
22849
23003
|
startDevServerTask.done();
|
|
22850
23004
|
if (hostname) {
|