@jsenv/core 31.1.4 → 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 +493 -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_analysis/webmanifest/webmanifest_urls.js +10 -0
- 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,
|
|
@@ -10175,6 +10274,17 @@ const parseAndTransformWebmanifestUrls = async (urlInfo, context) => {
|
|
|
10175
10274
|
const content = urlInfo.content;
|
|
10176
10275
|
const manifest = JSON.parse(content);
|
|
10177
10276
|
const actions = [];
|
|
10277
|
+
const {
|
|
10278
|
+
start_url
|
|
10279
|
+
} = manifest;
|
|
10280
|
+
if (start_url) {
|
|
10281
|
+
if (context.build) {
|
|
10282
|
+
manifest.start_url = "/";
|
|
10283
|
+
} else {
|
|
10284
|
+
const parentUrl = context.reference.parentUrl;
|
|
10285
|
+
manifest.start_url = `${parentUrl.slice(context.rootDirectoryUrl.length)}`;
|
|
10286
|
+
}
|
|
10287
|
+
}
|
|
10178
10288
|
const {
|
|
10179
10289
|
icons = []
|
|
10180
10290
|
} = manifest;
|
|
@@ -17052,7 +17162,7 @@ const addRelationshipWithPackageJson = ({
|
|
|
17052
17162
|
*/
|
|
17053
17163
|
const jsenvPluginUrlResolution = ({
|
|
17054
17164
|
runtimeCompat,
|
|
17055
|
-
|
|
17165
|
+
mainFileUrl,
|
|
17056
17166
|
urlResolution
|
|
17057
17167
|
}) => {
|
|
17058
17168
|
const resolveUrlUsingWebResolution = reference => {
|
|
@@ -17113,7 +17223,7 @@ const jsenvPluginUrlResolution = ({
|
|
|
17113
17223
|
appliesDuring: "*",
|
|
17114
17224
|
resolveUrl: (reference, context) => {
|
|
17115
17225
|
if (reference.specifier === "/") {
|
|
17116
|
-
return String(
|
|
17226
|
+
return String(mainFileUrl);
|
|
17117
17227
|
}
|
|
17118
17228
|
if (reference.specifier[0] === "/") {
|
|
17119
17229
|
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl).href;
|
|
@@ -20181,13 +20291,14 @@ const explorerHtmlFileUrl = new URL("./html/explorer.html", import.meta.url);
|
|
|
20181
20291
|
const jsenvPluginExplorer = ({
|
|
20182
20292
|
groups = {
|
|
20183
20293
|
src: {
|
|
20184
|
-
"
|
|
20294
|
+
"./**/*.html": true,
|
|
20295
|
+
"./**/*.test.html": false
|
|
20185
20296
|
},
|
|
20186
20297
|
tests: {
|
|
20187
|
-
"
|
|
20298
|
+
"./**/*.test.html": true
|
|
20188
20299
|
}
|
|
20189
20300
|
},
|
|
20190
|
-
|
|
20301
|
+
mainFileUrl
|
|
20191
20302
|
}) => {
|
|
20192
20303
|
const faviconClientFileUrl = new URL("./other/jsenv.png", import.meta.url);
|
|
20193
20304
|
return {
|
|
@@ -20195,7 +20306,7 @@ const jsenvPluginExplorer = ({
|
|
|
20195
20306
|
appliesDuring: "dev",
|
|
20196
20307
|
transformUrlContent: {
|
|
20197
20308
|
html: async (urlInfo, context) => {
|
|
20198
|
-
if (urlInfo.url !==
|
|
20309
|
+
if (urlInfo.url !== mainFileUrl) {
|
|
20199
20310
|
return null;
|
|
20200
20311
|
}
|
|
20201
20312
|
let html = urlInfo.content;
|
|
@@ -20297,6 +20408,7 @@ injectRibbon(${paramsJson})`
|
|
|
20297
20408
|
|
|
20298
20409
|
const getCorePlugins = ({
|
|
20299
20410
|
rootDirectoryUrl,
|
|
20411
|
+
mainFileUrl,
|
|
20300
20412
|
runtimeCompat,
|
|
20301
20413
|
urlAnalysis = {},
|
|
20302
20414
|
urlResolution = {},
|
|
@@ -20304,7 +20416,6 @@ const getCorePlugins = ({
|
|
|
20304
20416
|
directoryReferenceAllowed,
|
|
20305
20417
|
supervisor,
|
|
20306
20418
|
transpilation = true,
|
|
20307
|
-
clientMainFileUrl,
|
|
20308
20419
|
clientAutoreload = false,
|
|
20309
20420
|
clientFileChangeCallbackList,
|
|
20310
20421
|
clientFilesPruneCallbackList,
|
|
@@ -20328,11 +20439,6 @@ const getCorePlugins = ({
|
|
|
20328
20439
|
if (clientAutoreload === true) {
|
|
20329
20440
|
clientAutoreload = {};
|
|
20330
20441
|
}
|
|
20331
|
-
if (clientMainFileUrl === undefined) {
|
|
20332
|
-
clientMainFileUrl = explorer ? String(explorerHtmlFileUrl) : String(new URL("./index.html", rootDirectoryUrl));
|
|
20333
|
-
} else {
|
|
20334
|
-
clientMainFileUrl = String(clientMainFileUrl);
|
|
20335
|
-
}
|
|
20336
20442
|
if (ribbon === true) {
|
|
20337
20443
|
ribbon = {};
|
|
20338
20444
|
}
|
|
@@ -20351,7 +20457,7 @@ const getCorePlugins = ({
|
|
|
20351
20457
|
...fileSystemMagicRedirection
|
|
20352
20458
|
}), jsenvPluginHttpUrls(), jsenvPluginUrlResolution({
|
|
20353
20459
|
runtimeCompat,
|
|
20354
|
-
|
|
20460
|
+
mainFileUrl,
|
|
20355
20461
|
urlResolution
|
|
20356
20462
|
}), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []), jsenvPluginNodeRuntime({
|
|
20357
20463
|
runtimeCompat
|
|
@@ -20361,7 +20467,7 @@ const getCorePlugins = ({
|
|
|
20361
20467
|
clientFilesPruneCallbackList
|
|
20362
20468
|
})] : []), ...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []), ...(explorer ? [jsenvPluginExplorer({
|
|
20363
20469
|
...explorer,
|
|
20364
|
-
|
|
20470
|
+
mainFileUrl
|
|
20365
20471
|
})] : []), ...(ribbon ? [jsenvPluginRibbon({
|
|
20366
20472
|
rootDirectoryUrl,
|
|
20367
20473
|
...ribbon
|
|
@@ -20720,12 +20826,13 @@ const defaultRuntimeCompat = {
|
|
|
20720
20826
|
/**
|
|
20721
20827
|
* Generate an optimized version of source files into a directory
|
|
20722
20828
|
* @param {Object} buildParameters
|
|
20723
|
-
* @param {string|url} buildParameters.
|
|
20829
|
+
* @param {string|url} buildParameters.sourceDirectoryUrl
|
|
20724
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
|
|
20725
20834
|
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
20726
20835
|
* Directory where optimized files will be written
|
|
20727
|
-
* @param {object} buildParameters.entryPoints
|
|
20728
|
-
* Describe entry point paths and control their names in the build directory
|
|
20729
20836
|
* @param {object} buildParameters.runtimeCompat
|
|
20730
20837
|
* Code generated will be compatible with these runtimes
|
|
20731
20838
|
* @param {string} [buildParameters.assetsDirectory=""]
|
|
@@ -20750,10 +20857,10 @@ const build = async ({
|
|
|
20750
20857
|
signal = new AbortController().signal,
|
|
20751
20858
|
handleSIGINT = true,
|
|
20752
20859
|
logLevel = "info",
|
|
20753
|
-
|
|
20860
|
+
sourceDirectoryUrl,
|
|
20861
|
+
entryPoints = {},
|
|
20754
20862
|
buildDirectoryUrl,
|
|
20755
20863
|
assetsDirectory = "",
|
|
20756
|
-
entryPoints = {},
|
|
20757
20864
|
runtimeCompat = defaultRuntimeCompat,
|
|
20758
20865
|
base = runtimeCompat.node ? "./" : "/",
|
|
20759
20866
|
plugins = [],
|
|
@@ -20770,9 +20877,7 @@ const build = async ({
|
|
|
20770
20877
|
// "filename", "search_param"
|
|
20771
20878
|
versioningViaImportmap = true,
|
|
20772
20879
|
lineBreakNormalization = process.platform === "win32",
|
|
20773
|
-
|
|
20774
|
-
"./src/": true
|
|
20775
|
-
},
|
|
20880
|
+
sourceFilesConfig = {},
|
|
20776
20881
|
cooldownBetweenFileEvents,
|
|
20777
20882
|
watch = false,
|
|
20778
20883
|
directoryToClean,
|
|
@@ -20788,16 +20893,27 @@ const build = async ({
|
|
|
20788
20893
|
if (unexpectedParamNames.length > 0) {
|
|
20789
20894
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
20790
20895
|
}
|
|
20791
|
-
|
|
20792
|
-
if (
|
|
20793
|
-
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}`);
|
|
20794
20899
|
}
|
|
20795
|
-
|
|
20796
|
-
|
|
20797
|
-
|
|
20798
|
-
|
|
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}`);
|
|
20799
20916
|
}
|
|
20800
|
-
buildDirectoryUrl = buildDirectoryUrlValidation.value;
|
|
20801
20917
|
}
|
|
20802
20918
|
const operation = Abort.startOperation();
|
|
20803
20919
|
operation.addAbortSignal(signal);
|
|
@@ -20808,12 +20924,6 @@ const build = async ({
|
|
|
20808
20924
|
}, abort);
|
|
20809
20925
|
});
|
|
20810
20926
|
}
|
|
20811
|
-
assertEntryPoints({
|
|
20812
|
-
entryPoints
|
|
20813
|
-
});
|
|
20814
|
-
if (!["filename", "search_param"].includes(versioningMethod)) {
|
|
20815
|
-
throw new Error(`Unexpected "versioningMethod": must be "filename", "search_param"; got ${versioning}`);
|
|
20816
|
-
}
|
|
20817
20927
|
if (assetsDirectory && assetsDirectory[assetsDirectory.length - 1] !== "/") {
|
|
20818
20928
|
assetsDirectory = `${assetsDirectory}/`;
|
|
20819
20929
|
}
|
|
@@ -20824,9 +20934,10 @@ const build = async ({
|
|
|
20824
20934
|
directoryToClean = new URL(assetsDirectory, buildDirectoryUrl).href;
|
|
20825
20935
|
}
|
|
20826
20936
|
}
|
|
20937
|
+
const jsenvInternalDirectoryUrl = determineJsenvInternalDirectoryUrl(sourceDirectoryUrl);
|
|
20827
20938
|
const asFormattedBuildUrl = (generatedUrl, reference) => {
|
|
20828
20939
|
if (base === "./") {
|
|
20829
|
-
const urlRelativeToParent = urlToRelativeUrl(generatedUrl, reference.parentUrl ===
|
|
20940
|
+
const urlRelativeToParent = urlToRelativeUrl(generatedUrl, reference.parentUrl === sourceDirectoryUrl ? buildDirectoryUrl : reference.parentUrl);
|
|
20830
20941
|
if (urlRelativeToParent[0] !== ".") {
|
|
20831
20942
|
// ensure "./" on relative url (otherwise it could be a "bare specifier")
|
|
20832
20943
|
return `./${urlRelativeToParent}`;
|
|
@@ -20876,7 +20987,8 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20876
20987
|
const rawGraphKitchen = createKitchen({
|
|
20877
20988
|
signal,
|
|
20878
20989
|
logLevel,
|
|
20879
|
-
rootDirectoryUrl,
|
|
20990
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20991
|
+
jsenvInternalDirectoryUrl,
|
|
20880
20992
|
urlGraph: rawGraph,
|
|
20881
20993
|
build: true,
|
|
20882
20994
|
runtimeCompat,
|
|
@@ -20895,7 +21007,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20895
21007
|
return null;
|
|
20896
21008
|
}
|
|
20897
21009
|
}, ...getCorePlugins({
|
|
20898
|
-
rootDirectoryUrl,
|
|
21010
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20899
21011
|
urlGraph: rawGraph,
|
|
20900
21012
|
runtimeCompat,
|
|
20901
21013
|
urlAnalysis,
|
|
@@ -20912,7 +21024,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
20912
21024
|
sourcemaps,
|
|
20913
21025
|
sourcemapsSourcesContent,
|
|
20914
21026
|
writeGeneratedFiles,
|
|
20915
|
-
outDirectoryUrl: new URL(
|
|
21027
|
+
outDirectoryUrl: new URL("build/", jsenvInternalDirectoryUrl)
|
|
20916
21028
|
});
|
|
20917
21029
|
const buildUrlsGenerator = createBuildUrlsGenerator({
|
|
20918
21030
|
buildDirectoryUrl,
|
|
@@ -20934,12 +21046,13 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
20934
21046
|
const bundlers = {};
|
|
20935
21047
|
const finalGraph = createUrlGraph();
|
|
20936
21048
|
const urlAnalysisPlugin = jsenvPluginUrlAnalysis({
|
|
20937
|
-
rootDirectoryUrl,
|
|
21049
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
20938
21050
|
...urlAnalysis
|
|
20939
21051
|
});
|
|
20940
21052
|
const finalGraphKitchen = createKitchen({
|
|
20941
21053
|
logLevel,
|
|
20942
21054
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
21055
|
+
jsenvInternalDirectoryUrl,
|
|
20943
21056
|
urlGraph: finalGraph,
|
|
20944
21057
|
build: true,
|
|
20945
21058
|
runtimeCompat,
|
|
@@ -21186,7 +21299,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21186
21299
|
sourcemapsSourcesContent,
|
|
21187
21300
|
sourcemapsSourcesRelative: !versioning,
|
|
21188
21301
|
writeGeneratedFiles,
|
|
21189
|
-
outDirectoryUrl: new URL("
|
|
21302
|
+
outDirectoryUrl: new URL("postbuild/", jsenvInternalDirectoryUrl)
|
|
21190
21303
|
});
|
|
21191
21304
|
const finalEntryUrls = [];
|
|
21192
21305
|
{
|
|
@@ -21195,7 +21308,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21195
21308
|
});
|
|
21196
21309
|
try {
|
|
21197
21310
|
if (writeGeneratedFiles) {
|
|
21198
|
-
await ensureEmptyDirectory(new URL(
|
|
21311
|
+
await ensureEmptyDirectory(new URL(`build/`, sourceDirectoryUrl));
|
|
21199
21312
|
}
|
|
21200
21313
|
const rawUrlGraphLoader = createUrlGraphLoader(rawGraphKitchen.kitchenContext);
|
|
21201
21314
|
Object.keys(entryPoints).forEach(key => {
|
|
@@ -21203,7 +21316,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21203
21316
|
trace: {
|
|
21204
21317
|
message: `"${key}" in entryPoints parameter`
|
|
21205
21318
|
},
|
|
21206
|
-
parentUrl:
|
|
21319
|
+
parentUrl: sourceDirectoryUrl,
|
|
21207
21320
|
type: "entry_point",
|
|
21208
21321
|
specifier: key
|
|
21209
21322
|
});
|
|
@@ -21409,7 +21522,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21409
21522
|
});
|
|
21410
21523
|
try {
|
|
21411
21524
|
if (writeGeneratedFiles) {
|
|
21412
|
-
await ensureEmptyDirectory(new URL(
|
|
21525
|
+
await ensureEmptyDirectory(new URL(`postbuild/`, jsenvInternalDirectoryUrl));
|
|
21413
21526
|
}
|
|
21414
21527
|
const finalUrlGraphLoader = createUrlGraphLoader(finalGraphKitchen.kitchenContext);
|
|
21415
21528
|
entryUrls.forEach(entryUrl => {
|
|
@@ -21417,7 +21530,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21417
21530
|
trace: {
|
|
21418
21531
|
message: `entryPoint`
|
|
21419
21532
|
},
|
|
21420
|
-
parentUrl:
|
|
21533
|
+
parentUrl: sourceDirectoryUrl,
|
|
21421
21534
|
type: "entry_point",
|
|
21422
21535
|
specifier: entryUrl
|
|
21423
21536
|
});
|
|
@@ -21609,6 +21722,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21609
21722
|
const versioningKitchen = createKitchen({
|
|
21610
21723
|
logLevel: logger.level,
|
|
21611
21724
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
21725
|
+
jsenvInternalDirectoryUrl,
|
|
21612
21726
|
urlGraph: finalGraph,
|
|
21613
21727
|
build: true,
|
|
21614
21728
|
runtimeCompat,
|
|
@@ -21701,7 +21815,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21701
21815
|
sourcemapsSourcesContent,
|
|
21702
21816
|
sourcemapsSourcesRelative: true,
|
|
21703
21817
|
writeGeneratedFiles,
|
|
21704
|
-
outDirectoryUrl: new URL("
|
|
21818
|
+
outDirectoryUrl: new URL("postbuild/", jsenvInternalDirectoryUrl)
|
|
21705
21819
|
});
|
|
21706
21820
|
const versioningUrlGraphLoader = createUrlGraphLoader(versioningKitchen.kitchenContext);
|
|
21707
21821
|
finalEntryUrls.forEach(finalEntryUrl => {
|
|
@@ -22077,13 +22191,12 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22077
22191
|
};
|
|
22078
22192
|
startBuild();
|
|
22079
22193
|
let startTimeout;
|
|
22080
|
-
const
|
|
22081
|
-
|
|
22194
|
+
const stopWatchingSourceFiles = watchSourceFiles(sourceDirectoryUrl, ({
|
|
22195
|
+
url,
|
|
22082
22196
|
event
|
|
22083
22197
|
}) => {
|
|
22084
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
22085
22198
|
if (watchFilesTask) {
|
|
22086
|
-
watchFilesTask.happen(`${url.slice(
|
|
22199
|
+
watchFilesTask.happen(`${url.slice(sourceDirectoryUrl.length)} ${event}`);
|
|
22087
22200
|
watchFilesTask = null;
|
|
22088
22201
|
}
|
|
22089
22202
|
buildAbortController.abort();
|
|
@@ -22092,42 +22205,16 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22092
22205
|
// then logs about re-running the build happens
|
|
22093
22206
|
clearTimeout(startTimeout);
|
|
22094
22207
|
startTimeout = setTimeout(startBuild, 20);
|
|
22095
|
-
}
|
|
22096
|
-
|
|
22097
|
-
watchPatterns: clientFiles,
|
|
22098
|
-
cooldownBetweenFileEvents,
|
|
22208
|
+
}, {
|
|
22209
|
+
sourceFilesConfig,
|
|
22099
22210
|
keepProcessAlive: true,
|
|
22100
|
-
|
|
22101
|
-
added: ({
|
|
22102
|
-
relativeUrl
|
|
22103
|
-
}) => {
|
|
22104
|
-
clientFileChangeCallback({
|
|
22105
|
-
relativeUrl,
|
|
22106
|
-
event: "added"
|
|
22107
|
-
});
|
|
22108
|
-
},
|
|
22109
|
-
updated: ({
|
|
22110
|
-
relativeUrl
|
|
22111
|
-
}) => {
|
|
22112
|
-
clientFileChangeCallback({
|
|
22113
|
-
relativeUrl,
|
|
22114
|
-
event: "modified"
|
|
22115
|
-
});
|
|
22116
|
-
},
|
|
22117
|
-
removed: ({
|
|
22118
|
-
relativeUrl
|
|
22119
|
-
}) => {
|
|
22120
|
-
clientFileChangeCallback({
|
|
22121
|
-
relativeUrl,
|
|
22122
|
-
event: "removed"
|
|
22123
|
-
});
|
|
22124
|
-
}
|
|
22211
|
+
cooldownBetweenFileEvents
|
|
22125
22212
|
});
|
|
22126
22213
|
operation.addAbortCallback(() => {
|
|
22127
|
-
|
|
22214
|
+
stopWatchingSourceFiles();
|
|
22128
22215
|
});
|
|
22129
22216
|
await firstBuildPromise;
|
|
22130
|
-
return
|
|
22217
|
+
return stopWatchingSourceFiles;
|
|
22131
22218
|
};
|
|
22132
22219
|
const findKey = (map, value) => {
|
|
22133
22220
|
for (const [keyCandidate, valueCandidate] of map) {
|
|
@@ -22153,26 +22240,6 @@ const injectVersionIntoBuildUrl = ({
|
|
|
22153
22240
|
const versionedUrl = setUrlFilename(buildUrl, versionedFilename);
|
|
22154
22241
|
return versionedUrl;
|
|
22155
22242
|
};
|
|
22156
|
-
const assertEntryPoints = ({
|
|
22157
|
-
entryPoints
|
|
22158
|
-
}) => {
|
|
22159
|
-
if (typeof entryPoints !== "object" || entryPoints === null) {
|
|
22160
|
-
throw new TypeError(`entryPoints must be an object, got ${entryPoints}`);
|
|
22161
|
-
}
|
|
22162
|
-
const keys = Object.keys(entryPoints);
|
|
22163
|
-
keys.forEach(key => {
|
|
22164
|
-
if (!key.startsWith("./")) {
|
|
22165
|
-
throw new TypeError(`unexpected key in entryPoints, all keys must start with ./ but found ${key}`);
|
|
22166
|
-
}
|
|
22167
|
-
const value = entryPoints[key];
|
|
22168
|
-
if (typeof value !== "string") {
|
|
22169
|
-
throw new TypeError(`unexpected value in entryPoints, all values must be strings found ${value} for key ${key}`);
|
|
22170
|
-
}
|
|
22171
|
-
if (value.includes("/")) {
|
|
22172
|
-
throw new TypeError(`unexpected value in entryPoints, all values must be plain strings (no "/") but found ${value} for key ${key}`);
|
|
22173
|
-
}
|
|
22174
|
-
});
|
|
22175
|
-
};
|
|
22176
22243
|
const isUsed = urlInfo => {
|
|
22177
22244
|
// nothing uses this url anymore
|
|
22178
22245
|
// - versioning update inline content
|
|
@@ -22195,57 +22262,6 @@ const canUseVersionedUrl = urlInfo => {
|
|
|
22195
22262
|
return urlInfo.type !== "webmanifest";
|
|
22196
22263
|
};
|
|
22197
22264
|
|
|
22198
|
-
// https://nodejs.org/api/worker_threads.html
|
|
22199
|
-
const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
22200
|
-
const workerFilePath = fileURLToPath(workerFileUrl);
|
|
22201
|
-
const isPrimary = !workerData || workerData.workerFilePath !== workerFilePath;
|
|
22202
|
-
let worker;
|
|
22203
|
-
const terminate = async () => {
|
|
22204
|
-
if (worker) {
|
|
22205
|
-
let _worker = worker;
|
|
22206
|
-
worker = null;
|
|
22207
|
-
const exitPromise = new Promise(resolve => {
|
|
22208
|
-
_worker.once("exit", resolve);
|
|
22209
|
-
});
|
|
22210
|
-
_worker.terminate();
|
|
22211
|
-
await exitPromise;
|
|
22212
|
-
}
|
|
22213
|
-
};
|
|
22214
|
-
const load = async () => {
|
|
22215
|
-
if (!isPrimary) {
|
|
22216
|
-
throw new Error(`worker can be loaded from primary file only`);
|
|
22217
|
-
}
|
|
22218
|
-
worker = new Worker(workerFilePath, {
|
|
22219
|
-
...options,
|
|
22220
|
-
workerData: {
|
|
22221
|
-
...options.workerData,
|
|
22222
|
-
workerFilePath
|
|
22223
|
-
}
|
|
22224
|
-
});
|
|
22225
|
-
worker.once("error", error => {
|
|
22226
|
-
console.error(error);
|
|
22227
|
-
});
|
|
22228
|
-
worker.once("exit", () => {
|
|
22229
|
-
worker = null;
|
|
22230
|
-
});
|
|
22231
|
-
await new Promise(resolve => {
|
|
22232
|
-
worker.once("online", resolve);
|
|
22233
|
-
});
|
|
22234
|
-
return worker;
|
|
22235
|
-
};
|
|
22236
|
-
const reload = async () => {
|
|
22237
|
-
await terminate();
|
|
22238
|
-
await load();
|
|
22239
|
-
};
|
|
22240
|
-
return {
|
|
22241
|
-
isPrimary,
|
|
22242
|
-
isWorker: !isPrimary,
|
|
22243
|
-
load,
|
|
22244
|
-
reload,
|
|
22245
|
-
terminate
|
|
22246
|
-
};
|
|
22247
|
-
};
|
|
22248
|
-
|
|
22249
22265
|
/*
|
|
22250
22266
|
* This plugin is very special because it is here
|
|
22251
22267
|
* to provide "serverEvents" used by other plugins
|
|
@@ -22309,7 +22325,9 @@ const createFileService = ({
|
|
|
22309
22325
|
serverStopCallbacks,
|
|
22310
22326
|
serverEventsDispatcher,
|
|
22311
22327
|
contextCache,
|
|
22312
|
-
|
|
22328
|
+
sourceDirectoryUrl,
|
|
22329
|
+
sourceMainFilePath,
|
|
22330
|
+
sourceFilesConfig,
|
|
22313
22331
|
runtimeCompat,
|
|
22314
22332
|
plugins,
|
|
22315
22333
|
urlAnalysis,
|
|
@@ -22318,8 +22336,6 @@ const createFileService = ({
|
|
|
22318
22336
|
supervisor,
|
|
22319
22337
|
transpilation,
|
|
22320
22338
|
clientAutoreload,
|
|
22321
|
-
clientFiles,
|
|
22322
|
-
clientMainFileUrl,
|
|
22323
22339
|
cooldownBetweenFileEvents,
|
|
22324
22340
|
explorer,
|
|
22325
22341
|
cacheControl,
|
|
@@ -22329,49 +22345,18 @@ const createFileService = ({
|
|
|
22329
22345
|
sourcemapsSourcesContent,
|
|
22330
22346
|
writeGeneratedFiles
|
|
22331
22347
|
}) => {
|
|
22332
|
-
const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href;
|
|
22333
22348
|
const clientFileChangeCallbackList = [];
|
|
22334
22349
|
const clientFilesPruneCallbackList = [];
|
|
22335
|
-
const
|
|
22336
|
-
...clientFiles,
|
|
22337
|
-
".jsenv/": false
|
|
22338
|
-
};
|
|
22339
|
-
const onFileChange = url => {
|
|
22350
|
+
const stopWatchingSourceFiles = watchSourceFiles(sourceDirectoryUrl, fileInfo => {
|
|
22340
22351
|
clientFileChangeCallbackList.forEach(callback => {
|
|
22341
|
-
callback(
|
|
22352
|
+
callback(fileInfo);
|
|
22342
22353
|
});
|
|
22343
|
-
}
|
|
22344
|
-
|
|
22345
|
-
watchPatterns: clientFilePatterns,
|
|
22346
|
-
cooldownBetweenFileEvents,
|
|
22354
|
+
}, {
|
|
22355
|
+
sourceFilesConfig,
|
|
22347
22356
|
keepProcessAlive: false,
|
|
22348
|
-
|
|
22349
|
-
added: ({
|
|
22350
|
-
relativeUrl
|
|
22351
|
-
}) => {
|
|
22352
|
-
onFileChange({
|
|
22353
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
22354
|
-
event: "added"
|
|
22355
|
-
});
|
|
22356
|
-
},
|
|
22357
|
-
updated: ({
|
|
22358
|
-
relativeUrl
|
|
22359
|
-
}) => {
|
|
22360
|
-
onFileChange({
|
|
22361
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
22362
|
-
event: "modified"
|
|
22363
|
-
});
|
|
22364
|
-
},
|
|
22365
|
-
removed: ({
|
|
22366
|
-
relativeUrl
|
|
22367
|
-
}) => {
|
|
22368
|
-
onFileChange({
|
|
22369
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
22370
|
-
event: "removed"
|
|
22371
|
-
});
|
|
22372
|
-
}
|
|
22357
|
+
cooldownBetweenFileEvents
|
|
22373
22358
|
});
|
|
22374
|
-
serverStopCallbacks.push(
|
|
22359
|
+
serverStopCallbacks.push(stopWatchingSourceFiles);
|
|
22375
22360
|
const getOrCreateContext = request => {
|
|
22376
22361
|
const {
|
|
22377
22362
|
runtimeName,
|
|
@@ -22383,8 +22368,8 @@ const createFileService = ({
|
|
|
22383
22368
|
return existingContext;
|
|
22384
22369
|
}
|
|
22385
22370
|
const watchAssociations = URL_META.resolveAssociations({
|
|
22386
|
-
watch:
|
|
22387
|
-
},
|
|
22371
|
+
watch: stopWatchingSourceFiles.watchPatterns
|
|
22372
|
+
}, sourceDirectoryUrl);
|
|
22388
22373
|
const urlGraph = createUrlGraph();
|
|
22389
22374
|
clientFileChangeCallbackList.push(({
|
|
22390
22375
|
url
|
|
@@ -22407,24 +22392,32 @@ const createFileService = ({
|
|
|
22407
22392
|
const clientRuntimeCompat = {
|
|
22408
22393
|
[runtimeName]: runtimeVersion
|
|
22409
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
|
+
}
|
|
22410
22402
|
const kitchen = createKitchen({
|
|
22411
22403
|
signal,
|
|
22412
22404
|
logLevel,
|
|
22413
|
-
rootDirectoryUrl,
|
|
22405
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22406
|
+
jsenvInternalDirectoryUrl,
|
|
22414
22407
|
urlGraph,
|
|
22415
22408
|
dev: true,
|
|
22416
22409
|
runtimeCompat,
|
|
22417
22410
|
clientRuntimeCompat,
|
|
22418
22411
|
systemJsTranspilation: !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "script_type_module") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_dynamic") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_meta"),
|
|
22419
22412
|
plugins: [...plugins, ...getCorePlugins({
|
|
22420
|
-
rootDirectoryUrl,
|
|
22413
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22414
|
+
mainFileUrl,
|
|
22421
22415
|
runtimeCompat,
|
|
22422
22416
|
urlAnalysis,
|
|
22423
22417
|
urlResolution,
|
|
22424
22418
|
fileSystemMagicRedirection,
|
|
22425
22419
|
supervisor,
|
|
22426
22420
|
transpilation,
|
|
22427
|
-
clientMainFileUrl,
|
|
22428
22421
|
clientAutoreload,
|
|
22429
22422
|
clientFileChangeCallbackList,
|
|
22430
22423
|
clientFilesPruneCallbackList,
|
|
@@ -22438,7 +22431,7 @@ const createFileService = ({
|
|
|
22438
22431
|
sourcemapsSourcesProtocol,
|
|
22439
22432
|
sourcemapsSourcesContent,
|
|
22440
22433
|
writeGeneratedFiles,
|
|
22441
|
-
outDirectoryUrl: `${
|
|
22434
|
+
outDirectoryUrl: new URL(`${runtimeName}@${runtimeVersion}/`, jsenvInternalDirectoryUrl)
|
|
22442
22435
|
});
|
|
22443
22436
|
urlGraph.createUrlInfoCallbackRef.current = urlInfo => {
|
|
22444
22437
|
const {
|
|
@@ -22517,7 +22510,7 @@ const createFileService = ({
|
|
|
22517
22510
|
if (serverEventNames.length > 0) {
|
|
22518
22511
|
Object.keys(allServerEvents).forEach(serverEventName => {
|
|
22519
22512
|
allServerEvents[serverEventName]({
|
|
22520
|
-
rootDirectoryUrl,
|
|
22513
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22521
22514
|
urlGraph,
|
|
22522
22515
|
dev: true,
|
|
22523
22516
|
sendServerEvent: data => {
|
|
@@ -22533,7 +22526,7 @@ const createFileService = ({
|
|
|
22533
22526
|
}
|
|
22534
22527
|
}
|
|
22535
22528
|
const context = {
|
|
22536
|
-
rootDirectoryUrl,
|
|
22529
|
+
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22537
22530
|
dev: true,
|
|
22538
22531
|
runtimeName,
|
|
22539
22532
|
runtimeVersion,
|
|
@@ -22544,13 +22537,6 @@ const createFileService = ({
|
|
|
22544
22537
|
return context;
|
|
22545
22538
|
};
|
|
22546
22539
|
return async request => {
|
|
22547
|
-
// serve file inside ".jsenv" directory
|
|
22548
|
-
const requestFileUrl = new URL(request.resource.slice(1), rootDirectoryUrl).href;
|
|
22549
|
-
if (urlIsInsideOf(requestFileUrl, jsenvDirectoryUrl)) {
|
|
22550
|
-
return fetchFileSystem(requestFileUrl, {
|
|
22551
|
-
headers: request.headers
|
|
22552
|
-
});
|
|
22553
|
-
}
|
|
22554
22540
|
const {
|
|
22555
22541
|
urlGraph,
|
|
22556
22542
|
kitchen
|
|
@@ -22560,16 +22546,16 @@ const createFileService = ({
|
|
|
22560
22546
|
return responseFromPlugin;
|
|
22561
22547
|
}
|
|
22562
22548
|
let reference;
|
|
22563
|
-
const parentUrl = inferParentFromRequest(request,
|
|
22549
|
+
const parentUrl = inferParentFromRequest(request, sourceDirectoryUrl);
|
|
22564
22550
|
if (parentUrl) {
|
|
22565
22551
|
reference = urlGraph.inferReference(request.resource, parentUrl);
|
|
22566
22552
|
}
|
|
22567
22553
|
if (!reference) {
|
|
22568
22554
|
const entryPoint = kitchen.injectReference({
|
|
22569
22555
|
trace: {
|
|
22570
|
-
message: parentUrl ||
|
|
22556
|
+
message: parentUrl || sourceDirectoryUrl
|
|
22571
22557
|
},
|
|
22572
|
-
parentUrl: parentUrl ||
|
|
22558
|
+
parentUrl: parentUrl || sourceDirectoryUrl,
|
|
22573
22559
|
type: "http_request",
|
|
22574
22560
|
specifier: request.resource
|
|
22575
22561
|
});
|
|
@@ -22691,7 +22677,7 @@ const createFileService = ({
|
|
|
22691
22677
|
accept: "text/html"
|
|
22692
22678
|
},
|
|
22693
22679
|
canReadDirectory: true,
|
|
22694
|
-
rootDirectoryUrl
|
|
22680
|
+
rootDirectoryUrl: sourceDirectoryUrl
|
|
22695
22681
|
});
|
|
22696
22682
|
}
|
|
22697
22683
|
if (code === "NOT_ALLOWED") {
|
|
@@ -22718,7 +22704,7 @@ const createFileService = ({
|
|
|
22718
22704
|
}
|
|
22719
22705
|
};
|
|
22720
22706
|
};
|
|
22721
|
-
const inferParentFromRequest = (request,
|
|
22707
|
+
const inferParentFromRequest = (request, sourceDirectoryUrl) => {
|
|
22722
22708
|
const {
|
|
22723
22709
|
referer
|
|
22724
22710
|
} = request.headers;
|
|
@@ -22739,7 +22725,7 @@ const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
|
22739
22725
|
return moveUrl({
|
|
22740
22726
|
url: referer,
|
|
22741
22727
|
from: `${request.origin}/`,
|
|
22742
|
-
to:
|
|
22728
|
+
to: sourceDirectoryUrl,
|
|
22743
22729
|
preferAbsolute: true
|
|
22744
22730
|
});
|
|
22745
22731
|
};
|
|
@@ -22749,38 +22735,28 @@ const inferParentFromRequest = (request, rootDirectoryUrl) => {
|
|
|
22749
22735
|
* - cook source files according to jsenv plugins
|
|
22750
22736
|
* - inject code to autoreload the browser when a file is modified
|
|
22751
22737
|
* @param {Object} devServerParameters
|
|
22752
|
-
* @param {string|url} devServerParameters.
|
|
22738
|
+
* @param {string|url} devServerParameters.sourceDirectoryUrl Root directory of the project
|
|
22753
22739
|
* @return {Object} A dev server object
|
|
22754
22740
|
*/
|
|
22755
22741
|
const startDevServer = async ({
|
|
22756
|
-
|
|
22757
|
-
|
|
22758
|
-
|
|
22759
|
-
|
|
22742
|
+
sourceDirectoryUrl,
|
|
22743
|
+
sourceMainFilePath,
|
|
22744
|
+
port = 3456,
|
|
22745
|
+
hostname,
|
|
22746
|
+
acceptAnyIp,
|
|
22760
22747
|
https,
|
|
22761
22748
|
// it's better to use http1 by default because it allows to get statusText in devtools
|
|
22762
22749
|
// which gives valuable information when there is errors
|
|
22763
22750
|
http2 = false,
|
|
22764
|
-
|
|
22765
|
-
|
|
22766
|
-
acceptAnyIp,
|
|
22767
|
-
keepProcessAlive = true,
|
|
22751
|
+
logLevel = process.env.IMPORTED_BY_TEST_PLAN ? "warn" : "info",
|
|
22752
|
+
serverLogLevel = "warn",
|
|
22768
22753
|
services = [],
|
|
22754
|
+
signal = new AbortController().signal,
|
|
22755
|
+
handleSIGINT = true,
|
|
22756
|
+
keepProcessAlive = true,
|
|
22769
22757
|
onStop = () => {},
|
|
22770
|
-
|
|
22771
|
-
clientFiles = {
|
|
22772
|
-
"./src/": true,
|
|
22773
|
-
"./tests/": true,
|
|
22774
|
-
"./package.json": true
|
|
22775
|
-
},
|
|
22776
|
-
devServerFiles = {
|
|
22777
|
-
"./package.json": true,
|
|
22778
|
-
"./jsenv.config.mjs": true
|
|
22779
|
-
},
|
|
22758
|
+
sourceFilesConfig,
|
|
22780
22759
|
clientAutoreload = true,
|
|
22781
|
-
clientMainFileUrl,
|
|
22782
|
-
devServerAutoreload = false,
|
|
22783
|
-
devServerMainFile = getCallerPosition().url,
|
|
22784
22760
|
cooldownBetweenFileEvents,
|
|
22785
22761
|
// runtimeCompat is the runtimeCompat for the build
|
|
22786
22762
|
// when specified, dev server use it to warn in case
|
|
@@ -22812,11 +22788,7 @@ const startDevServer = async ({
|
|
|
22812
22788
|
if (unexpectedParamNames.length > 0) {
|
|
22813
22789
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
22814
22790
|
}
|
|
22815
|
-
|
|
22816
|
-
if (!rootDirectoryUrlValidation.valid) {
|
|
22817
|
-
throw new TypeError(`rootDirectoryUrl ${rootDirectoryUrlValidation.message}, got ${rootDirectoryUrl}`);
|
|
22818
|
-
}
|
|
22819
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
22791
|
+
sourceDirectoryUrl = assertAndNormalizeDirectoryUrl(sourceDirectoryUrl, "sourceDirectoryUrl");
|
|
22820
22792
|
}
|
|
22821
22793
|
const logger = createLogger({
|
|
22822
22794
|
logLevel
|
|
@@ -22830,70 +22802,6 @@ const startDevServer = async ({
|
|
|
22830
22802
|
}, abort);
|
|
22831
22803
|
});
|
|
22832
22804
|
}
|
|
22833
|
-
let reloadableWorker;
|
|
22834
|
-
if (devServerAutoreload) {
|
|
22835
|
-
reloadableWorker = createReloadableWorker(devServerMainFile);
|
|
22836
|
-
if (reloadableWorker.isPrimary) {
|
|
22837
|
-
const devServerFileChangeCallback = ({
|
|
22838
|
-
relativeUrl,
|
|
22839
|
-
event
|
|
22840
|
-
}) => {
|
|
22841
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
22842
|
-
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
22843
|
-
reloadableWorker.reload();
|
|
22844
|
-
};
|
|
22845
|
-
const stopWatchingDevServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
22846
|
-
watchPatterns: {
|
|
22847
|
-
...devServerFiles.include,
|
|
22848
|
-
[devServerMainFile]: true,
|
|
22849
|
-
".jsenv/": false
|
|
22850
|
-
},
|
|
22851
|
-
cooldownBetweenFileEvents,
|
|
22852
|
-
keepProcessAlive: false,
|
|
22853
|
-
recursive: true,
|
|
22854
|
-
added: ({
|
|
22855
|
-
relativeUrl
|
|
22856
|
-
}) => {
|
|
22857
|
-
devServerFileChangeCallback({
|
|
22858
|
-
relativeUrl,
|
|
22859
|
-
event: "added"
|
|
22860
|
-
});
|
|
22861
|
-
},
|
|
22862
|
-
updated: ({
|
|
22863
|
-
relativeUrl
|
|
22864
|
-
}) => {
|
|
22865
|
-
devServerFileChangeCallback({
|
|
22866
|
-
relativeUrl,
|
|
22867
|
-
event: "modified"
|
|
22868
|
-
});
|
|
22869
|
-
},
|
|
22870
|
-
removed: ({
|
|
22871
|
-
relativeUrl
|
|
22872
|
-
}) => {
|
|
22873
|
-
devServerFileChangeCallback({
|
|
22874
|
-
relativeUrl,
|
|
22875
|
-
event: "removed"
|
|
22876
|
-
});
|
|
22877
|
-
}
|
|
22878
|
-
});
|
|
22879
|
-
operation.addAbortCallback(() => {
|
|
22880
|
-
stopWatchingDevServerFiles();
|
|
22881
|
-
reloadableWorker.terminate();
|
|
22882
|
-
});
|
|
22883
|
-
const worker = await reloadableWorker.load();
|
|
22884
|
-
const messagePromise = new Promise(resolve => {
|
|
22885
|
-
worker.once("message", resolve);
|
|
22886
|
-
});
|
|
22887
|
-
const origin = await messagePromise;
|
|
22888
|
-
return {
|
|
22889
|
-
origin,
|
|
22890
|
-
stop: () => {
|
|
22891
|
-
stopWatchingDevServerFiles();
|
|
22892
|
-
reloadableWorker.terminate();
|
|
22893
|
-
}
|
|
22894
|
-
};
|
|
22895
|
-
}
|
|
22896
|
-
}
|
|
22897
22805
|
const startDevServerTask = createTaskLog("start dev server", {
|
|
22898
22806
|
disabled: !logger.levels.info
|
|
22899
22807
|
});
|
|
@@ -22924,7 +22832,30 @@ const startDevServer = async ({
|
|
|
22924
22832
|
accessControlAllowedRequestHeaders: [...jsenvAccessControlAllowedHeaders, "x-jsenv-execution-id"],
|
|
22925
22833
|
accessControlAllowCredentials: true,
|
|
22926
22834
|
timingAllowOrigin: true
|
|
22927
|
-
}),
|
|
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, {
|
|
22928
22859
|
name: "jsenv:omega_file_service",
|
|
22929
22860
|
handleRequest: createFileService({
|
|
22930
22861
|
signal,
|
|
@@ -22932,7 +22863,9 @@ const startDevServer = async ({
|
|
|
22932
22863
|
serverStopCallbacks,
|
|
22933
22864
|
serverEventsDispatcher,
|
|
22934
22865
|
contextCache,
|
|
22935
|
-
|
|
22866
|
+
sourceDirectoryUrl,
|
|
22867
|
+
sourceMainFilePath,
|
|
22868
|
+
sourceFilesConfig,
|
|
22936
22869
|
runtimeCompat,
|
|
22937
22870
|
plugins,
|
|
22938
22871
|
urlAnalysis,
|
|
@@ -22941,8 +22874,6 @@ const startDevServer = async ({
|
|
|
22941
22874
|
supervisor,
|
|
22942
22875
|
transpilation,
|
|
22943
22876
|
clientAutoreload,
|
|
22944
|
-
clientFiles,
|
|
22945
|
-
clientMainFileUrl,
|
|
22946
22877
|
cooldownBetweenFileEvents,
|
|
22947
22878
|
explorer,
|
|
22948
22879
|
cacheControl,
|
|
@@ -23015,9 +22946,6 @@ const startDevServer = async ({
|
|
|
23015
22946
|
logger.info(`- ${server.origins[key]}`);
|
|
23016
22947
|
});
|
|
23017
22948
|
logger.info(``);
|
|
23018
|
-
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
23019
|
-
parentPort.postMessage(server.origin);
|
|
23020
|
-
}
|
|
23021
22949
|
return {
|
|
23022
22950
|
origin: server.origin,
|
|
23023
22951
|
stop: () => {
|
|
@@ -23027,6 +22955,80 @@ const startDevServer = async ({
|
|
|
23027
22955
|
};
|
|
23028
22956
|
};
|
|
23029
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
|
+
|
|
23030
23032
|
const generateCoverageJsonFile = async ({
|
|
23031
23033
|
coverage,
|
|
23032
23034
|
coverageJsonFileUrl,
|
|
@@ -23116,7 +23118,7 @@ const readNodeV8CoverageDirectory = async ({
|
|
|
23116
23118
|
try {
|
|
23117
23119
|
operation.throwIfAborted();
|
|
23118
23120
|
const dirContent = await tryReadDirectory();
|
|
23119
|
-
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE);
|
|
23121
|
+
const coverageDirectoryUrl = assertAndNormalizeDirectoryUrl(NODE_V8_COVERAGE, "NODE_V8_COVERAGE");
|
|
23120
23122
|
await dirContent.reduce(async (previous, dirEntry) => {
|
|
23121
23123
|
operation.throwIfAborted();
|
|
23122
23124
|
await previous;
|
|
@@ -23739,37 +23741,6 @@ const run = async ({
|
|
|
23739
23741
|
return result;
|
|
23740
23742
|
};
|
|
23741
23743
|
|
|
23742
|
-
const pingServer = async url => {
|
|
23743
|
-
const server = createServer();
|
|
23744
|
-
const {
|
|
23745
|
-
hostname,
|
|
23746
|
-
port
|
|
23747
|
-
} = new URL(url);
|
|
23748
|
-
try {
|
|
23749
|
-
await new Promise((resolve, reject) => {
|
|
23750
|
-
server.on("error", reject);
|
|
23751
|
-
server.on("listening", () => {
|
|
23752
|
-
resolve();
|
|
23753
|
-
});
|
|
23754
|
-
server.listen(port, hostname);
|
|
23755
|
-
});
|
|
23756
|
-
} catch (error) {
|
|
23757
|
-
if (error && error.code === "EADDRINUSE") {
|
|
23758
|
-
return true;
|
|
23759
|
-
}
|
|
23760
|
-
if (error && error.code === "EACCES") {
|
|
23761
|
-
return true;
|
|
23762
|
-
}
|
|
23763
|
-
throw error;
|
|
23764
|
-
}
|
|
23765
|
-
await new Promise((resolve, reject) => {
|
|
23766
|
-
server.on("error", reject);
|
|
23767
|
-
server.on("close", resolve);
|
|
23768
|
-
server.close();
|
|
23769
|
-
});
|
|
23770
|
-
return false;
|
|
23771
|
-
};
|
|
23772
|
-
|
|
23773
23744
|
const ensureGlobalGc = () => {
|
|
23774
23745
|
if (!global.gc) {
|
|
23775
23746
|
v8.setFlagsFromString("--expose_gc");
|
|
@@ -24197,7 +24168,7 @@ const executePlan = async (plan, {
|
|
|
24197
24168
|
coverageMethodForBrowsers,
|
|
24198
24169
|
coverageMethodForNodeJs,
|
|
24199
24170
|
coverageV8ConflictWarning,
|
|
24200
|
-
|
|
24171
|
+
coverageTempDirectoryUrl,
|
|
24201
24172
|
beforeExecutionCallback = () => {},
|
|
24202
24173
|
afterExecutionCallback = () => {}
|
|
24203
24174
|
} = {}) => {
|
|
@@ -24207,30 +24178,6 @@ const executePlan = async (plan, {
|
|
|
24207
24178
|
const stopAfterAllSignal = {
|
|
24208
24179
|
notify: () => {}
|
|
24209
24180
|
};
|
|
24210
|
-
let someNeedsServer = false;
|
|
24211
|
-
let someNodeRuntime = false;
|
|
24212
|
-
const runtimes = {};
|
|
24213
|
-
Object.keys(plan).forEach(filePattern => {
|
|
24214
|
-
const filePlan = plan[filePattern];
|
|
24215
|
-
Object.keys(filePlan).forEach(executionName => {
|
|
24216
|
-
const executionConfig = filePlan[executionName];
|
|
24217
|
-
const {
|
|
24218
|
-
runtime
|
|
24219
|
-
} = executionConfig;
|
|
24220
|
-
if (runtime) {
|
|
24221
|
-
runtimes[runtime.name] = runtime.version;
|
|
24222
|
-
if (runtime.type === "browser") {
|
|
24223
|
-
someNeedsServer = true;
|
|
24224
|
-
}
|
|
24225
|
-
if (runtime.type === "node") {
|
|
24226
|
-
someNodeRuntime = true;
|
|
24227
|
-
}
|
|
24228
|
-
}
|
|
24229
|
-
});
|
|
24230
|
-
});
|
|
24231
|
-
logger.debug(createDetailedMessage$1(`Prepare executing plan`, {
|
|
24232
|
-
runtimes: JSON.stringify(runtimes, null, " ")
|
|
24233
|
-
}));
|
|
24234
24181
|
const multipleExecutionsOperation = Abort.startOperation();
|
|
24235
24182
|
multipleExecutionsOperation.addAbortSignal(signal);
|
|
24236
24183
|
if (handleSIGINT) {
|
|
@@ -24248,19 +24195,6 @@ const executePlan = async (plan, {
|
|
|
24248
24195
|
multipleExecutionsOperation.addAbortSignal(failFastAbortController.signal);
|
|
24249
24196
|
}
|
|
24250
24197
|
try {
|
|
24251
|
-
const coverageTempDirectoryUrl = new URL(coverageTempDirectoryRelativeUrl, rootDirectoryUrl).href;
|
|
24252
|
-
if (someNodeRuntime && coverageEnabled && coverageMethodForNodeJs === "NODE_V8_COVERAGE") {
|
|
24253
|
-
if (process.env.NODE_V8_COVERAGE) {
|
|
24254
|
-
// when runned multiple times, we don't want to keep previous files in this directory
|
|
24255
|
-
await ensureEmptyDirectory(process.env.NODE_V8_COVERAGE);
|
|
24256
|
-
} else {
|
|
24257
|
-
coverageMethodForNodeJs = "Profiler";
|
|
24258
|
-
logger.warn(createDetailedMessage$1(`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`, {
|
|
24259
|
-
"suggestion": `set process.env.NODE_V8_COVERAGE`,
|
|
24260
|
-
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`
|
|
24261
|
-
}));
|
|
24262
|
-
}
|
|
24263
|
-
}
|
|
24264
24198
|
if (gcBetweenExecutions) {
|
|
24265
24199
|
ensureGlobalGc();
|
|
24266
24200
|
}
|
|
@@ -24307,15 +24241,6 @@ const executePlan = async (plan, {
|
|
|
24307
24241
|
coverageMethodForNodeJs,
|
|
24308
24242
|
stopAfterAllSignal
|
|
24309
24243
|
};
|
|
24310
|
-
if (someNeedsServer) {
|
|
24311
|
-
if (!devServerOrigin) {
|
|
24312
|
-
throw new TypeError(`devServerOrigin is required when running tests on browser(s)`);
|
|
24313
|
-
}
|
|
24314
|
-
const devServerStarted = await pingServer(devServerOrigin);
|
|
24315
|
-
if (!devServerStarted) {
|
|
24316
|
-
throw new Error(`dev server not started at ${devServerOrigin}. It is required to run tests`);
|
|
24317
|
-
}
|
|
24318
|
-
}
|
|
24319
24244
|
logger.debug(`Generate executions`);
|
|
24320
24245
|
const executionSteps = await getExecutionAsSteps({
|
|
24321
24246
|
plan,
|
|
@@ -24412,7 +24337,7 @@ const executePlan = async (plan, {
|
|
|
24412
24337
|
executionResult = await run({
|
|
24413
24338
|
signal: multipleExecutionsOperation.signal,
|
|
24414
24339
|
logger,
|
|
24415
|
-
allocatedMs: executionParams.allocatedMs,
|
|
24340
|
+
allocatedMs: typeof executionParams.allocatedMs === "function" ? executionParams.allocatedMs(beforeExecutionInfo) : executionParams.allocatedMs,
|
|
24416
24341
|
keepRunning,
|
|
24417
24342
|
mirrorConsole: false,
|
|
24418
24343
|
// file are executed in parallel, log would be a mess to read
|
|
@@ -24628,8 +24553,8 @@ const executeInParallel = async ({
|
|
|
24628
24553
|
/**
|
|
24629
24554
|
* Execute a list of files and log how it goes.
|
|
24630
24555
|
* @param {Object} testPlanParameters
|
|
24631
|
-
* @param {string|url} testPlanParameters.
|
|
24632
|
-
* @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
|
|
24633
24558
|
* @param {Object} testPlanParameters.testPlan Object associating patterns leading to files to runtimes where they should be executed
|
|
24634
24559
|
* @param {boolean} [testPlanParameters.completedExecutionLogAbbreviation=false] Abbreviate completed execution information to shorten terminal output
|
|
24635
24560
|
* @param {boolean} [testPlanParameters.completedExecutionLogMerging=false] Merge completed execution logs to shorten terminal output
|
|
@@ -24655,7 +24580,8 @@ const executeTestPlan = async ({
|
|
|
24655
24580
|
logFileRelativeUrl = ".jsenv/test_plan_debug.txt",
|
|
24656
24581
|
completedExecutionLogAbbreviation = false,
|
|
24657
24582
|
completedExecutionLogMerging = false,
|
|
24658
|
-
|
|
24583
|
+
testDirectoryUrl,
|
|
24584
|
+
devServerModuleUrl,
|
|
24659
24585
|
devServerOrigin,
|
|
24660
24586
|
testPlan,
|
|
24661
24587
|
updateProcessExitCode = true,
|
|
@@ -24672,7 +24598,7 @@ const executeTestPlan = async ({
|
|
|
24672
24598
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
24673
24599
|
coverageEnabled = process.argv.includes("--coverage"),
|
|
24674
24600
|
coverageConfig = {
|
|
24675
|
-
"
|
|
24601
|
+
"./**/*": true
|
|
24676
24602
|
},
|
|
24677
24603
|
coverageIncludeMissing = true,
|
|
24678
24604
|
coverageAndExecutionAllowed = false,
|
|
@@ -24680,30 +24606,87 @@ const executeTestPlan = async ({
|
|
|
24680
24606
|
coverageMethodForBrowsers = "playwright_api",
|
|
24681
24607
|
// "istanbul" also accepted
|
|
24682
24608
|
coverageV8ConflictWarning = true,
|
|
24683
|
-
|
|
24609
|
+
coverageTempDirectoryUrl,
|
|
24610
|
+
coverageReportRootDirectoryUrl,
|
|
24684
24611
|
// skip empty means empty files won't appear in the coverage reports (json and html)
|
|
24685
24612
|
coverageReportSkipEmpty = false,
|
|
24686
24613
|
// skip full means file with 100% coverage won't appear in coverage reports (json and html)
|
|
24687
24614
|
coverageReportSkipFull = false,
|
|
24688
24615
|
coverageReportTextLog = true,
|
|
24689
|
-
|
|
24690
|
-
|
|
24616
|
+
coverageReportJson = process.env.CI,
|
|
24617
|
+
coverageReportJsonFileUrl,
|
|
24618
|
+
coverageReportHtml = !process.env.CI,
|
|
24619
|
+
coverageReportHtmlDirectoryUrl,
|
|
24691
24620
|
...rest
|
|
24692
24621
|
}) => {
|
|
24622
|
+
let someNeedsServer = false;
|
|
24623
|
+
let someNodeRuntime = false;
|
|
24624
|
+
let stopDevServerNeeded = false;
|
|
24625
|
+
const runtimes = {};
|
|
24693
24626
|
// param validation
|
|
24694
24627
|
{
|
|
24695
24628
|
const unexpectedParamNames = Object.keys(rest);
|
|
24696
24629
|
if (unexpectedParamNames.length > 0) {
|
|
24697
24630
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
24698
24631
|
}
|
|
24699
|
-
|
|
24700
|
-
if (!
|
|
24701
|
-
throw new
|
|
24632
|
+
testDirectoryUrl = assertAndNormalizeDirectoryUrl(testDirectoryUrl, "testDirectoryUrl");
|
|
24633
|
+
if (!existsSync(new URL(testDirectoryUrl))) {
|
|
24634
|
+
throw new Error(`ENOENT on testDirectoryUrl at ${testDirectoryUrl}`);
|
|
24702
24635
|
}
|
|
24703
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
24704
24636
|
if (typeof testPlan !== "object") {
|
|
24705
24637
|
throw new Error(`testPlan must be an object, got ${testPlan}`);
|
|
24706
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
|
+
}
|
|
24707
24690
|
if (coverageEnabled) {
|
|
24708
24691
|
if (typeof coverageConfig !== "object") {
|
|
24709
24692
|
throw new TypeError(`coverageConfig must be an object, got ${coverageConfig}`);
|
|
@@ -24731,14 +24714,63 @@ const executeTestPlan = async ({
|
|
|
24731
24714
|
}));
|
|
24732
24715
|
}
|
|
24733
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
|
+
}
|
|
24734
24741
|
}
|
|
24735
24742
|
}
|
|
24736
24743
|
const logger = createLogger({
|
|
24737
24744
|
logLevel
|
|
24738
24745
|
});
|
|
24739
|
-
|
|
24740
|
-
|
|
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
|
+
}
|
|
24741
24769
|
}
|
|
24770
|
+
testPlan = {
|
|
24771
|
+
...testPlan,
|
|
24772
|
+
"**/.jsenv/": null
|
|
24773
|
+
};
|
|
24742
24774
|
const result = await executePlan(testPlan, {
|
|
24743
24775
|
signal,
|
|
24744
24776
|
handleSIGINT,
|
|
@@ -24752,7 +24784,7 @@ const executeTestPlan = async ({
|
|
|
24752
24784
|
logFileRelativeUrl,
|
|
24753
24785
|
completedExecutionLogMerging,
|
|
24754
24786
|
completedExecutionLogAbbreviation,
|
|
24755
|
-
rootDirectoryUrl,
|
|
24787
|
+
rootDirectoryUrl: testDirectoryUrl,
|
|
24756
24788
|
devServerOrigin,
|
|
24757
24789
|
maxExecutionsInParallel,
|
|
24758
24790
|
defaultMsAllocatedPerExecution,
|
|
@@ -24766,8 +24798,17 @@ const executeTestPlan = async ({
|
|
|
24766
24798
|
coverageMethodForBrowsers,
|
|
24767
24799
|
coverageMethodForNodeJs,
|
|
24768
24800
|
coverageV8ConflictWarning,
|
|
24769
|
-
|
|
24801
|
+
coverageTempDirectoryUrl
|
|
24770
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
|
+
}
|
|
24771
24812
|
if (updateProcessExitCode && result.planSummary.counters.total !== result.planSummary.counters.completed) {
|
|
24772
24813
|
process.exitCode = 1;
|
|
24773
24814
|
}
|
|
@@ -24778,26 +24819,21 @@ const executeTestPlan = async ({
|
|
|
24778
24819
|
// keep this one first because it does ensureEmptyDirectory
|
|
24779
24820
|
// and in case coverage json file gets written in the same directory
|
|
24780
24821
|
// it must be done before
|
|
24781
|
-
if (coverageEnabled &&
|
|
24782
|
-
|
|
24783
|
-
|
|
24784
|
-
throw new Error(`coverageReportHtmlDirectory must be inside rootDirectoryUrl`);
|
|
24785
|
-
}
|
|
24786
|
-
await ensureEmptyDirectory(coverageHtmlDirectoryUrl);
|
|
24787
|
-
const htmlCoverageDirectoryIndexFileUrl = `${coverageHtmlDirectoryUrl}index.html`;
|
|
24822
|
+
if (coverageEnabled && coverageReportHtml) {
|
|
24823
|
+
await ensureEmptyDirectory(coverageReportHtmlDirectoryUrl);
|
|
24824
|
+
const htmlCoverageDirectoryIndexFileUrl = `${coverageReportHtmlDirectoryUrl}index.html`;
|
|
24788
24825
|
logger.info(`-> ${urlToFileSystemPath(htmlCoverageDirectoryIndexFileUrl)}`);
|
|
24789
24826
|
promises.push(generateCoverageHtmlDirectory(planCoverage, {
|
|
24790
|
-
rootDirectoryUrl,
|
|
24791
|
-
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(
|
|
24827
|
+
rootDirectoryUrl: coverageReportRootDirectoryUrl,
|
|
24828
|
+
coverageHtmlDirectoryRelativeUrl: urlToRelativeUrl(coverageReportHtmlDirectoryUrl, coverageReportRootDirectoryUrl),
|
|
24792
24829
|
coverageReportSkipEmpty,
|
|
24793
24830
|
coverageReportSkipFull
|
|
24794
24831
|
}));
|
|
24795
24832
|
}
|
|
24796
|
-
if (coverageEnabled &&
|
|
24797
|
-
const coverageJsonFileUrl = new URL(coverageReportJsonFile, rootDirectoryUrl).href;
|
|
24833
|
+
if (coverageEnabled && coverageReportJson) {
|
|
24798
24834
|
promises.push(generateCoverageJsonFile({
|
|
24799
24835
|
coverage: result.planCoverage,
|
|
24800
|
-
coverageJsonFileUrl,
|
|
24836
|
+
coverageJsonFileUrl: coverageReportJsonFileUrl,
|
|
24801
24837
|
logger
|
|
24802
24838
|
}));
|
|
24803
24839
|
}
|
|
@@ -25661,7 +25697,6 @@ nodeChildProcess.run = async ({
|
|
|
25661
25697
|
env: envForChildProcess
|
|
25662
25698
|
});
|
|
25663
25699
|
logger.debug(createDetailedMessage$1(`child process forked (pid ${childProcess.pid})`, {
|
|
25664
|
-
"execArgv": execArgv.join(`\n`),
|
|
25665
25700
|
"custom env": JSON.stringify(env, null, " ")
|
|
25666
25701
|
}));
|
|
25667
25702
|
// if we pass stream, pipe them https://github.com/sindresorhus/execa/issues/81
|
|
@@ -26184,32 +26219,23 @@ const onceWorkerThreadEvent = (worker, type, callback) => {
|
|
|
26184
26219
|
/**
|
|
26185
26220
|
* Start a server for build files.
|
|
26186
26221
|
* @param {Object} buildServerParameters
|
|
26187
|
-
* @param {string|url} buildServerParameters.rootDirectoryUrl Root directory of the project
|
|
26188
26222
|
* @param {string|url} buildServerParameters.buildDirectoryUrl Directory where build files are written
|
|
26189
26223
|
* @return {Object} A build server object
|
|
26190
26224
|
*/
|
|
26191
26225
|
const startBuildServer = async ({
|
|
26192
|
-
|
|
26193
|
-
|
|
26194
|
-
logLevel,
|
|
26195
|
-
serverLogLevel = "warn",
|
|
26196
|
-
https,
|
|
26197
|
-
http2,
|
|
26198
|
-
acceptAnyIp,
|
|
26199
|
-
hostname,
|
|
26226
|
+
buildDirectoryUrl,
|
|
26227
|
+
buildMainFilePath = "index.html",
|
|
26200
26228
|
port = 9779,
|
|
26201
26229
|
services = [],
|
|
26230
|
+
acceptAnyIp,
|
|
26231
|
+
hostname,
|
|
26232
|
+
https,
|
|
26233
|
+
http2,
|
|
26234
|
+
logLevel,
|
|
26235
|
+
serverLogLevel = "warn",
|
|
26236
|
+
signal = new AbortController().signal,
|
|
26237
|
+
handleSIGINT = true,
|
|
26202
26238
|
keepProcessAlive = true,
|
|
26203
|
-
rootDirectoryUrl,
|
|
26204
|
-
buildDirectoryUrl,
|
|
26205
|
-
buildIndexPath = "index.html",
|
|
26206
|
-
buildServerFiles = {
|
|
26207
|
-
"./package.json": true,
|
|
26208
|
-
"./jsenv.config.mjs": true
|
|
26209
|
-
},
|
|
26210
|
-
buildServerAutoreload = false,
|
|
26211
|
-
buildServerMainFile = getCallerPosition().url,
|
|
26212
|
-
cooldownBetweenFileEvents,
|
|
26213
26239
|
...rest
|
|
26214
26240
|
}) => {
|
|
26215
26241
|
// params validation
|
|
@@ -26218,31 +26244,22 @@ const startBuildServer = async ({
|
|
|
26218
26244
|
if (unexpectedParamNames.length > 0) {
|
|
26219
26245
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
26220
26246
|
}
|
|
26221
|
-
|
|
26222
|
-
if (
|
|
26223
|
-
|
|
26224
|
-
|
|
26225
|
-
rootDirectoryUrl = rootDirectoryUrlValidation.value;
|
|
26226
|
-
const buildDirectoryUrlValidation = validateDirectoryUrl(buildDirectoryUrl);
|
|
26227
|
-
if (!buildDirectoryUrlValidation.valid) {
|
|
26228
|
-
throw new TypeError(`buildDirectoryUrl ${buildDirectoryUrlValidation.message}, got ${buildDirectoryUrlValidation}`);
|
|
26229
|
-
}
|
|
26230
|
-
buildDirectoryUrl = buildDirectoryUrlValidation.value;
|
|
26231
|
-
if (buildIndexPath) {
|
|
26232
|
-
if (typeof buildIndexPath !== "string") {
|
|
26233
|
-
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}`);
|
|
26234
26251
|
}
|
|
26235
|
-
if (
|
|
26236
|
-
|
|
26252
|
+
if (buildMainFilePath[0] === "/") {
|
|
26253
|
+
buildMainFilePath = buildMainFilePath.slice(1);
|
|
26237
26254
|
} else {
|
|
26238
|
-
const
|
|
26239
|
-
if (!
|
|
26240
|
-
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}`);
|
|
26241
26258
|
}
|
|
26242
|
-
|
|
26259
|
+
buildMainFilePath = buildMainFileUrl.slice(buildDirectoryUrl.length);
|
|
26243
26260
|
}
|
|
26244
|
-
if (!existsSync(new URL(
|
|
26245
|
-
|
|
26261
|
+
if (!existsSync(new URL(buildMainFilePath, buildDirectoryUrl))) {
|
|
26262
|
+
buildMainFilePath = null;
|
|
26246
26263
|
}
|
|
26247
26264
|
}
|
|
26248
26265
|
}
|
|
@@ -26258,73 +26275,6 @@ const startBuildServer = async ({
|
|
|
26258
26275
|
}, abort);
|
|
26259
26276
|
});
|
|
26260
26277
|
}
|
|
26261
|
-
let reloadableWorker;
|
|
26262
|
-
if (buildServerAutoreload) {
|
|
26263
|
-
reloadableWorker = createReloadableWorker(buildServerMainFile);
|
|
26264
|
-
if (reloadableWorker.isPrimary) {
|
|
26265
|
-
const buildServerFileChangeCallback = ({
|
|
26266
|
-
relativeUrl,
|
|
26267
|
-
event
|
|
26268
|
-
}) => {
|
|
26269
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
26270
|
-
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
26271
|
-
reloadableWorker.reload();
|
|
26272
|
-
};
|
|
26273
|
-
const stopWatchingBuildServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
26274
|
-
watchPatterns: {
|
|
26275
|
-
...buildServerFiles,
|
|
26276
|
-
[buildServerMainFile]: true,
|
|
26277
|
-
".jsenv/": false
|
|
26278
|
-
},
|
|
26279
|
-
cooldownBetweenFileEvents,
|
|
26280
|
-
keepProcessAlive: false,
|
|
26281
|
-
recursive: true,
|
|
26282
|
-
added: ({
|
|
26283
|
-
relativeUrl
|
|
26284
|
-
}) => {
|
|
26285
|
-
buildServerFileChangeCallback({
|
|
26286
|
-
relativeUrl,
|
|
26287
|
-
event: "added"
|
|
26288
|
-
});
|
|
26289
|
-
},
|
|
26290
|
-
updated: ({
|
|
26291
|
-
relativeUrl
|
|
26292
|
-
}) => {
|
|
26293
|
-
buildServerFileChangeCallback({
|
|
26294
|
-
relativeUrl,
|
|
26295
|
-
event: "modified"
|
|
26296
|
-
});
|
|
26297
|
-
},
|
|
26298
|
-
removed: ({
|
|
26299
|
-
relativeUrl
|
|
26300
|
-
}) => {
|
|
26301
|
-
buildServerFileChangeCallback({
|
|
26302
|
-
relativeUrl,
|
|
26303
|
-
event: "removed"
|
|
26304
|
-
});
|
|
26305
|
-
}
|
|
26306
|
-
});
|
|
26307
|
-
operation.addAbortCallback(() => {
|
|
26308
|
-
stopWatchingBuildServerFiles();
|
|
26309
|
-
reloadableWorker.terminate();
|
|
26310
|
-
});
|
|
26311
|
-
const worker = await reloadableWorker.load();
|
|
26312
|
-
const messagePromise = new Promise(resolve => {
|
|
26313
|
-
worker.once("message", resolve);
|
|
26314
|
-
});
|
|
26315
|
-
const origin = await messagePromise;
|
|
26316
|
-
// if (!keepProcessAlive) {
|
|
26317
|
-
// worker.unref()
|
|
26318
|
-
// }
|
|
26319
|
-
return {
|
|
26320
|
-
origin,
|
|
26321
|
-
stop: () => {
|
|
26322
|
-
stopWatchingBuildServerFiles();
|
|
26323
|
-
reloadableWorker.terminate();
|
|
26324
|
-
}
|
|
26325
|
-
};
|
|
26326
|
-
}
|
|
26327
|
-
}
|
|
26328
26278
|
const startBuildServerTask = createTaskLog("start build server", {
|
|
26329
26279
|
disabled: !logger.levels.info
|
|
26330
26280
|
});
|
|
@@ -26355,7 +26305,7 @@ const startBuildServer = async ({
|
|
|
26355
26305
|
name: "jsenv:build_files_service",
|
|
26356
26306
|
handleRequest: createBuildFilesService({
|
|
26357
26307
|
buildDirectoryUrl,
|
|
26358
|
-
|
|
26308
|
+
buildMainFilePath
|
|
26359
26309
|
})
|
|
26360
26310
|
}, jsenvServiceErrorHandler({
|
|
26361
26311
|
sendErrorDetails: true
|
|
@@ -26371,9 +26321,6 @@ const startBuildServer = async ({
|
|
|
26371
26321
|
logger.info(`- ${server.origins[key]}`);
|
|
26372
26322
|
});
|
|
26373
26323
|
logger.info(``);
|
|
26374
|
-
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
26375
|
-
parentPort.postMessage(server.origin);
|
|
26376
|
-
}
|
|
26377
26324
|
return {
|
|
26378
26325
|
origin: server.origin,
|
|
26379
26326
|
stop: () => {
|
|
@@ -26383,14 +26330,14 @@ const startBuildServer = async ({
|
|
|
26383
26330
|
};
|
|
26384
26331
|
const createBuildFilesService = ({
|
|
26385
26332
|
buildDirectoryUrl,
|
|
26386
|
-
|
|
26333
|
+
buildMainFilePath
|
|
26387
26334
|
}) => {
|
|
26388
26335
|
return request => {
|
|
26389
26336
|
const urlIsVersioned = new URL(request.url).searchParams.has("v");
|
|
26390
|
-
if (
|
|
26337
|
+
if (buildMainFilePath && request.resource === "/") {
|
|
26391
26338
|
request = {
|
|
26392
26339
|
...request,
|
|
26393
|
-
resource: `/${
|
|
26340
|
+
resource: `/${buildMainFilePath}`
|
|
26394
26341
|
};
|
|
26395
26342
|
}
|
|
26396
26343
|
return fetchFileSystem(new URL(request.resource.slice(1), buildDirectoryUrl), {
|
|
@@ -26437,7 +26384,7 @@ const execute = async ({
|
|
|
26437
26384
|
const logger = createLogger({
|
|
26438
26385
|
logLevel
|
|
26439
26386
|
});
|
|
26440
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl);
|
|
26387
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl, "rootDirectoryUrl");
|
|
26441
26388
|
const executeOperation = Abort.startOperation();
|
|
26442
26389
|
executeOperation.addAbortSignal(signal);
|
|
26443
26390
|
if (handleSIGINT) {
|