@jsenv/core 31.2.0 → 32.0.0
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/dist/js/v8_coverage.js +36 -23
- package/dist/main.js +482 -546
- package/package.json +5 -5
- package/src/basic_fetch.js +42 -0
- package/src/build/build.js +81 -93
- package/src/build/start_build_server.js +32 -112
- package/src/dev/file_service.js +49 -66
- package/src/dev/start_dev_server.js +43 -94
- package/src/execute/execute.js +4 -1
- package/src/execute/runtimes/node/node_child_process.js +0 -1
- package/src/jsenv_internal_directory.js +18 -0
- package/src/kitchen/kitchen.js +2 -0
- package/src/lookup_package_directory.js +34 -0
- package/src/plugins/explorer/jsenv_plugin_explorer.js +5 -4
- package/src/plugins/plugins.js +4 -16
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +2 -2
- package/src/test/coverage/v8_coverage_node_directory.js +4 -2
- package/src/test/execute_plan.js +6 -67
- package/src/test/execute_test_plan.js +199 -45
- package/src/watch_source_files.js +50 -0
package/dist/main.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { workerData, Worker, parentPort } from "node:worker_threads";
|
|
2
1
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
3
2
|
import { chmod, stat, lstat, readdir, promises, unlink, openSync, closeSync, rmdir, readFile as readFile$1, readFileSync as readFileSync$1, watch, readdirSync, statSync, writeFile as writeFile$1, writeFileSync as writeFileSync$1, mkdirSync, createReadStream, existsSync, realpathSync } from "node:fs";
|
|
4
3
|
import crypto, { createHash } from "node:crypto";
|
|
5
|
-
import { dirname, extname } from "node:path";
|
|
4
|
+
import { dirname, extname, basename } from "node:path";
|
|
6
5
|
import { URL_META, filterV8Coverage } from "./js/v8_coverage.js";
|
|
7
6
|
import process$1, { memoryUsage } from "node:process";
|
|
8
7
|
import os, { networkInterfaces } from "node:os";
|
|
@@ -26,6 +25,7 @@ import stripAnsi from "strip-ansi";
|
|
|
26
25
|
import { createId } from "@paralleldrive/cuid2";
|
|
27
26
|
import { runInNewContext } from "node:vm";
|
|
28
27
|
import { fork } from "node:child_process";
|
|
28
|
+
import { Worker } from "node:worker_threads";
|
|
29
29
|
|
|
30
30
|
/*
|
|
31
31
|
* data:[<mediatype>][;base64],<data>
|
|
@@ -454,11 +454,6 @@ const resolveUrl$1 = (specifier, baseUrl) => {
|
|
|
454
454
|
return String(new URL(specifier, baseUrl));
|
|
455
455
|
};
|
|
456
456
|
|
|
457
|
-
const resolveDirectoryUrl = (specifier, baseUrl) => {
|
|
458
|
-
const url = resolveUrl$1(specifier, baseUrl);
|
|
459
|
-
return ensurePathnameTrailingSlash(url);
|
|
460
|
-
};
|
|
461
|
-
|
|
462
457
|
const getCommonPathname = (pathname, otherPathname) => {
|
|
463
458
|
if (pathname === otherPathname) {
|
|
464
459
|
return pathname;
|
|
@@ -629,14 +624,14 @@ const validateDirectoryUrl = value => {
|
|
|
629
624
|
value: ensurePathnameTrailingSlash(urlString)
|
|
630
625
|
};
|
|
631
626
|
};
|
|
632
|
-
const assertAndNormalizeDirectoryUrl = directoryUrl => {
|
|
627
|
+
const assertAndNormalizeDirectoryUrl = (directoryUrl, name = "directoryUrl") => {
|
|
633
628
|
const {
|
|
634
629
|
valid,
|
|
635
630
|
message,
|
|
636
631
|
value
|
|
637
632
|
} = validateDirectoryUrl(directoryUrl);
|
|
638
633
|
if (!valid) {
|
|
639
|
-
throw new TypeError(
|
|
634
|
+
throw new TypeError(`${name} ${message}, got ${value}`);
|
|
640
635
|
}
|
|
641
636
|
return value;
|
|
642
637
|
};
|
|
@@ -678,14 +673,14 @@ const validateFileUrl = (value, baseUrl) => {
|
|
|
678
673
|
value: urlString
|
|
679
674
|
};
|
|
680
675
|
};
|
|
681
|
-
const assertAndNormalizeFileUrl = (fileUrl, baseUrl) => {
|
|
676
|
+
const assertAndNormalizeFileUrl = (fileUrl, baseUrl, name = "fileUrl") => {
|
|
682
677
|
const {
|
|
683
678
|
valid,
|
|
684
679
|
message,
|
|
685
680
|
value
|
|
686
681
|
} = validateFileUrl(fileUrl, baseUrl);
|
|
687
682
|
if (!valid) {
|
|
688
|
-
throw new TypeError(
|
|
683
|
+
throw new TypeError(`${name} ${message}, got ${fileUrl}`);
|
|
689
684
|
}
|
|
690
685
|
return value;
|
|
691
686
|
};
|
|
@@ -7063,6 +7058,108 @@ const createServerEventsDispatcher = () => {
|
|
|
7063
7058
|
};
|
|
7064
7059
|
};
|
|
7065
7060
|
|
|
7061
|
+
const lookupPackageDirectory = currentUrl => {
|
|
7062
|
+
if (currentUrl === "file:///") {
|
|
7063
|
+
return null;
|
|
7064
|
+
}
|
|
7065
|
+
const packageJsonFileUrl = `${currentUrl}package.json`;
|
|
7066
|
+
if (existsSync(new URL(packageJsonFileUrl))) {
|
|
7067
|
+
return currentUrl;
|
|
7068
|
+
}
|
|
7069
|
+
return lookupPackageDirectory(getParentUrl$1(currentUrl));
|
|
7070
|
+
};
|
|
7071
|
+
const getParentUrl$1 = url => {
|
|
7072
|
+
if (url.startsWith("file://")) {
|
|
7073
|
+
// With node.js new URL('../', 'file:///C:/').href
|
|
7074
|
+
// returns "file:///C:/" instead of "file:///"
|
|
7075
|
+
const resource = url.slice("file://".length);
|
|
7076
|
+
const slashLastIndex = resource.lastIndexOf("/");
|
|
7077
|
+
if (slashLastIndex === -1) {
|
|
7078
|
+
return url;
|
|
7079
|
+
}
|
|
7080
|
+
const lastCharIndex = resource.length - 1;
|
|
7081
|
+
if (slashLastIndex === lastCharIndex) {
|
|
7082
|
+
const slashBeforeLastIndex = resource.lastIndexOf("/", slashLastIndex - 1);
|
|
7083
|
+
if (slashBeforeLastIndex === -1) {
|
|
7084
|
+
return url;
|
|
7085
|
+
}
|
|
7086
|
+
return `file://${resource.slice(0, slashBeforeLastIndex + 1)}`;
|
|
7087
|
+
}
|
|
7088
|
+
return `file://${resource.slice(0, slashLastIndex + 1)}`;
|
|
7089
|
+
}
|
|
7090
|
+
return new URL(url.endsWith("/") ? "../" : "./", url).href;
|
|
7091
|
+
};
|
|
7092
|
+
|
|
7093
|
+
const determineJsenvInternalDirectoryUrl = currentUrl => {
|
|
7094
|
+
const packageDirectoryUrl = lookupPackageDirectory(currentUrl);
|
|
7095
|
+
if (packageDirectoryUrl) {
|
|
7096
|
+
return `${packageDirectoryUrl}.jsenv/${getDirectoryName(packageDirectoryUrl)}/`;
|
|
7097
|
+
}
|
|
7098
|
+
return `${currentUrl}.jsenv/`;
|
|
7099
|
+
};
|
|
7100
|
+
const getDirectoryName = directoryUrl => {
|
|
7101
|
+
const {
|
|
7102
|
+
pathname
|
|
7103
|
+
} = new URL(directoryUrl);
|
|
7104
|
+
return basename(pathname);
|
|
7105
|
+
};
|
|
7106
|
+
|
|
7107
|
+
const watchSourceFiles = (sourceDirectoryUrl, callback, {
|
|
7108
|
+
sourceFileConfig = {},
|
|
7109
|
+
keepProcessAlive,
|
|
7110
|
+
cooldownBetweenFileEvents
|
|
7111
|
+
}) => {
|
|
7112
|
+
// Project should use a dedicated directory (usually "src/")
|
|
7113
|
+
// passed to the dev server via "sourceDirectoryUrl" param
|
|
7114
|
+
// In that case all files inside the source directory should be watched
|
|
7115
|
+
// But some project might want to use their root directory as source directory
|
|
7116
|
+
// In that case source directory might contain files matching "node_modules/*" or ".git/*"
|
|
7117
|
+
// And jsenv should not consider these as source files and watch them (to not hurt performances)
|
|
7118
|
+
const watchPatterns = {
|
|
7119
|
+
"**/*": true,
|
|
7120
|
+
// by default watch everything inside the source directory
|
|
7121
|
+
"**/.*": false,
|
|
7122
|
+
// file starting with a dot -> do not watch
|
|
7123
|
+
"**/.*/": false,
|
|
7124
|
+
// directory starting with a dot -> do not watch
|
|
7125
|
+
"**/node_modules/": false,
|
|
7126
|
+
// node_modules directory -> do not watch
|
|
7127
|
+
...sourceFileConfig
|
|
7128
|
+
};
|
|
7129
|
+
const stopWatchingSourceFiles = registerDirectoryLifecycle(sourceDirectoryUrl, {
|
|
7130
|
+
watchPatterns,
|
|
7131
|
+
cooldownBetweenFileEvents,
|
|
7132
|
+
keepProcessAlive,
|
|
7133
|
+
recursive: true,
|
|
7134
|
+
added: ({
|
|
7135
|
+
relativeUrl
|
|
7136
|
+
}) => {
|
|
7137
|
+
callback({
|
|
7138
|
+
url: new URL(relativeUrl, sourceDirectoryUrl).href,
|
|
7139
|
+
event: "added"
|
|
7140
|
+
});
|
|
7141
|
+
},
|
|
7142
|
+
updated: ({
|
|
7143
|
+
relativeUrl
|
|
7144
|
+
}) => {
|
|
7145
|
+
callback({
|
|
7146
|
+
url: new URL(relativeUrl, sourceDirectoryUrl).href,
|
|
7147
|
+
event: "modified"
|
|
7148
|
+
});
|
|
7149
|
+
},
|
|
7150
|
+
removed: ({
|
|
7151
|
+
relativeUrl
|
|
7152
|
+
}) => {
|
|
7153
|
+
callback({
|
|
7154
|
+
url: new URL(relativeUrl, sourceDirectoryUrl).href,
|
|
7155
|
+
event: "removed"
|
|
7156
|
+
});
|
|
7157
|
+
}
|
|
7158
|
+
});
|
|
7159
|
+
stopWatchingSourceFiles.watchPatterns = watchPatterns;
|
|
7160
|
+
return stopWatchingSourceFiles;
|
|
7161
|
+
};
|
|
7162
|
+
|
|
7066
7163
|
const urlSpecifierEncoding = {
|
|
7067
7164
|
encode: reference => {
|
|
7068
7165
|
const {
|
|
@@ -8653,6 +8750,7 @@ const createKitchen = ({
|
|
|
8653
8750
|
signal,
|
|
8654
8751
|
logLevel,
|
|
8655
8752
|
rootDirectoryUrl,
|
|
8753
|
+
jsenvInternalDirectoryUrl,
|
|
8656
8754
|
urlGraph,
|
|
8657
8755
|
dev = false,
|
|
8658
8756
|
build = false,
|
|
@@ -8678,6 +8776,7 @@ const createKitchen = ({
|
|
|
8678
8776
|
signal,
|
|
8679
8777
|
logger,
|
|
8680
8778
|
rootDirectoryUrl,
|
|
8779
|
+
jsenvInternalDirectoryUrl,
|
|
8681
8780
|
urlGraph,
|
|
8682
8781
|
dev,
|
|
8683
8782
|
build,
|
|
@@ -17063,7 +17162,7 @@ const addRelationshipWithPackageJson = ({
|
|
|
17063
17162
|
*/
|
|
17064
17163
|
const jsenvPluginUrlResolution = ({
|
|
17065
17164
|
runtimeCompat,
|
|
17066
|
-
|
|
17165
|
+
mainFileUrl,
|
|
17067
17166
|
urlResolution
|
|
17068
17167
|
}) => {
|
|
17069
17168
|
const resolveUrlUsingWebResolution = reference => {
|
|
@@ -17124,7 +17223,7 @@ const jsenvPluginUrlResolution = ({
|
|
|
17124
17223
|
appliesDuring: "*",
|
|
17125
17224
|
resolveUrl: (reference, context) => {
|
|
17126
17225
|
if (reference.specifier === "/") {
|
|
17127
|
-
return String(
|
|
17226
|
+
return String(mainFileUrl);
|
|
17128
17227
|
}
|
|
17129
17228
|
if (reference.specifier[0] === "/") {
|
|
17130
17229
|
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl).href;
|
|
@@ -20192,13 +20291,14 @@ const explorerHtmlFileUrl = new URL("./html/explorer.html", import.meta.url);
|
|
|
20192
20291
|
const jsenvPluginExplorer = ({
|
|
20193
20292
|
groups = {
|
|
20194
20293
|
src: {
|
|
20195
|
-
"
|
|
20294
|
+
"./**/*.html": true,
|
|
20295
|
+
"./**/*.test.html": false
|
|
20196
20296
|
},
|
|
20197
20297
|
tests: {
|
|
20198
|
-
"
|
|
20298
|
+
"./**/*.test.html": true
|
|
20199
20299
|
}
|
|
20200
20300
|
},
|
|
20201
|
-
|
|
20301
|
+
mainFileUrl
|
|
20202
20302
|
}) => {
|
|
20203
20303
|
const faviconClientFileUrl = new URL("./other/jsenv.png", import.meta.url);
|
|
20204
20304
|
return {
|
|
@@ -20206,7 +20306,7 @@ const jsenvPluginExplorer = ({
|
|
|
20206
20306
|
appliesDuring: "dev",
|
|
20207
20307
|
transformUrlContent: {
|
|
20208
20308
|
html: async (urlInfo, context) => {
|
|
20209
|
-
if (urlInfo.url !==
|
|
20309
|
+
if (urlInfo.url !== mainFileUrl) {
|
|
20210
20310
|
return null;
|
|
20211
20311
|
}
|
|
20212
20312
|
let html = urlInfo.content;
|
|
@@ -20308,6 +20408,7 @@ injectRibbon(${paramsJson})`
|
|
|
20308
20408
|
|
|
20309
20409
|
const getCorePlugins = ({
|
|
20310
20410
|
rootDirectoryUrl,
|
|
20411
|
+
mainFileUrl,
|
|
20311
20412
|
runtimeCompat,
|
|
20312
20413
|
urlAnalysis = {},
|
|
20313
20414
|
urlResolution = {},
|
|
@@ -20315,7 +20416,6 @@ const getCorePlugins = ({
|
|
|
20315
20416
|
directoryReferenceAllowed,
|
|
20316
20417
|
supervisor,
|
|
20317
20418
|
transpilation = true,
|
|
20318
|
-
clientMainFileUrl,
|
|
20319
20419
|
clientAutoreload = false,
|
|
20320
20420
|
clientFileChangeCallbackList,
|
|
20321
20421
|
clientFilesPruneCallbackList,
|
|
@@ -20339,11 +20439,6 @@ const getCorePlugins = ({
|
|
|
20339
20439
|
if (clientAutoreload === true) {
|
|
20340
20440
|
clientAutoreload = {};
|
|
20341
20441
|
}
|
|
20342
|
-
if (clientMainFileUrl === undefined) {
|
|
20343
|
-
clientMainFileUrl = explorer ? String(explorerHtmlFileUrl) : String(new URL("./index.html", rootDirectoryUrl));
|
|
20344
|
-
} else {
|
|
20345
|
-
clientMainFileUrl = String(clientMainFileUrl);
|
|
20346
|
-
}
|
|
20347
20442
|
if (ribbon === true) {
|
|
20348
20443
|
ribbon = {};
|
|
20349
20444
|
}
|
|
@@ -20362,7 +20457,7 @@ const getCorePlugins = ({
|
|
|
20362
20457
|
...fileSystemMagicRedirection
|
|
20363
20458
|
}), jsenvPluginHttpUrls(), jsenvPluginUrlResolution({
|
|
20364
20459
|
runtimeCompat,
|
|
20365
|
-
|
|
20460
|
+
mainFileUrl,
|
|
20366
20461
|
urlResolution
|
|
20367
20462
|
}), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []), jsenvPluginNodeRuntime({
|
|
20368
20463
|
runtimeCompat
|
|
@@ -20372,7 +20467,7 @@ const getCorePlugins = ({
|
|
|
20372
20467
|
clientFilesPruneCallbackList
|
|
20373
20468
|
})] : []), ...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []), ...(explorer ? [jsenvPluginExplorer({
|
|
20374
20469
|
...explorer,
|
|
20375
|
-
|
|
20470
|
+
mainFileUrl
|
|
20376
20471
|
})] : []), ...(ribbon ? [jsenvPluginRibbon({
|
|
20377
20472
|
rootDirectoryUrl,
|
|
20378
20473
|
...ribbon
|
|
@@ -20731,12 +20826,13 @@ const defaultRuntimeCompat = {
|
|
|
20731
20826
|
/**
|
|
20732
20827
|
* Generate an optimized version of source files into a directory
|
|
20733
20828
|
* @param {Object} buildParameters
|
|
20734
|
-
* @param {string|url} buildParameters.
|
|
20829
|
+
* @param {string|url} buildParameters.sourceDirectoryUrl
|
|
20735
20830
|
* Directory containing source files
|
|
20831
|
+
* @param {object} buildParameters.entryPoints
|
|
20832
|
+
* Object where keys are paths to source files and values are their future name in the build directory.
|
|
20833
|
+
* Keys are relative to sourceDirectoryUrl
|
|
20736
20834
|
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
20737
20835
|
* Directory where optimized files will be written
|
|
20738
|
-
* @param {object} buildParameters.entryPoints
|
|
20739
|
-
* Describe entry point paths and control their names in the build directory
|
|
20740
20836
|
* @param {object} buildParameters.runtimeCompat
|
|
20741
20837
|
* Code generated will be compatible with these runtimes
|
|
20742
20838
|
* @param {string} [buildParameters.assetsDirectory=""]
|
|
@@ -20761,10 +20857,10 @@ const build = async ({
|
|
|
20761
20857
|
signal = new AbortController().signal,
|
|
20762
20858
|
handleSIGINT = true,
|
|
20763
20859
|
logLevel = "info",
|
|
20764
|
-
|
|
20860
|
+
sourceDirectoryUrl,
|
|
20861
|
+
entryPoints = {},
|
|
20765
20862
|
buildDirectoryUrl,
|
|
20766
20863
|
assetsDirectory = "",
|
|
20767
|
-
entryPoints = {},
|
|
20768
20864
|
runtimeCompat = defaultRuntimeCompat,
|
|
20769
20865
|
base = runtimeCompat.node ? "./" : "/",
|
|
20770
20866
|
plugins = [],
|
|
@@ -20781,9 +20877,7 @@ const build = async ({
|
|
|
20781
20877
|
// "filename", "search_param"
|
|
20782
20878
|
versioningViaImportmap = true,
|
|
20783
20879
|
lineBreakNormalization = process.platform === "win32",
|
|
20784
|
-
|
|
20785
|
-
"./src/": true
|
|
20786
|
-
},
|
|
20880
|
+
sourceFilesConfig = {},
|
|
20787
20881
|
cooldownBetweenFileEvents,
|
|
20788
20882
|
watch = false,
|
|
20789
20883
|
directoryToClean,
|
|
@@ -20799,16 +20893,27 @@ const build = async ({
|
|
|
20799
20893
|
if (unexpectedParamNames.length > 0) {
|
|
20800
20894
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
20801
20895
|
}
|
|
20802
|
-
|
|
20803
|
-
if (
|
|
20804
|
-
throw new TypeError(`
|
|
20896
|
+
sourceDirectoryUrl = assertAndNormalizeDirectoryUrl(sourceDirectoryUrl, "sourceDirectoryUrl");
|
|
20897
|
+
if (typeof entryPoints !== "object" || entryPoints === null) {
|
|
20898
|
+
throw new TypeError(`entryPoints must be an object, got ${entryPoints}`);
|
|
20805
20899
|
}
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
|
|
20809
|
-
|
|
20900
|
+
const keys = Object.keys(entryPoints);
|
|
20901
|
+
keys.forEach(key => {
|
|
20902
|
+
if (!key.startsWith("./")) {
|
|
20903
|
+
throw new TypeError(`entryPoints keys must start with "./", found ${key}`);
|
|
20904
|
+
}
|
|
20905
|
+
const value = entryPoints[key];
|
|
20906
|
+
if (typeof value !== "string") {
|
|
20907
|
+
throw new TypeError(`entryPoints values must be strings, found "${value}" on key "${key}"`);
|
|
20908
|
+
}
|
|
20909
|
+
if (value.includes("/")) {
|
|
20910
|
+
throw new TypeError(`entryPoints values must be plain strings (no "/"), found "${value}" on key "${key}"`);
|
|
20911
|
+
}
|
|
20912
|
+
});
|
|
20913
|
+
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl, "buildDirectoryUrl");
|
|
20914
|
+
if (!["filename", "search_param"].includes(versioningMethod)) {
|
|
20915
|
+
throw new TypeError(`versioningMethod must be "filename" or "search_param", got ${versioning}`);
|
|
20810
20916
|
}
|
|
20811
|
-
buildDirectoryUrl = buildDirectoryUrlValidation.value;
|
|
20812
20917
|
}
|
|
20813
20918
|
const operation = Abort.startOperation();
|
|
20814
20919
|
operation.addAbortSignal(signal);
|
|
@@ -20819,12 +20924,6 @@ const build = async ({
|
|
|
20819
20924
|
}, abort);
|
|
20820
20925
|
});
|
|
20821
20926
|
}
|
|
20822
|
-
assertEntryPoints({
|
|
20823
|
-
entryPoints
|
|
20824
|
-
});
|
|
20825
|
-
if (!["filename", "search_param"].includes(versioningMethod)) {
|
|
20826
|
-
throw new Error(`Unexpected "versioningMethod": must be "filename", "search_param"; got ${versioning}`);
|
|
20827
|
-
}
|
|
20828
20927
|
if (assetsDirectory && assetsDirectory[assetsDirectory.length - 1] !== "/") {
|
|
20829
20928
|
assetsDirectory = `${assetsDirectory}/`;
|
|
20830
20929
|
}
|
|
@@ -20835,9 +20934,10 @@ const build = async ({
|
|
|
20835
20934
|
directoryToClean = new URL(assetsDirectory, buildDirectoryUrl).href;
|
|
20836
20935
|
}
|
|
20837
20936
|
}
|
|
20937
|
+
const jsenvInternalDirectoryUrl = determineJsenvInternalDirectoryUrl(sourceDirectoryUrl);
|
|
20838
20938
|
const asFormattedBuildUrl = (generatedUrl, reference) => {
|
|
20839
20939
|
if (base === "./") {
|
|
20840
|
-
const urlRelativeToParent = urlToRelativeUrl(generatedUrl, reference.parentUrl ===
|
|
20940
|
+
const urlRelativeToParent = urlToRelativeUrl(generatedUrl, reference.parentUrl === sourceDirectoryUrl ? buildDirectoryUrl : reference.parentUrl);
|
|
20841
20941
|
if (urlRelativeToParent[0] !== ".") {
|
|
20842
20942
|
// ensure "./" on relative url (otherwise it could be a "bare specifier")
|
|
20843
20943
|
return `./${urlRelativeToParent}`;
|
|
@@ -20887,7 +20987,8 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20887
20987
|
const rawGraphKitchen = createKitchen({
|
|
20888
20988
|
signal,
|
|
20889
20989
|
logLevel,
|
|
20890
|
-
rootDirectoryUrl,
|
|
20990
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20991
|
+
jsenvInternalDirectoryUrl,
|
|
20891
20992
|
urlGraph: rawGraph,
|
|
20892
20993
|
build: true,
|
|
20893
20994
|
runtimeCompat,
|
|
@@ -20906,7 +21007,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20906
21007
|
return null;
|
|
20907
21008
|
}
|
|
20908
21009
|
}, ...getCorePlugins({
|
|
20909
|
-
rootDirectoryUrl,
|
|
21010
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20910
21011
|
urlGraph: rawGraph,
|
|
20911
21012
|
runtimeCompat,
|
|
20912
21013
|
urlAnalysis,
|
|
@@ -20923,7 +21024,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20923
21024
|
sourcemaps,
|
|
20924
21025
|
sourcemapsSourcesContent,
|
|
20925
21026
|
writeGeneratedFiles,
|
|
20926
|
-
outDirectoryUrl: new URL(
|
|
21027
|
+
outDirectoryUrl: new URL("build/", jsenvInternalDirectoryUrl)
|
|
20927
21028
|
});
|
|
20928
21029
|
const buildUrlsGenerator = createBuildUrlsGenerator({
|
|
20929
21030
|
buildDirectoryUrl,
|
|
@@ -20945,12 +21046,13 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20945
21046
|
const bundlers = {};
|
|
20946
21047
|
const finalGraph = createUrlGraph();
|
|
20947
21048
|
const urlAnalysisPlugin = jsenvPluginUrlAnalysis({
|
|
20948
|
-
rootDirectoryUrl,
|
|
21049
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20949
21050
|
...urlAnalysis
|
|
20950
21051
|
});
|
|
20951
21052
|
const finalGraphKitchen = createKitchen({
|
|
20952
21053
|
logLevel,
|
|
20953
21054
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
21055
|
+
jsenvInternalDirectoryUrl,
|
|
20954
21056
|
urlGraph: finalGraph,
|
|
20955
21057
|
build: true,
|
|
20956
21058
|
runtimeCompat,
|
|
@@ -21197,7 +21299,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21197
21299
|
sourcemapsSourcesContent,
|
|
21198
21300
|
sourcemapsSourcesRelative: !versioning,
|
|
21199
21301
|
writeGeneratedFiles,
|
|
21200
|
-
outDirectoryUrl: new URL("
|
|
21302
|
+
outDirectoryUrl: new URL("postbuild/", jsenvInternalDirectoryUrl)
|
|
21201
21303
|
});
|
|
21202
21304
|
const finalEntryUrls = [];
|
|
21203
21305
|
{
|
|
@@ -21206,7 +21308,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21206
21308
|
});
|
|
21207
21309
|
try {
|
|
21208
21310
|
if (writeGeneratedFiles) {
|
|
21209
|
-
await ensureEmptyDirectory(new URL(
|
|
21311
|
+
await ensureEmptyDirectory(new URL(`build/`, sourceDirectoryUrl));
|
|
21210
21312
|
}
|
|
21211
21313
|
const rawUrlGraphLoader = createUrlGraphLoader(rawGraphKitchen.kitchenContext);
|
|
21212
21314
|
Object.keys(entryPoints).forEach(key => {
|
|
@@ -21214,7 +21316,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21214
21316
|
trace: {
|
|
21215
21317
|
message: `"${key}" in entryPoints parameter`
|
|
21216
21318
|
},
|
|
21217
|
-
parentUrl:
|
|
21319
|
+
parentUrl: sourceDirectoryUrl,
|
|
21218
21320
|
type: "entry_point",
|
|
21219
21321
|
specifier: key
|
|
21220
21322
|
});
|
|
@@ -21420,7 +21522,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21420
21522
|
});
|
|
21421
21523
|
try {
|
|
21422
21524
|
if (writeGeneratedFiles) {
|
|
21423
|
-
await ensureEmptyDirectory(new URL(
|
|
21525
|
+
await ensureEmptyDirectory(new URL(`postbuild/`, jsenvInternalDirectoryUrl));
|
|
21424
21526
|
}
|
|
21425
21527
|
const finalUrlGraphLoader = createUrlGraphLoader(finalGraphKitchen.kitchenContext);
|
|
21426
21528
|
entryUrls.forEach(entryUrl => {
|
|
@@ -21428,7 +21530,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21428
21530
|
trace: {
|
|
21429
21531
|
message: `entryPoint`
|
|
21430
21532
|
},
|
|
21431
|
-
parentUrl:
|
|
21533
|
+
parentUrl: sourceDirectoryUrl,
|
|
21432
21534
|
type: "entry_point",
|
|
21433
21535
|
specifier: entryUrl
|
|
21434
21536
|
});
|
|
@@ -21620,6 +21722,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21620
21722
|
const versioningKitchen = createKitchen({
|
|
21621
21723
|
logLevel: logger.level,
|
|
21622
21724
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
21725
|
+
jsenvInternalDirectoryUrl,
|
|
21623
21726
|
urlGraph: finalGraph,
|
|
21624
21727
|
build: true,
|
|
21625
21728
|
runtimeCompat,
|
|
@@ -21712,7 +21815,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21712
21815
|
sourcemapsSourcesContent,
|
|
21713
21816
|
sourcemapsSourcesRelative: true,
|
|
21714
21817
|
writeGeneratedFiles,
|
|
21715
|
-
outDirectoryUrl: new URL("
|
|
21818
|
+
outDirectoryUrl: new URL("postbuild/", jsenvInternalDirectoryUrl)
|
|
21716
21819
|
});
|
|
21717
21820
|
const versioningUrlGraphLoader = createUrlGraphLoader(versioningKitchen.kitchenContext);
|
|
21718
21821
|
finalEntryUrls.forEach(finalEntryUrl => {
|
|
@@ -22088,13 +22191,12 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22088
22191
|
};
|
|
22089
22192
|
startBuild();
|
|
22090
22193
|
let startTimeout;
|
|
22091
|
-
const
|
|
22092
|
-
|
|
22194
|
+
const stopWatchingSourceFiles = watchSourceFiles(sourceDirectoryUrl, ({
|
|
22195
|
+
url,
|
|
22093
22196
|
event
|
|
22094
22197
|
}) => {
|
|
22095
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
22096
22198
|
if (watchFilesTask) {
|
|
22097
|
-
watchFilesTask.happen(`${url.slice(
|
|
22199
|
+
watchFilesTask.happen(`${url.slice(sourceDirectoryUrl.length)} ${event}`);
|
|
22098
22200
|
watchFilesTask = null;
|
|
22099
22201
|
}
|
|
22100
22202
|
buildAbortController.abort();
|
|
@@ -22103,42 +22205,16 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22103
22205
|
// then logs about re-running the build happens
|
|
22104
22206
|
clearTimeout(startTimeout);
|
|
22105
22207
|
startTimeout = setTimeout(startBuild, 20);
|
|
22106
|
-
}
|
|
22107
|
-
|
|
22108
|
-
watchPatterns: clientFiles,
|
|
22109
|
-
cooldownBetweenFileEvents,
|
|
22208
|
+
}, {
|
|
22209
|
+
sourceFilesConfig,
|
|
22110
22210
|
keepProcessAlive: true,
|
|
22111
|
-
|
|
22112
|
-
added: ({
|
|
22113
|
-
relativeUrl
|
|
22114
|
-
}) => {
|
|
22115
|
-
clientFileChangeCallback({
|
|
22116
|
-
relativeUrl,
|
|
22117
|
-
event: "added"
|
|
22118
|
-
});
|
|
22119
|
-
},
|
|
22120
|
-
updated: ({
|
|
22121
|
-
relativeUrl
|
|
22122
|
-
}) => {
|
|
22123
|
-
clientFileChangeCallback({
|
|
22124
|
-
relativeUrl,
|
|
22125
|
-
event: "modified"
|
|
22126
|
-
});
|
|
22127
|
-
},
|
|
22128
|
-
removed: ({
|
|
22129
|
-
relativeUrl
|
|
22130
|
-
}) => {
|
|
22131
|
-
clientFileChangeCallback({
|
|
22132
|
-
relativeUrl,
|
|
22133
|
-
event: "removed"
|
|
22134
|
-
});
|
|
22135
|
-
}
|
|
22211
|
+
cooldownBetweenFileEvents
|
|
22136
22212
|
});
|
|
22137
22213
|
operation.addAbortCallback(() => {
|
|
22138
|
-
|
|
22214
|
+
stopWatchingSourceFiles();
|
|
22139
22215
|
});
|
|
22140
22216
|
await firstBuildPromise;
|
|
22141
|
-
return
|
|
22217
|
+
return stopWatchingSourceFiles;
|
|
22142
22218
|
};
|
|
22143
22219
|
const findKey = (map, value) => {
|
|
22144
22220
|
for (const [keyCandidate, valueCandidate] of map) {
|
|
@@ -22164,26 +22240,6 @@ const injectVersionIntoBuildUrl = ({
|
|
|
22164
22240
|
const versionedUrl = setUrlFilename(buildUrl, versionedFilename);
|
|
22165
22241
|
return versionedUrl;
|
|
22166
22242
|
};
|
|
22167
|
-
const assertEntryPoints = ({
|
|
22168
|
-
entryPoints
|
|
22169
|
-
}) => {
|
|
22170
|
-
if (typeof entryPoints !== "object" || entryPoints === null) {
|
|
22171
|
-
throw new TypeError(`entryPoints must be an object, got ${entryPoints}`);
|
|
22172
|
-
}
|
|
22173
|
-
const keys = Object.keys(entryPoints);
|
|
22174
|
-
keys.forEach(key => {
|
|
22175
|
-
if (!key.startsWith("./")) {
|
|
22176
|
-
throw new TypeError(`unexpected key in entryPoints, all keys must start with ./ but found ${key}`);
|
|
22177
|
-
}
|
|
22178
|
-
const value = entryPoints[key];
|
|
22179
|
-
if (typeof value !== "string") {
|
|
22180
|
-
throw new TypeError(`unexpected value in entryPoints, all values must be strings found ${value} for key ${key}`);
|
|
22181
|
-
}
|
|
22182
|
-
if (value.includes("/")) {
|
|
22183
|
-
throw new TypeError(`unexpected value in entryPoints, all values must be plain strings (no "/") but found ${value} for key ${key}`);
|
|
22184
|
-
}
|
|
22185
|
-
});
|
|
22186
|
-
};
|
|
22187
22243
|
const isUsed = urlInfo => {
|
|
22188
22244
|
// nothing uses this url anymore
|
|
22189
22245
|
// - versioning update inline content
|
|
@@ -22206,57 +22262,6 @@ const canUseVersionedUrl = urlInfo => {
|
|
|
22206
22262
|
return urlInfo.type !== "webmanifest";
|
|
22207
22263
|
};
|
|
22208
22264
|
|
|
22209
|
-
// https://nodejs.org/api/worker_threads.html
|
|
22210
|
-
const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
22211
|
-
const workerFilePath = fileURLToPath(workerFileUrl);
|
|
22212
|
-
const isPrimary = !workerData || workerData.workerFilePath !== workerFilePath;
|
|
22213
|
-
let worker;
|
|
22214
|
-
const terminate = async () => {
|
|
22215
|
-
if (worker) {
|
|
22216
|
-
let _worker = worker;
|
|
22217
|
-
worker = null;
|
|
22218
|
-
const exitPromise = new Promise(resolve => {
|
|
22219
|
-
_worker.once("exit", resolve);
|
|
22220
|
-
});
|
|
22221
|
-
_worker.terminate();
|
|
22222
|
-
await exitPromise;
|
|
22223
|
-
}
|
|
22224
|
-
};
|
|
22225
|
-
const load = async () => {
|
|
22226
|
-
if (!isPrimary) {
|
|
22227
|
-
throw new Error(`worker can be loaded from primary file only`);
|
|
22228
|
-
}
|
|
22229
|
-
worker = new Worker(workerFilePath, {
|
|
22230
|
-
...options,
|
|
22231
|
-
workerData: {
|
|
22232
|
-
...options.workerData,
|
|
22233
|
-
workerFilePath
|
|
22234
|
-
}
|
|
22235
|
-
});
|
|
22236
|
-
worker.once("error", error => {
|
|
22237
|
-
console.error(error);
|
|
22238
|
-
});
|
|
22239
|
-
worker.once("exit", () => {
|
|
22240
|
-
worker = null;
|
|
22241
|
-
});
|
|
22242
|
-
await new Promise(resolve => {
|
|
22243
|
-
worker.once("online", resolve);
|
|
22244
|
-
});
|
|
22245
|
-
return worker;
|
|
22246
|
-
};
|
|
22247
|
-
const reload = async () => {
|
|
22248
|
-
await terminate();
|
|
22249
|
-
await load();
|
|
22250
|
-
};
|
|
22251
|
-
return {
|
|
22252
|
-
isPrimary,
|
|
22253
|
-
isWorker: !isPrimary,
|
|
22254
|
-
load,
|
|
22255
|
-
reload,
|
|
22256
|
-
terminate
|
|
22257
|
-
};
|
|
22258
|
-
};
|
|
22259
|
-
|
|
22260
22265
|
/*
|
|
22261
22266
|
* This plugin is very special because it is here
|
|
22262
22267
|
* to provide "serverEvents" used by other plugins
|
|
@@ -22320,7 +22325,9 @@ const createFileService = ({
|
|
|
22320
22325
|
serverStopCallbacks,
|
|
22321
22326
|
serverEventsDispatcher,
|
|
22322
22327
|
contextCache,
|
|
22323
|
-
|
|
22328
|
+
sourceDirectoryUrl,
|
|
22329
|
+
sourceMainFilePath,
|
|
22330
|
+
sourceFilesConfig,
|
|
22324
22331
|
runtimeCompat,
|
|
22325
22332
|
plugins,
|
|
22326
22333
|
urlAnalysis,
|
|
@@ -22329,8 +22336,6 @@ const createFileService = ({
|
|
|
22329
22336
|
supervisor,
|
|
22330
22337
|
transpilation,
|
|
22331
22338
|
clientAutoreload,
|
|
22332
|
-
clientFiles,
|
|
22333
|
-
clientMainFileUrl,
|
|
22334
22339
|
cooldownBetweenFileEvents,
|
|
22335
22340
|
explorer,
|
|
22336
22341
|
cacheControl,
|
|
@@ -22340,49 +22345,18 @@ const createFileService = ({
|
|
|
22340
22345
|
sourcemapsSourcesContent,
|
|
22341
22346
|
writeGeneratedFiles
|
|
22342
22347
|
}) => {
|
|
22343
|
-
const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href;
|
|
22344
22348
|
const clientFileChangeCallbackList = [];
|
|
22345
22349
|
const clientFilesPruneCallbackList = [];
|
|
22346
|
-
const
|
|
22347
|
-
...clientFiles,
|
|
22348
|
-
".jsenv/": false
|
|
22349
|
-
};
|
|
22350
|
-
const onFileChange = url => {
|
|
22350
|
+
const stopWatchingSourceFiles = watchSourceFiles(sourceDirectoryUrl, fileInfo => {
|
|
22351
22351
|
clientFileChangeCallbackList.forEach(callback => {
|
|
22352
|
-
callback(
|
|
22352
|
+
callback(fileInfo);
|
|
22353
22353
|
});
|
|
22354
|
-
}
|
|
22355
|
-
|
|
22356
|
-
watchPatterns: clientFilePatterns,
|
|
22357
|
-
cooldownBetweenFileEvents,
|
|
22354
|
+
}, {
|
|
22355
|
+
sourceFilesConfig,
|
|
22358
22356
|
keepProcessAlive: false,
|
|
22359
|
-
|
|
22360
|
-
added: ({
|
|
22361
|
-
relativeUrl
|
|
22362
|
-
}) => {
|
|
22363
|
-
onFileChange({
|
|
22364
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
22365
|
-
event: "added"
|
|
22366
|
-
});
|
|
22367
|
-
},
|
|
22368
|
-
updated: ({
|
|
22369
|
-
relativeUrl
|
|
22370
|
-
}) => {
|
|
22371
|
-
onFileChange({
|
|
22372
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
22373
|
-
event: "modified"
|
|
22374
|
-
});
|
|
22375
|
-
},
|
|
22376
|
-
removed: ({
|
|
22377
|
-
relativeUrl
|
|
22378
|
-
}) => {
|
|
22379
|
-
onFileChange({
|
|
22380
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
22381
|
-
event: "removed"
|
|
22382
|
-
});
|
|
22383
|
-
}
|
|
22357
|
+
cooldownBetweenFileEvents
|
|
22384
22358
|
});
|
|
22385
|
-
serverStopCallbacks.push(
|
|
22359
|
+
serverStopCallbacks.push(stopWatchingSourceFiles);
|
|
22386
22360
|
const getOrCreateContext = request => {
|
|
22387
22361
|
const {
|
|
22388
22362
|
runtimeName,
|
|
@@ -22394,8 +22368,8 @@ const createFileService = ({
|
|
|
22394
22368
|
return existingContext;
|
|
22395
22369
|
}
|
|
22396
22370
|
const watchAssociations = URL_META.resolveAssociations({
|
|
22397
|
-
watch:
|
|
22398
|
-
},
|
|
22371
|
+
watch: stopWatchingSourceFiles.watchPatterns
|
|
22372
|
+
}, sourceDirectoryUrl);
|
|
22399
22373
|
const urlGraph = createUrlGraph();
|
|
22400
22374
|
clientFileChangeCallbackList.push(({
|
|
22401
22375
|
url
|
|
@@ -22418,24 +22392,32 @@ const createFileService = ({
|
|
|
22418
22392
|
const clientRuntimeCompat = {
|
|
22419
22393
|
[runtimeName]: runtimeVersion
|
|
22420
22394
|
};
|
|
22395
|
+
const jsenvInternalDirectoryUrl = determineJsenvInternalDirectoryUrl(sourceDirectoryUrl);
|
|
22396
|
+
let mainFileUrl;
|
|
22397
|
+
if (sourceMainFilePath === undefined) {
|
|
22398
|
+
mainFileUrl = explorer ? String(explorerHtmlFileUrl) : String(new URL("./index.html", sourceDirectoryUrl));
|
|
22399
|
+
} else {
|
|
22400
|
+
mainFileUrl = String(new URL(sourceMainFilePath, sourceDirectoryUrl));
|
|
22401
|
+
}
|
|
22421
22402
|
const kitchen = createKitchen({
|
|
22422
22403
|
signal,
|
|
22423
22404
|
logLevel,
|
|
22424
|
-
rootDirectoryUrl,
|
|
22405
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22406
|
+
jsenvInternalDirectoryUrl,
|
|
22425
22407
|
urlGraph,
|
|
22426
22408
|
dev: true,
|
|
22427
22409
|
runtimeCompat,
|
|
22428
22410
|
clientRuntimeCompat,
|
|
22429
22411
|
systemJsTranspilation: !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "script_type_module") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_dynamic") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_meta"),
|
|
22430
22412
|
plugins: [...plugins, ...getCorePlugins({
|
|
22431
|
-
rootDirectoryUrl,
|
|
22413
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22414
|
+
mainFileUrl,
|
|
22432
22415
|
runtimeCompat,
|
|
22433
22416
|
urlAnalysis,
|
|
22434
22417
|
urlResolution,
|
|
22435
22418
|
fileSystemMagicRedirection,
|
|
22436
22419
|
supervisor,
|
|
22437
22420
|
transpilation,
|
|
22438
|
-
clientMainFileUrl,
|
|
22439
22421
|
clientAutoreload,
|
|
22440
22422
|
clientFileChangeCallbackList,
|
|
22441
22423
|
clientFilesPruneCallbackList,
|
|
@@ -22449,7 +22431,7 @@ const createFileService = ({
|
|
|
22449
22431
|
sourcemapsSourcesProtocol,
|
|
22450
22432
|
sourcemapsSourcesContent,
|
|
22451
22433
|
writeGeneratedFiles,
|
|
22452
|
-
outDirectoryUrl: `${
|
|
22434
|
+
outDirectoryUrl: new URL(`${runtimeName}@${runtimeVersion}/`, jsenvInternalDirectoryUrl)
|
|
22453
22435
|
});
|
|
22454
22436
|
urlGraph.createUrlInfoCallbackRef.current = urlInfo => {
|
|
22455
22437
|
const {
|
|
@@ -22528,7 +22510,7 @@ const createFileService = ({
|
|
|
22528
22510
|
if (serverEventNames.length > 0) {
|
|
22529
22511
|
Object.keys(allServerEvents).forEach(serverEventName => {
|
|
22530
22512
|
allServerEvents[serverEventName]({
|
|
22531
|
-
rootDirectoryUrl,
|
|
22513
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22532
22514
|
urlGraph,
|
|
22533
22515
|
dev: true,
|
|
22534
22516
|
sendServerEvent: data => {
|
|
@@ -22544,7 +22526,7 @@ const createFileService = ({
|
|
|
22544
22526
|
}
|
|
22545
22527
|
}
|
|
22546
22528
|
const context = {
|
|
22547
|
-
rootDirectoryUrl,
|
|
22529
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22548
22530
|
dev: true,
|
|
22549
22531
|
runtimeName,
|
|
22550
22532
|
runtimeVersion,
|
|
@@ -22555,13 +22537,6 @@ const createFileService = ({
|
|
|
22555
22537
|
return context;
|
|
22556
22538
|
};
|
|
22557
22539
|
return async request => {
|
|
22558
|
-
// serve file inside ".jsenv" directory
|
|
22559
|
-
const requestFileUrl = new URL(request.resource.slice(1), rootDirectoryUrl).href;
|
|
22560
|
-
if (urlIsInsideOf(requestFileUrl, jsenvDirectoryUrl)) {
|
|
22561
|
-
return fetchFileSystem(requestFileUrl, {
|
|
22562
|
-
headers: request.headers
|
|
22563
|
-
});
|
|
22564
|
-
}
|
|
22565
22540
|
const {
|
|
22566
22541
|
urlGraph,
|
|
22567
22542
|
kitchen
|
|
@@ -22571,16 +22546,16 @@ const createFileService = ({
|
|
|
22571
22546
|
return responseFromPlugin;
|
|
22572
22547
|
}
|
|
22573
22548
|
let reference;
|
|
22574
|
-
const parentUrl = inferParentFromRequest(request,
|
|
22549
|
+
const parentUrl = inferParentFromRequest(request, sourceDirectoryUrl);
|
|
22575
22550
|
if (parentUrl) {
|
|
22576
22551
|
reference = urlGraph.inferReference(request.resource, parentUrl);
|
|
22577
22552
|
}
|
|
22578
22553
|
if (!reference) {
|
|
22579
22554
|
const entryPoint = kitchen.injectReference({
|
|
22580
22555
|
trace: {
|
|
22581
|
-
message: parentUrl ||
|
|
22556
|
+
message: parentUrl || sourceDirectoryUrl
|
|
22582
22557
|
},
|
|
22583
|
-
parentUrl: parentUrl ||
|
|
22558
|
+
parentUrl: parentUrl || sourceDirectoryUrl,
|
|
22584
22559
|
type: "http_request",
|
|
22585
22560
|
specifier: request.resource
|
|
22586
22561
|
});
|
|
@@ -22702,7 +22677,7 @@ const createFileService = ({
|
|
|
22702
22677
|
accept: "text/html"
|
|
22703
22678
|
},
|
|
22704
22679
|
canReadDirectory: true,
|
|
22705
|
-
rootDirectoryUrl
|
|
22680
|
+
rootDirectoryUrl: sourceDirectoryUrl
|
|
22706
22681
|
});
|
|
22707
22682
|
}
|
|
22708
22683
|
if (code === "NOT_ALLOWED") {
|
|
@@ -22729,7 +22704,7 @@ const createFileService = ({
|
|
|
22729
22704
|
}
|
|
22730
22705
|
};
|
|
22731
22706
|
};
|
|
22732
|
-
const inferParentFromRequest = (request,
|
|
22707
|
+
const inferParentFromRequest = (request, sourceDirectoryUrl) => {
|
|
22733
22708
|
const {
|
|
22734
22709
|
referer
|
|
22735
22710
|
} = request.headers;
|
|
@@ -22750,7 +22725,7 @@ const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
|
22750
22725
|
return moveUrl({
|
|
22751
22726
|
url: referer,
|
|
22752
22727
|
from: `${request.origin}/`,
|
|
22753
|
-
to:
|
|
22728
|
+
to: sourceDirectoryUrl,
|
|
22754
22729
|
preferAbsolute: true
|
|
22755
22730
|
});
|
|
22756
22731
|
};
|
|
@@ -22760,38 +22735,28 @@ const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
|
22760
22735
|
* - cook source files according to jsenv plugins
|
|
22761
22736
|
* - inject code to autoreload the browser when a file is modified
|
|
22762
22737
|
* @param {Object} devServerParameters
|
|
22763
|
-
* @param {string|url} devServerParameters.
|
|
22738
|
+
* @param {string|url} devServerParameters.sourceDirectoryUrl Root directory of the project
|
|
22764
22739
|
* @return {Object} A dev server object
|
|
22765
22740
|
*/
|
|
22766
22741
|
const startDevServer = async ({
|
|
22767
|
-
|
|
22768
|
-
|
|
22769
|
-
|
|
22770
|
-
|
|
22742
|
+
sourceDirectoryUrl,
|
|
22743
|
+
sourceMainFilePath,
|
|
22744
|
+
port = 3456,
|
|
22745
|
+
hostname,
|
|
22746
|
+
acceptAnyIp,
|
|
22771
22747
|
https,
|
|
22772
22748
|
// it's better to use http1 by default because it allows to get statusText in devtools
|
|
22773
22749
|
// which gives valuable information when there is errors
|
|
22774
22750
|
http2 = false,
|
|
22775
|
-
|
|
22776
|
-
|
|
22777
|
-
acceptAnyIp,
|
|
22778
|
-
keepProcessAlive = true,
|
|
22751
|
+
logLevel = process.env.IMPORTED_BY_TEST_PLAN ? "warn" : "info",
|
|
22752
|
+
serverLogLevel = "warn",
|
|
22779
22753
|
services = [],
|
|
22754
|
+
signal = new AbortController().signal,
|
|
22755
|
+
handleSIGINT = true,
|
|
22756
|
+
keepProcessAlive = true,
|
|
22780
22757
|
onStop = () => {},
|
|
22781
|
-
|
|
22782
|
-
clientFiles = {
|
|
22783
|
-
"./src/": true,
|
|
22784
|
-
"./tests/": true,
|
|
22785
|
-
"./package.json": true
|
|
22786
|
-
},
|
|
22787
|
-
devServerFiles = {
|
|
22788
|
-
"./package.json": true,
|
|
22789
|
-
"./jsenv.config.mjs": true
|
|
22790
|
-
},
|
|
22758
|
+
sourceFilesConfig,
|
|
22791
22759
|
clientAutoreload = true,
|
|
22792
|
-
clientMainFileUrl,
|
|
22793
|
-
devServerAutoreload = false,
|
|
22794
|
-
devServerMainFile = getCallerPosition().url,
|
|
22795
22760
|
cooldownBetweenFileEvents,
|
|
22796
22761
|
// runtimeCompat is the runtimeCompat for the build
|
|
22797
22762
|
// when specified, dev server use it to warn in case
|
|
@@ -22823,11 +22788,7 @@ const startDevServer = async ({
|
|
|
22823
22788
|
if (unexpectedParamNames.length > 0) {
|
|
22824
22789
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
22825
22790
|
}
|
|
22826
|
-
|
|
22827
|
-
if (!rootDirectoryUrlValidation.valid) {
|
|
22828
|
-
throw new TypeError(`rootDirectoryUrl ${rootDirectoryUrlValidation.message}, got ${rootDirectoryUrl}`);
|
|
22829
|
-
}
|
|
22830
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
22791
|
+
sourceDirectoryUrl = assertAndNormalizeDirectoryUrl(sourceDirectoryUrl, "sourceDirectoryUrl");
|
|
22831
22792
|
}
|
|
22832
22793
|
const logger = createLogger({
|
|
22833
22794
|
logLevel
|
|
@@ -22841,70 +22802,6 @@ const startDevServer = async ({
|
|
|
22841
22802
|
}, abort);
|
|
22842
22803
|
});
|
|
22843
22804
|
}
|
|
22844
|
-
let reloadableWorker;
|
|
22845
|
-
if (devServerAutoreload) {
|
|
22846
|
-
reloadableWorker = createReloadableWorker(devServerMainFile);
|
|
22847
|
-
if (reloadableWorker.isPrimary) {
|
|
22848
|
-
const devServerFileChangeCallback = ({
|
|
22849
|
-
relativeUrl,
|
|
22850
|
-
event
|
|
22851
|
-
}) => {
|
|
22852
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
22853
|
-
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
22854
|
-
reloadableWorker.reload();
|
|
22855
|
-
};
|
|
22856
|
-
const stopWatchingDevServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
22857
|
-
watchPatterns: {
|
|
22858
|
-
...devServerFiles.include,
|
|
22859
|
-
[devServerMainFile]: true,
|
|
22860
|
-
".jsenv/": false
|
|
22861
|
-
},
|
|
22862
|
-
cooldownBetweenFileEvents,
|
|
22863
|
-
keepProcessAlive: false,
|
|
22864
|
-
recursive: true,
|
|
22865
|
-
added: ({
|
|
22866
|
-
relativeUrl
|
|
22867
|
-
}) => {
|
|
22868
|
-
devServerFileChangeCallback({
|
|
22869
|
-
relativeUrl,
|
|
22870
|
-
event: "added"
|
|
22871
|
-
});
|
|
22872
|
-
},
|
|
22873
|
-
updated: ({
|
|
22874
|
-
relativeUrl
|
|
22875
|
-
}) => {
|
|
22876
|
-
devServerFileChangeCallback({
|
|
22877
|
-
relativeUrl,
|
|
22878
|
-
event: "modified"
|
|
22879
|
-
});
|
|
22880
|
-
},
|
|
22881
|
-
removed: ({
|
|
22882
|
-
relativeUrl
|
|
22883
|
-
}) => {
|
|
22884
|
-
devServerFileChangeCallback({
|
|
22885
|
-
relativeUrl,
|
|
22886
|
-
event: "removed"
|
|
22887
|
-
});
|
|
22888
|
-
}
|
|
22889
|
-
});
|
|
22890
|
-
operation.addAbortCallback(() => {
|
|
22891
|
-
stopWatchingDevServerFiles();
|
|
22892
|
-
reloadableWorker.terminate();
|
|
22893
|
-
});
|
|
22894
|
-
const worker = await reloadableWorker.load();
|
|
22895
|
-
const messagePromise = new Promise(resolve => {
|
|
22896
|
-
worker.once("message", resolve);
|
|
22897
|
-
});
|
|
22898
|
-
const origin = await messagePromise;
|
|
22899
|
-
return {
|
|
22900
|
-
origin,
|
|
22901
|
-
stop: () => {
|
|
22902
|
-
stopWatchingDevServerFiles();
|
|
22903
|
-
reloadableWorker.terminate();
|
|
22904
|
-
}
|
|
22905
|
-
};
|
|
22906
|
-
}
|
|
22907
|
-
}
|
|
22908
22805
|
const startDevServerTask = createTaskLog("start dev server", {
|
|
22909
22806
|
disabled: !logger.levels.info
|
|
22910
22807
|
});
|
|
@@ -22935,7 +22832,30 @@ const startDevServer = async ({
|
|
|
22935
22832
|
accessControlAllowedRequestHeaders: [...jsenvAccessControlAllowedHeaders, "x-jsenv-execution-id"],
|
|
22936
22833
|
accessControlAllowCredentials: true,
|
|
22937
22834
|
timingAllowOrigin: true
|
|
22938
|
-
}),
|
|
22835
|
+
}), {
|
|
22836
|
+
handleRequest: request => {
|
|
22837
|
+
if (request.pathname === "/__server_params__.json") {
|
|
22838
|
+
const json = JSON.stringify({
|
|
22839
|
+
sourceDirectoryUrl
|
|
22840
|
+
});
|
|
22841
|
+
return {
|
|
22842
|
+
status: 200,
|
|
22843
|
+
headers: {
|
|
22844
|
+
"content-type": "application/json",
|
|
22845
|
+
"content-length": Buffer.byteLength(json)
|
|
22846
|
+
},
|
|
22847
|
+
body: json
|
|
22848
|
+
};
|
|
22849
|
+
}
|
|
22850
|
+
if (request.pathname === "/__stop__") {
|
|
22851
|
+
server.stop();
|
|
22852
|
+
return {
|
|
22853
|
+
status: 200
|
|
22854
|
+
};
|
|
22855
|
+
}
|
|
22856
|
+
return null;
|
|
22857
|
+
}
|
|
22858
|
+
}, ...services, {
|
|
22939
22859
|
name: "jsenv:omega_file_service",
|
|
22940
22860
|
handleRequest: createFileService({
|
|
22941
22861
|
signal,
|
|
@@ -22943,7 +22863,9 @@ const startDevServer = async ({
|
|
|
22943
22863
|
serverStopCallbacks,
|
|
22944
22864
|
serverEventsDispatcher,
|
|
22945
22865
|
contextCache,
|
|
22946
|
-
|
|
22866
|
+
sourceDirectoryUrl,
|
|
22867
|
+
sourceMainFilePath,
|
|
22868
|
+
sourceFilesConfig,
|
|
22947
22869
|
runtimeCompat,
|
|
22948
22870
|
plugins,
|
|
22949
22871
|
urlAnalysis,
|
|
@@ -22952,8 +22874,6 @@ const startDevServer = async ({
|
|
|
22952
22874
|
supervisor,
|
|
22953
22875
|
transpilation,
|
|
22954
22876
|
clientAutoreload,
|
|
22955
|
-
clientFiles,
|
|
22956
|
-
clientMainFileUrl,
|
|
22957
22877
|
cooldownBetweenFileEvents,
|
|
22958
22878
|
explorer,
|
|
22959
22879
|
cacheControl,
|
|
@@ -23026,9 +22946,6 @@ const startDevServer = async ({
|
|
|
23026
22946
|
logger.info(`- ${server.origins[key]}`);
|
|
23027
22947
|
});
|
|
23028
22948
|
logger.info(``);
|
|
23029
|
-
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
23030
|
-
parentPort.postMessage(server.origin);
|
|
23031
|
-
}
|
|
23032
22949
|
return {
|
|
23033
22950
|
origin: server.origin,
|
|
23034
22951
|
stop: () => {
|
|
@@ -23038,6 +22955,80 @@ const startDevServer = async ({
|
|
|
23038
22955
|
};
|
|
23039
22956
|
};
|
|
23040
22957
|
|
|
22958
|
+
const pingServer = async url => {
|
|
22959
|
+
const server = createServer();
|
|
22960
|
+
const {
|
|
22961
|
+
hostname,
|
|
22962
|
+
port
|
|
22963
|
+
} = new URL(url);
|
|
22964
|
+
try {
|
|
22965
|
+
await new Promise((resolve, reject) => {
|
|
22966
|
+
server.on("error", reject);
|
|
22967
|
+
server.on("listening", () => {
|
|
22968
|
+
resolve();
|
|
22969
|
+
});
|
|
22970
|
+
server.listen(port, hostname);
|
|
22971
|
+
});
|
|
22972
|
+
} catch (error) {
|
|
22973
|
+
if (error && error.code === "EADDRINUSE") {
|
|
22974
|
+
return true;
|
|
22975
|
+
}
|
|
22976
|
+
if (error && error.code === "EACCES") {
|
|
22977
|
+
return true;
|
|
22978
|
+
}
|
|
22979
|
+
throw error;
|
|
22980
|
+
}
|
|
22981
|
+
await new Promise((resolve, reject) => {
|
|
22982
|
+
server.on("error", reject);
|
|
22983
|
+
server.on("close", resolve);
|
|
22984
|
+
server.close();
|
|
22985
|
+
});
|
|
22986
|
+
return false;
|
|
22987
|
+
};
|
|
22988
|
+
|
|
22989
|
+
const basicFetch = async (url, {
|
|
22990
|
+
method = "GET",
|
|
22991
|
+
headers = {}
|
|
22992
|
+
} = {}) => {
|
|
22993
|
+
let requestModule;
|
|
22994
|
+
if (url.startsWith("http:")) {
|
|
22995
|
+
requestModule = await import("node:http");
|
|
22996
|
+
} else {
|
|
22997
|
+
requestModule = await import("node:https");
|
|
22998
|
+
}
|
|
22999
|
+
const {
|
|
23000
|
+
request
|
|
23001
|
+
} = requestModule;
|
|
23002
|
+
const urlObject = new URL(url);
|
|
23003
|
+
return new Promise((resolve, reject) => {
|
|
23004
|
+
const req = request({
|
|
23005
|
+
hostname: urlObject.hostname,
|
|
23006
|
+
port: urlObject.port,
|
|
23007
|
+
path: urlObject.pathname,
|
|
23008
|
+
method,
|
|
23009
|
+
headers
|
|
23010
|
+
});
|
|
23011
|
+
req.on("response", response => {
|
|
23012
|
+
req.setTimeout(0);
|
|
23013
|
+
let responseBody = "";
|
|
23014
|
+
response.setEncoding("utf8");
|
|
23015
|
+
response.on("data", chunk => {
|
|
23016
|
+
responseBody += chunk;
|
|
23017
|
+
});
|
|
23018
|
+
response.on("end", () => {
|
|
23019
|
+
req.destroy();
|
|
23020
|
+
if (response.headers["content-type"] === "application/json") {
|
|
23021
|
+
resolve(JSON.parse(responseBody));
|
|
23022
|
+
} else {
|
|
23023
|
+
resolve(responseBody);
|
|
23024
|
+
}
|
|
23025
|
+
});
|
|
23026
|
+
});
|
|
23027
|
+
req.on("error", reject);
|
|
23028
|
+
req.end();
|
|
23029
|
+
});
|
|
23030
|
+
};
|
|
23031
|
+
|
|
23041
23032
|
const generateCoverageJsonFile = async ({
|
|
23042
23033
|
coverage,
|
|
23043
23034
|
coverageJsonFileUrl,
|
|
@@ -23127,7 +23118,7 @@ const readNodeV8CoverageDirectory = async ({
|
|
|
23127
23118
|
try {
|
|
23128
23119
|
operation.throwIfAborted();
|
|
23129
23120
|
const dirContent = await tryReadDirectory();
|
|
23130
|
-
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE);
|
|
23121
|
+
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE, "NODE_V8_COVERAGE");
|
|
23131
23122
|
await dirContent.reduce(async (previous, dirEntry) => {
|
|
23132
23123
|
operation.throwIfAborted();
|
|
23133
23124
|
await previous;
|
|
@@ -23750,37 +23741,6 @@ const run = async ({
|
|
|
23750
23741
|
return result;
|
|
23751
23742
|
};
|
|
23752
23743
|
|
|
23753
|
-
const pingServer = async url => {
|
|
23754
|
-
const server = createServer();
|
|
23755
|
-
const {
|
|
23756
|
-
hostname,
|
|
23757
|
-
port
|
|
23758
|
-
} = new URL(url);
|
|
23759
|
-
try {
|
|
23760
|
-
await new Promise((resolve, reject) => {
|
|
23761
|
-
server.on("error", reject);
|
|
23762
|
-
server.on("listening", () => {
|
|
23763
|
-
resolve();
|
|
23764
|
-
});
|
|
23765
|
-
server.listen(port, hostname);
|
|
23766
|
-
});
|
|
23767
|
-
} catch (error) {
|
|
23768
|
-
if (error && error.code === "EADDRINUSE") {
|
|
23769
|
-
return true;
|
|
23770
|
-
}
|
|
23771
|
-
if (error && error.code === "EACCES") {
|
|
23772
|
-
return true;
|
|
23773
|
-
}
|
|
23774
|
-
throw error;
|
|
23775
|
-
}
|
|
23776
|
-
await new Promise((resolve, reject) => {
|
|
23777
|
-
server.on("error", reject);
|
|
23778
|
-
server.on("close", resolve);
|
|
23779
|
-
server.close();
|
|
23780
|
-
});
|
|
23781
|
-
return false;
|
|
23782
|
-
};
|
|
23783
|
-
|
|
23784
23744
|
const ensureGlobalGc = () => {
|
|
23785
23745
|
if (!global.gc) {
|
|
23786
23746
|
v8.setFlagsFromString("--expose_gc");
|
|
@@ -24208,7 +24168,7 @@ const executePlan = async (plan, {
|
|
|
24208
24168
|
coverageMethodForBrowsers,
|
|
24209
24169
|
coverageMethodForNodeJs,
|
|
24210
24170
|
coverageV8ConflictWarning,
|
|
24211
|
-
|
|
24171
|
+
coverageTempDirectoryUrl,
|
|
24212
24172
|
beforeExecutionCallback = () => {},
|
|
24213
24173
|
afterExecutionCallback = () => {}
|
|
24214
24174
|
} = {}) => {
|
|
@@ -24218,30 +24178,6 @@ const executePlan = async (plan, {
|
|
|
24218
24178
|
const stopAfterAllSignal = {
|
|
24219
24179
|
notify: () => {}
|
|
24220
24180
|
};
|
|
24221
|
-
let someNeedsServer = false;
|
|
24222
|
-
let someNodeRuntime = false;
|
|
24223
|
-
const runtimes = {};
|
|
24224
|
-
Object.keys(plan).forEach(filePattern => {
|
|
24225
|
-
const filePlan = plan[filePattern];
|
|
24226
|
-
Object.keys(filePlan).forEach(executionName => {
|
|
24227
|
-
const executionConfig = filePlan[executionName];
|
|
24228
|
-
const {
|
|
24229
|
-
runtime
|
|
24230
|
-
} = executionConfig;
|
|
24231
|
-
if (runtime) {
|
|
24232
|
-
runtimes[runtime.name] = runtime.version;
|
|
24233
|
-
if (runtime.type === "browser") {
|
|
24234
|
-
someNeedsServer = true;
|
|
24235
|
-
}
|
|
24236
|
-
if (runtime.type === "node") {
|
|
24237
|
-
someNodeRuntime = true;
|
|
24238
|
-
}
|
|
24239
|
-
}
|
|
24240
|
-
});
|
|
24241
|
-
});
|
|
24242
|
-
logger.debug(createDetailedMessage$1(`Prepare executing plan`, {
|
|
24243
|
-
runtimes: JSON.stringify(runtimes, null, " ")
|
|
24244
|
-
}));
|
|
24245
24181
|
const multipleExecutionsOperation = Abort.startOperation();
|
|
24246
24182
|
multipleExecutionsOperation.addAbortSignal(signal);
|
|
24247
24183
|
if (handleSIGINT) {
|
|
@@ -24259,19 +24195,6 @@ const executePlan = async (plan, {
|
|
|
24259
24195
|
multipleExecutionsOperation.addAbortSignal(failFastAbortController.signal);
|
|
24260
24196
|
}
|
|
24261
24197
|
try {
|
|
24262
|
-
const coverageTempDirectoryUrl = new URL(coverageTempDirectoryRelativeUrl, rootDirectoryUrl).href;
|
|
24263
|
-
if (someNodeRuntime && coverageEnabled && coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
24264
|
-
if (process.env.NODE_V8_COVERAGE) {
|
|
24265
|
-
// when runned multiple times, we don't want to keep previous files in this directory
|
|
24266
|
-
await ensureEmptyDirectory(process.env.NODE_V8_COVERAGE);
|
|
24267
|
-
} else {
|
|
24268
|
-
coverageMethodForNodeJs = "Profiler";
|
|
24269
|
-
logger.warn(createDetailedMessage$1(`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`, {
|
|
24270
|
-
"suggestion": `set process.env.NODE_V8_COVERAGE`,
|
|
24271
|
-
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`
|
|
24272
|
-
}));
|
|
24273
|
-
}
|
|
24274
|
-
}
|
|
24275
24198
|
if (gcBetweenExecutions) {
|
|
24276
24199
|
ensureGlobalGc();
|
|
24277
24200
|
}
|
|
@@ -24318,15 +24241,6 @@ const executePlan = async (plan, {
|
|
|
24318
24241
|
coverageMethodForNodeJs,
|
|
24319
24242
|
stopAfterAllSignal
|
|
24320
24243
|
};
|
|
24321
|
-
if (someNeedsServer) {
|
|
24322
|
-
if (!devServerOrigin) {
|
|
24323
|
-
throw new TypeError(`devServerOrigin is required when running tests on browser(s)`);
|
|
24324
|
-
}
|
|
24325
|
-
const devServerStarted = await pingServer(devServerOrigin);
|
|
24326
|
-
if (!devServerStarted) {
|
|
24327
|
-
throw new Error(`dev server not started at ${devServerOrigin}. It is required to run tests`);
|
|
24328
|
-
}
|
|
24329
|
-
}
|
|
24330
24244
|
logger.debug(`Generate executions`);
|
|
24331
24245
|
const executionSteps = await getExecutionAsSteps({
|
|
24332
24246
|
plan,
|
|
@@ -24423,7 +24337,7 @@ const executePlan = async (plan, {
|
|
|
24423
24337
|
executionResult = await run({
|
|
24424
24338
|
signal: multipleExecutionsOperation.signal,
|
|
24425
24339
|
logger,
|
|
24426
|
-
allocatedMs: executionParams.allocatedMs,
|
|
24340
|
+
allocatedMs: typeof executionParams.allocatedMs === "function" ? executionParams.allocatedMs(beforeExecutionInfo) : executionParams.allocatedMs,
|
|
24427
24341
|
keepRunning,
|
|
24428
24342
|
mirrorConsole: false,
|
|
24429
24343
|
// file are executed in parallel, log would be a mess to read
|
|
@@ -24639,8 +24553,8 @@ const executeInParallel = async ({
|
|
|
24639
24553
|
/**
|
|
24640
24554
|
* Execute a list of files and log how it goes.
|
|
24641
24555
|
* @param {Object} testPlanParameters
|
|
24642
|
-
* @param {string|url} testPlanParameters.
|
|
24643
|
-
* @param {string|url} [testPlanParameters.
|
|
24556
|
+
* @param {string|url} testPlanParameters.testDirectoryUrl Directory containing test files
|
|
24557
|
+
* @param {string|url} [testPlanParameters.devServerOrigin=undefined] Jsenv dev server origin; required when executing test on browsers
|
|
24644
24558
|
* @param {Object} testPlanParameters.testPlan Object associating patterns leading to files to runtimes where they should be executed
|
|
24645
24559
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
24646
24560
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
@@ -24666,7 +24580,8 @@ const executeTestPlan = async ({
|
|
|
24666
24580
|
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
24667
24581
|
completedExecutionLogAbbreviation = false,
|
|
24668
24582
|
completedExecutionLogMerging = false,
|
|
24669
|
-
|
|
24583
|
+
testDirectoryUrl,
|
|
24584
|
+
devServerModuleUrl,
|
|
24670
24585
|
devServerOrigin,
|
|
24671
24586
|
testPlan,
|
|
24672
24587
|
updateProcessExitCode = true,
|
|
@@ -24683,7 +24598,7 @@ const executeTestPlan = async ({
|
|
|
24683
24598
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
24684
24599
|
coverageEnabled = process.argv.includes("--coverage"),
|
|
24685
24600
|
coverageConfig = {
|
|
24686
|
-
"
|
|
24601
|
+
"./**/*": true
|
|
24687
24602
|
},
|
|
24688
24603
|
coverageIncludeMissing = true,
|
|
24689
24604
|
coverageAndExecutionAllowed = false,
|
|
@@ -24691,30 +24606,87 @@ const executeTestPlan = async ({
|
|
|
24691
24606
|
coverageMethodForBrowsers = "playwright_api",
|
|
24692
24607
|
// "istanbul" also accepted
|
|
24693
24608
|
coverageV8ConflictWarning = true,
|
|
24694
|
-
|
|
24609
|
+
coverageTempDirectoryUrl,
|
|
24610
|
+
coverageReportRootDirectoryUrl,
|
|
24695
24611
|
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
24696
24612
|
coverageReportSkipEmpty = false,
|
|
24697
24613
|
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
24698
24614
|
coverageReportSkipFull = false,
|
|
24699
24615
|
coverageReportTextLog = true,
|
|
24700
|
-
|
|
24701
|
-
|
|
24616
|
+
coverageReportJson = process.env.CI,
|
|
24617
|
+
coverageReportJsonFileUrl,
|
|
24618
|
+
coverageReportHtml = !process.env.CI,
|
|
24619
|
+
coverageReportHtmlDirectoryUrl,
|
|
24702
24620
|
...rest
|
|
24703
24621
|
}) => {
|
|
24622
|
+
let someNeedsServer = false;
|
|
24623
|
+
let someNodeRuntime = false;
|
|
24624
|
+
let stopDevServerNeeded = false;
|
|
24625
|
+
const runtimes = {};
|
|
24704
24626
|
// param validation
|
|
24705
24627
|
{
|
|
24706
24628
|
const unexpectedParamNames = Object.keys(rest);
|
|
24707
24629
|
if (unexpectedParamNames.length > 0) {
|
|
24708
24630
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
24709
24631
|
}
|
|
24710
|
-
|
|
24711
|
-
if (!
|
|
24712
|
-
throw new
|
|
24632
|
+
testDirectoryUrl = assertAndNormalizeDirectoryUrl(testDirectoryUrl, "testDirectoryUrl");
|
|
24633
|
+
if (!existsSync(new URL(testDirectoryUrl))) {
|
|
24634
|
+
throw new Error(`ENOENT on testDirectoryUrl at ${testDirectoryUrl}`);
|
|
24713
24635
|
}
|
|
24714
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
24715
24636
|
if (typeof testPlan !== "object") {
|
|
24716
24637
|
throw new Error(`testPlan must be an object, got ${testPlan}`);
|
|
24717
24638
|
}
|
|
24639
|
+
Object.keys(testPlan).forEach(filePattern => {
|
|
24640
|
+
const filePlan = testPlan[filePattern];
|
|
24641
|
+
if (!filePlan) return;
|
|
24642
|
+
Object.keys(filePlan).forEach(executionName => {
|
|
24643
|
+
const executionConfig = filePlan[executionName];
|
|
24644
|
+
const {
|
|
24645
|
+
runtime
|
|
24646
|
+
} = executionConfig;
|
|
24647
|
+
if (runtime) {
|
|
24648
|
+
runtimes[runtime.name] = runtime.version;
|
|
24649
|
+
if (runtime.type === "browser") {
|
|
24650
|
+
someNeedsServer = true;
|
|
24651
|
+
}
|
|
24652
|
+
if (runtime.type === "node") {
|
|
24653
|
+
someNodeRuntime = true;
|
|
24654
|
+
}
|
|
24655
|
+
}
|
|
24656
|
+
});
|
|
24657
|
+
});
|
|
24658
|
+
if (someNeedsServer) {
|
|
24659
|
+
if (!devServerOrigin) {
|
|
24660
|
+
throw new TypeError(`devServerOrigin is required when running tests on browser(s)`);
|
|
24661
|
+
}
|
|
24662
|
+
let devServerStarted = await pingServer(devServerOrigin);
|
|
24663
|
+
if (!devServerStarted) {
|
|
24664
|
+
if (!devServerModuleUrl) {
|
|
24665
|
+
throw new TypeError(`devServerModuleUrl is required when dev server is not started in order to run tests on browser(s)`);
|
|
24666
|
+
}
|
|
24667
|
+
try {
|
|
24668
|
+
process.env.IMPORTED_BY_TEST_PLAN = "1";
|
|
24669
|
+
await import(devServerModuleUrl);
|
|
24670
|
+
delete process.env.IMPORTED_BY_TEST_PLAN;
|
|
24671
|
+
} catch (e) {
|
|
24672
|
+
if (e.code === "MODULE_NOT_FOUND") {
|
|
24673
|
+
throw new Error(`Cannot find file responsible to start dev server at "${devServerModuleUrl}"`);
|
|
24674
|
+
}
|
|
24675
|
+
throw e;
|
|
24676
|
+
}
|
|
24677
|
+
devServerStarted = await pingServer(devServerOrigin);
|
|
24678
|
+
if (!devServerStarted) {
|
|
24679
|
+
throw new Error(`dev server not started after importing "${devServerModuleUrl}", ensure this module file is starting a server at "${devServerOrigin}"`);
|
|
24680
|
+
}
|
|
24681
|
+
stopDevServerNeeded = true;
|
|
24682
|
+
}
|
|
24683
|
+
const {
|
|
24684
|
+
sourceDirectoryUrl
|
|
24685
|
+
} = await basicFetch(`${devServerOrigin}/__server_params__.json`);
|
|
24686
|
+
if (testDirectoryUrl !== sourceDirectoryUrl && !urlIsInsideOf(testDirectoryUrl, sourceDirectoryUrl)) {
|
|
24687
|
+
throw new Error(`testDirectoryUrl must be inside sourceDirectoryUrl when running tests on browser(s)`);
|
|
24688
|
+
}
|
|
24689
|
+
}
|
|
24718
24690
|
if (coverageEnabled) {
|
|
24719
24691
|
if (typeof coverageConfig !== "object") {
|
|
24720
24692
|
throw new TypeError(`coverageConfig must be an object, got ${coverageConfig}`);
|
|
@@ -24742,14 +24714,63 @@ const executeTestPlan = async ({
|
|
|
24742
24714
|
}));
|
|
24743
24715
|
}
|
|
24744
24716
|
}
|
|
24717
|
+
if (coverageReportRootDirectoryUrl === undefined) {
|
|
24718
|
+
coverageReportRootDirectoryUrl = lookupPackageDirectory(testDirectoryUrl);
|
|
24719
|
+
} else {
|
|
24720
|
+
coverageReportRootDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageReportRootDirectoryUrl, "coverageReportRootDirectoryUrl");
|
|
24721
|
+
}
|
|
24722
|
+
if (coverageTempDirectoryUrl === undefined) {
|
|
24723
|
+
coverageTempDirectoryUrl = new URL("./.coverage/tmp/", coverageReportRootDirectoryUrl);
|
|
24724
|
+
} else {
|
|
24725
|
+
coverageTempDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageTempDirectoryUrl, "coverageTempDirectoryUrl");
|
|
24726
|
+
}
|
|
24727
|
+
if (coverageReportJson) {
|
|
24728
|
+
if (coverageReportJsonFileUrl === undefined) {
|
|
24729
|
+
coverageReportJsonFileUrl = new URL("./.coverage/coverage.json", coverageReportRootDirectoryUrl);
|
|
24730
|
+
} else {
|
|
24731
|
+
coverageReportJsonFileUrl = assertAndNormalizeFileUrl(coverageReportJsonFileUrl, "coverageReportJsonFileUrl");
|
|
24732
|
+
}
|
|
24733
|
+
}
|
|
24734
|
+
if (coverageReportHtml) {
|
|
24735
|
+
if (coverageReportHtmlDirectoryUrl === undefined) {
|
|
24736
|
+
coverageReportHtmlDirectoryUrl = new URL("./.coverage/", coverageReportRootDirectoryUrl);
|
|
24737
|
+
} else {
|
|
24738
|
+
coverageReportHtmlDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageReportHtmlDirectoryUrl, "coverageReportHtmlDirectoryUrl");
|
|
24739
|
+
}
|
|
24740
|
+
}
|
|
24745
24741
|
}
|
|
24746
24742
|
}
|
|
24747
24743
|
const logger = createLogger({
|
|
24748
24744
|
logLevel
|
|
24749
24745
|
});
|
|
24750
|
-
|
|
24751
|
-
|
|
24746
|
+
logger.debug(createDetailedMessage$1(`Prepare executing plan`, {
|
|
24747
|
+
runtimes: JSON.stringify(runtimes, null, " ")
|
|
24748
|
+
}));
|
|
24749
|
+
|
|
24750
|
+
// param normalization
|
|
24751
|
+
{
|
|
24752
|
+
if (coverageEnabled) {
|
|
24753
|
+
if (Object.keys(coverageConfig).length === 0) {
|
|
24754
|
+
logger.warn(`coverageConfig is an empty object. Nothing will be instrumented for coverage so your coverage will be empty`);
|
|
24755
|
+
}
|
|
24756
|
+
if (someNodeRuntime && coverageEnabled && coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
24757
|
+
if (process.env.NODE_V8_COVERAGE) {
|
|
24758
|
+
// when runned multiple times, we don't want to keep previous files in this directory
|
|
24759
|
+
await ensureEmptyDirectory(process.env.NODE_V8_COVERAGE);
|
|
24760
|
+
} else {
|
|
24761
|
+
coverageMethodForNodeJs = "Profiler";
|
|
24762
|
+
logger.warn(createDetailedMessage$1(`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`, {
|
|
24763
|
+
"suggestion": `set process.env.NODE_V8_COVERAGE`,
|
|
24764
|
+
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`
|
|
24765
|
+
}));
|
|
24766
|
+
}
|
|
24767
|
+
}
|
|
24768
|
+
}
|
|
24752
24769
|
}
|
|
24770
|
+
testPlan = {
|
|
24771
|
+
...testPlan,
|
|
24772
|
+
"**/.jsenv/": null
|
|
24773
|
+
};
|
|
24753
24774
|
const result = await executePlan(testPlan, {
|
|
24754
24775
|
signal,
|
|
24755
24776
|
handleSIGINT,
|
|
@@ -24763,7 +24784,7 @@ const executeTestPlan = async ({
|
|
|
24763
24784
|
logFileRelativeUrl,
|
|
24764
24785
|
completedExecutionLogMerging,
|
|
24765
24786
|
completedExecutionLogAbbreviation,
|
|
24766
|
-
rootDirectoryUrl,
|
|
24787
|
+
rootDirectoryUrl: testDirectoryUrl,
|
|
24767
24788
|
devServerOrigin,
|
|
24768
24789
|
maxExecutionsInParallel,
|
|
24769
24790
|
defaultMsAllocatedPerExecution,
|
|
@@ -24777,8 +24798,17 @@ const executeTestPlan = async ({
|
|
|
24777
24798
|
coverageMethodForBrowsers,
|
|
24778
24799
|
coverageMethodForNodeJs,
|
|
24779
24800
|
coverageV8ConflictWarning,
|
|
24780
|
-
|
|
24801
|
+
coverageTempDirectoryUrl
|
|
24781
24802
|
});
|
|
24803
|
+
if (stopDevServerNeeded) {
|
|
24804
|
+
// we are expecting ECONNRESET because server will be stopped by the request
|
|
24805
|
+
basicFetch(`${devServerOrigin}/__stop__`).catch(e => {
|
|
24806
|
+
if (e.code === "ECONNRESET") {
|
|
24807
|
+
return;
|
|
24808
|
+
}
|
|
24809
|
+
throw e;
|
|
24810
|
+
});
|
|
24811
|
+
}
|
|
24782
24812
|
if (updateProcessExitCode && result.planSummary.counters.total !== result.planSummary.counters.completed) {
|
|
24783
24813
|
process.exitCode = 1;
|
|
24784
24814
|
}
|
|
@@ -24789,26 +24819,21 @@ const executeTestPlan = async ({
|
|
|
24789
24819
|
// keep this one first because it does ensureEmptyDirectory
|
|
24790
24820
|
// and in case coverage json file gets written in the same directory
|
|
24791
24821
|
// it must be done before
|
|
24792
|
-
if (coverageEnabled &&
|
|
24793
|
-
|
|
24794
|
-
|
|
24795
|
-
throw new Error(`coverageReportHtmlDirectory must be inside rootDirectoryUrl`);
|
|
24796
|
-
}
|
|
24797
|
-
await ensureEmptyDirectory(coverageHtmlDirectoryUrl);
|
|
24798
|
-
const htmlCoverageDirectoryIndexFileUrl = `${coverageHtmlDirectoryUrl}index.html`;
|
|
24822
|
+
if (coverageEnabled && coverageReportHtml) {
|
|
24823
|
+
await ensureEmptyDirectory(coverageReportHtmlDirectoryUrl);
|
|
24824
|
+
const htmlCoverageDirectoryIndexFileUrl = `${coverageReportHtmlDirectoryUrl}index.html`;
|
|
24799
24825
|
logger.info(`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`);
|
|
24800
24826
|
promises.push(generateCoverageHtmlDirectory(planCoverage, {
|
|
24801
|
-
rootDirectoryUrl,
|
|
24802
|
-
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(
|
|
24827
|
+
rootDirectoryUrl: coverageReportRootDirectoryUrl,
|
|
24828
|
+
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(coverageReportHtmlDirectoryUrl, coverageReportRootDirectoryUrl),
|
|
24803
24829
|
coverageReportSkipEmpty,
|
|
24804
24830
|
coverageReportSkipFull
|
|
24805
24831
|
}));
|
|
24806
24832
|
}
|
|
24807
|
-
if (coverageEnabled &&
|
|
24808
|
-
const coverageJsonFileUrl = new URL(coverageReportJsonFile, rootDirectoryUrl).href;
|
|
24833
|
+
if (coverageEnabled && coverageReportJson) {
|
|
24809
24834
|
promises.push(generateCoverageJsonFile({
|
|
24810
24835
|
coverage: result.planCoverage,
|
|
24811
|
-
coverageJsonFileUrl,
|
|
24836
|
+
coverageJsonFileUrl: coverageReportJsonFileUrl,
|
|
24812
24837
|
logger
|
|
24813
24838
|
}));
|
|
24814
24839
|
}
|
|
@@ -25672,7 +25697,6 @@ nodeChildProcess.run = async ({
|
|
|
25672
25697
|
env: envForChildProcess
|
|
25673
25698
|
});
|
|
25674
25699
|
logger.debug(createDetailedMessage$1(`child process forked (pid ${childProcess.pid})`, {
|
|
25675
|
-
"execArgv": execArgv.join(`\n`),
|
|
25676
25700
|
"custom env": JSON.stringify(env, null, " ")
|
|
25677
25701
|
}));
|
|
25678
25702
|
// if we pass stream, pipe them https://github.com/sindresorhus/execa/issues/81
|
|
@@ -26195,32 +26219,23 @@ const onceWorkerThreadEvent = (worker, type, callback) => {
|
|
|
26195
26219
|
/**
|
|
26196
26220
|
* Start a server for build files.
|
|
26197
26221
|
* @param {Object} buildServerParameters
|
|
26198
|
-
* @param {string|url} buildServerParameters.rootDirectoryUrl Root directory of the project
|
|
26199
26222
|
* @param {string|url} buildServerParameters.buildDirectoryUrl Directory where build files are written
|
|
26200
26223
|
* @return {Object} A build server object
|
|
26201
26224
|
*/
|
|
26202
26225
|
const startBuildServer = async ({
|
|
26203
|
-
|
|
26204
|
-
|
|
26205
|
-
logLevel,
|
|
26206
|
-
serverLogLevel = "warn",
|
|
26207
|
-
https,
|
|
26208
|
-
http2,
|
|
26209
|
-
acceptAnyIp,
|
|
26210
|
-
hostname,
|
|
26226
|
+
buildDirectoryUrl,
|
|
26227
|
+
buildMainFilePath = "index.html",
|
|
26211
26228
|
port = 9779,
|
|
26212
26229
|
services = [],
|
|
26230
|
+
acceptAnyIp,
|
|
26231
|
+
hostname,
|
|
26232
|
+
https,
|
|
26233
|
+
http2,
|
|
26234
|
+
logLevel,
|
|
26235
|
+
serverLogLevel = "warn",
|
|
26236
|
+
signal = new AbortController().signal,
|
|
26237
|
+
handleSIGINT = true,
|
|
26213
26238
|
keepProcessAlive = true,
|
|
26214
|
-
rootDirectoryUrl,
|
|
26215
|
-
buildDirectoryUrl,
|
|
26216
|
-
buildIndexPath = "index.html",
|
|
26217
|
-
buildServerFiles = {
|
|
26218
|
-
"./package.json": true,
|
|
26219
|
-
"./jsenv.config.mjs": true
|
|
26220
|
-
},
|
|
26221
|
-
buildServerAutoreload = false,
|
|
26222
|
-
buildServerMainFile = getCallerPosition().url,
|
|
26223
|
-
cooldownBetweenFileEvents,
|
|
26224
26239
|
...rest
|
|
26225
26240
|
}) => {
|
|
26226
26241
|
// params validation
|
|
@@ -26229,31 +26244,22 @@ const startBuildServer = async ({
|
|
|
26229
26244
|
if (unexpectedParamNames.length > 0) {
|
|
26230
26245
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
26231
26246
|
}
|
|
26232
|
-
|
|
26233
|
-
if (
|
|
26234
|
-
|
|
26235
|
-
|
|
26236
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
26237
|
-
const buildDirectoryUrlValidation = validateDirectoryUrl(buildDirectoryUrl);
|
|
26238
|
-
if (!buildDirectoryUrlValidation.valid) {
|
|
26239
|
-
throw new TypeError(`buildDirectoryUrl ${buildDirectoryUrlValidation.message}, got ${buildDirectoryUrlValidation}`);
|
|
26240
|
-
}
|
|
26241
|
-
buildDirectoryUrl = buildDirectoryUrlValidation.value;
|
|
26242
|
-
if (buildIndexPath) {
|
|
26243
|
-
if (typeof buildIndexPath !== "string") {
|
|
26244
|
-
throw new TypeError(`buildIndexPath must be a string, got ${buildIndexPath}`);
|
|
26247
|
+
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl, "buildDirectoryUrl");
|
|
26248
|
+
if (buildMainFilePath) {
|
|
26249
|
+
if (typeof buildMainFilePath !== "string") {
|
|
26250
|
+
throw new TypeError(`buildMainFilePath must be a string, got ${buildMainFilePath}`);
|
|
26245
26251
|
}
|
|
26246
|
-
if (
|
|
26247
|
-
|
|
26252
|
+
if (buildMainFilePath[0] === "/") {
|
|
26253
|
+
buildMainFilePath = buildMainFilePath.slice(1);
|
|
26248
26254
|
} else {
|
|
26249
|
-
const
|
|
26250
|
-
if (!
|
|
26251
|
-
throw new Error(`
|
|
26255
|
+
const buildMainFileUrl = new URL(buildMainFilePath, buildDirectoryUrl).href;
|
|
26256
|
+
if (!buildMainFileUrl.startsWith(buildDirectoryUrl)) {
|
|
26257
|
+
throw new Error(`buildMainFilePath must be relative, got ${buildMainFilePath}`);
|
|
26252
26258
|
}
|
|
26253
|
-
|
|
26259
|
+
buildMainFilePath = buildMainFileUrl.slice(buildDirectoryUrl.length);
|
|
26254
26260
|
}
|
|
26255
|
-
if (!existsSync(new URL(
|
|
26256
|
-
|
|
26261
|
+
if (!existsSync(new URL(buildMainFilePath, buildDirectoryUrl))) {
|
|
26262
|
+
buildMainFilePath = null;
|
|
26257
26263
|
}
|
|
26258
26264
|
}
|
|
26259
26265
|
}
|
|
@@ -26269,73 +26275,6 @@ const startBuildServer = async ({
|
|
|
26269
26275
|
}, abort);
|
|
26270
26276
|
});
|
|
26271
26277
|
}
|
|
26272
|
-
let reloadableWorker;
|
|
26273
|
-
if (buildServerAutoreload) {
|
|
26274
|
-
reloadableWorker = createReloadableWorker(buildServerMainFile);
|
|
26275
|
-
if (reloadableWorker.isPrimary) {
|
|
26276
|
-
const buildServerFileChangeCallback = ({
|
|
26277
|
-
relativeUrl,
|
|
26278
|
-
event
|
|
26279
|
-
}) => {
|
|
26280
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
26281
|
-
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
26282
|
-
reloadableWorker.reload();
|
|
26283
|
-
};
|
|
26284
|
-
const stopWatchingBuildServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
26285
|
-
watchPatterns: {
|
|
26286
|
-
...buildServerFiles,
|
|
26287
|
-
[buildServerMainFile]: true,
|
|
26288
|
-
".jsenv/": false
|
|
26289
|
-
},
|
|
26290
|
-
cooldownBetweenFileEvents,
|
|
26291
|
-
keepProcessAlive: false,
|
|
26292
|
-
recursive: true,
|
|
26293
|
-
added: ({
|
|
26294
|
-
relativeUrl
|
|
26295
|
-
}) => {
|
|
26296
|
-
buildServerFileChangeCallback({
|
|
26297
|
-
relativeUrl,
|
|
26298
|
-
event: "added"
|
|
26299
|
-
});
|
|
26300
|
-
},
|
|
26301
|
-
updated: ({
|
|
26302
|
-
relativeUrl
|
|
26303
|
-
}) => {
|
|
26304
|
-
buildServerFileChangeCallback({
|
|
26305
|
-
relativeUrl,
|
|
26306
|
-
event: "modified"
|
|
26307
|
-
});
|
|
26308
|
-
},
|
|
26309
|
-
removed: ({
|
|
26310
|
-
relativeUrl
|
|
26311
|
-
}) => {
|
|
26312
|
-
buildServerFileChangeCallback({
|
|
26313
|
-
relativeUrl,
|
|
26314
|
-
event: "removed"
|
|
26315
|
-
});
|
|
26316
|
-
}
|
|
26317
|
-
});
|
|
26318
|
-
operation.addAbortCallback(() => {
|
|
26319
|
-
stopWatchingBuildServerFiles();
|
|
26320
|
-
reloadableWorker.terminate();
|
|
26321
|
-
});
|
|
26322
|
-
const worker = await reloadableWorker.load();
|
|
26323
|
-
const messagePromise = new Promise(resolve => {
|
|
26324
|
-
worker.once("message", resolve);
|
|
26325
|
-
});
|
|
26326
|
-
const origin = await messagePromise;
|
|
26327
|
-
// if (!keepProcessAlive) {
|
|
26328
|
-
// worker.unref()
|
|
26329
|
-
// }
|
|
26330
|
-
return {
|
|
26331
|
-
origin,
|
|
26332
|
-
stop: () => {
|
|
26333
|
-
stopWatchingBuildServerFiles();
|
|
26334
|
-
reloadableWorker.terminate();
|
|
26335
|
-
}
|
|
26336
|
-
};
|
|
26337
|
-
}
|
|
26338
|
-
}
|
|
26339
26278
|
const startBuildServerTask = createTaskLog("start build server", {
|
|
26340
26279
|
disabled: !logger.levels.info
|
|
26341
26280
|
});
|
|
@@ -26366,7 +26305,7 @@ const startBuildServer = async ({
|
|
|
26366
26305
|
name: "jsenv:build_files_service",
|
|
26367
26306
|
handleRequest: createBuildFilesService({
|
|
26368
26307
|
buildDirectoryUrl,
|
|
26369
|
-
|
|
26308
|
+
buildMainFilePath
|
|
26370
26309
|
})
|
|
26371
26310
|
}, jsenvServiceErrorHandler({
|
|
26372
26311
|
sendErrorDetails: true
|
|
@@ -26382,9 +26321,6 @@ const startBuildServer = async ({
|
|
|
26382
26321
|
logger.info(`- ${server.origins[key]}`);
|
|
26383
26322
|
});
|
|
26384
26323
|
logger.info(``);
|
|
26385
|
-
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
26386
|
-
parentPort.postMessage(server.origin);
|
|
26387
|
-
}
|
|
26388
26324
|
return {
|
|
26389
26325
|
origin: server.origin,
|
|
26390
26326
|
stop: () => {
|
|
@@ -26394,14 +26330,14 @@ const startBuildServer = async ({
|
|
|
26394
26330
|
};
|
|
26395
26331
|
const createBuildFilesService = ({
|
|
26396
26332
|
buildDirectoryUrl,
|
|
26397
|
-
|
|
26333
|
+
buildMainFilePath
|
|
26398
26334
|
}) => {
|
|
26399
26335
|
return request => {
|
|
26400
26336
|
const urlIsVersioned = new URL(request.url).searchParams.has("v");
|
|
26401
|
-
if (
|
|
26337
|
+
if (buildMainFilePath && request.resource === "/") {
|
|
26402
26338
|
request = {
|
|
26403
26339
|
...request,
|
|
26404
|
-
resource: `/${
|
|
26340
|
+
resource: `/${buildMainFilePath}`
|
|
26405
26341
|
};
|
|
26406
26342
|
}
|
|
26407
26343
|
return fetchFileSystem(new URL(request.resource.slice(1), buildDirectoryUrl), {
|
|
@@ -26448,7 +26384,7 @@ const execute = async ({
|
|
|
26448
26384
|
const logger = createLogger({
|
|
26449
26385
|
logLevel
|
|
26450
26386
|
});
|
|
26451
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl);
|
|
26387
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl, "rootDirectoryUrl");
|
|
26452
26388
|
const executeOperation = Abort.startOperation();
|
|
26453
26389
|
executeOperation.addAbortSignal(signal);
|
|
26454
26390
|
if (handleSIGINT) {
|