@jsenv/core 27.4.0 → 27.5.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/autoreload.js +359 -0
- package/dist/js/execute_using_dynamic_import.js +1 -1
- package/dist/js/html_supervisor_installer.js +221 -73
- package/dist/js/html_supervisor_setup.js +3 -4
- package/dist/js/new_stylesheet.js +26 -58
- package/dist/js/server_events_client.js +307 -0
- package/dist/main.js +7483 -7281
- package/package.json +11 -10
- package/{README.md → readme.md} +8 -9
- package/src/build/build.js +12 -16
- package/src/build/start_build_server.js +24 -28
- package/src/dev/start_dev_server.js +30 -94
- package/src/execute/execute.js +17 -35
- package/src/omega/errors.js +20 -18
- package/src/omega/kitchen.js +7 -6
- package/src/omega/omega_server.js +96 -127
- package/src/omega/server/file_service.js +247 -46
- package/src/omega/url_graph.js +33 -20
- package/src/plugins/autoreload/client/autoreload.js +201 -0
- package/src/plugins/autoreload/{dev_sse/client → client}/autoreload_preference.js +0 -0
- package/src/plugins/autoreload/{dev_sse/client → client}/reload.js +29 -10
- package/src/plugins/autoreload/{dev_sse/client → client}/url_helpers.js +0 -0
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +4 -4
- package/src/plugins/autoreload/{dev_sse/jsenv_plugin_dev_sse_client.js → jsenv_plugin_autoreload_client.js} +8 -8
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +196 -0
- package/src/{dev/plugins → plugins}/explorer/client/explorer.html +0 -0
- package/src/{dev/plugins → plugins}/explorer/client/jsenv.png +0 -0
- package/src/{dev/plugins → plugins}/explorer/jsenv_plugin_explorer.js +1 -3
- package/src/plugins/html_supervisor/client/{error_in_document.js → error_overlay.js} +73 -17
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +127 -54
- package/src/plugins/html_supervisor/client/html_supervisor_setup.js +3 -4
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +19 -12
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +97 -117
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +66 -58
- package/src/plugins/plugin_controller.js +102 -67
- package/src/plugins/plugins.js +10 -8
- package/src/{helpers/event_source/event_source.js → plugins/server_events/client/event_source_connection.js} +102 -31
- package/src/plugins/server_events/client/server_events_client.js +17 -0
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +48 -0
- package/src/plugins/server_events/server_events_dispatcher.js +69 -0
- package/src/{dev/plugins → plugins}/toolbar/client/animation/toolbar_animation.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/eventsource/eventsource.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/eventsource/toolbar_eventsource.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/execution/execution.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/execution/toolbar_execution.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/focus/focus.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/focus/toolbar_focus.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/jsenv_logo.svg +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/notification/toolbar_notification.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/responsive/overflow_menu.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/responsive/toolbar_responsive.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/settings/settings.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/settings/toolbar_settings.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/theme/jsenv_theme.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/theme/light_theme.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/theme/toolbar_theme.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar.html +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar_injector.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar_main.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/toolbar_main.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/tooltip/tooltip.css +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/tooltip/tooltip.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/animation.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/dom.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/fetch_using_xhr.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/fetching.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/iframe_to_parent_href.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/jsenv_logger.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/preferences.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/responsive.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/util/util.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/client/variant/variant.js +0 -0
- package/src/{dev/plugins → plugins}/toolbar/jsenv_plugin_toolbar.js +0 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +4 -3
- package/src/plugins/transpilation/babel/new_stylesheet/client/new_stylesheet.js +25 -55
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +44 -24
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +6 -1
- package/src/plugins/url_analysis/html/html_urls.js +8 -8
- package/src/test/execute_plan.js +36 -54
- package/src/test/execute_test_plan.js +2 -2
- package/dist/js/event_source_client.js +0 -549
- package/src/helpers/event_source/sse_service.js +0 -53
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +0 -193
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +0 -192
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
jsenvAccessControlAllowedHeaders,
|
|
3
3
|
startServer,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
pluginRequestWaitingCheck,
|
|
7
|
-
pluginCORS,
|
|
4
|
+
jsenvServiceCORS,
|
|
5
|
+
jsenvServiceErrorHandler,
|
|
8
6
|
} from "@jsenv/server"
|
|
9
7
|
import { convertFileSystemErrorToResponseProperties } from "@jsenv/server/src/internal/convertFileSystemErrorToResponseProperties.js"
|
|
10
|
-
import {
|
|
11
|
-
createCallbackListNotifiedOnce,
|
|
12
|
-
createCallbackList,
|
|
13
|
-
} from "@jsenv/abort"
|
|
14
8
|
|
|
15
|
-
import { createSSEService } from "@jsenv/core/src/helpers/event_source/sse_service.js"
|
|
16
9
|
import { createFileService } from "./server/file_service.js"
|
|
17
10
|
|
|
18
11
|
export const startOmegaServer = async ({
|
|
@@ -23,76 +16,31 @@ export const startOmegaServer = async ({
|
|
|
23
16
|
http2 = protocol === "https",
|
|
24
17
|
privateKey,
|
|
25
18
|
certificate,
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
acceptAnyIp,
|
|
20
|
+
host,
|
|
28
21
|
port = 0,
|
|
29
22
|
keepProcessAlive = false,
|
|
30
23
|
onStop = () => {},
|
|
31
|
-
|
|
32
|
-
services,
|
|
24
|
+
services = [],
|
|
33
25
|
|
|
34
26
|
rootDirectoryUrl,
|
|
35
27
|
scenario,
|
|
36
|
-
|
|
37
|
-
kitchen,
|
|
38
|
-
}) => {
|
|
39
|
-
const serverStopCallbackList = createCallbackListNotifiedOnce()
|
|
28
|
+
runtimeCompat,
|
|
40
29
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
rootDirectoryUrl,
|
|
56
|
-
urlGraph,
|
|
57
|
-
scenario,
|
|
58
|
-
},
|
|
59
|
-
() => {},
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
const sendServerErrorEvent = (event) => {
|
|
63
|
-
// setTimeout display first the error
|
|
64
|
-
// dispatched on window by browser
|
|
65
|
-
// then display the jsenv error
|
|
66
|
-
setTimeout(() => {
|
|
67
|
-
sendServerEvent(event)
|
|
68
|
-
}, 10)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const coreServices = {
|
|
72
|
-
"service:server_events": (request) => {
|
|
73
|
-
const { accept } = request.headers
|
|
74
|
-
if (accept && accept.includes("text/event-stream")) {
|
|
75
|
-
const room = sseService.getOrCreateSSERoom(request)
|
|
76
|
-
return room.join(request)
|
|
77
|
-
}
|
|
78
|
-
return null
|
|
79
|
-
},
|
|
80
|
-
"service:file": createFileService({
|
|
81
|
-
rootDirectoryUrl,
|
|
82
|
-
urlGraph,
|
|
83
|
-
kitchen,
|
|
84
|
-
scenario,
|
|
85
|
-
onFileNotFound: (data) => {
|
|
86
|
-
sendServerErrorEvent({ type: "file_not_found", data })
|
|
87
|
-
},
|
|
88
|
-
onParseError: (data) => {
|
|
89
|
-
sendServerErrorEvent({ type: "parse_error", data })
|
|
90
|
-
},
|
|
91
|
-
onUnexpectedError: (data) => {
|
|
92
|
-
sendServerErrorEvent({ type: "unexpected_error", data })
|
|
93
|
-
},
|
|
94
|
-
}),
|
|
95
|
-
}
|
|
30
|
+
plugins,
|
|
31
|
+
urlAnalysis,
|
|
32
|
+
htmlSupervisor,
|
|
33
|
+
nodeEsmResolution,
|
|
34
|
+
fileSystemMagicResolution,
|
|
35
|
+
transpilation,
|
|
36
|
+
clientAutoreload,
|
|
37
|
+
clientFiles,
|
|
38
|
+
cooldownBetweenFileEvents,
|
|
39
|
+
explorer,
|
|
40
|
+
sourcemaps,
|
|
41
|
+
writeGeneratedFiles,
|
|
42
|
+
}) => {
|
|
43
|
+
const serverStopCallbacks = []
|
|
96
44
|
const server = await startServer({
|
|
97
45
|
signal,
|
|
98
46
|
stopOnExit: false,
|
|
@@ -106,12 +54,12 @@ export const startOmegaServer = async ({
|
|
|
106
54
|
http2,
|
|
107
55
|
certificate,
|
|
108
56
|
privateKey,
|
|
109
|
-
|
|
110
|
-
|
|
57
|
+
acceptAnyIp,
|
|
58
|
+
host,
|
|
111
59
|
port,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
60
|
+
requestWaitingMs: 60_1000,
|
|
61
|
+
services: [
|
|
62
|
+
jsenvServiceCORS({
|
|
115
63
|
accessControlAllowRequestOrigin: true,
|
|
116
64
|
accessControlAllowRequestMethod: true,
|
|
117
65
|
accessControlAllowRequestHeaders: true,
|
|
@@ -120,62 +68,83 @@ export const startOmegaServer = async ({
|
|
|
120
68
|
"x-jsenv-execution-id",
|
|
121
69
|
],
|
|
122
70
|
accessControlAllowCredentials: true,
|
|
71
|
+
timingAllowOrigin: true,
|
|
123
72
|
}),
|
|
124
|
-
...
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
73
|
+
...services,
|
|
74
|
+
{
|
|
75
|
+
name: "jsenv:omega_file_service",
|
|
76
|
+
handleRequest: createFileService({
|
|
77
|
+
signal,
|
|
78
|
+
logLevel,
|
|
79
|
+
serverStopCallbacks,
|
|
80
|
+
|
|
81
|
+
rootDirectoryUrl,
|
|
82
|
+
scenario,
|
|
83
|
+
runtimeCompat,
|
|
84
|
+
|
|
85
|
+
plugins,
|
|
86
|
+
urlAnalysis,
|
|
87
|
+
htmlSupervisor,
|
|
88
|
+
nodeEsmResolution,
|
|
89
|
+
fileSystemMagicResolution,
|
|
90
|
+
transpilation,
|
|
91
|
+
clientAutoreload,
|
|
92
|
+
clientFiles,
|
|
93
|
+
cooldownBetweenFileEvents,
|
|
94
|
+
explorer,
|
|
95
|
+
sourcemaps,
|
|
96
|
+
writeGeneratedFiles,
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "jsenv:omega_error_handler",
|
|
101
|
+
handleError: (error) => {
|
|
102
|
+
const getResponseForError = () => {
|
|
103
|
+
if (error && error.asResponse) {
|
|
104
|
+
return error.asResponse()
|
|
105
|
+
}
|
|
106
|
+
if (
|
|
107
|
+
error &&
|
|
108
|
+
error.statusText === "Unexpected directory operation"
|
|
109
|
+
) {
|
|
110
|
+
return {
|
|
111
|
+
status: 403,
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return convertFileSystemErrorToResponseProperties(error)
|
|
115
|
+
}
|
|
116
|
+
const response = getResponseForError()
|
|
117
|
+
if (!response) {
|
|
118
|
+
return null
|
|
119
|
+
}
|
|
120
|
+
const body = JSON.stringify({
|
|
121
|
+
status: response.status,
|
|
122
|
+
statusText: response.statusText,
|
|
123
|
+
headers: response.headers,
|
|
124
|
+
body: response.body,
|
|
125
|
+
})
|
|
136
126
|
return {
|
|
137
|
-
status:
|
|
127
|
+
status: 200,
|
|
128
|
+
headers: {
|
|
129
|
+
"content-type": "application/json",
|
|
130
|
+
"content-length": Buffer.byteLength(body),
|
|
131
|
+
},
|
|
132
|
+
body,
|
|
138
133
|
}
|
|
139
|
-
}
|
|
140
|
-
return convertFileSystemErrorToResponseProperties(error)
|
|
141
|
-
}
|
|
142
|
-
const response = getResponseForError()
|
|
143
|
-
if (!response) {
|
|
144
|
-
return null
|
|
145
|
-
}
|
|
146
|
-
const isInspectRequest = new URL(
|
|
147
|
-
request.ressource,
|
|
148
|
-
request.origin,
|
|
149
|
-
).searchParams.has("__inspect__")
|
|
150
|
-
if (!isInspectRequest) {
|
|
151
|
-
return response
|
|
152
|
-
}
|
|
153
|
-
const body = JSON.stringify({
|
|
154
|
-
status: response.status,
|
|
155
|
-
statusText: response.statusText,
|
|
156
|
-
headers: response.headers,
|
|
157
|
-
body: response.body,
|
|
158
|
-
})
|
|
159
|
-
return {
|
|
160
|
-
status: 200,
|
|
161
|
-
headers: {
|
|
162
|
-
"content-type": "application/json",
|
|
163
|
-
"content-length": Buffer.byteLength(body),
|
|
164
134
|
},
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}),
|
|
135
|
+
},
|
|
136
|
+
// default error handling
|
|
137
|
+
jsenvServiceErrorHandler({
|
|
138
|
+
sendErrorDetails: true,
|
|
139
|
+
}),
|
|
140
|
+
],
|
|
172
141
|
onStop: (reason) => {
|
|
173
142
|
onStop()
|
|
174
|
-
|
|
175
|
-
|
|
143
|
+
serverStopCallbacks.forEach((serverStopCallback) => {
|
|
144
|
+
serverStopCallback(reason)
|
|
145
|
+
})
|
|
146
|
+
serverStopCallbacks.length = 0
|
|
176
147
|
},
|
|
177
148
|
})
|
|
178
|
-
return
|
|
179
|
-
...server,
|
|
180
|
-
}
|
|
149
|
+
return server
|
|
181
150
|
}
|
|
@@ -3,46 +3,242 @@ import {
|
|
|
3
3
|
serveDirectory,
|
|
4
4
|
composeTwoResponses,
|
|
5
5
|
} from "@jsenv/server"
|
|
6
|
+
import { registerDirectoryLifecycle } from "@jsenv/filesystem"
|
|
6
7
|
import { urlIsInsideOf, moveUrl } from "@jsenv/urls"
|
|
8
|
+
import { URL_META } from "@jsenv/url-meta"
|
|
7
9
|
|
|
10
|
+
import { getCorePlugins } from "@jsenv/core/src/plugins/plugins.js"
|
|
11
|
+
import { createUrlGraph } from "@jsenv/core/src/omega/url_graph.js"
|
|
12
|
+
import { createKitchen } from "@jsenv/core/src/omega/kitchen.js"
|
|
13
|
+
import { createServerEventsDispatcher } from "@jsenv/core/src/plugins/server_events/server_events_dispatcher.js"
|
|
14
|
+
import { jsenvPluginServerEventsClientInjection } from "@jsenv/core/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js"
|
|
8
15
|
import { parseUserAgentHeader } from "./user_agent.js"
|
|
9
16
|
|
|
10
17
|
export const createFileService = ({
|
|
18
|
+
signal,
|
|
19
|
+
logLevel,
|
|
20
|
+
serverStopCallbacks,
|
|
21
|
+
|
|
11
22
|
rootDirectoryUrl,
|
|
12
|
-
urlGraph,
|
|
13
|
-
kitchen,
|
|
14
23
|
scenario,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
runtimeCompat,
|
|
25
|
+
|
|
26
|
+
plugins,
|
|
27
|
+
urlAnalysis,
|
|
28
|
+
htmlSupervisor,
|
|
29
|
+
nodeEsmResolution,
|
|
30
|
+
fileSystemMagicResolution,
|
|
31
|
+
transpilation,
|
|
32
|
+
clientAutoreload,
|
|
33
|
+
clientFiles,
|
|
34
|
+
cooldownBetweenFileEvents,
|
|
35
|
+
explorer,
|
|
36
|
+
sourcemaps,
|
|
37
|
+
writeGeneratedFiles,
|
|
18
38
|
}) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
39
|
+
const jsenvDirectoryUrl = new URL(".jsenv/", rootDirectoryUrl).href
|
|
40
|
+
const onErrorWhileServingFileCallbacks = []
|
|
41
|
+
const onErrorWhileServingFile = (data) => {
|
|
42
|
+
onErrorWhileServingFileCallbacks.forEach(
|
|
43
|
+
(onErrorWhileServingFileCallback) => {
|
|
44
|
+
onErrorWhileServingFileCallback(data)
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const clientFileChangeCallbackList = []
|
|
50
|
+
const clientFilesPruneCallbackList = []
|
|
51
|
+
const clientFileChangeCallback = ({ relativeUrl, event }) => {
|
|
52
|
+
const url = new URL(relativeUrl, rootDirectoryUrl).href
|
|
53
|
+
clientFileChangeCallbackList.forEach((callback) => {
|
|
54
|
+
callback({ url, event })
|
|
55
|
+
})
|
|
25
56
|
}
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
57
|
+
const clientFilePatterns = {
|
|
58
|
+
...clientFiles,
|
|
59
|
+
".jsenv/": false,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (scenario === "dev") {
|
|
63
|
+
const stopWatchingClientFiles = registerDirectoryLifecycle(
|
|
64
|
+
rootDirectoryUrl,
|
|
65
|
+
{
|
|
66
|
+
watchPatterns: clientFilePatterns,
|
|
67
|
+
cooldownBetweenFileEvents,
|
|
68
|
+
keepProcessAlive: false,
|
|
69
|
+
recursive: true,
|
|
70
|
+
added: ({ relativeUrl }) => {
|
|
71
|
+
clientFileChangeCallback({ event: "added", relativeUrl })
|
|
72
|
+
},
|
|
73
|
+
updated: ({ relativeUrl }) => {
|
|
74
|
+
clientFileChangeCallback({ event: "modified", relativeUrl })
|
|
75
|
+
},
|
|
76
|
+
removed: ({ relativeUrl }) => {
|
|
77
|
+
clientFileChangeCallback({ event: "removed", relativeUrl })
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
serverStopCallbacks.push(stopWatchingClientFiles)
|
|
30
82
|
}
|
|
31
83
|
|
|
32
|
-
const
|
|
84
|
+
const contextCache = new Map()
|
|
85
|
+
const getOrCreateContext = (request) => {
|
|
86
|
+
const { runtimeName, runtimeVersion } = parseUserAgentHeader(
|
|
87
|
+
request.headers["user-agent"],
|
|
88
|
+
)
|
|
89
|
+
const runtimeId = `${runtimeName}@${runtimeVersion}`
|
|
90
|
+
const existingContext = contextCache.get(runtimeId)
|
|
91
|
+
if (existingContext) {
|
|
92
|
+
return existingContext
|
|
93
|
+
}
|
|
94
|
+
const watchAssociations = URL_META.resolveAssociations(
|
|
95
|
+
{ watch: clientFilePatterns },
|
|
96
|
+
rootDirectoryUrl,
|
|
97
|
+
)
|
|
98
|
+
const urlGraph = createUrlGraph({
|
|
99
|
+
clientFileChangeCallbackList,
|
|
100
|
+
clientFilesPruneCallbackList,
|
|
101
|
+
onCreateUrlInfo: (urlInfo) => {
|
|
102
|
+
const { watch } = URL_META.applyAssociations({
|
|
103
|
+
url: urlInfo.url,
|
|
104
|
+
associations: watchAssociations,
|
|
105
|
+
})
|
|
106
|
+
urlInfo.isValid = () => watch
|
|
107
|
+
},
|
|
108
|
+
includeOriginalUrls: scenario === "dev",
|
|
109
|
+
})
|
|
110
|
+
const kitchen = createKitchen({
|
|
111
|
+
signal,
|
|
112
|
+
logLevel,
|
|
113
|
+
rootDirectoryUrl,
|
|
114
|
+
scenario,
|
|
115
|
+
runtimeCompat,
|
|
116
|
+
urlGraph,
|
|
117
|
+
plugins: [
|
|
118
|
+
...plugins,
|
|
119
|
+
...getCorePlugins({
|
|
120
|
+
rootDirectoryUrl,
|
|
121
|
+
scenario,
|
|
122
|
+
runtimeCompat,
|
|
123
|
+
|
|
124
|
+
urlAnalysis,
|
|
125
|
+
htmlSupervisor,
|
|
126
|
+
nodeEsmResolution,
|
|
127
|
+
fileSystemMagicResolution,
|
|
128
|
+
transpilation,
|
|
129
|
+
|
|
130
|
+
clientAutoreload,
|
|
131
|
+
clientFileChangeCallbackList,
|
|
132
|
+
clientFilesPruneCallbackList,
|
|
133
|
+
explorer,
|
|
134
|
+
}),
|
|
135
|
+
],
|
|
136
|
+
sourcemaps,
|
|
137
|
+
writeGeneratedFiles,
|
|
138
|
+
})
|
|
139
|
+
serverStopCallbacks.push(() => {
|
|
140
|
+
kitchen.pluginController.callHooks("destroy", kitchen.kitchenContext)
|
|
141
|
+
})
|
|
142
|
+
server_events: {
|
|
143
|
+
const allServerEvents = {}
|
|
144
|
+
kitchen.pluginController.plugins.forEach((plugin) => {
|
|
145
|
+
const { serverEvents } = plugin
|
|
146
|
+
if (serverEvents) {
|
|
147
|
+
Object.keys(serverEvents).forEach((serverEventName) => {
|
|
148
|
+
// we could throw on serverEvent name conflict
|
|
149
|
+
// we could throw if serverEvents[serverEventName] is not a function
|
|
150
|
+
allServerEvents[serverEventName] = serverEvents[serverEventName]
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
const serverEventNames = Object.keys(allServerEvents)
|
|
155
|
+
if (serverEventNames.length > 0) {
|
|
156
|
+
const serverEventsDispatcher = createServerEventsDispatcher()
|
|
157
|
+
serverStopCallbacks.push(() => {
|
|
158
|
+
serverEventsDispatcher.destroy()
|
|
159
|
+
})
|
|
160
|
+
Object.keys(allServerEvents).forEach((serverEventName) => {
|
|
161
|
+
allServerEvents[serverEventName]({
|
|
162
|
+
rootDirectoryUrl,
|
|
163
|
+
urlGraph,
|
|
164
|
+
scenario,
|
|
165
|
+
sendServerEvent: (data) => {
|
|
166
|
+
serverEventsDispatcher.dispatch({
|
|
167
|
+
type: serverEventName,
|
|
168
|
+
data,
|
|
169
|
+
})
|
|
170
|
+
},
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
onErrorWhileServingFileCallbacks.push((data) => {
|
|
174
|
+
serverEventsDispatcher.dispatchToRoomsMatching(
|
|
175
|
+
{
|
|
176
|
+
type: "error_while_serving_file",
|
|
177
|
+
data,
|
|
178
|
+
},
|
|
179
|
+
(room) => {
|
|
180
|
+
// send only to page depending on this file
|
|
181
|
+
const errorFileUrl = data.url
|
|
182
|
+
const roomEntryPointUrl = new URL(
|
|
183
|
+
room.request.ressource.slice(1),
|
|
184
|
+
rootDirectoryUrl,
|
|
185
|
+
).href
|
|
186
|
+
const isErrorRelatedToEntryPoint = Boolean(
|
|
187
|
+
urlGraph.findDependent(errorFileUrl, (dependentUrlInfo) => {
|
|
188
|
+
return dependentUrlInfo.url === roomEntryPointUrl
|
|
189
|
+
}),
|
|
190
|
+
)
|
|
191
|
+
return isErrorRelatedToEntryPoint
|
|
192
|
+
},
|
|
193
|
+
)
|
|
194
|
+
})
|
|
195
|
+
// "unshift" because serve must come first to catch event source client request
|
|
196
|
+
kitchen.pluginController.unshiftPlugin({
|
|
197
|
+
name: "jsenv:provide_server_events",
|
|
198
|
+
serve: (request) => {
|
|
199
|
+
const { accept } = request.headers
|
|
200
|
+
if (accept && accept.includes("text/event-stream")) {
|
|
201
|
+
const room = serverEventsDispatcher.addRoom(request)
|
|
202
|
+
return room.join(request)
|
|
203
|
+
}
|
|
204
|
+
return null
|
|
205
|
+
},
|
|
206
|
+
})
|
|
207
|
+
// "push" so that event source client connection can be put as early as possible in html
|
|
208
|
+
kitchen.pluginController.pushPlugin(
|
|
209
|
+
jsenvPluginServerEventsClientInjection(),
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const context = {
|
|
215
|
+
rootDirectoryUrl,
|
|
216
|
+
scenario,
|
|
217
|
+
runtimeName,
|
|
218
|
+
runtimeVersion,
|
|
219
|
+
urlGraph,
|
|
220
|
+
kitchen,
|
|
221
|
+
}
|
|
222
|
+
contextCache.set(runtimeId, context)
|
|
223
|
+
return context
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return async (request) => {
|
|
33
227
|
// serve file inside ".jsenv" directory
|
|
34
228
|
const requestFileUrl = new URL(request.ressource.slice(1), rootDirectoryUrl)
|
|
35
229
|
.href
|
|
36
|
-
if (urlIsInsideOf(requestFileUrl,
|
|
230
|
+
if (urlIsInsideOf(requestFileUrl, jsenvDirectoryUrl)) {
|
|
37
231
|
return fetchFileSystem(requestFileUrl, {
|
|
38
232
|
headers: request.headers,
|
|
39
233
|
})
|
|
40
234
|
}
|
|
235
|
+
const { runtimeName, runtimeVersion, urlGraph, kitchen } =
|
|
236
|
+
getOrCreateContext(request)
|
|
41
237
|
const responseFromPlugin =
|
|
42
238
|
await kitchen.pluginController.callAsyncHooksUntil(
|
|
43
239
|
"serve",
|
|
44
240
|
request,
|
|
45
|
-
|
|
241
|
+
kitchen.kitchenContext,
|
|
46
242
|
)
|
|
47
243
|
if (responseFromPlugin) {
|
|
48
244
|
return responseFromPlugin
|
|
@@ -67,8 +263,12 @@ export const createFileService = ({
|
|
|
67
263
|
if (
|
|
68
264
|
ifNoneMatch &&
|
|
69
265
|
urlInfo.contentEtag === ifNoneMatch &&
|
|
70
|
-
//
|
|
71
|
-
// -
|
|
266
|
+
// urlInfo.isValid
|
|
267
|
+
// - is false by default because there must be some logic capable
|
|
268
|
+
// to invalidate the url (otherwise server would return 304 forever)
|
|
269
|
+
// - is set to a function returning true if the file is watched
|
|
270
|
+
// in start_dev_server.js
|
|
271
|
+
// - is set to a custom function by cjs_to_esm in compiled_file_cache.js
|
|
72
272
|
urlInfo.isValid()
|
|
73
273
|
) {
|
|
74
274
|
return {
|
|
@@ -95,9 +295,6 @@ export const createFileService = ({
|
|
|
95
295
|
urlInfo.dependsOnPackageJson = false
|
|
96
296
|
urlInfo.timing = {}
|
|
97
297
|
}
|
|
98
|
-
const { runtimeName, runtimeVersion } = parseUserAgentHeader(
|
|
99
|
-
request.headers["user-agent"],
|
|
100
|
-
)
|
|
101
298
|
await kitchen.cook(urlInfo, {
|
|
102
299
|
request,
|
|
103
300
|
reference,
|
|
@@ -129,7 +326,7 @@ export const createFileService = ({
|
|
|
129
326
|
kitchen.pluginController.callHooks(
|
|
130
327
|
"augmentResponse",
|
|
131
328
|
{ reference, urlInfo },
|
|
132
|
-
|
|
329
|
+
kitchen.kitchenContext,
|
|
133
330
|
(returnValue) => {
|
|
134
331
|
response = composeTwoResponses(response, returnValue)
|
|
135
332
|
},
|
|
@@ -138,13 +335,15 @@ export const createFileService = ({
|
|
|
138
335
|
} catch (e) {
|
|
139
336
|
const code = e.code
|
|
140
337
|
if (code === "PARSE_ERROR") {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
338
|
+
onErrorWhileServingFile({
|
|
339
|
+
requestedRessource: request.ressource,
|
|
340
|
+
code: "PARSE_ERROR",
|
|
341
|
+
message: e.reason,
|
|
144
342
|
url: e.url,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
343
|
+
traceUrl: e.traceUrl,
|
|
344
|
+
traceLine: e.traceLine,
|
|
345
|
+
traceColumn: e.traceColumn,
|
|
346
|
+
traceMessage: e.traceMessage,
|
|
148
347
|
})
|
|
149
348
|
return {
|
|
150
349
|
url: reference.url,
|
|
@@ -176,13 +375,18 @@ export const createFileService = ({
|
|
|
176
375
|
}
|
|
177
376
|
}
|
|
178
377
|
if (code === "NOT_FOUND") {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
378
|
+
onErrorWhileServingFile({
|
|
379
|
+
requestedRessource: request.ressource,
|
|
380
|
+
isFaviconAutoRequest:
|
|
381
|
+
request.ressource === "/favicon.ico" &&
|
|
382
|
+
reference.type === "http_request",
|
|
383
|
+
code: "NOT_FOUND",
|
|
384
|
+
message: e.reason,
|
|
182
385
|
url: e.url,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
386
|
+
traceUrl: e.traceUrl,
|
|
387
|
+
traceLine: e.traceLine,
|
|
388
|
+
traceColumn: e.traceColumn,
|
|
389
|
+
traceMessage: e.traceMessage,
|
|
186
390
|
})
|
|
187
391
|
return {
|
|
188
392
|
url: reference.url,
|
|
@@ -191,14 +395,15 @@ export const createFileService = ({
|
|
|
191
395
|
statusMessage: e.message,
|
|
192
396
|
}
|
|
193
397
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
398
|
+
onErrorWhileServingFile({
|
|
399
|
+
requestedRessource: request.ressource,
|
|
400
|
+
code: "UNEXPECTED",
|
|
197
401
|
stack: e.stack,
|
|
198
402
|
url: e.url,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
403
|
+
traceUrl: e.traceUrl,
|
|
404
|
+
traceLine: e.traceLine,
|
|
405
|
+
traceColumn: e.traceColumn,
|
|
406
|
+
traceMessage: e.traceMessage,
|
|
202
407
|
})
|
|
203
408
|
return {
|
|
204
409
|
url: reference.url,
|
|
@@ -208,10 +413,6 @@ export const createFileService = ({
|
|
|
208
413
|
}
|
|
209
414
|
}
|
|
210
415
|
}
|
|
211
|
-
return async (request) => {
|
|
212
|
-
let response = await getResponse(request)
|
|
213
|
-
return response
|
|
214
|
-
}
|
|
215
416
|
}
|
|
216
417
|
|
|
217
418
|
const inferParentFromRequest = (request, rootDirectoryUrl) => {
|