@jsenv/core 27.3.4 → 27.4.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/README.md +16 -4
- package/dist/js/event_source_client.js +45 -24
- package/dist/js/html_supervisor_installer.js +368 -139
- package/dist/main.js +515 -334
- package/package.json +5 -6
- package/src/build/build.js +4 -2
- package/src/helpers/event_source/event_source.js +38 -17
- package/src/omega/errors.js +41 -9
- package/src/omega/kitchen.js +35 -19
- package/src/omega/omega_server.js +54 -1
- package/src/omega/server/file_service.js +30 -3
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +8 -8
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +160 -171
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +0 -4
- package/src/plugins/html_supervisor/client/error_in_document.js +268 -121
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +47 -5
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +37 -12
- package/src/plugins/plugins.js +0 -2
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +3 -1
- package/src/test/logs_file_execution.js +60 -27
- package/src/test/logs_file_execution.test.mjs +41 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.4.0",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
"eslint": "npx eslint . --ext=.js,.mjs,.cjs,.html",
|
|
44
44
|
"dev": "node --conditions=development ./scripts/dev/dev.mjs",
|
|
45
45
|
"test": "node --conditions=development ./scripts/test/test.mjs",
|
|
46
|
-
"test:coverage": "cross-env NODE_V8_COVERAGE=.coverage/node npm run test -- --coverage",
|
|
47
46
|
"test:workspace": "npm run test --workspaces --if-present -- --workspace",
|
|
48
47
|
"build": "node --conditions=development ./scripts/build/build.mjs",
|
|
49
48
|
"workspace:versions": "node ./scripts/publish/workspace_versions.mjs",
|
|
@@ -68,16 +67,16 @@
|
|
|
68
67
|
"@jsenv/abort": "4.2.3",
|
|
69
68
|
"@jsenv/ast": "1.1.2",
|
|
70
69
|
"@jsenv/babel-plugins": "1.0.6",
|
|
71
|
-
"@jsenv/filesystem": "4.1.
|
|
70
|
+
"@jsenv/filesystem": "4.1.1",
|
|
72
71
|
"@jsenv/importmap": "1.2.1",
|
|
73
72
|
"@jsenv/integrity": "0.0.1",
|
|
74
73
|
"@jsenv/log": "3.1.0",
|
|
75
74
|
"@jsenv/node-esm-resolution": "0.1.0",
|
|
76
75
|
"@jsenv/server": "12.8.0",
|
|
77
|
-
"@jsenv/sourcemap": "1.0.
|
|
76
|
+
"@jsenv/sourcemap": "1.0.2",
|
|
78
77
|
"@jsenv/uneval": "1.6.0",
|
|
79
78
|
"@jsenv/url-meta": "7.0.0",
|
|
80
|
-
"@jsenv/urls": "1.2.
|
|
79
|
+
"@jsenv/urls": "1.2.7",
|
|
81
80
|
"@jsenv/utils": "2.0.1",
|
|
82
81
|
"acorn-import-assertions": "1.8.0",
|
|
83
82
|
"cuid": "2.1.8",
|
|
@@ -86,6 +85,7 @@
|
|
|
86
85
|
"istanbul-lib-instrument": "5.2.0",
|
|
87
86
|
"istanbul-lib-report": "3.0.0",
|
|
88
87
|
"istanbul-reports": "3.1.4",
|
|
88
|
+
"launch-editor": "2.4.0",
|
|
89
89
|
"pidtree": "0.6.0",
|
|
90
90
|
"rollup": "2.76.0",
|
|
91
91
|
"string-width": "5.1.2",
|
|
@@ -103,7 +103,6 @@
|
|
|
103
103
|
"@jsenv/https-local": "2.1.0",
|
|
104
104
|
"@jsenv/package-workspace": "0.4.1",
|
|
105
105
|
"@jsenv/performance-impact": "3.0.1",
|
|
106
|
-
"cross-env": "7.0.3",
|
|
107
106
|
"eslint": "8.19.0",
|
|
108
107
|
"eslint-plugin-html": "6.2.0",
|
|
109
108
|
"eslint-plugin-import": "2.26.0",
|
package/src/build/build.js
CHANGED
|
@@ -228,7 +228,9 @@ build ${entryPointKeys.length} entry points`)
|
|
|
228
228
|
startLoading: (cookEntryFile) => {
|
|
229
229
|
Object.keys(entryPoints).forEach((key) => {
|
|
230
230
|
const [, entryUrlInfo] = cookEntryFile({
|
|
231
|
-
trace:
|
|
231
|
+
trace: {
|
|
232
|
+
message: `"${key}" in entryPoints parameter`,
|
|
233
|
+
},
|
|
232
234
|
type: "entry_point",
|
|
233
235
|
specifier: key,
|
|
234
236
|
})
|
|
@@ -722,7 +724,7 @@ build ${entryPointKeys.length} entry points`)
|
|
|
722
724
|
startLoading: (cookEntryFile) => {
|
|
723
725
|
entryUrls.forEach((entryUrl) => {
|
|
724
726
|
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
725
|
-
trace: `entryPoint
|
|
727
|
+
trace: { message: `entryPoint` },
|
|
726
728
|
type: "entry_point",
|
|
727
729
|
specifier: entryUrl,
|
|
728
730
|
})
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/* eslint-env browser */
|
|
2
2
|
|
|
3
|
+
const STATUSES = {
|
|
4
|
+
CONNECTING: "connecting",
|
|
5
|
+
CONNECTED: "connected",
|
|
6
|
+
DISCONNECTED: "disconnected",
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
export const createEventSourceConnection = (
|
|
4
10
|
eventSourceUrl,
|
|
5
|
-
events = {},
|
|
6
11
|
{ retryMaxAttempt = Infinity, retryAllocatedMs = Infinity, lastEventId } = {},
|
|
7
12
|
) => {
|
|
8
13
|
const { EventSource } = window
|
|
@@ -10,18 +15,26 @@ export const createEventSourceConnection = (
|
|
|
10
15
|
return () => {}
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
let eventSource
|
|
19
|
+
const events = {}
|
|
13
20
|
const eventSourceOrigin = new URL(eventSourceUrl).origin
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (e.
|
|
19
|
-
|
|
21
|
+
const addEventCallbacks = (eventCallbacks) => {
|
|
22
|
+
Object.keys(eventCallbacks).forEach((eventName) => {
|
|
23
|
+
const eventCallback = eventCallbacks[eventName]
|
|
24
|
+
events[eventName] = (e) => {
|
|
25
|
+
if (e.origin === eventSourceOrigin) {
|
|
26
|
+
if (e.lastEventId) {
|
|
27
|
+
lastEventId = e.lastEventId
|
|
28
|
+
}
|
|
29
|
+
eventCallback(e)
|
|
20
30
|
}
|
|
21
|
-
eventCallback(e)
|
|
22
31
|
}
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
if (eventSource) {
|
|
33
|
+
eventSource.addEventListener(eventName, events[eventName])
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
addEventCallbacks(events)
|
|
25
38
|
|
|
26
39
|
const status = {
|
|
27
40
|
value: "default",
|
|
@@ -37,11 +50,14 @@ export const createEventSourceConnection = (
|
|
|
37
50
|
let _disconnect = () => {}
|
|
38
51
|
|
|
39
52
|
const attemptConnection = (url) => {
|
|
40
|
-
|
|
53
|
+
eventSource = new EventSource(url, {
|
|
41
54
|
withCredentials: true,
|
|
42
55
|
})
|
|
43
56
|
_disconnect = () => {
|
|
44
|
-
if (
|
|
57
|
+
if (
|
|
58
|
+
status.value !== STATUSES.CONNECTING &&
|
|
59
|
+
status.value !== STATUSES.CONNECTED
|
|
60
|
+
) {
|
|
45
61
|
console.warn(
|
|
46
62
|
`disconnect() ignored because connection is ${status.value}`,
|
|
47
63
|
)
|
|
@@ -52,7 +68,8 @@ export const createEventSourceConnection = (
|
|
|
52
68
|
Object.keys(events).forEach((eventName) => {
|
|
53
69
|
eventSource.removeEventListener(eventName, events[eventName])
|
|
54
70
|
})
|
|
55
|
-
|
|
71
|
+
eventSource = null
|
|
72
|
+
status.goTo(STATUSES.DISCONNECTED)
|
|
56
73
|
}
|
|
57
74
|
let retryCount = 0
|
|
58
75
|
let firstRetryMs = Date.now()
|
|
@@ -78,7 +95,7 @@ export const createEventSourceConnection = (
|
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
retryCount++
|
|
81
|
-
status.goTo(
|
|
98
|
+
status.goTo(STATUSES.CONNECTING)
|
|
82
99
|
return
|
|
83
100
|
}
|
|
84
101
|
|
|
@@ -88,7 +105,7 @@ export const createEventSourceConnection = (
|
|
|
88
105
|
}
|
|
89
106
|
}
|
|
90
107
|
eventSource.onopen = () => {
|
|
91
|
-
status.goTo(
|
|
108
|
+
status.goTo(STATUSES.CONNECTED)
|
|
92
109
|
}
|
|
93
110
|
Object.keys(events).forEach((eventName) => {
|
|
94
111
|
eventSource.addEventListener(eventName, events[eventName])
|
|
@@ -100,7 +117,7 @@ export const createEventSourceConnection = (
|
|
|
100
117
|
}
|
|
101
118
|
})
|
|
102
119
|
}
|
|
103
|
-
status.goTo(
|
|
120
|
+
status.goTo(STATUSES.CONNECTING)
|
|
104
121
|
}
|
|
105
122
|
|
|
106
123
|
let connect = () => {
|
|
@@ -115,7 +132,10 @@ export const createEventSourceConnection = (
|
|
|
115
132
|
}
|
|
116
133
|
|
|
117
134
|
const removePageUnloadListener = listenPageUnload(() => {
|
|
118
|
-
if (
|
|
135
|
+
if (
|
|
136
|
+
status.value === STATUSES.CONNECTING ||
|
|
137
|
+
status.value === STATUSES.CONNECTED
|
|
138
|
+
) {
|
|
119
139
|
_disconnect()
|
|
120
140
|
}
|
|
121
141
|
})
|
|
@@ -128,6 +148,7 @@ export const createEventSourceConnection = (
|
|
|
128
148
|
return {
|
|
129
149
|
status,
|
|
130
150
|
connect,
|
|
151
|
+
addEventCallbacks,
|
|
131
152
|
disconnect: () => _disconnect(),
|
|
132
153
|
destroy,
|
|
133
154
|
}
|
package/src/omega/errors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createDetailedMessage } from "@jsenv/log"
|
|
2
|
+
import { stringifyUrlSite } from "@jsenv/urls"
|
|
2
3
|
|
|
3
4
|
export const createResolveUrlError = ({
|
|
4
5
|
pluginController,
|
|
@@ -15,7 +16,7 @@ export const createResolveUrlError = ({
|
|
|
15
16
|
reason,
|
|
16
17
|
...details,
|
|
17
18
|
"specifier": `"${reference.specifier}"`,
|
|
18
|
-
"specifier trace": reference.trace,
|
|
19
|
+
"specifier trace": reference.trace.message,
|
|
19
20
|
...detailsFromPluginController(pluginController),
|
|
20
21
|
}),
|
|
21
22
|
)
|
|
@@ -46,19 +47,23 @@ export const createFetchUrlContentError = ({
|
|
|
46
47
|
reason,
|
|
47
48
|
...details
|
|
48
49
|
}) => {
|
|
49
|
-
const
|
|
50
|
+
const fetchError = new Error(
|
|
50
51
|
createDetailedMessage(`Failed to fetch url content`, {
|
|
51
52
|
reason,
|
|
52
53
|
...details,
|
|
53
54
|
"url": urlInfo.url,
|
|
54
|
-
"url reference trace": reference.trace,
|
|
55
|
+
"url reference trace": reference.trace.message,
|
|
55
56
|
...detailsFromPluginController(pluginController),
|
|
56
57
|
}),
|
|
57
58
|
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
fetchError.name = "FETCH_URL_CONTENT_ERROR"
|
|
60
|
+
fetchError.code = code
|
|
61
|
+
fetchError.reason = reason
|
|
62
|
+
fetchError.url = reference.trace.url
|
|
63
|
+
fetchError.line = reference.trace.line
|
|
64
|
+
fetchError.column = reference.trace.column
|
|
65
|
+
fetchError.contentFrame = reference.trace.message
|
|
66
|
+
return fetchError
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
if (error.code === "EPERM") {
|
|
@@ -103,7 +108,7 @@ export const createTransformUrlContentError = ({
|
|
|
103
108
|
reason,
|
|
104
109
|
...details,
|
|
105
110
|
"url": urlInfo.url,
|
|
106
|
-
"url reference trace": reference.trace,
|
|
111
|
+
"url reference trace": reference.trace.message,
|
|
107
112
|
...detailsFromPluginController(pluginController),
|
|
108
113
|
},
|
|
109
114
|
),
|
|
@@ -111,6 +116,33 @@ export const createTransformUrlContentError = ({
|
|
|
111
116
|
transformError.name = "TRANSFORM_URL_CONTENT_ERROR"
|
|
112
117
|
transformError.code = code
|
|
113
118
|
transformError.reason = reason
|
|
119
|
+
transformError.url = reference.trace.url
|
|
120
|
+
transformError.line = reference.trace.line
|
|
121
|
+
transformError.column = reference.trace.column
|
|
122
|
+
transformError.stack = error.stack
|
|
123
|
+
transformError.contentFrame = reference.trace.message
|
|
124
|
+
if (code === "PARSE_ERROR") {
|
|
125
|
+
transformError.reason = error.message
|
|
126
|
+
if (urlInfo.isInline) {
|
|
127
|
+
transformError.line = reference.trace.line + error.line - 1
|
|
128
|
+
transformError.column = reference.trace.column + error.column
|
|
129
|
+
transformError.contentFrame = stringifyUrlSite({
|
|
130
|
+
url: urlInfo.inlineUrlSite.url,
|
|
131
|
+
line: transformError.line,
|
|
132
|
+
column: transformError.column,
|
|
133
|
+
content: urlInfo.inlineUrlSite.content,
|
|
134
|
+
})
|
|
135
|
+
} else {
|
|
136
|
+
transformError.line = error.line
|
|
137
|
+
transformError.column = error.column
|
|
138
|
+
transformError.contentFrame = stringifyUrlSite({
|
|
139
|
+
url: urlInfo.url,
|
|
140
|
+
line: transformError.line,
|
|
141
|
+
column: transformError.column,
|
|
142
|
+
content: urlInfo.content,
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
}
|
|
114
146
|
return transformError
|
|
115
147
|
}
|
|
116
148
|
return createFailedToTransformError({
|
|
@@ -130,7 +162,7 @@ export const createFinalizeUrlContentError = ({
|
|
|
130
162
|
"reason": `An error occured during "finalizeUrlContent"`,
|
|
131
163
|
...detailsFromValueThrown(error),
|
|
132
164
|
"url": urlInfo.url,
|
|
133
|
-
"url reference trace": reference.trace,
|
|
165
|
+
"url reference trace": reference.trace.message,
|
|
134
166
|
...detailsFromPluginController(pluginController),
|
|
135
167
|
}),
|
|
136
168
|
)
|
package/src/omega/kitchen.js
CHANGED
|
@@ -221,7 +221,10 @@ export const createKitchen = ({
|
|
|
221
221
|
sourcemapsRelativeSources,
|
|
222
222
|
injectSourcemapPlaceholder: ({ urlInfo, specifier }) => {
|
|
223
223
|
const sourcemapReference = createReference({
|
|
224
|
-
trace:
|
|
224
|
+
trace: {
|
|
225
|
+
message: `sourcemap comment placeholder`,
|
|
226
|
+
url: urlInfo.url,
|
|
227
|
+
},
|
|
225
228
|
type: "sourcemap_comment",
|
|
226
229
|
subtype: urlInfo.contentType === "text/javascript" ? "js" : "css",
|
|
227
230
|
parentUrl: urlInfo.url,
|
|
@@ -238,15 +241,14 @@ export const createKitchen = ({
|
|
|
238
241
|
specifierLine,
|
|
239
242
|
specifierColumn,
|
|
240
243
|
}) => {
|
|
244
|
+
const sourcemapUrlSite = adjustUrlSite(urlInfo, {
|
|
245
|
+
urlGraph,
|
|
246
|
+
url: urlInfo.url,
|
|
247
|
+
line: specifierLine,
|
|
248
|
+
column: specifierColumn,
|
|
249
|
+
})
|
|
241
250
|
const sourcemapReference = createReference({
|
|
242
|
-
trace:
|
|
243
|
-
adjustUrlSite(urlInfo, {
|
|
244
|
-
urlGraph,
|
|
245
|
-
url: urlInfo.url,
|
|
246
|
-
line: specifierLine,
|
|
247
|
-
column: specifierColumn,
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
251
|
+
trace: traceFromUrlSite(sourcemapUrlSite),
|
|
250
252
|
type,
|
|
251
253
|
parentUrl: urlInfo.url,
|
|
252
254
|
specifier,
|
|
@@ -273,7 +275,7 @@ export const createKitchen = ({
|
|
|
273
275
|
`no plugin has handled url during "fetchUrlContent" hook -> url will be ignored`,
|
|
274
276
|
{
|
|
275
277
|
"url": urlInfo.url,
|
|
276
|
-
"url reference trace": reference.trace,
|
|
278
|
+
"url reference trace": reference.trace.message,
|
|
277
279
|
},
|
|
278
280
|
),
|
|
279
281
|
)
|
|
@@ -408,7 +410,7 @@ export const createKitchen = ({
|
|
|
408
410
|
},
|
|
409
411
|
found: ({ trace, ...rest }) => {
|
|
410
412
|
if (trace === undefined) {
|
|
411
|
-
trace =
|
|
413
|
+
trace = traceFromUrlSite(
|
|
412
414
|
adjustUrlSite(urlInfo, {
|
|
413
415
|
urlGraph,
|
|
414
416
|
url: urlInfo.url,
|
|
@@ -423,7 +425,12 @@ export const createKitchen = ({
|
|
|
423
425
|
...rest,
|
|
424
426
|
})
|
|
425
427
|
},
|
|
426
|
-
foundInline: ({
|
|
428
|
+
foundInline: ({
|
|
429
|
+
isOriginalPosition,
|
|
430
|
+
specifierLine,
|
|
431
|
+
specifierColumn,
|
|
432
|
+
...rest
|
|
433
|
+
}) => {
|
|
427
434
|
const parentUrl = isOriginalPosition
|
|
428
435
|
? urlInfo.url
|
|
429
436
|
: urlInfo.generatedUrl
|
|
@@ -431,15 +438,15 @@ export const createKitchen = ({
|
|
|
431
438
|
? urlInfo.originalContent
|
|
432
439
|
: urlInfo.content
|
|
433
440
|
return addReference({
|
|
434
|
-
trace:
|
|
441
|
+
trace: traceFromUrlSite({
|
|
435
442
|
url: parentUrl,
|
|
436
443
|
content: parentContent,
|
|
437
|
-
line,
|
|
438
|
-
column,
|
|
444
|
+
line: specifierLine,
|
|
445
|
+
column: specifierColumn,
|
|
439
446
|
}),
|
|
440
447
|
isOriginalPosition,
|
|
441
|
-
|
|
442
|
-
|
|
448
|
+
specifierLine,
|
|
449
|
+
specifierColumn,
|
|
443
450
|
isInline: true,
|
|
444
451
|
...rest,
|
|
445
452
|
})
|
|
@@ -487,7 +494,7 @@ export const createKitchen = ({
|
|
|
487
494
|
? urlInfo.originalContent
|
|
488
495
|
: urlInfo.content
|
|
489
496
|
return referenceUtils.update(reference, {
|
|
490
|
-
trace:
|
|
497
|
+
trace: traceFromUrlSite({
|
|
491
498
|
url: parentUrl,
|
|
492
499
|
content: parentContent,
|
|
493
500
|
line: specifierLine,
|
|
@@ -505,7 +512,7 @@ export const createKitchen = ({
|
|
|
505
512
|
inject: ({ trace, ...rest }) => {
|
|
506
513
|
if (trace === undefined) {
|
|
507
514
|
const { url, line, column } = getCallerPosition()
|
|
508
|
-
trace =
|
|
515
|
+
trace = traceFromUrlSite({
|
|
509
516
|
url,
|
|
510
517
|
line,
|
|
511
518
|
column,
|
|
@@ -722,6 +729,15 @@ const memoizeCook = (cook) => {
|
|
|
722
729
|
}
|
|
723
730
|
}
|
|
724
731
|
|
|
732
|
+
const traceFromUrlSite = (urlSite) => {
|
|
733
|
+
return {
|
|
734
|
+
message: stringifyUrlSite(urlSite),
|
|
735
|
+
url: urlSite.url,
|
|
736
|
+
line: urlSite.line,
|
|
737
|
+
column: urlSite.column,
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
725
741
|
const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
726
742
|
if (reference.shouldHandle) {
|
|
727
743
|
urlInfo.shouldHandle = true
|
|
@@ -7,8 +7,12 @@ import {
|
|
|
7
7
|
pluginCORS,
|
|
8
8
|
} from "@jsenv/server"
|
|
9
9
|
import { convertFileSystemErrorToResponseProperties } from "@jsenv/server/src/internal/convertFileSystemErrorToResponseProperties.js"
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
createCallbackListNotifiedOnce,
|
|
12
|
+
createCallbackList,
|
|
13
|
+
} from "@jsenv/abort"
|
|
11
14
|
|
|
15
|
+
import { createSSEService } from "@jsenv/core/src/helpers/event_source/sse_service.js"
|
|
12
16
|
import { createFileService } from "./server/file_service.js"
|
|
13
17
|
|
|
14
18
|
export const startOmegaServer = async ({
|
|
@@ -33,12 +37,60 @@ export const startOmegaServer = async ({
|
|
|
33
37
|
kitchen,
|
|
34
38
|
}) => {
|
|
35
39
|
const serverStopCallbackList = createCallbackListNotifiedOnce()
|
|
40
|
+
|
|
41
|
+
const serverEventCallbackList = createCallbackList()
|
|
42
|
+
const sseService = createSSEService({ serverEventCallbackList })
|
|
43
|
+
const sendServerEvent = ({ type, data }) => {
|
|
44
|
+
serverEventCallbackList.notify({
|
|
45
|
+
type,
|
|
46
|
+
data: JSON.stringify(data),
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
kitchen.pluginController.addHook("registerServerEvents")
|
|
51
|
+
kitchen.pluginController.callHooks(
|
|
52
|
+
"registerServerEvents",
|
|
53
|
+
{ sendServerEvent },
|
|
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
|
+
|
|
36
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
|
+
},
|
|
37
80
|
"service:file": createFileService({
|
|
38
81
|
rootDirectoryUrl,
|
|
39
82
|
urlGraph,
|
|
40
83
|
kitchen,
|
|
41
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
|
+
},
|
|
42
94
|
}),
|
|
43
95
|
}
|
|
44
96
|
const server = await startServer({
|
|
@@ -119,6 +171,7 @@ export const startOmegaServer = async ({
|
|
|
119
171
|
}),
|
|
120
172
|
onStop: (reason) => {
|
|
121
173
|
onStop()
|
|
174
|
+
sseService.destroy()
|
|
122
175
|
serverStopCallbackList.notify(reason)
|
|
123
176
|
},
|
|
124
177
|
})
|
|
@@ -12,6 +12,9 @@ export const createFileService = ({
|
|
|
12
12
|
urlGraph,
|
|
13
13
|
kitchen,
|
|
14
14
|
scenario,
|
|
15
|
+
onParseError,
|
|
16
|
+
onFileNotFound,
|
|
17
|
+
onUnexpectedError,
|
|
15
18
|
}) => {
|
|
16
19
|
kitchen.pluginController.addHook("serve")
|
|
17
20
|
kitchen.pluginController.addHook("augmentResponse")
|
|
@@ -51,7 +54,7 @@ export const createFileService = ({
|
|
|
51
54
|
}
|
|
52
55
|
if (!reference) {
|
|
53
56
|
const entryPoint = kitchen.injectReference({
|
|
54
|
-
trace: parentUrl || rootDirectoryUrl,
|
|
57
|
+
trace: { message: parentUrl || rootDirectoryUrl },
|
|
55
58
|
parentUrl: parentUrl || rootDirectoryUrl,
|
|
56
59
|
type: "http_request",
|
|
57
60
|
specifier: request.ressource,
|
|
@@ -135,10 +138,17 @@ export const createFileService = ({
|
|
|
135
138
|
} catch (e) {
|
|
136
139
|
const code = e.code
|
|
137
140
|
if (code === "PARSE_ERROR") {
|
|
138
|
-
|
|
141
|
+
onParseError({
|
|
142
|
+
reason: e.reason,
|
|
143
|
+
message: e.message,
|
|
144
|
+
url: e.url,
|
|
145
|
+
line: e.line,
|
|
146
|
+
column: e.column,
|
|
147
|
+
contentFrame: e.contentFrame,
|
|
148
|
+
})
|
|
139
149
|
return {
|
|
140
150
|
url: reference.url,
|
|
141
|
-
status: 200,
|
|
151
|
+
status: 200, // let the browser re-throw the syntax error
|
|
142
152
|
statusText: e.reason,
|
|
143
153
|
statusMessage: e.message,
|
|
144
154
|
headers: {
|
|
@@ -166,6 +176,14 @@ export const createFileService = ({
|
|
|
166
176
|
}
|
|
167
177
|
}
|
|
168
178
|
if (code === "NOT_FOUND") {
|
|
179
|
+
onFileNotFound({
|
|
180
|
+
reason: e.reason,
|
|
181
|
+
message: e.message,
|
|
182
|
+
url: e.url,
|
|
183
|
+
line: e.line,
|
|
184
|
+
column: e.column,
|
|
185
|
+
contentFrame: e.contentFrame,
|
|
186
|
+
})
|
|
169
187
|
return {
|
|
170
188
|
url: reference.url,
|
|
171
189
|
status: 404,
|
|
@@ -173,6 +191,15 @@ export const createFileService = ({
|
|
|
173
191
|
statusMessage: e.message,
|
|
174
192
|
}
|
|
175
193
|
}
|
|
194
|
+
onUnexpectedError({
|
|
195
|
+
reason: e.reason,
|
|
196
|
+
message: e.message,
|
|
197
|
+
stack: e.stack,
|
|
198
|
+
url: e.url,
|
|
199
|
+
line: e.line,
|
|
200
|
+
column: e.column,
|
|
201
|
+
contentFrame: e.contentFrame,
|
|
202
|
+
})
|
|
176
203
|
return {
|
|
177
204
|
url: reference.url,
|
|
178
205
|
status: 500,
|
|
@@ -157,21 +157,21 @@ const addReloadMessage = (reloadMessage) => {
|
|
|
157
157
|
|
|
158
158
|
const eventsourceConnection = createEventSourceConnection(
|
|
159
159
|
document.location.href,
|
|
160
|
-
{
|
|
161
|
-
reload: ({ data }) => {
|
|
162
|
-
const reloadMessage = JSON.parse(data)
|
|
163
|
-
addReloadMessage(reloadMessage)
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
160
|
{
|
|
167
161
|
retryMaxAttempt: Infinity,
|
|
168
162
|
retryAllocatedMs: 20 * 1000,
|
|
169
163
|
},
|
|
170
164
|
)
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
const { status, connect, addEventCallbacks, disconnect } = eventsourceConnection
|
|
166
|
+
eventsourceConnection.addEventCallbacks({
|
|
167
|
+
reload: ({ data }) => {
|
|
168
|
+
const reloadMessage = JSON.parse(data)
|
|
169
|
+
addReloadMessage(reloadMessage)
|
|
170
|
+
},
|
|
171
|
+
})
|
|
173
172
|
connect()
|
|
174
173
|
window.__jsenv_event_source_client__ = {
|
|
174
|
+
addEventCallbacks,
|
|
175
175
|
status,
|
|
176
176
|
connect,
|
|
177
177
|
disconnect,
|