@jsenv/core 27.0.0-alpha.21 → 27.0.0-alpha.22
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/package.json +2 -2
- package/src/build/start_build_server.js +136 -128
- package/src/dev/start_dev_server.js +37 -4
- package/src/omega/kitchen.js +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "27.0.0-alpha.
|
|
3
|
+
"version": "27.0.0-alpha.22",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@jsenv/node-esm-resolution": "0.0.4",
|
|
68
68
|
"@jsenv/server": "12.6.1",
|
|
69
69
|
"@jsenv/uneval": "1.6.0",
|
|
70
|
-
"@jsenv/utils": "1.4.
|
|
70
|
+
"@jsenv/utils": "1.4.1",
|
|
71
71
|
"construct-style-sheets-polyfill": "3.1.0",
|
|
72
72
|
"cssnano": "5.1.7",
|
|
73
73
|
"cssnano-preset-default": "5.2.7",
|
|
@@ -21,12 +21,11 @@ import {
|
|
|
21
21
|
pluginCORS,
|
|
22
22
|
fetchFileSystem,
|
|
23
23
|
} from "@jsenv/server"
|
|
24
|
-
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
|
|
25
24
|
import { createLogger } from "@jsenv/logger"
|
|
26
25
|
|
|
26
|
+
import { initProcessAutorestart } from "@jsenv/utils/file_watcher/process_auto_restart.js"
|
|
27
27
|
import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
|
|
28
28
|
import { watchFiles } from "@jsenv/utils/file_watcher/file_watcher.js"
|
|
29
|
-
import { setupFileRestart } from "@jsenv/utils/file_watcher/file_restart.js"
|
|
30
29
|
import { executeCommand } from "@jsenv/utils/command/command.js"
|
|
31
30
|
|
|
32
31
|
export const startBuildServer = async ({
|
|
@@ -34,155 +33,164 @@ export const startBuildServer = async ({
|
|
|
34
33
|
handleSIGINT = true,
|
|
35
34
|
logLevel,
|
|
36
35
|
buildCommandLogLevel = "warn",
|
|
37
|
-
protocol,
|
|
36
|
+
protocol = "http",
|
|
38
37
|
http2,
|
|
39
38
|
certificate,
|
|
40
39
|
privateKey,
|
|
41
40
|
listenAnyIp,
|
|
42
41
|
ip,
|
|
43
|
-
port,
|
|
42
|
+
port = 9779,
|
|
44
43
|
|
|
45
44
|
rootDirectoryUrl,
|
|
46
45
|
buildDirectoryUrl,
|
|
47
46
|
buildCommand,
|
|
47
|
+
mainBuildFile,
|
|
48
48
|
watchedFilePatterns,
|
|
49
49
|
cooldownBetweenFileEvents,
|
|
50
50
|
autorestart,
|
|
51
51
|
}) => {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
52
|
+
const autorestartProcess = await initProcessAutorestart({
|
|
53
|
+
signal,
|
|
54
|
+
handleSIGINT,
|
|
55
|
+
...(autorestart
|
|
56
|
+
? {
|
|
57
|
+
enabled: true,
|
|
58
|
+
logLevel: autorestart.logLevel,
|
|
59
|
+
urlToRestart: autorestart.url,
|
|
60
|
+
urlsToWatch: [
|
|
61
|
+
...(autorestart.urlsToWatch || []),
|
|
62
|
+
new URL("package.json", rootDirectoryUrl),
|
|
63
|
+
new URL("jsenv.config.mjs", rootDirectoryUrl),
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
: {
|
|
67
|
+
enabled: false,
|
|
68
|
+
}),
|
|
69
|
+
})
|
|
70
|
+
if (autorestartProcess.isPrimary) {
|
|
71
|
+
return {
|
|
72
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
73
|
+
stop: () => {
|
|
74
|
+
autorestartProcess.stop()
|
|
75
|
+
},
|
|
76
|
+
}
|
|
63
77
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
autorestart,
|
|
67
|
-
injectedUrlsToWatch: [
|
|
68
|
-
new URL("package.json", rootDirectoryUrl),
|
|
69
|
-
new URL("jsenv.config.mjs", rootDirectoryUrl),
|
|
70
|
-
],
|
|
71
|
-
job: async () => {
|
|
72
|
-
const logger = createLogger({ logLevel })
|
|
78
|
+
signal = autorestartProcess.signal
|
|
79
|
+
const logger = createLogger({ logLevel })
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
buildTask.fail(`execute build command aborted`)
|
|
93
|
-
} else {
|
|
94
|
-
buildTask.fail()
|
|
95
|
-
throw e
|
|
96
|
-
}
|
|
97
|
-
}
|
|
81
|
+
let buildPromise
|
|
82
|
+
let abortController
|
|
83
|
+
const runBuild = async () => {
|
|
84
|
+
const buildTask = createTaskLog(logger, `execute build command`)
|
|
85
|
+
buildPromise = executeCommand(buildCommand, {
|
|
86
|
+
cwd: rootDirectoryUrl,
|
|
87
|
+
logLevel: buildCommandLogLevel,
|
|
88
|
+
signal,
|
|
89
|
+
})
|
|
90
|
+
try {
|
|
91
|
+
await buildPromise
|
|
92
|
+
buildTask.done()
|
|
93
|
+
} catch (e) {
|
|
94
|
+
if (e.code === "ABORT_ERR") {
|
|
95
|
+
buildTask.fail(`execute build command aborted`)
|
|
96
|
+
} else {
|
|
97
|
+
buildTask.fail()
|
|
98
|
+
throw e
|
|
98
99
|
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
protocol,
|
|
111
|
-
http2,
|
|
112
|
-
certificate,
|
|
113
|
-
privateKey,
|
|
114
|
-
listenAnyIp,
|
|
115
|
-
ip,
|
|
116
|
-
port,
|
|
117
|
-
plugins: {
|
|
118
|
-
...pluginCORS({
|
|
119
|
-
accessControlAllowRequestOrigin: true,
|
|
120
|
-
accessControlAllowRequestMethod: true,
|
|
121
|
-
accessControlAllowRequestHeaders: true,
|
|
122
|
-
accessControlAllowedRequestHeaders: [
|
|
123
|
-
...jsenvAccessControlAllowedHeaders,
|
|
124
|
-
"x-jsenv-execution-id",
|
|
125
|
-
],
|
|
126
|
-
accessControlAllowCredentials: true,
|
|
127
|
-
}),
|
|
128
|
-
...pluginServerTiming(),
|
|
129
|
-
...pluginRequestWaitingCheck({
|
|
130
|
-
requestWaitingMs: 60 * 1000,
|
|
131
|
-
}),
|
|
132
|
-
},
|
|
133
|
-
sendErrorDetails: true,
|
|
134
|
-
requestToResponse: async (request) => {
|
|
135
|
-
await buildPromise
|
|
136
|
-
const urlIsVersioned = new URL(
|
|
137
|
-
request.ressource,
|
|
138
|
-
request.origin,
|
|
139
|
-
).searchParams.has("v")
|
|
103
|
+
const startServerTask = createTaskLog(logger, "start build server")
|
|
104
|
+
const server = await startServer({
|
|
105
|
+
signal,
|
|
106
|
+
stopOnExit: false,
|
|
107
|
+
stopOnSIGINT: false,
|
|
108
|
+
stopOnInternalError: false,
|
|
109
|
+
keepProcessAlive: true,
|
|
110
|
+
logLevel,
|
|
111
|
+
startLog: false,
|
|
140
112
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
113
|
+
protocol,
|
|
114
|
+
http2,
|
|
115
|
+
certificate,
|
|
116
|
+
privateKey,
|
|
117
|
+
listenAnyIp,
|
|
118
|
+
ip,
|
|
119
|
+
port,
|
|
120
|
+
plugins: {
|
|
121
|
+
...pluginCORS({
|
|
122
|
+
accessControlAllowRequestOrigin: true,
|
|
123
|
+
accessControlAllowRequestMethod: true,
|
|
124
|
+
accessControlAllowRequestHeaders: true,
|
|
125
|
+
accessControlAllowedRequestHeaders: [
|
|
126
|
+
...jsenvAccessControlAllowedHeaders,
|
|
127
|
+
"x-jsenv-execution-id",
|
|
128
|
+
],
|
|
129
|
+
accessControlAllowCredentials: true,
|
|
130
|
+
}),
|
|
131
|
+
...pluginServerTiming(),
|
|
132
|
+
...pluginRequestWaitingCheck({
|
|
133
|
+
requestWaitingMs: 60 * 1000,
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
sendErrorDetails: true,
|
|
137
|
+
requestToResponse: async (request) => {
|
|
138
|
+
await buildPromise
|
|
139
|
+
const urlIsVersioned = new URL(
|
|
140
|
+
request.ressource,
|
|
141
|
+
request.origin,
|
|
142
|
+
).searchParams.has("v")
|
|
143
|
+
if (mainBuildFile && request.ressource === "/") {
|
|
144
|
+
request = {
|
|
145
|
+
...request,
|
|
146
|
+
ressource: `/${mainBuildFile}`,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return fetchFileSystem(
|
|
150
|
+
new URL(request.ressource.slice(1), buildDirectoryUrl),
|
|
151
|
+
{
|
|
152
|
+
headers: request.headers,
|
|
153
|
+
cacheControl: urlIsVersioned
|
|
154
|
+
? `private,max-age=${SECONDS_IN_30_DAYS},immutable`
|
|
155
|
+
: "private,max-age=0,must-revalidate",
|
|
156
|
+
etagEnabled: true,
|
|
157
|
+
compressionEnabled: !request.pathname.endsWith(".mp4"),
|
|
158
|
+
rootDirectoryUrl: buildDirectoryUrl,
|
|
159
|
+
canReadDirectory: true,
|
|
154
160
|
},
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
)
|
|
162
|
+
},
|
|
163
|
+
})
|
|
164
|
+
startServerTask.done()
|
|
165
|
+
logger.info(``)
|
|
166
|
+
Object.keys(server.origins).forEach((key) => {
|
|
167
|
+
logger.info(`- ${server.origins[key]}`)
|
|
168
|
+
})
|
|
169
|
+
logger.info(``)
|
|
162
170
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
176
|
-
runBuild()
|
|
177
|
-
})
|
|
178
|
-
},
|
|
171
|
+
const unregisterDirectoryLifecyle = watchFiles({
|
|
172
|
+
rootDirectoryUrl,
|
|
173
|
+
watchedFilePatterns,
|
|
174
|
+
cooldownBetweenFileEvents,
|
|
175
|
+
fileChangeCallback: ({ url, event }) => {
|
|
176
|
+
abortController.abort()
|
|
177
|
+
// setTimeout is to ensure the abortController.abort() above
|
|
178
|
+
// is properly taken into account so that logs about abort comes first
|
|
179
|
+
// then logs about re-running the build happens
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
logger.info(`${url.slice(rootDirectoryUrl.length)} ${event} -> rebuild`)
|
|
182
|
+
runBuild()
|
|
179
183
|
})
|
|
180
|
-
operation.addAbortCallback(() => {
|
|
181
|
-
unregisterDirectoryLifecyle()
|
|
182
|
-
})
|
|
183
|
-
runBuild()
|
|
184
184
|
},
|
|
185
185
|
})
|
|
186
|
+
signal.addEventListener("abort", () => {
|
|
187
|
+
unregisterDirectoryLifecyle()
|
|
188
|
+
})
|
|
189
|
+
runBuild()
|
|
190
|
+
return {
|
|
191
|
+
origin: server.origin,
|
|
192
|
+
stop: () => server.stop(),
|
|
193
|
+
}
|
|
186
194
|
}
|
|
187
195
|
|
|
188
196
|
const SECONDS_IN_30_DAYS = 60 * 60 * 24 * 30
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
|
|
2
2
|
import { createLogger } from "@jsenv/logger"
|
|
3
3
|
|
|
4
|
+
import { initProcessAutorestart } from "@jsenv/utils/file_watcher/process_auto_restart.js"
|
|
4
5
|
import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
|
|
5
6
|
import { getCorePlugins } from "@jsenv/core/src/plugins/plugins.js"
|
|
6
7
|
import { createUrlGraph } from "@jsenv/core/src/omega/url_graph.js"
|
|
@@ -12,9 +13,10 @@ import { jsenvPluginToolbar } from "./plugins/toolbar/jsenv_plugin_toolbar.js"
|
|
|
12
13
|
|
|
13
14
|
export const startDevServer = async ({
|
|
14
15
|
signal = new AbortController().signal,
|
|
16
|
+
handleSIGINT,
|
|
15
17
|
logLevel,
|
|
16
|
-
port,
|
|
17
|
-
protocol,
|
|
18
|
+
port = 3456,
|
|
19
|
+
protocol = "http",
|
|
18
20
|
listenAnyIp,
|
|
19
21
|
// it's better to use http1 by default because it allows to get statusText in devtools
|
|
20
22
|
// which gives valuable information when there is errors
|
|
@@ -41,11 +43,39 @@ export const startDevServer = async ({
|
|
|
41
43
|
},
|
|
42
44
|
},
|
|
43
45
|
toolbar = false,
|
|
46
|
+
autorestart,
|
|
44
47
|
}) => {
|
|
48
|
+
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
49
|
+
const autorestartProcess = await initProcessAutorestart({
|
|
50
|
+
signal,
|
|
51
|
+
handleSIGINT,
|
|
52
|
+
...(autorestart
|
|
53
|
+
? {
|
|
54
|
+
enabled: true,
|
|
55
|
+
logLevel: autorestart.logLevel,
|
|
56
|
+
urlToRestart: autorestart.url,
|
|
57
|
+
urlsToWatch: [
|
|
58
|
+
...(autorestart.urlsToWatch || []),
|
|
59
|
+
new URL("package.json", rootDirectoryUrl),
|
|
60
|
+
new URL("jsenv.config.mjs", rootDirectoryUrl),
|
|
61
|
+
],
|
|
62
|
+
}
|
|
63
|
+
: {
|
|
64
|
+
enabled: false,
|
|
65
|
+
}),
|
|
66
|
+
})
|
|
67
|
+
if (autorestartProcess.isPrimary) {
|
|
68
|
+
return {
|
|
69
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
70
|
+
stop: () => {
|
|
71
|
+
autorestartProcess.stop()
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
45
76
|
const logger = createLogger({ logLevel })
|
|
46
77
|
const startServerTask = createTaskLog(logger, "start server")
|
|
47
78
|
|
|
48
|
-
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
49
79
|
const urlGraph = createUrlGraph()
|
|
50
80
|
const kitchen = createKitchen({
|
|
51
81
|
signal,
|
|
@@ -98,5 +128,8 @@ export const startDevServer = async ({
|
|
|
98
128
|
kitchen.pluginController.callHooks("destroy")
|
|
99
129
|
}
|
|
100
130
|
})
|
|
101
|
-
return
|
|
131
|
+
return {
|
|
132
|
+
origin: server.origin,
|
|
133
|
+
stop: server.stop,
|
|
134
|
+
}
|
|
102
135
|
}
|
package/src/omega/kitchen.js
CHANGED
|
@@ -670,9 +670,11 @@ const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
|
670
670
|
}
|
|
671
671
|
urlInfo.contentType = reference.contentType
|
|
672
672
|
urlInfo.originalContent =
|
|
673
|
-
|
|
674
|
-
?
|
|
675
|
-
|
|
673
|
+
context === "build"
|
|
674
|
+
? urlInfo.originalContent === undefined
|
|
675
|
+
? reference.content
|
|
676
|
+
: urlInfo.originalContent
|
|
677
|
+
: reference.content
|
|
676
678
|
urlInfo.content = reference.content
|
|
677
679
|
}
|
|
678
680
|
if (isWebWorkerEntryPointReference(reference)) {
|