@jsenv/core 40.0.0 → 40.0.2
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/build.js +17639 -0
- package/dist/js/directory_listing.js +4 -4
- package/dist/js/main.js +994 -0
- package/dist/js/new_stylesheet.js +1 -1
- package/dist/js/process_teardown_events.js +1848 -0
- package/dist/js/regenerator_runtime.js +1 -1
- package/dist/js/server_events_client.js +0 -1
- package/dist/js/start_build_server.js +206 -0
- package/dist/js/start_dev_server.js +846 -0
- package/dist/jsenv_core.js +2 -21359
- package/package.json +18 -14
- package/src/build/build_specifier_manager.js +2 -1
- package/src/main.js +13 -3
- package/src/plugins/resolution_node_esm/node_esm_resolver.js +17 -1
|
@@ -225,7 +225,7 @@ var runtime = (function (exports) {
|
|
|
225
225
|
// AsyncIterator objects; they just return a Promise for the value of
|
|
226
226
|
// the final result produced by the iterator.
|
|
227
227
|
exports.async = function(innerFn, outerFn, self, tryLocsList, PromiseImpl) {
|
|
228
|
-
if (PromiseImpl ===
|
|
228
|
+
if (PromiseImpl === void 0) PromiseImpl = Promise;
|
|
229
229
|
|
|
230
230
|
var iter = new AsyncIterator(
|
|
231
231
|
wrap(innerFn, outerFn, self, tryLocsList),
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { assertAndNormalizeDirectoryUrl, createLogger, Abort, raceProcessTeardownEvents, createTaskLog } from "./process_teardown_events.js";
|
|
2
|
+
import { startServer, jsenvServiceCORS, jsenvServiceErrorHandler, jsenvAccessControlAllowedHeaders, createFileSystemFetch } from "@jsenv/server";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { urlToExtension, urlToPathname } from "./main.js";
|
|
5
|
+
import "node:process";
|
|
6
|
+
import "node:os";
|
|
7
|
+
import "node:tty";
|
|
8
|
+
import "string-width";
|
|
9
|
+
import "node:url";
|
|
10
|
+
import "@jsenv/sourcemap";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* startBuildServer is mean to interact with the build files;
|
|
14
|
+
* files that will be deployed to production server(s).
|
|
15
|
+
* We want to be as close as possible from the production in order to:
|
|
16
|
+
* - run lighthouse
|
|
17
|
+
* - run an automated test tool such as cypress, playwright
|
|
18
|
+
* - see exactly how build file behaves (debug, measure perf, etc)
|
|
19
|
+
* For these reasons "startBuildServer" must be as close as possible from a static file server.
|
|
20
|
+
* It is not meant to provide a nice developper experience: this is the role "startDevServer".
|
|
21
|
+
*
|
|
22
|
+
* Conclusion:
|
|
23
|
+
* "startBuildServer" must be as close as possible from a static file server because
|
|
24
|
+
* we want to be in the user shoes and we should not alter build files.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Start a server for build files.
|
|
30
|
+
* @param {Object} buildServerParameters
|
|
31
|
+
* @param {string|url} buildServerParameters.buildDirectoryUrl Directory where build files are written
|
|
32
|
+
* @return {Object} A build server object
|
|
33
|
+
*/
|
|
34
|
+
const startBuildServer = async ({
|
|
35
|
+
buildDirectoryUrl,
|
|
36
|
+
buildMainFilePath = "index.html",
|
|
37
|
+
port = 9779,
|
|
38
|
+
routes,
|
|
39
|
+
services = [],
|
|
40
|
+
acceptAnyIp,
|
|
41
|
+
hostname,
|
|
42
|
+
https,
|
|
43
|
+
http2,
|
|
44
|
+
logLevel,
|
|
45
|
+
serverLogLevel = "warn",
|
|
46
|
+
|
|
47
|
+
signal = new AbortController().signal,
|
|
48
|
+
handleSIGINT = true,
|
|
49
|
+
keepProcessAlive = true,
|
|
50
|
+
|
|
51
|
+
...rest
|
|
52
|
+
}) => {
|
|
53
|
+
// params validation
|
|
54
|
+
{
|
|
55
|
+
const unexpectedParamNames = Object.keys(rest);
|
|
56
|
+
if (unexpectedParamNames.length > 0) {
|
|
57
|
+
throw new TypeError(
|
|
58
|
+
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(
|
|
62
|
+
buildDirectoryUrl,
|
|
63
|
+
"buildDirectoryUrl",
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
if (buildMainFilePath) {
|
|
67
|
+
if (typeof buildMainFilePath !== "string") {
|
|
68
|
+
throw new TypeError(
|
|
69
|
+
`buildMainFilePath must be a string, got ${buildMainFilePath}`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if (buildMainFilePath[0] === "/") {
|
|
73
|
+
buildMainFilePath = buildMainFilePath.slice(1);
|
|
74
|
+
} else {
|
|
75
|
+
const buildMainFileUrl = new URL(buildMainFilePath, buildDirectoryUrl)
|
|
76
|
+
.href;
|
|
77
|
+
if (!buildMainFileUrl.startsWith(buildDirectoryUrl)) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`buildMainFilePath must be relative, got ${buildMainFilePath}`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
buildMainFilePath = buildMainFileUrl.slice(buildDirectoryUrl.length);
|
|
83
|
+
}
|
|
84
|
+
if (!existsSync(new URL(buildMainFilePath, buildDirectoryUrl))) {
|
|
85
|
+
buildMainFilePath = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const logger = createLogger({ logLevel });
|
|
91
|
+
const operation = Abort.startOperation();
|
|
92
|
+
operation.addAbortSignal(signal);
|
|
93
|
+
if (handleSIGINT) {
|
|
94
|
+
operation.addAbortSource((abort) => {
|
|
95
|
+
return raceProcessTeardownEvents(
|
|
96
|
+
{
|
|
97
|
+
SIGINT: true,
|
|
98
|
+
},
|
|
99
|
+
abort,
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const startBuildServerTask = createTaskLog("start build server", {
|
|
105
|
+
disabled: !logger.levels.info,
|
|
106
|
+
});
|
|
107
|
+
const server = await startServer({
|
|
108
|
+
signal,
|
|
109
|
+
stopOnExit: false,
|
|
110
|
+
stopOnSIGINT: false,
|
|
111
|
+
stopOnInternalError: false,
|
|
112
|
+
keepProcessAlive,
|
|
113
|
+
logLevel: serverLogLevel,
|
|
114
|
+
startLog: false,
|
|
115
|
+
|
|
116
|
+
https,
|
|
117
|
+
http2,
|
|
118
|
+
acceptAnyIp,
|
|
119
|
+
hostname,
|
|
120
|
+
port,
|
|
121
|
+
serverTiming: true,
|
|
122
|
+
requestWaitingMs: 60_000,
|
|
123
|
+
routes,
|
|
124
|
+
services: [
|
|
125
|
+
jsenvServiceCORS({
|
|
126
|
+
accessControlAllowRequestOrigin: true,
|
|
127
|
+
accessControlAllowRequestMethod: true,
|
|
128
|
+
accessControlAllowRequestHeaders: true,
|
|
129
|
+
accessControlAllowedRequestHeaders: jsenvAccessControlAllowedHeaders,
|
|
130
|
+
accessControlAllowCredentials: true,
|
|
131
|
+
timingAllowOrigin: true,
|
|
132
|
+
}),
|
|
133
|
+
...services,
|
|
134
|
+
jsenvBuildFileService({
|
|
135
|
+
buildDirectoryUrl,
|
|
136
|
+
buildMainFilePath,
|
|
137
|
+
}),
|
|
138
|
+
jsenvServiceErrorHandler({
|
|
139
|
+
sendErrorDetails: true,
|
|
140
|
+
}),
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
startBuildServerTask.done();
|
|
144
|
+
if (hostname) {
|
|
145
|
+
delete server.origins.localip;
|
|
146
|
+
delete server.origins.externalip;
|
|
147
|
+
}
|
|
148
|
+
logger.info(``);
|
|
149
|
+
Object.keys(server.origins).forEach((key) => {
|
|
150
|
+
logger.info(`- ${server.origins[key]}`);
|
|
151
|
+
});
|
|
152
|
+
logger.info(``);
|
|
153
|
+
return {
|
|
154
|
+
origin: server.origin,
|
|
155
|
+
stop: () => {
|
|
156
|
+
server.stop();
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const jsenvBuildFileService = ({ buildDirectoryUrl, buildMainFilePath }) => {
|
|
162
|
+
return {
|
|
163
|
+
name: "jsenv:build_files",
|
|
164
|
+
routes: [
|
|
165
|
+
{
|
|
166
|
+
endpoint: "GET *",
|
|
167
|
+
description: "Serve static files.",
|
|
168
|
+
fetch: (request, helpers) => {
|
|
169
|
+
const urlIsVersioned = new URL(request.url).searchParams.has("v");
|
|
170
|
+
if (buildMainFilePath && request.resource === "/") {
|
|
171
|
+
request = {
|
|
172
|
+
...request,
|
|
173
|
+
resource: `/${buildMainFilePath}`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const urlObject = new URL(
|
|
177
|
+
request.resource.slice(1),
|
|
178
|
+
buildDirectoryUrl,
|
|
179
|
+
);
|
|
180
|
+
return createFileSystemFetch(buildDirectoryUrl, {
|
|
181
|
+
cacheControl: urlIsVersioned
|
|
182
|
+
? `private,max-age=${SECONDS_IN_30_DAYS},immutable`
|
|
183
|
+
: "private,max-age=0,must-revalidate",
|
|
184
|
+
etagEnabled: true,
|
|
185
|
+
compressionEnabled: true,
|
|
186
|
+
rootDirectoryUrl: buildDirectoryUrl,
|
|
187
|
+
canReadDirectory: true,
|
|
188
|
+
ENOENTFallback: () => {
|
|
189
|
+
if (
|
|
190
|
+
!urlToExtension(urlObject) &&
|
|
191
|
+
!urlToPathname(urlObject).endsWith("/")
|
|
192
|
+
) {
|
|
193
|
+
return new URL(buildMainFilePath, buildDirectoryUrl);
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
},
|
|
197
|
+
})(request, helpers);
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const SECONDS_IN_30_DAYS = 60 * 60 * 24 * 30;
|
|
205
|
+
|
|
206
|
+
export { startBuildServer };
|