@jsenv/core 31.2.0 → 32.0.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/dist/js/v8_coverage.js +36 -23
- package/dist/main.js +483 -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 +52 -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,109 @@ 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
|
+
// line below is commented until @jsenv/url-meta fixes the fact that is matches
|
|
7122
|
+
// any file with an extension
|
|
7123
|
+
// "**/.*": false, // file starting with a dot -> do not watch
|
|
7124
|
+
"**/.*/": false,
|
|
7125
|
+
// directory starting with a dot -> do not watch
|
|
7126
|
+
"**/node_modules/": false,
|
|
7127
|
+
// node_modules directory -> do not watch
|
|
7128
|
+
...sourceFileConfig
|
|
7129
|
+
};
|
|
7130
|
+
const stopWatchingSourceFiles = registerDirectoryLifecycle(sourceDirectoryUrl, {
|
|
7131
|
+
watchPatterns,
|
|
7132
|
+
cooldownBetweenFileEvents,
|
|
7133
|
+
keepProcessAlive,
|
|
7134
|
+
recursive: true,
|
|
7135
|
+
added: ({
|
|
7136
|
+
relativeUrl
|
|
7137
|
+
}) => {
|
|
7138
|
+
callback({
|
|
7139
|
+
url: new URL(relativeUrl, sourceDirectoryUrl).href,
|
|
7140
|
+
event: "added"
|
|
7141
|
+
});
|
|
7142
|
+
},
|
|
7143
|
+
updated: ({
|
|
7144
|
+
relativeUrl
|
|
7145
|
+
}) => {
|
|
7146
|
+
callback({
|
|
7147
|
+
url: new URL(relativeUrl, sourceDirectoryUrl).href,
|
|
7148
|
+
event: "modified"
|
|
7149
|
+
});
|
|
7150
|
+
},
|
|
7151
|
+
removed: ({
|
|
7152
|
+
relativeUrl
|
|
7153
|
+
}) => {
|
|
7154
|
+
callback({
|
|
7155
|
+
url: new URL(relativeUrl, sourceDirectoryUrl).href,
|
|
7156
|
+
event: "removed"
|
|
7157
|
+
});
|
|
7158
|
+
}
|
|
7159
|
+
});
|
|
7160
|
+
stopWatchingSourceFiles.watchPatterns = watchPatterns;
|
|
7161
|
+
return stopWatchingSourceFiles;
|
|
7162
|
+
};
|
|
7163
|
+
|
|
7066
7164
|
const urlSpecifierEncoding = {
|
|
7067
7165
|
encode: reference => {
|
|
7068
7166
|
const {
|
|
@@ -8653,6 +8751,7 @@ const createKitchen = ({
|
|
|
8653
8751
|
signal,
|
|
8654
8752
|
logLevel,
|
|
8655
8753
|
rootDirectoryUrl,
|
|
8754
|
+
jsenvInternalDirectoryUrl,
|
|
8656
8755
|
urlGraph,
|
|
8657
8756
|
dev = false,
|
|
8658
8757
|
build = false,
|
|
@@ -8678,6 +8777,7 @@ const createKitchen = ({
|
|
|
8678
8777
|
signal,
|
|
8679
8778
|
logger,
|
|
8680
8779
|
rootDirectoryUrl,
|
|
8780
|
+
jsenvInternalDirectoryUrl,
|
|
8681
8781
|
urlGraph,
|
|
8682
8782
|
dev,
|
|
8683
8783
|
build,
|
|
@@ -17063,7 +17163,7 @@ const addRelationshipWithPackageJson = ({
|
|
|
17063
17163
|
*/
|
|
17064
17164
|
const jsenvPluginUrlResolution = ({
|
|
17065
17165
|
runtimeCompat,
|
|
17066
|
-
|
|
17166
|
+
mainFileUrl,
|
|
17067
17167
|
urlResolution
|
|
17068
17168
|
}) => {
|
|
17069
17169
|
const resolveUrlUsingWebResolution = reference => {
|
|
@@ -17124,7 +17224,7 @@ const jsenvPluginUrlResolution = ({
|
|
|
17124
17224
|
appliesDuring: "*",
|
|
17125
17225
|
resolveUrl: (reference, context) => {
|
|
17126
17226
|
if (reference.specifier === "/") {
|
|
17127
|
-
return String(
|
|
17227
|
+
return String(mainFileUrl);
|
|
17128
17228
|
}
|
|
17129
17229
|
if (reference.specifier[0] === "/") {
|
|
17130
17230
|
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl).href;
|
|
@@ -20192,13 +20292,14 @@ const explorerHtmlFileUrl = new URL("./html/explorer.html", import.meta.url);
|
|
|
20192
20292
|
const jsenvPluginExplorer = ({
|
|
20193
20293
|
groups = {
|
|
20194
20294
|
src: {
|
|
20195
|
-
"
|
|
20295
|
+
"./**/*.html": true,
|
|
20296
|
+
"./**/*.test.html": false
|
|
20196
20297
|
},
|
|
20197
20298
|
tests: {
|
|
20198
|
-
"
|
|
20299
|
+
"./**/*.test.html": true
|
|
20199
20300
|
}
|
|
20200
20301
|
},
|
|
20201
|
-
|
|
20302
|
+
mainFileUrl
|
|
20202
20303
|
}) => {
|
|
20203
20304
|
const faviconClientFileUrl = new URL("./other/jsenv.png", import.meta.url);
|
|
20204
20305
|
return {
|
|
@@ -20206,7 +20307,7 @@ const jsenvPluginExplorer = ({
|
|
|
20206
20307
|
appliesDuring: "dev",
|
|
20207
20308
|
transformUrlContent: {
|
|
20208
20309
|
html: async (urlInfo, context) => {
|
|
20209
|
-
if (urlInfo.url !==
|
|
20310
|
+
if (urlInfo.url !== mainFileUrl) {
|
|
20210
20311
|
return null;
|
|
20211
20312
|
}
|
|
20212
20313
|
let html = urlInfo.content;
|
|
@@ -20308,6 +20409,7 @@ injectRibbon(${paramsJson})`
|
|
|
20308
20409
|
|
|
20309
20410
|
const getCorePlugins = ({
|
|
20310
20411
|
rootDirectoryUrl,
|
|
20412
|
+
mainFileUrl,
|
|
20311
20413
|
runtimeCompat,
|
|
20312
20414
|
urlAnalysis = {},
|
|
20313
20415
|
urlResolution = {},
|
|
@@ -20315,7 +20417,6 @@ const getCorePlugins = ({
|
|
|
20315
20417
|
directoryReferenceAllowed,
|
|
20316
20418
|
supervisor,
|
|
20317
20419
|
transpilation = true,
|
|
20318
|
-
clientMainFileUrl,
|
|
20319
20420
|
clientAutoreload = false,
|
|
20320
20421
|
clientFileChangeCallbackList,
|
|
20321
20422
|
clientFilesPruneCallbackList,
|
|
@@ -20339,11 +20440,6 @@ const getCorePlugins = ({
|
|
|
20339
20440
|
if (clientAutoreload === true) {
|
|
20340
20441
|
clientAutoreload = {};
|
|
20341
20442
|
}
|
|
20342
|
-
if (clientMainFileUrl === undefined) {
|
|
20343
|
-
clientMainFileUrl = explorer ? String(explorerHtmlFileUrl) : String(new URL("./index.html", rootDirectoryUrl));
|
|
20344
|
-
} else {
|
|
20345
|
-
clientMainFileUrl = String(clientMainFileUrl);
|
|
20346
|
-
}
|
|
20347
20443
|
if (ribbon === true) {
|
|
20348
20444
|
ribbon = {};
|
|
20349
20445
|
}
|
|
@@ -20362,7 +20458,7 @@ const getCorePlugins = ({
|
|
|
20362
20458
|
...fileSystemMagicRedirection
|
|
20363
20459
|
}), jsenvPluginHttpUrls(), jsenvPluginUrlResolution({
|
|
20364
20460
|
runtimeCompat,
|
|
20365
|
-
|
|
20461
|
+
mainFileUrl,
|
|
20366
20462
|
urlResolution
|
|
20367
20463
|
}), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []), jsenvPluginNodeRuntime({
|
|
20368
20464
|
runtimeCompat
|
|
@@ -20372,7 +20468,7 @@ const getCorePlugins = ({
|
|
|
20372
20468
|
clientFilesPruneCallbackList
|
|
20373
20469
|
})] : []), ...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []), ...(explorer ? [jsenvPluginExplorer({
|
|
20374
20470
|
...explorer,
|
|
20375
|
-
|
|
20471
|
+
mainFileUrl
|
|
20376
20472
|
})] : []), ...(ribbon ? [jsenvPluginRibbon({
|
|
20377
20473
|
rootDirectoryUrl,
|
|
20378
20474
|
...ribbon
|
|
@@ -20731,12 +20827,13 @@ const defaultRuntimeCompat = {
|
|
|
20731
20827
|
/**
|
|
20732
20828
|
* Generate an optimized version of source files into a directory
|
|
20733
20829
|
* @param {Object} buildParameters
|
|
20734
|
-
* @param {string|url} buildParameters.
|
|
20830
|
+
* @param {string|url} buildParameters.sourceDirectoryUrl
|
|
20735
20831
|
* Directory containing source files
|
|
20832
|
+
* @param {object} buildParameters.entryPoints
|
|
20833
|
+
* Object where keys are paths to source files and values are their future name in the build directory.
|
|
20834
|
+
* Keys are relative to sourceDirectoryUrl
|
|
20736
20835
|
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
20737
20836
|
* 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
20837
|
* @param {object} buildParameters.runtimeCompat
|
|
20741
20838
|
* Code generated will be compatible with these runtimes
|
|
20742
20839
|
* @param {string} [buildParameters.assetsDirectory=""]
|
|
@@ -20761,10 +20858,10 @@ const build = async ({
|
|
|
20761
20858
|
signal = new AbortController().signal,
|
|
20762
20859
|
handleSIGINT = true,
|
|
20763
20860
|
logLevel = "info",
|
|
20764
|
-
|
|
20861
|
+
sourceDirectoryUrl,
|
|
20862
|
+
entryPoints = {},
|
|
20765
20863
|
buildDirectoryUrl,
|
|
20766
20864
|
assetsDirectory = "",
|
|
20767
|
-
entryPoints = {},
|
|
20768
20865
|
runtimeCompat = defaultRuntimeCompat,
|
|
20769
20866
|
base = runtimeCompat.node ? "./" : "/",
|
|
20770
20867
|
plugins = [],
|
|
@@ -20781,9 +20878,7 @@ const build = async ({
|
|
|
20781
20878
|
// "filename", "search_param"
|
|
20782
20879
|
versioningViaImportmap = true,
|
|
20783
20880
|
lineBreakNormalization = process.platform === "win32",
|
|
20784
|
-
|
|
20785
|
-
"./src/": true
|
|
20786
|
-
},
|
|
20881
|
+
sourceFilesConfig = {},
|
|
20787
20882
|
cooldownBetweenFileEvents,
|
|
20788
20883
|
watch = false,
|
|
20789
20884
|
directoryToClean,
|
|
@@ -20799,16 +20894,27 @@ const build = async ({
|
|
|
20799
20894
|
if (unexpectedParamNames.length > 0) {
|
|
20800
20895
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
20801
20896
|
}
|
|
20802
|
-
|
|
20803
|
-
if (
|
|
20804
|
-
throw new TypeError(`
|
|
20897
|
+
sourceDirectoryUrl = assertAndNormalizeDirectoryUrl(sourceDirectoryUrl, "sourceDirectoryUrl");
|
|
20898
|
+
if (typeof entryPoints !== "object" || entryPoints === null) {
|
|
20899
|
+
throw new TypeError(`entryPoints must be an object, got ${entryPoints}`);
|
|
20805
20900
|
}
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
|
|
20809
|
-
|
|
20901
|
+
const keys = Object.keys(entryPoints);
|
|
20902
|
+
keys.forEach(key => {
|
|
20903
|
+
if (!key.startsWith("./")) {
|
|
20904
|
+
throw new TypeError(`entryPoints keys must start with "./", found ${key}`);
|
|
20905
|
+
}
|
|
20906
|
+
const value = entryPoints[key];
|
|
20907
|
+
if (typeof value !== "string") {
|
|
20908
|
+
throw new TypeError(`entryPoints values must be strings, found "${value}" on key "${key}"`);
|
|
20909
|
+
}
|
|
20910
|
+
if (value.includes("/")) {
|
|
20911
|
+
throw new TypeError(`entryPoints values must be plain strings (no "/"), found "${value}" on key "${key}"`);
|
|
20912
|
+
}
|
|
20913
|
+
});
|
|
20914
|
+
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl, "buildDirectoryUrl");
|
|
20915
|
+
if (!["filename", "search_param"].includes(versioningMethod)) {
|
|
20916
|
+
throw new TypeError(`versioningMethod must be "filename" or "search_param", got ${versioning}`);
|
|
20810
20917
|
}
|
|
20811
|
-
buildDirectoryUrl = buildDirectoryUrlValidation.value;
|
|
20812
20918
|
}
|
|
20813
20919
|
const operation = Abort.startOperation();
|
|
20814
20920
|
operation.addAbortSignal(signal);
|
|
@@ -20819,12 +20925,6 @@ const build = async ({
|
|
|
20819
20925
|
}, abort);
|
|
20820
20926
|
});
|
|
20821
20927
|
}
|
|
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
20928
|
if (assetsDirectory && assetsDirectory[assetsDirectory.length - 1] !== "/") {
|
|
20829
20929
|
assetsDirectory = `${assetsDirectory}/`;
|
|
20830
20930
|
}
|
|
@@ -20835,9 +20935,10 @@ const build = async ({
|
|
|
20835
20935
|
directoryToClean = new URL(assetsDirectory, buildDirectoryUrl).href;
|
|
20836
20936
|
}
|
|
20837
20937
|
}
|
|
20938
|
+
const jsenvInternalDirectoryUrl = determineJsenvInternalDirectoryUrl(sourceDirectoryUrl);
|
|
20838
20939
|
const asFormattedBuildUrl = (generatedUrl, reference) => {
|
|
20839
20940
|
if (base === "./") {
|
|
20840
|
-
const urlRelativeToParent = urlToRelativeUrl(generatedUrl, reference.parentUrl ===
|
|
20941
|
+
const urlRelativeToParent = urlToRelativeUrl(generatedUrl, reference.parentUrl === sourceDirectoryUrl ? buildDirectoryUrl : reference.parentUrl);
|
|
20841
20942
|
if (urlRelativeToParent[0] !== ".") {
|
|
20842
20943
|
// ensure "./" on relative url (otherwise it could be a "bare specifier")
|
|
20843
20944
|
return `./${urlRelativeToParent}`;
|
|
@@ -20887,7 +20988,8 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20887
20988
|
const rawGraphKitchen = createKitchen({
|
|
20888
20989
|
signal,
|
|
20889
20990
|
logLevel,
|
|
20890
|
-
rootDirectoryUrl,
|
|
20991
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20992
|
+
jsenvInternalDirectoryUrl,
|
|
20891
20993
|
urlGraph: rawGraph,
|
|
20892
20994
|
build: true,
|
|
20893
20995
|
runtimeCompat,
|
|
@@ -20906,7 +21008,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20906
21008
|
return null;
|
|
20907
21009
|
}
|
|
20908
21010
|
}, ...getCorePlugins({
|
|
20909
|
-
rootDirectoryUrl,
|
|
21011
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20910
21012
|
urlGraph: rawGraph,
|
|
20911
21013
|
runtimeCompat,
|
|
20912
21014
|
urlAnalysis,
|
|
@@ -20923,7 +21025,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20923
21025
|
sourcemaps,
|
|
20924
21026
|
sourcemapsSourcesContent,
|
|
20925
21027
|
writeGeneratedFiles,
|
|
20926
|
-
outDirectoryUrl: new URL(
|
|
21028
|
+
outDirectoryUrl: new URL("build/", jsenvInternalDirectoryUrl)
|
|
20927
21029
|
});
|
|
20928
21030
|
const buildUrlsGenerator = createBuildUrlsGenerator({
|
|
20929
21031
|
buildDirectoryUrl,
|
|
@@ -20945,12 +21047,13 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20945
21047
|
const bundlers = {};
|
|
20946
21048
|
const finalGraph = createUrlGraph();
|
|
20947
21049
|
const urlAnalysisPlugin = jsenvPluginUrlAnalysis({
|
|
20948
|
-
rootDirectoryUrl,
|
|
21050
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20949
21051
|
...urlAnalysis
|
|
20950
21052
|
});
|
|
20951
21053
|
const finalGraphKitchen = createKitchen({
|
|
20952
21054
|
logLevel,
|
|
20953
21055
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
21056
|
+
jsenvInternalDirectoryUrl,
|
|
20954
21057
|
urlGraph: finalGraph,
|
|
20955
21058
|
build: true,
|
|
20956
21059
|
runtimeCompat,
|
|
@@ -21197,7 +21300,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21197
21300
|
sourcemapsSourcesContent,
|
|
21198
21301
|
sourcemapsSourcesRelative: !versioning,
|
|
21199
21302
|
writeGeneratedFiles,
|
|
21200
|
-
outDirectoryUrl: new URL("
|
|
21303
|
+
outDirectoryUrl: new URL("postbuild/", jsenvInternalDirectoryUrl)
|
|
21201
21304
|
});
|
|
21202
21305
|
const finalEntryUrls = [];
|
|
21203
21306
|
{
|
|
@@ -21206,7 +21309,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21206
21309
|
});
|
|
21207
21310
|
try {
|
|
21208
21311
|
if (writeGeneratedFiles) {
|
|
21209
|
-
await ensureEmptyDirectory(new URL(
|
|
21312
|
+
await ensureEmptyDirectory(new URL(`build/`, sourceDirectoryUrl));
|
|
21210
21313
|
}
|
|
21211
21314
|
const rawUrlGraphLoader = createUrlGraphLoader(rawGraphKitchen.kitchenContext);
|
|
21212
21315
|
Object.keys(entryPoints).forEach(key => {
|
|
@@ -21214,7 +21317,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21214
21317
|
trace: {
|
|
21215
21318
|
message: `"${key}" in entryPoints parameter`
|
|
21216
21319
|
},
|
|
21217
|
-
parentUrl:
|
|
21320
|
+
parentUrl: sourceDirectoryUrl,
|
|
21218
21321
|
type: "entry_point",
|
|
21219
21322
|
specifier: key
|
|
21220
21323
|
});
|
|
@@ -21420,7 +21523,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21420
21523
|
});
|
|
21421
21524
|
try {
|
|
21422
21525
|
if (writeGeneratedFiles) {
|
|
21423
|
-
await ensureEmptyDirectory(new URL(
|
|
21526
|
+
await ensureEmptyDirectory(new URL(`postbuild/`, jsenvInternalDirectoryUrl));
|
|
21424
21527
|
}
|
|
21425
21528
|
const finalUrlGraphLoader = createUrlGraphLoader(finalGraphKitchen.kitchenContext);
|
|
21426
21529
|
entryUrls.forEach(entryUrl => {
|
|
@@ -21428,7 +21531,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21428
21531
|
trace: {
|
|
21429
21532
|
message: `entryPoint`
|
|
21430
21533
|
},
|
|
21431
|
-
parentUrl:
|
|
21534
|
+
parentUrl: sourceDirectoryUrl,
|
|
21432
21535
|
type: "entry_point",
|
|
21433
21536
|
specifier: entryUrl
|
|
21434
21537
|
});
|
|
@@ -21620,6 +21723,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21620
21723
|
const versioningKitchen = createKitchen({
|
|
21621
21724
|
logLevel: logger.level,
|
|
21622
21725
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
21726
|
+
jsenvInternalDirectoryUrl,
|
|
21623
21727
|
urlGraph: finalGraph,
|
|
21624
21728
|
build: true,
|
|
21625
21729
|
runtimeCompat,
|
|
@@ -21712,7 +21816,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21712
21816
|
sourcemapsSourcesContent,
|
|
21713
21817
|
sourcemapsSourcesRelative: true,
|
|
21714
21818
|
writeGeneratedFiles,
|
|
21715
|
-
outDirectoryUrl: new URL("
|
|
21819
|
+
outDirectoryUrl: new URL("postbuild/", jsenvInternalDirectoryUrl)
|
|
21716
21820
|
});
|
|
21717
21821
|
const versioningUrlGraphLoader = createUrlGraphLoader(versioningKitchen.kitchenContext);
|
|
21718
21822
|
finalEntryUrls.forEach(finalEntryUrl => {
|
|
@@ -22088,13 +22192,12 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22088
22192
|
};
|
|
22089
22193
|
startBuild();
|
|
22090
22194
|
let startTimeout;
|
|
22091
|
-
const
|
|
22092
|
-
|
|
22195
|
+
const stopWatchingSourceFiles = watchSourceFiles(sourceDirectoryUrl, ({
|
|
22196
|
+
url,
|
|
22093
22197
|
event
|
|
22094
22198
|
}) => {
|
|
22095
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
22096
22199
|
if (watchFilesTask) {
|
|
22097
|
-
watchFilesTask.happen(`${url.slice(
|
|
22200
|
+
watchFilesTask.happen(`${url.slice(sourceDirectoryUrl.length)} ${event}`);
|
|
22098
22201
|
watchFilesTask = null;
|
|
22099
22202
|
}
|
|
22100
22203
|
buildAbortController.abort();
|
|
@@ -22103,42 +22206,16 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22103
22206
|
// then logs about re-running the build happens
|
|
22104
22207
|
clearTimeout(startTimeout);
|
|
22105
22208
|
startTimeout = setTimeout(startBuild, 20);
|
|
22106
|
-
}
|
|
22107
|
-
|
|
22108
|
-
watchPatterns: clientFiles,
|
|
22109
|
-
cooldownBetweenFileEvents,
|
|
22209
|
+
}, {
|
|
22210
|
+
sourceFilesConfig,
|
|
22110
22211
|
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
|
-
}
|
|
22212
|
+
cooldownBetweenFileEvents
|
|
22136
22213
|
});
|
|
22137
22214
|
operation.addAbortCallback(() => {
|
|
22138
|
-
|
|
22215
|
+
stopWatchingSourceFiles();
|
|
22139
22216
|
});
|
|
22140
22217
|
await firstBuildPromise;
|
|
22141
|
-
return
|
|
22218
|
+
return stopWatchingSourceFiles;
|
|
22142
22219
|
};
|
|
22143
22220
|
const findKey = (map, value) => {
|
|
22144
22221
|
for (const [keyCandidate, valueCandidate] of map) {
|
|
@@ -22164,26 +22241,6 @@ const injectVersionIntoBuildUrl = ({
|
|
|
22164
22241
|
const versionedUrl = setUrlFilename(buildUrl, versionedFilename);
|
|
22165
22242
|
return versionedUrl;
|
|
22166
22243
|
};
|
|
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
22244
|
const isUsed = urlInfo => {
|
|
22188
22245
|
// nothing uses this url anymore
|
|
22189
22246
|
// - versioning update inline content
|
|
@@ -22206,57 +22263,6 @@ const canUseVersionedUrl = urlInfo => {
|
|
|
22206
22263
|
return urlInfo.type !== "webmanifest";
|
|
22207
22264
|
};
|
|
22208
22265
|
|
|
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
22266
|
/*
|
|
22261
22267
|
* This plugin is very special because it is here
|
|
22262
22268
|
* to provide "serverEvents" used by other plugins
|
|
@@ -22320,7 +22326,9 @@ const createFileService = ({
|
|
|
22320
22326
|
serverStopCallbacks,
|
|
22321
22327
|
serverEventsDispatcher,
|
|
22322
22328
|
contextCache,
|
|
22323
|
-
|
|
22329
|
+
sourceDirectoryUrl,
|
|
22330
|
+
sourceMainFilePath,
|
|
22331
|
+
sourceFilesConfig,
|
|
22324
22332
|
runtimeCompat,
|
|
22325
22333
|
plugins,
|
|
22326
22334
|
urlAnalysis,
|
|
@@ -22329,8 +22337,6 @@ const createFileService = ({
|
|
|
22329
22337
|
supervisor,
|
|
22330
22338
|
transpilation,
|
|
22331
22339
|
clientAutoreload,
|
|
22332
|
-
clientFiles,
|
|
22333
|
-
clientMainFileUrl,
|
|
22334
22340
|
cooldownBetweenFileEvents,
|
|
22335
22341
|
explorer,
|
|
22336
22342
|
cacheControl,
|
|
@@ -22340,49 +22346,18 @@ const createFileService = ({
|
|
|
22340
22346
|
sourcemapsSourcesContent,
|
|
22341
22347
|
writeGeneratedFiles
|
|
22342
22348
|
}) => {
|
|
22343
|
-
const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href;
|
|
22344
22349
|
const clientFileChangeCallbackList = [];
|
|
22345
22350
|
const clientFilesPruneCallbackList = [];
|
|
22346
|
-
const
|
|
22347
|
-
...clientFiles,
|
|
22348
|
-
".jsenv/": false
|
|
22349
|
-
};
|
|
22350
|
-
const onFileChange = url => {
|
|
22351
|
+
const stopWatchingSourceFiles = watchSourceFiles(sourceDirectoryUrl, fileInfo => {
|
|
22351
22352
|
clientFileChangeCallbackList.forEach(callback => {
|
|
22352
|
-
callback(
|
|
22353
|
+
callback(fileInfo);
|
|
22353
22354
|
});
|
|
22354
|
-
}
|
|
22355
|
-
|
|
22356
|
-
watchPatterns: clientFilePatterns,
|
|
22357
|
-
cooldownBetweenFileEvents,
|
|
22355
|
+
}, {
|
|
22356
|
+
sourceFilesConfig,
|
|
22358
22357
|
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
|
-
}
|
|
22358
|
+
cooldownBetweenFileEvents
|
|
22384
22359
|
});
|
|
22385
|
-
serverStopCallbacks.push(
|
|
22360
|
+
serverStopCallbacks.push(stopWatchingSourceFiles);
|
|
22386
22361
|
const getOrCreateContext = request => {
|
|
22387
22362
|
const {
|
|
22388
22363
|
runtimeName,
|
|
@@ -22394,8 +22369,8 @@ const createFileService = ({
|
|
|
22394
22369
|
return existingContext;
|
|
22395
22370
|
}
|
|
22396
22371
|
const watchAssociations = URL_META.resolveAssociations({
|
|
22397
|
-
watch:
|
|
22398
|
-
},
|
|
22372
|
+
watch: stopWatchingSourceFiles.watchPatterns
|
|
22373
|
+
}, sourceDirectoryUrl);
|
|
22399
22374
|
const urlGraph = createUrlGraph();
|
|
22400
22375
|
clientFileChangeCallbackList.push(({
|
|
22401
22376
|
url
|
|
@@ -22418,24 +22393,32 @@ const createFileService = ({
|
|
|
22418
22393
|
const clientRuntimeCompat = {
|
|
22419
22394
|
[runtimeName]: runtimeVersion
|
|
22420
22395
|
};
|
|
22396
|
+
const jsenvInternalDirectoryUrl = determineJsenvInternalDirectoryUrl(sourceDirectoryUrl);
|
|
22397
|
+
let mainFileUrl;
|
|
22398
|
+
if (sourceMainFilePath === undefined) {
|
|
22399
|
+
mainFileUrl = explorer ? String(explorerHtmlFileUrl) : String(new URL("./index.html", sourceDirectoryUrl));
|
|
22400
|
+
} else {
|
|
22401
|
+
mainFileUrl = String(new URL(sourceMainFilePath, sourceDirectoryUrl));
|
|
22402
|
+
}
|
|
22421
22403
|
const kitchen = createKitchen({
|
|
22422
22404
|
signal,
|
|
22423
22405
|
logLevel,
|
|
22424
|
-
rootDirectoryUrl,
|
|
22406
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22407
|
+
jsenvInternalDirectoryUrl,
|
|
22425
22408
|
urlGraph,
|
|
22426
22409
|
dev: true,
|
|
22427
22410
|
runtimeCompat,
|
|
22428
22411
|
clientRuntimeCompat,
|
|
22429
22412
|
systemJsTranspilation: !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "script_type_module") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_dynamic") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_meta"),
|
|
22430
22413
|
plugins: [...plugins, ...getCorePlugins({
|
|
22431
|
-
rootDirectoryUrl,
|
|
22414
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22415
|
+
mainFileUrl,
|
|
22432
22416
|
runtimeCompat,
|
|
22433
22417
|
urlAnalysis,
|
|
22434
22418
|
urlResolution,
|
|
22435
22419
|
fileSystemMagicRedirection,
|
|
22436
22420
|
supervisor,
|
|
22437
22421
|
transpilation,
|
|
22438
|
-
clientMainFileUrl,
|
|
22439
22422
|
clientAutoreload,
|
|
22440
22423
|
clientFileChangeCallbackList,
|
|
22441
22424
|
clientFilesPruneCallbackList,
|
|
@@ -22449,7 +22432,7 @@ const createFileService = ({
|
|
|
22449
22432
|
sourcemapsSourcesProtocol,
|
|
22450
22433
|
sourcemapsSourcesContent,
|
|
22451
22434
|
writeGeneratedFiles,
|
|
22452
|
-
outDirectoryUrl: `${
|
|
22435
|
+
outDirectoryUrl: new URL(`${runtimeName}@${runtimeVersion}/`, jsenvInternalDirectoryUrl)
|
|
22453
22436
|
});
|
|
22454
22437
|
urlGraph.createUrlInfoCallbackRef.current = urlInfo => {
|
|
22455
22438
|
const {
|
|
@@ -22528,7 +22511,7 @@ const createFileService = ({
|
|
|
22528
22511
|
if (serverEventNames.length > 0) {
|
|
22529
22512
|
Object.keys(allServerEvents).forEach(serverEventName => {
|
|
22530
22513
|
allServerEvents[serverEventName]({
|
|
22531
|
-
rootDirectoryUrl,
|
|
22514
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22532
22515
|
urlGraph,
|
|
22533
22516
|
dev: true,
|
|
22534
22517
|
sendServerEvent: data => {
|
|
@@ -22544,7 +22527,7 @@ const createFileService = ({
|
|
|
22544
22527
|
}
|
|
22545
22528
|
}
|
|
22546
22529
|
const context = {
|
|
22547
|
-
rootDirectoryUrl,
|
|
22530
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22548
22531
|
dev: true,
|
|
22549
22532
|
runtimeName,
|
|
22550
22533
|
runtimeVersion,
|
|
@@ -22555,13 +22538,6 @@ const createFileService = ({
|
|
|
22555
22538
|
return context;
|
|
22556
22539
|
};
|
|
22557
22540
|
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
22541
|
const {
|
|
22566
22542
|
urlGraph,
|
|
22567
22543
|
kitchen
|
|
@@ -22571,16 +22547,16 @@ const createFileService = ({
|
|
|
22571
22547
|
return responseFromPlugin;
|
|
22572
22548
|
}
|
|
22573
22549
|
let reference;
|
|
22574
|
-
const parentUrl = inferParentFromRequest(request,
|
|
22550
|
+
const parentUrl = inferParentFromRequest(request, sourceDirectoryUrl);
|
|
22575
22551
|
if (parentUrl) {
|
|
22576
22552
|
reference = urlGraph.inferReference(request.resource, parentUrl);
|
|
22577
22553
|
}
|
|
22578
22554
|
if (!reference) {
|
|
22579
22555
|
const entryPoint = kitchen.injectReference({
|
|
22580
22556
|
trace: {
|
|
22581
|
-
message: parentUrl ||
|
|
22557
|
+
message: parentUrl || sourceDirectoryUrl
|
|
22582
22558
|
},
|
|
22583
|
-
parentUrl: parentUrl ||
|
|
22559
|
+
parentUrl: parentUrl || sourceDirectoryUrl,
|
|
22584
22560
|
type: "http_request",
|
|
22585
22561
|
specifier: request.resource
|
|
22586
22562
|
});
|
|
@@ -22702,7 +22678,7 @@ const createFileService = ({
|
|
|
22702
22678
|
accept: "text/html"
|
|
22703
22679
|
},
|
|
22704
22680
|
canReadDirectory: true,
|
|
22705
|
-
rootDirectoryUrl
|
|
22681
|
+
rootDirectoryUrl: sourceDirectoryUrl
|
|
22706
22682
|
});
|
|
22707
22683
|
}
|
|
22708
22684
|
if (code === "NOT_ALLOWED") {
|
|
@@ -22729,7 +22705,7 @@ const createFileService = ({
|
|
|
22729
22705
|
}
|
|
22730
22706
|
};
|
|
22731
22707
|
};
|
|
22732
|
-
const inferParentFromRequest = (request,
|
|
22708
|
+
const inferParentFromRequest = (request, sourceDirectoryUrl) => {
|
|
22733
22709
|
const {
|
|
22734
22710
|
referer
|
|
22735
22711
|
} = request.headers;
|
|
@@ -22750,7 +22726,7 @@ const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
|
22750
22726
|
return moveUrl({
|
|
22751
22727
|
url: referer,
|
|
22752
22728
|
from: `${request.origin}/`,
|
|
22753
|
-
to:
|
|
22729
|
+
to: sourceDirectoryUrl,
|
|
22754
22730
|
preferAbsolute: true
|
|
22755
22731
|
});
|
|
22756
22732
|
};
|
|
@@ -22760,38 +22736,28 @@ const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
|
22760
22736
|
* - cook source files according to jsenv plugins
|
|
22761
22737
|
* - inject code to autoreload the browser when a file is modified
|
|
22762
22738
|
* @param {Object} devServerParameters
|
|
22763
|
-
* @param {string|url} devServerParameters.
|
|
22739
|
+
* @param {string|url} devServerParameters.sourceDirectoryUrl Root directory of the project
|
|
22764
22740
|
* @return {Object} A dev server object
|
|
22765
22741
|
*/
|
|
22766
22742
|
const startDevServer = async ({
|
|
22767
|
-
|
|
22768
|
-
|
|
22769
|
-
|
|
22770
|
-
|
|
22743
|
+
sourceDirectoryUrl,
|
|
22744
|
+
sourceMainFilePath,
|
|
22745
|
+
port = 3456,
|
|
22746
|
+
hostname,
|
|
22747
|
+
acceptAnyIp,
|
|
22771
22748
|
https,
|
|
22772
22749
|
// it's better to use http1 by default because it allows to get statusText in devtools
|
|
22773
22750
|
// which gives valuable information when there is errors
|
|
22774
22751
|
http2 = false,
|
|
22775
|
-
|
|
22776
|
-
|
|
22777
|
-
acceptAnyIp,
|
|
22778
|
-
keepProcessAlive = true,
|
|
22752
|
+
logLevel = process.env.IMPORTED_BY_TEST_PLAN ? "warn" : "info",
|
|
22753
|
+
serverLogLevel = "warn",
|
|
22779
22754
|
services = [],
|
|
22755
|
+
signal = new AbortController().signal,
|
|
22756
|
+
handleSIGINT = true,
|
|
22757
|
+
keepProcessAlive = true,
|
|
22780
22758
|
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
|
-
},
|
|
22759
|
+
sourceFilesConfig,
|
|
22791
22760
|
clientAutoreload = true,
|
|
22792
|
-
clientMainFileUrl,
|
|
22793
|
-
devServerAutoreload = false,
|
|
22794
|
-
devServerMainFile = getCallerPosition().url,
|
|
22795
22761
|
cooldownBetweenFileEvents,
|
|
22796
22762
|
// runtimeCompat is the runtimeCompat for the build
|
|
22797
22763
|
// when specified, dev server use it to warn in case
|
|
@@ -22823,11 +22789,7 @@ const startDevServer = async ({
|
|
|
22823
22789
|
if (unexpectedParamNames.length > 0) {
|
|
22824
22790
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
22825
22791
|
}
|
|
22826
|
-
|
|
22827
|
-
if (!rootDirectoryUrlValidation.valid) {
|
|
22828
|
-
throw new TypeError(`rootDirectoryUrl ${rootDirectoryUrlValidation.message}, got ${rootDirectoryUrl}`);
|
|
22829
|
-
}
|
|
22830
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
22792
|
+
sourceDirectoryUrl = assertAndNormalizeDirectoryUrl(sourceDirectoryUrl, "sourceDirectoryUrl");
|
|
22831
22793
|
}
|
|
22832
22794
|
const logger = createLogger({
|
|
22833
22795
|
logLevel
|
|
@@ -22841,70 +22803,6 @@ const startDevServer = async ({
|
|
|
22841
22803
|
}, abort);
|
|
22842
22804
|
});
|
|
22843
22805
|
}
|
|
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
22806
|
const startDevServerTask = createTaskLog("start dev server", {
|
|
22909
22807
|
disabled: !logger.levels.info
|
|
22910
22808
|
});
|
|
@@ -22935,7 +22833,30 @@ const startDevServer = async ({
|
|
|
22935
22833
|
accessControlAllowedRequestHeaders: [...jsenvAccessControlAllowedHeaders, "x-jsenv-execution-id"],
|
|
22936
22834
|
accessControlAllowCredentials: true,
|
|
22937
22835
|
timingAllowOrigin: true
|
|
22938
|
-
}),
|
|
22836
|
+
}), {
|
|
22837
|
+
handleRequest: request => {
|
|
22838
|
+
if (request.pathname === "/__server_params__.json") {
|
|
22839
|
+
const json = JSON.stringify({
|
|
22840
|
+
sourceDirectoryUrl
|
|
22841
|
+
});
|
|
22842
|
+
return {
|
|
22843
|
+
status: 200,
|
|
22844
|
+
headers: {
|
|
22845
|
+
"content-type": "application/json",
|
|
22846
|
+
"content-length": Buffer.byteLength(json)
|
|
22847
|
+
},
|
|
22848
|
+
body: json
|
|
22849
|
+
};
|
|
22850
|
+
}
|
|
22851
|
+
if (request.pathname === "/__stop__") {
|
|
22852
|
+
server.stop();
|
|
22853
|
+
return {
|
|
22854
|
+
status: 200
|
|
22855
|
+
};
|
|
22856
|
+
}
|
|
22857
|
+
return null;
|
|
22858
|
+
}
|
|
22859
|
+
}, ...services, {
|
|
22939
22860
|
name: "jsenv:omega_file_service",
|
|
22940
22861
|
handleRequest: createFileService({
|
|
22941
22862
|
signal,
|
|
@@ -22943,7 +22864,9 @@ const startDevServer = async ({
|
|
|
22943
22864
|
serverStopCallbacks,
|
|
22944
22865
|
serverEventsDispatcher,
|
|
22945
22866
|
contextCache,
|
|
22946
|
-
|
|
22867
|
+
sourceDirectoryUrl,
|
|
22868
|
+
sourceMainFilePath,
|
|
22869
|
+
sourceFilesConfig,
|
|
22947
22870
|
runtimeCompat,
|
|
22948
22871
|
plugins,
|
|
22949
22872
|
urlAnalysis,
|
|
@@ -22952,8 +22875,6 @@ const startDevServer = async ({
|
|
|
22952
22875
|
supervisor,
|
|
22953
22876
|
transpilation,
|
|
22954
22877
|
clientAutoreload,
|
|
22955
|
-
clientFiles,
|
|
22956
|
-
clientMainFileUrl,
|
|
22957
22878
|
cooldownBetweenFileEvents,
|
|
22958
22879
|
explorer,
|
|
22959
22880
|
cacheControl,
|
|
@@ -23026,9 +22947,6 @@ const startDevServer = async ({
|
|
|
23026
22947
|
logger.info(`- ${server.origins[key]}`);
|
|
23027
22948
|
});
|
|
23028
22949
|
logger.info(``);
|
|
23029
|
-
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
23030
|
-
parentPort.postMessage(server.origin);
|
|
23031
|
-
}
|
|
23032
22950
|
return {
|
|
23033
22951
|
origin: server.origin,
|
|
23034
22952
|
stop: () => {
|
|
@@ -23038,6 +22956,80 @@ const startDevServer = async ({
|
|
|
23038
22956
|
};
|
|
23039
22957
|
};
|
|
23040
22958
|
|
|
22959
|
+
const pingServer = async url => {
|
|
22960
|
+
const server = createServer();
|
|
22961
|
+
const {
|
|
22962
|
+
hostname,
|
|
22963
|
+
port
|
|
22964
|
+
} = new URL(url);
|
|
22965
|
+
try {
|
|
22966
|
+
await new Promise((resolve, reject) => {
|
|
22967
|
+
server.on("error", reject);
|
|
22968
|
+
server.on("listening", () => {
|
|
22969
|
+
resolve();
|
|
22970
|
+
});
|
|
22971
|
+
server.listen(port, hostname);
|
|
22972
|
+
});
|
|
22973
|
+
} catch (error) {
|
|
22974
|
+
if (error && error.code === "EADDRINUSE") {
|
|
22975
|
+
return true;
|
|
22976
|
+
}
|
|
22977
|
+
if (error && error.code === "EACCES") {
|
|
22978
|
+
return true;
|
|
22979
|
+
}
|
|
22980
|
+
throw error;
|
|
22981
|
+
}
|
|
22982
|
+
await new Promise((resolve, reject) => {
|
|
22983
|
+
server.on("error", reject);
|
|
22984
|
+
server.on("close", resolve);
|
|
22985
|
+
server.close();
|
|
22986
|
+
});
|
|
22987
|
+
return false;
|
|
22988
|
+
};
|
|
22989
|
+
|
|
22990
|
+
const basicFetch = async (url, {
|
|
22991
|
+
method = "GET",
|
|
22992
|
+
headers = {}
|
|
22993
|
+
} = {}) => {
|
|
22994
|
+
let requestModule;
|
|
22995
|
+
if (url.startsWith("http:")) {
|
|
22996
|
+
requestModule = await import("node:http");
|
|
22997
|
+
} else {
|
|
22998
|
+
requestModule = await import("node:https");
|
|
22999
|
+
}
|
|
23000
|
+
const {
|
|
23001
|
+
request
|
|
23002
|
+
} = requestModule;
|
|
23003
|
+
const urlObject = new URL(url);
|
|
23004
|
+
return new Promise((resolve, reject) => {
|
|
23005
|
+
const req = request({
|
|
23006
|
+
hostname: urlObject.hostname,
|
|
23007
|
+
port: urlObject.port,
|
|
23008
|
+
path: urlObject.pathname,
|
|
23009
|
+
method,
|
|
23010
|
+
headers
|
|
23011
|
+
});
|
|
23012
|
+
req.on("response", response => {
|
|
23013
|
+
req.setTimeout(0);
|
|
23014
|
+
let responseBody = "";
|
|
23015
|
+
response.setEncoding("utf8");
|
|
23016
|
+
response.on("data", chunk => {
|
|
23017
|
+
responseBody += chunk;
|
|
23018
|
+
});
|
|
23019
|
+
response.on("end", () => {
|
|
23020
|
+
req.destroy();
|
|
23021
|
+
if (response.headers["content-type"] === "application/json") {
|
|
23022
|
+
resolve(JSON.parse(responseBody));
|
|
23023
|
+
} else {
|
|
23024
|
+
resolve(responseBody);
|
|
23025
|
+
}
|
|
23026
|
+
});
|
|
23027
|
+
});
|
|
23028
|
+
req.on("error", reject);
|
|
23029
|
+
req.end();
|
|
23030
|
+
});
|
|
23031
|
+
};
|
|
23032
|
+
|
|
23041
23033
|
const generateCoverageJsonFile = async ({
|
|
23042
23034
|
coverage,
|
|
23043
23035
|
coverageJsonFileUrl,
|
|
@@ -23127,7 +23119,7 @@ const readNodeV8CoverageDirectory = async ({
|
|
|
23127
23119
|
try {
|
|
23128
23120
|
operation.throwIfAborted();
|
|
23129
23121
|
const dirContent = await tryReadDirectory();
|
|
23130
|
-
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE);
|
|
23122
|
+
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE, "NODE_V8_COVERAGE");
|
|
23131
23123
|
await dirContent.reduce(async (previous, dirEntry) => {
|
|
23132
23124
|
operation.throwIfAborted();
|
|
23133
23125
|
await previous;
|
|
@@ -23750,37 +23742,6 @@ const run = async ({
|
|
|
23750
23742
|
return result;
|
|
23751
23743
|
};
|
|
23752
23744
|
|
|
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
23745
|
const ensureGlobalGc = () => {
|
|
23785
23746
|
if (!global.gc) {
|
|
23786
23747
|
v8.setFlagsFromString("--expose_gc");
|
|
@@ -24208,7 +24169,7 @@ const executePlan = async (plan, {
|
|
|
24208
24169
|
coverageMethodForBrowsers,
|
|
24209
24170
|
coverageMethodForNodeJs,
|
|
24210
24171
|
coverageV8ConflictWarning,
|
|
24211
|
-
|
|
24172
|
+
coverageTempDirectoryUrl,
|
|
24212
24173
|
beforeExecutionCallback = () => {},
|
|
24213
24174
|
afterExecutionCallback = () => {}
|
|
24214
24175
|
} = {}) => {
|
|
@@ -24218,30 +24179,6 @@ const executePlan = async (plan, {
|
|
|
24218
24179
|
const stopAfterAllSignal = {
|
|
24219
24180
|
notify: () => {}
|
|
24220
24181
|
};
|
|
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
24182
|
const multipleExecutionsOperation = Abort.startOperation();
|
|
24246
24183
|
multipleExecutionsOperation.addAbortSignal(signal);
|
|
24247
24184
|
if (handleSIGINT) {
|
|
@@ -24259,19 +24196,6 @@ const executePlan = async (plan, {
|
|
|
24259
24196
|
multipleExecutionsOperation.addAbortSignal(failFastAbortController.signal);
|
|
24260
24197
|
}
|
|
24261
24198
|
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
24199
|
if (gcBetweenExecutions) {
|
|
24276
24200
|
ensureGlobalGc();
|
|
24277
24201
|
}
|
|
@@ -24318,15 +24242,6 @@ const executePlan = async (plan, {
|
|
|
24318
24242
|
coverageMethodForNodeJs,
|
|
24319
24243
|
stopAfterAllSignal
|
|
24320
24244
|
};
|
|
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
24245
|
logger.debug(`Generate executions`);
|
|
24331
24246
|
const executionSteps = await getExecutionAsSteps({
|
|
24332
24247
|
plan,
|
|
@@ -24423,7 +24338,7 @@ const executePlan = async (plan, {
|
|
|
24423
24338
|
executionResult = await run({
|
|
24424
24339
|
signal: multipleExecutionsOperation.signal,
|
|
24425
24340
|
logger,
|
|
24426
|
-
allocatedMs: executionParams.allocatedMs,
|
|
24341
|
+
allocatedMs: typeof executionParams.allocatedMs === "function" ? executionParams.allocatedMs(beforeExecutionInfo) : executionParams.allocatedMs,
|
|
24427
24342
|
keepRunning,
|
|
24428
24343
|
mirrorConsole: false,
|
|
24429
24344
|
// file are executed in parallel, log would be a mess to read
|
|
@@ -24639,8 +24554,8 @@ const executeInParallel = async ({
|
|
|
24639
24554
|
/**
|
|
24640
24555
|
* Execute a list of files and log how it goes.
|
|
24641
24556
|
* @param {Object} testPlanParameters
|
|
24642
|
-
* @param {string|url} testPlanParameters.
|
|
24643
|
-
* @param {string|url} [testPlanParameters.
|
|
24557
|
+
* @param {string|url} testPlanParameters.testDirectoryUrl Directory containing test files
|
|
24558
|
+
* @param {string|url} [testPlanParameters.devServerOrigin=undefined] Jsenv dev server origin; required when executing test on browsers
|
|
24644
24559
|
* @param {Object} testPlanParameters.testPlan Object associating patterns leading to files to runtimes where they should be executed
|
|
24645
24560
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
24646
24561
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
@@ -24666,7 +24581,8 @@ const executeTestPlan = async ({
|
|
|
24666
24581
|
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
24667
24582
|
completedExecutionLogAbbreviation = false,
|
|
24668
24583
|
completedExecutionLogMerging = false,
|
|
24669
|
-
|
|
24584
|
+
testDirectoryUrl,
|
|
24585
|
+
devServerModuleUrl,
|
|
24670
24586
|
devServerOrigin,
|
|
24671
24587
|
testPlan,
|
|
24672
24588
|
updateProcessExitCode = true,
|
|
@@ -24683,7 +24599,7 @@ const executeTestPlan = async ({
|
|
|
24683
24599
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
24684
24600
|
coverageEnabled = process.argv.includes("--coverage"),
|
|
24685
24601
|
coverageConfig = {
|
|
24686
|
-
"
|
|
24602
|
+
"./**/*": true
|
|
24687
24603
|
},
|
|
24688
24604
|
coverageIncludeMissing = true,
|
|
24689
24605
|
coverageAndExecutionAllowed = false,
|
|
@@ -24691,30 +24607,87 @@ const executeTestPlan = async ({
|
|
|
24691
24607
|
coverageMethodForBrowsers = "playwright_api",
|
|
24692
24608
|
// "istanbul" also accepted
|
|
24693
24609
|
coverageV8ConflictWarning = true,
|
|
24694
|
-
|
|
24610
|
+
coverageTempDirectoryUrl,
|
|
24611
|
+
coverageReportRootDirectoryUrl,
|
|
24695
24612
|
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
24696
24613
|
coverageReportSkipEmpty = false,
|
|
24697
24614
|
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
24698
24615
|
coverageReportSkipFull = false,
|
|
24699
24616
|
coverageReportTextLog = true,
|
|
24700
|
-
|
|
24701
|
-
|
|
24617
|
+
coverageReportJson = process.env.CI,
|
|
24618
|
+
coverageReportJsonFileUrl,
|
|
24619
|
+
coverageReportHtml = !process.env.CI,
|
|
24620
|
+
coverageReportHtmlDirectoryUrl,
|
|
24702
24621
|
...rest
|
|
24703
24622
|
}) => {
|
|
24623
|
+
let someNeedsServer = false;
|
|
24624
|
+
let someNodeRuntime = false;
|
|
24625
|
+
let stopDevServerNeeded = false;
|
|
24626
|
+
const runtimes = {};
|
|
24704
24627
|
// param validation
|
|
24705
24628
|
{
|
|
24706
24629
|
const unexpectedParamNames = Object.keys(rest);
|
|
24707
24630
|
if (unexpectedParamNames.length > 0) {
|
|
24708
24631
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
24709
24632
|
}
|
|
24710
|
-
|
|
24711
|
-
if (!
|
|
24712
|
-
throw new
|
|
24633
|
+
testDirectoryUrl = assertAndNormalizeDirectoryUrl(testDirectoryUrl, "testDirectoryUrl");
|
|
24634
|
+
if (!existsSync(new URL(testDirectoryUrl))) {
|
|
24635
|
+
throw new Error(`ENOENT on testDirectoryUrl at ${testDirectoryUrl}`);
|
|
24713
24636
|
}
|
|
24714
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
24715
24637
|
if (typeof testPlan !== "object") {
|
|
24716
24638
|
throw new Error(`testPlan must be an object, got ${testPlan}`);
|
|
24717
24639
|
}
|
|
24640
|
+
Object.keys(testPlan).forEach(filePattern => {
|
|
24641
|
+
const filePlan = testPlan[filePattern];
|
|
24642
|
+
if (!filePlan) return;
|
|
24643
|
+
Object.keys(filePlan).forEach(executionName => {
|
|
24644
|
+
const executionConfig = filePlan[executionName];
|
|
24645
|
+
const {
|
|
24646
|
+
runtime
|
|
24647
|
+
} = executionConfig;
|
|
24648
|
+
if (runtime) {
|
|
24649
|
+
runtimes[runtime.name] = runtime.version;
|
|
24650
|
+
if (runtime.type === "browser") {
|
|
24651
|
+
someNeedsServer = true;
|
|
24652
|
+
}
|
|
24653
|
+
if (runtime.type === "node") {
|
|
24654
|
+
someNodeRuntime = true;
|
|
24655
|
+
}
|
|
24656
|
+
}
|
|
24657
|
+
});
|
|
24658
|
+
});
|
|
24659
|
+
if (someNeedsServer) {
|
|
24660
|
+
if (!devServerOrigin) {
|
|
24661
|
+
throw new TypeError(`devServerOrigin is required when running tests on browser(s)`);
|
|
24662
|
+
}
|
|
24663
|
+
let devServerStarted = await pingServer(devServerOrigin);
|
|
24664
|
+
if (!devServerStarted) {
|
|
24665
|
+
if (!devServerModuleUrl) {
|
|
24666
|
+
throw new TypeError(`devServerModuleUrl is required when dev server is not started in order to run tests on browser(s)`);
|
|
24667
|
+
}
|
|
24668
|
+
try {
|
|
24669
|
+
process.env.IMPORTED_BY_TEST_PLAN = "1";
|
|
24670
|
+
await import(devServerModuleUrl);
|
|
24671
|
+
delete process.env.IMPORTED_BY_TEST_PLAN;
|
|
24672
|
+
} catch (e) {
|
|
24673
|
+
if (e.code === "MODULE_NOT_FOUND") {
|
|
24674
|
+
throw new Error(`Cannot find file responsible to start dev server at "${devServerModuleUrl}"`);
|
|
24675
|
+
}
|
|
24676
|
+
throw e;
|
|
24677
|
+
}
|
|
24678
|
+
devServerStarted = await pingServer(devServerOrigin);
|
|
24679
|
+
if (!devServerStarted) {
|
|
24680
|
+
throw new Error(`dev server not started after importing "${devServerModuleUrl}", ensure this module file is starting a server at "${devServerOrigin}"`);
|
|
24681
|
+
}
|
|
24682
|
+
stopDevServerNeeded = true;
|
|
24683
|
+
}
|
|
24684
|
+
const {
|
|
24685
|
+
sourceDirectoryUrl
|
|
24686
|
+
} = await basicFetch(`${devServerOrigin}/__server_params__.json`);
|
|
24687
|
+
if (testDirectoryUrl !== sourceDirectoryUrl && !urlIsInsideOf(testDirectoryUrl, sourceDirectoryUrl)) {
|
|
24688
|
+
throw new Error(`testDirectoryUrl must be inside sourceDirectoryUrl when running tests on browser(s)`);
|
|
24689
|
+
}
|
|
24690
|
+
}
|
|
24718
24691
|
if (coverageEnabled) {
|
|
24719
24692
|
if (typeof coverageConfig !== "object") {
|
|
24720
24693
|
throw new TypeError(`coverageConfig must be an object, got ${coverageConfig}`);
|
|
@@ -24742,14 +24715,63 @@ const executeTestPlan = async ({
|
|
|
24742
24715
|
}));
|
|
24743
24716
|
}
|
|
24744
24717
|
}
|
|
24718
|
+
if (coverageReportRootDirectoryUrl === undefined) {
|
|
24719
|
+
coverageReportRootDirectoryUrl = lookupPackageDirectory(testDirectoryUrl);
|
|
24720
|
+
} else {
|
|
24721
|
+
coverageReportRootDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageReportRootDirectoryUrl, "coverageReportRootDirectoryUrl");
|
|
24722
|
+
}
|
|
24723
|
+
if (coverageTempDirectoryUrl === undefined) {
|
|
24724
|
+
coverageTempDirectoryUrl = new URL("./.coverage/tmp/", coverageReportRootDirectoryUrl);
|
|
24725
|
+
} else {
|
|
24726
|
+
coverageTempDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageTempDirectoryUrl, "coverageTempDirectoryUrl");
|
|
24727
|
+
}
|
|
24728
|
+
if (coverageReportJson) {
|
|
24729
|
+
if (coverageReportJsonFileUrl === undefined) {
|
|
24730
|
+
coverageReportJsonFileUrl = new URL("./.coverage/coverage.json", coverageReportRootDirectoryUrl);
|
|
24731
|
+
} else {
|
|
24732
|
+
coverageReportJsonFileUrl = assertAndNormalizeFileUrl(coverageReportJsonFileUrl, "coverageReportJsonFileUrl");
|
|
24733
|
+
}
|
|
24734
|
+
}
|
|
24735
|
+
if (coverageReportHtml) {
|
|
24736
|
+
if (coverageReportHtmlDirectoryUrl === undefined) {
|
|
24737
|
+
coverageReportHtmlDirectoryUrl = new URL("./.coverage/", coverageReportRootDirectoryUrl);
|
|
24738
|
+
} else {
|
|
24739
|
+
coverageReportHtmlDirectoryUrl = assertAndNormalizeDirectoryUrl(coverageReportHtmlDirectoryUrl, "coverageReportHtmlDirectoryUrl");
|
|
24740
|
+
}
|
|
24741
|
+
}
|
|
24745
24742
|
}
|
|
24746
24743
|
}
|
|
24747
24744
|
const logger = createLogger({
|
|
24748
24745
|
logLevel
|
|
24749
24746
|
});
|
|
24750
|
-
|
|
24751
|
-
|
|
24747
|
+
logger.debug(createDetailedMessage$1(`Prepare executing plan`, {
|
|
24748
|
+
runtimes: JSON.stringify(runtimes, null, " ")
|
|
24749
|
+
}));
|
|
24750
|
+
|
|
24751
|
+
// param normalization
|
|
24752
|
+
{
|
|
24753
|
+
if (coverageEnabled) {
|
|
24754
|
+
if (Object.keys(coverageConfig).length === 0) {
|
|
24755
|
+
logger.warn(`coverageConfig is an empty object. Nothing will be instrumented for coverage so your coverage will be empty`);
|
|
24756
|
+
}
|
|
24757
|
+
if (someNodeRuntime && coverageEnabled && coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
24758
|
+
if (process.env.NODE_V8_COVERAGE) {
|
|
24759
|
+
// when runned multiple times, we don't want to keep previous files in this directory
|
|
24760
|
+
await ensureEmptyDirectory(process.env.NODE_V8_COVERAGE);
|
|
24761
|
+
} else {
|
|
24762
|
+
coverageMethodForNodeJs = "Profiler";
|
|
24763
|
+
logger.warn(createDetailedMessage$1(`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`, {
|
|
24764
|
+
"suggestion": `set process.env.NODE_V8_COVERAGE`,
|
|
24765
|
+
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`
|
|
24766
|
+
}));
|
|
24767
|
+
}
|
|
24768
|
+
}
|
|
24769
|
+
}
|
|
24752
24770
|
}
|
|
24771
|
+
testPlan = {
|
|
24772
|
+
...testPlan,
|
|
24773
|
+
"**/.jsenv/": null
|
|
24774
|
+
};
|
|
24753
24775
|
const result = await executePlan(testPlan, {
|
|
24754
24776
|
signal,
|
|
24755
24777
|
handleSIGINT,
|
|
@@ -24763,7 +24785,7 @@ const executeTestPlan = async ({
|
|
|
24763
24785
|
logFileRelativeUrl,
|
|
24764
24786
|
completedExecutionLogMerging,
|
|
24765
24787
|
completedExecutionLogAbbreviation,
|
|
24766
|
-
rootDirectoryUrl,
|
|
24788
|
+
rootDirectoryUrl: testDirectoryUrl,
|
|
24767
24789
|
devServerOrigin,
|
|
24768
24790
|
maxExecutionsInParallel,
|
|
24769
24791
|
defaultMsAllocatedPerExecution,
|
|
@@ -24777,8 +24799,17 @@ const executeTestPlan = async ({
|
|
|
24777
24799
|
coverageMethodForBrowsers,
|
|
24778
24800
|
coverageMethodForNodeJs,
|
|
24779
24801
|
coverageV8ConflictWarning,
|
|
24780
|
-
|
|
24802
|
+
coverageTempDirectoryUrl
|
|
24781
24803
|
});
|
|
24804
|
+
if (stopDevServerNeeded) {
|
|
24805
|
+
// we are expecting ECONNRESET because server will be stopped by the request
|
|
24806
|
+
basicFetch(`${devServerOrigin}/__stop__`).catch(e => {
|
|
24807
|
+
if (e.code === "ECONNRESET") {
|
|
24808
|
+
return;
|
|
24809
|
+
}
|
|
24810
|
+
throw e;
|
|
24811
|
+
});
|
|
24812
|
+
}
|
|
24782
24813
|
if (updateProcessExitCode && result.planSummary.counters.total !== result.planSummary.counters.completed) {
|
|
24783
24814
|
process.exitCode = 1;
|
|
24784
24815
|
}
|
|
@@ -24789,26 +24820,21 @@ const executeTestPlan = async ({
|
|
|
24789
24820
|
// keep this one first because it does ensureEmptyDirectory
|
|
24790
24821
|
// and in case coverage json file gets written in the same directory
|
|
24791
24822
|
// 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`;
|
|
24823
|
+
if (coverageEnabled && coverageReportHtml) {
|
|
24824
|
+
await ensureEmptyDirectory(coverageReportHtmlDirectoryUrl);
|
|
24825
|
+
const htmlCoverageDirectoryIndexFileUrl = `${coverageReportHtmlDirectoryUrl}index.html`;
|
|
24799
24826
|
logger.info(`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`);
|
|
24800
24827
|
promises.push(generateCoverageHtmlDirectory(planCoverage, {
|
|
24801
|
-
rootDirectoryUrl,
|
|
24802
|
-
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(
|
|
24828
|
+
rootDirectoryUrl: coverageReportRootDirectoryUrl,
|
|
24829
|
+
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(coverageReportHtmlDirectoryUrl, coverageReportRootDirectoryUrl),
|
|
24803
24830
|
coverageReportSkipEmpty,
|
|
24804
24831
|
coverageReportSkipFull
|
|
24805
24832
|
}));
|
|
24806
24833
|
}
|
|
24807
|
-
if (coverageEnabled &&
|
|
24808
|
-
const coverageJsonFileUrl = new URL(coverageReportJsonFile, rootDirectoryUrl).href;
|
|
24834
|
+
if (coverageEnabled && coverageReportJson) {
|
|
24809
24835
|
promises.push(generateCoverageJsonFile({
|
|
24810
24836
|
coverage: result.planCoverage,
|
|
24811
|
-
coverageJsonFileUrl,
|
|
24837
|
+
coverageJsonFileUrl: coverageReportJsonFileUrl,
|
|
24812
24838
|
logger
|
|
24813
24839
|
}));
|
|
24814
24840
|
}
|
|
@@ -25672,7 +25698,6 @@ nodeChildProcess.run = async ({
|
|
|
25672
25698
|
env: envForChildProcess
|
|
25673
25699
|
});
|
|
25674
25700
|
logger.debug(createDetailedMessage$1(`child process forked (pid ${childProcess.pid})`, {
|
|
25675
|
-
"execArgv": execArgv.join(`\n`),
|
|
25676
25701
|
"custom env": JSON.stringify(env, null, " ")
|
|
25677
25702
|
}));
|
|
25678
25703
|
// if we pass stream, pipe them https://github.com/sindresorhus/execa/issues/81
|
|
@@ -26195,32 +26220,23 @@ const onceWorkerThreadEvent = (worker, type, callback) => {
|
|
|
26195
26220
|
/**
|
|
26196
26221
|
* Start a server for build files.
|
|
26197
26222
|
* @param {Object} buildServerParameters
|
|
26198
|
-
* @param {string|url} buildServerParameters.rootDirectoryUrl Root directory of the project
|
|
26199
26223
|
* @param {string|url} buildServerParameters.buildDirectoryUrl Directory where build files are written
|
|
26200
26224
|
* @return {Object} A build server object
|
|
26201
26225
|
*/
|
|
26202
26226
|
const startBuildServer = async ({
|
|
26203
|
-
|
|
26204
|
-
|
|
26205
|
-
logLevel,
|
|
26206
|
-
serverLogLevel = "warn",
|
|
26207
|
-
https,
|
|
26208
|
-
http2,
|
|
26209
|
-
acceptAnyIp,
|
|
26210
|
-
hostname,
|
|
26227
|
+
buildDirectoryUrl,
|
|
26228
|
+
buildMainFilePath = "index.html",
|
|
26211
26229
|
port = 9779,
|
|
26212
26230
|
services = [],
|
|
26231
|
+
acceptAnyIp,
|
|
26232
|
+
hostname,
|
|
26233
|
+
https,
|
|
26234
|
+
http2,
|
|
26235
|
+
logLevel,
|
|
26236
|
+
serverLogLevel = "warn",
|
|
26237
|
+
signal = new AbortController().signal,
|
|
26238
|
+
handleSIGINT = true,
|
|
26213
26239
|
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
26240
|
...rest
|
|
26225
26241
|
}) => {
|
|
26226
26242
|
// params validation
|
|
@@ -26229,31 +26245,22 @@ const startBuildServer = async ({
|
|
|
26229
26245
|
if (unexpectedParamNames.length > 0) {
|
|
26230
26246
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
26231
26247
|
}
|
|
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}`);
|
|
26248
|
+
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl, "buildDirectoryUrl");
|
|
26249
|
+
if (buildMainFilePath) {
|
|
26250
|
+
if (typeof buildMainFilePath !== "string") {
|
|
26251
|
+
throw new TypeError(`buildMainFilePath must be a string, got ${buildMainFilePath}`);
|
|
26245
26252
|
}
|
|
26246
|
-
if (
|
|
26247
|
-
|
|
26253
|
+
if (buildMainFilePath[0] === "/") {
|
|
26254
|
+
buildMainFilePath = buildMainFilePath.slice(1);
|
|
26248
26255
|
} else {
|
|
26249
|
-
const
|
|
26250
|
-
if (!
|
|
26251
|
-
throw new Error(`
|
|
26256
|
+
const buildMainFileUrl = new URL(buildMainFilePath, buildDirectoryUrl).href;
|
|
26257
|
+
if (!buildMainFileUrl.startsWith(buildDirectoryUrl)) {
|
|
26258
|
+
throw new Error(`buildMainFilePath must be relative, got ${buildMainFilePath}`);
|
|
26252
26259
|
}
|
|
26253
|
-
|
|
26260
|
+
buildMainFilePath = buildMainFileUrl.slice(buildDirectoryUrl.length);
|
|
26254
26261
|
}
|
|
26255
|
-
if (!existsSync(new URL(
|
|
26256
|
-
|
|
26262
|
+
if (!existsSync(new URL(buildMainFilePath, buildDirectoryUrl))) {
|
|
26263
|
+
buildMainFilePath = null;
|
|
26257
26264
|
}
|
|
26258
26265
|
}
|
|
26259
26266
|
}
|
|
@@ -26269,73 +26276,6 @@ const startBuildServer = async ({
|
|
|
26269
26276
|
}, abort);
|
|
26270
26277
|
});
|
|
26271
26278
|
}
|
|
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
26279
|
const startBuildServerTask = createTaskLog("start build server", {
|
|
26340
26280
|
disabled: !logger.levels.info
|
|
26341
26281
|
});
|
|
@@ -26366,7 +26306,7 @@ const startBuildServer = async ({
|
|
|
26366
26306
|
name: "jsenv:build_files_service",
|
|
26367
26307
|
handleRequest: createBuildFilesService({
|
|
26368
26308
|
buildDirectoryUrl,
|
|
26369
|
-
|
|
26309
|
+
buildMainFilePath
|
|
26370
26310
|
})
|
|
26371
26311
|
}, jsenvServiceErrorHandler({
|
|
26372
26312
|
sendErrorDetails: true
|
|
@@ -26382,9 +26322,6 @@ const startBuildServer = async ({
|
|
|
26382
26322
|
logger.info(`- ${server.origins[key]}`);
|
|
26383
26323
|
});
|
|
26384
26324
|
logger.info(``);
|
|
26385
|
-
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
26386
|
-
parentPort.postMessage(server.origin);
|
|
26387
|
-
}
|
|
26388
26325
|
return {
|
|
26389
26326
|
origin: server.origin,
|
|
26390
26327
|
stop: () => {
|
|
@@ -26394,14 +26331,14 @@ const startBuildServer = async ({
|
|
|
26394
26331
|
};
|
|
26395
26332
|
const createBuildFilesService = ({
|
|
26396
26333
|
buildDirectoryUrl,
|
|
26397
|
-
|
|
26334
|
+
buildMainFilePath
|
|
26398
26335
|
}) => {
|
|
26399
26336
|
return request => {
|
|
26400
26337
|
const urlIsVersioned = new URL(request.url).searchParams.has("v");
|
|
26401
|
-
if (
|
|
26338
|
+
if (buildMainFilePath && request.resource === "/") {
|
|
26402
26339
|
request = {
|
|
26403
26340
|
...request,
|
|
26404
|
-
resource: `/${
|
|
26341
|
+
resource: `/${buildMainFilePath}`
|
|
26405
26342
|
};
|
|
26406
26343
|
}
|
|
26407
26344
|
return fetchFileSystem(new URL(request.resource.slice(1), buildDirectoryUrl), {
|
|
@@ -26448,7 +26385,7 @@ const execute = async ({
|
|
|
26448
26385
|
const logger = createLogger({
|
|
26449
26386
|
logLevel
|
|
26450
26387
|
});
|
|
26451
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl);
|
|
26388
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl, "rootDirectoryUrl");
|
|
26452
26389
|
const executeOperation = Abort.startOperation();
|
|
26453
26390
|
executeOperation.addAbortSignal(signal);
|
|
26454
26391
|
if (handleSIGINT) {
|