@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
|
@@ -1,183 +1,180 @@
|
|
|
1
1
|
import { urlToRelativeUrl } from "@jsenv/urls"
|
|
2
|
-
import { createCallbackList } from "@jsenv/abort"
|
|
3
|
-
|
|
4
|
-
import { createSSEService } from "@jsenv/core/src/helpers/event_source/sse_service.js"
|
|
5
2
|
|
|
6
3
|
export const jsenvPluginDevSSEServer = ({
|
|
7
|
-
rootDirectoryUrl,
|
|
8
|
-
urlGraph,
|
|
9
4
|
clientFileChangeCallbackList,
|
|
10
5
|
clientFilesPruneCallbackList,
|
|
11
6
|
}) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
data: JSON.stringify({
|
|
30
|
-
cause,
|
|
31
|
-
type: "hot",
|
|
32
|
-
typeReason: reason,
|
|
33
|
-
hotInstructions: instructions,
|
|
34
|
-
}),
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
const propagateUpdate = (firstUrlInfo) => {
|
|
38
|
-
const iterate = (urlInfo, trace) => {
|
|
39
|
-
if (urlInfo.data.hotAcceptSelf) {
|
|
40
|
-
return {
|
|
41
|
-
accepted: true,
|
|
42
|
-
reason:
|
|
43
|
-
urlInfo === firstUrlInfo
|
|
44
|
-
? `file accepts hot reload`
|
|
45
|
-
: `a dependent file accepts hot reload`,
|
|
46
|
-
instructions: [
|
|
47
|
-
{
|
|
48
|
-
type: urlInfo.type,
|
|
49
|
-
boundary: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
50
|
-
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
}
|
|
7
|
+
return {
|
|
8
|
+
name: "jsenv:sse_server",
|
|
9
|
+
appliesDuring: { dev: true },
|
|
10
|
+
registerServerEvents: (
|
|
11
|
+
{ sendServerEvent },
|
|
12
|
+
{ rootDirectoryUrl, urlGraph },
|
|
13
|
+
) => {
|
|
14
|
+
const notifyDeclined = ({ cause, reason, declinedBy }) => {
|
|
15
|
+
sendServerEvent({
|
|
16
|
+
type: "reload",
|
|
17
|
+
data: {
|
|
18
|
+
cause,
|
|
19
|
+
type: "full",
|
|
20
|
+
typeReason: reason,
|
|
21
|
+
declinedBy,
|
|
22
|
+
},
|
|
23
|
+
})
|
|
54
24
|
}
|
|
55
|
-
const {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
25
|
+
const notifyAccepted = ({ cause, reason, instructions }) => {
|
|
26
|
+
sendServerEvent({
|
|
27
|
+
type: "reload",
|
|
28
|
+
data: {
|
|
29
|
+
cause,
|
|
30
|
+
type: "hot",
|
|
31
|
+
typeReason: reason,
|
|
32
|
+
hotInstructions: instructions,
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
const propagateUpdate = (firstUrlInfo) => {
|
|
37
|
+
const iterate = (urlInfo, seen) => {
|
|
38
|
+
if (urlInfo.data.hotAcceptSelf) {
|
|
39
|
+
return {
|
|
40
|
+
accepted: true,
|
|
41
|
+
reason:
|
|
42
|
+
urlInfo === firstUrlInfo
|
|
43
|
+
? `file accepts hot reload`
|
|
44
|
+
: `a dependent file accepts hot reload`,
|
|
45
|
+
instructions: [
|
|
46
|
+
{
|
|
47
|
+
type: urlInfo.type,
|
|
48
|
+
boundary: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
49
|
+
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const { dependents } = urlInfo
|
|
55
|
+
const instructions = []
|
|
56
|
+
for (const dependentUrl of dependents) {
|
|
57
|
+
const dependentUrlInfo = urlGraph.getUrlInfo(dependentUrl)
|
|
58
|
+
if (dependentUrlInfo.data.hotDecline) {
|
|
59
|
+
return {
|
|
60
|
+
declined: true,
|
|
61
|
+
reason: `a dependent file declines hot reload`,
|
|
62
|
+
declinedBy: dependentUrl,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const { hotAcceptDependencies = [] } = dependentUrlInfo.data
|
|
66
|
+
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
67
|
+
instructions.push({
|
|
68
|
+
type: dependentUrlInfo.type,
|
|
69
|
+
boundary: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
|
|
70
|
+
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
71
|
+
})
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
if (seen.includes(dependentUrl)) {
|
|
75
|
+
return {
|
|
76
|
+
declined: true,
|
|
77
|
+
reason: "circular dependency",
|
|
78
|
+
declinedBy: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const dependentPropagationResult = iterate(dependentUrlInfo, [
|
|
82
|
+
...seen,
|
|
83
|
+
dependentUrl,
|
|
84
|
+
])
|
|
85
|
+
if (dependentPropagationResult.accepted) {
|
|
86
|
+
instructions.push(...dependentPropagationResult.instructions)
|
|
87
|
+
continue
|
|
88
|
+
}
|
|
89
|
+
if (
|
|
90
|
+
// declined explicitely by an other file, it must decline the whole update
|
|
91
|
+
dependentPropagationResult.declinedBy
|
|
92
|
+
) {
|
|
93
|
+
return dependentPropagationResult
|
|
94
|
+
}
|
|
95
|
+
// declined by absence of boundary, we can keep searching
|
|
96
|
+
continue
|
|
97
|
+
}
|
|
98
|
+
if (instructions.length === 0) {
|
|
99
|
+
return {
|
|
100
|
+
declined: true,
|
|
101
|
+
reason: `there is no file accepting hot reload while propagating update`,
|
|
102
|
+
}
|
|
64
103
|
}
|
|
65
|
-
}
|
|
66
|
-
const { hotAcceptDependencies = [] } = dependentUrlInfo.data
|
|
67
|
-
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
68
|
-
instructions.push({
|
|
69
|
-
type: dependentUrlInfo.type,
|
|
70
|
-
boundary: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
|
|
71
|
-
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
72
|
-
})
|
|
73
|
-
continue
|
|
74
|
-
}
|
|
75
|
-
if (trace.includes(dependentUrl)) {
|
|
76
104
|
return {
|
|
77
|
-
|
|
78
|
-
reason:
|
|
79
|
-
|
|
105
|
+
accepted: true,
|
|
106
|
+
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
107
|
+
instructions,
|
|
80
108
|
}
|
|
81
109
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
dependentUrl,
|
|
85
|
-
])
|
|
86
|
-
if (dependentPropagationResult.accepted) {
|
|
87
|
-
instructions.push(...dependentPropagationResult.instructions)
|
|
88
|
-
continue
|
|
89
|
-
}
|
|
90
|
-
if (
|
|
91
|
-
// declined explicitely by an other file, it must decline the whole update
|
|
92
|
-
dependentPropagationResult.declinedBy
|
|
93
|
-
) {
|
|
94
|
-
return dependentPropagationResult
|
|
95
|
-
}
|
|
96
|
-
// declined by absence of boundary, we can keep searching
|
|
97
|
-
continue
|
|
110
|
+
const seen = []
|
|
111
|
+
return iterate(firstUrlInfo, seen)
|
|
98
112
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
clientFileChangeCallbackList.push(({ url, event }) => {
|
|
114
|
+
const urlInfo = urlGraph.getUrlInfo(url)
|
|
115
|
+
// file not part of dependency graph
|
|
116
|
+
if (!urlInfo) {
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
|
|
120
|
+
const hotUpdate = propagateUpdate(urlInfo)
|
|
121
|
+
if (hotUpdate.declined) {
|
|
122
|
+
notifyDeclined({
|
|
123
|
+
cause: `${relativeUrl} ${event}`,
|
|
124
|
+
reason: hotUpdate.reason,
|
|
125
|
+
declinedBy: hotUpdate.declinedBy,
|
|
126
|
+
})
|
|
127
|
+
} else {
|
|
128
|
+
notifyAccepted({
|
|
129
|
+
cause: `${relativeUrl} ${event}`,
|
|
130
|
+
reason: hotUpdate.reason,
|
|
131
|
+
instructions: hotUpdate.instructions,
|
|
132
|
+
})
|
|
103
133
|
}
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
accepted: true,
|
|
107
|
-
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
108
|
-
instructions,
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const trace = []
|
|
112
|
-
return iterate(firstUrlInfo, trace)
|
|
113
|
-
}
|
|
114
|
-
clientFileChangeCallbackList.push(({ url, event }) => {
|
|
115
|
-
const urlInfo = urlGraph.getUrlInfo(url)
|
|
116
|
-
// file not part of dependency graph
|
|
117
|
-
if (!urlInfo) {
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl)
|
|
121
|
-
const hotUpdate = propagateUpdate(urlInfo)
|
|
122
|
-
if (hotUpdate.declined) {
|
|
123
|
-
notifyDeclined({
|
|
124
|
-
cause: `${relativeUrl} ${event}`,
|
|
125
|
-
reason: hotUpdate.reason,
|
|
126
|
-
declinedBy: hotUpdate.declinedBy,
|
|
127
|
-
})
|
|
128
|
-
} else {
|
|
129
|
-
notifyAccepted({
|
|
130
|
-
cause: `${relativeUrl} ${event}`,
|
|
131
|
-
reason: hotUpdate.reason,
|
|
132
|
-
instructions: hotUpdate.instructions,
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
clientFilesPruneCallbackList.push(({ prunedUrlInfos, firstUrlInfo }) => {
|
|
137
|
-
const mainHotUpdate = propagateUpdate(firstUrlInfo)
|
|
138
|
-
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
|
|
139
|
-
(prunedUrlInfo) => urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
140
|
-
)}`
|
|
141
|
-
// now check if we can hot update the main ressource
|
|
142
|
-
// then if we can hot update all dependencies
|
|
143
|
-
if (mainHotUpdate.declined) {
|
|
144
|
-
notifyDeclined({
|
|
145
|
-
cause,
|
|
146
|
-
reason: mainHotUpdate.reason,
|
|
147
|
-
declinedBy: mainHotUpdate.declinedBy,
|
|
148
134
|
})
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
135
|
+
clientFilesPruneCallbackList.push(({ prunedUrlInfos, firstUrlInfo }) => {
|
|
136
|
+
const mainHotUpdate = propagateUpdate(firstUrlInfo)
|
|
137
|
+
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
|
|
138
|
+
(prunedUrlInfo) =>
|
|
139
|
+
urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
140
|
+
)}`
|
|
141
|
+
// now check if we can hot update the main ressource
|
|
142
|
+
// then if we can hot update all dependencies
|
|
143
|
+
if (mainHotUpdate.declined) {
|
|
144
|
+
notifyDeclined({
|
|
145
|
+
cause,
|
|
146
|
+
reason: mainHotUpdate.reason,
|
|
147
|
+
declinedBy: mainHotUpdate.declinedBy,
|
|
148
|
+
})
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
// main can hot update
|
|
152
|
+
let i = 0
|
|
153
|
+
const instructions = []
|
|
154
|
+
while (i < prunedUrlInfos.length) {
|
|
155
|
+
const prunedUrlInfo = prunedUrlInfos[i++]
|
|
156
|
+
if (prunedUrlInfo.data.hotDecline) {
|
|
157
|
+
notifyDeclined({
|
|
158
|
+
cause,
|
|
159
|
+
reason: `a pruned file declines hot reload`,
|
|
160
|
+
declinedBy: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
161
|
+
})
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
instructions.push({
|
|
165
|
+
type: "prune",
|
|
166
|
+
boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
167
|
+
acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl),
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
notifyAccepted({
|
|
158
171
|
cause,
|
|
159
|
-
reason:
|
|
160
|
-
|
|
172
|
+
reason: mainHotUpdate.reason,
|
|
173
|
+
instructions,
|
|
161
174
|
})
|
|
162
|
-
return
|
|
163
|
-
}
|
|
164
|
-
instructions.push({
|
|
165
|
-
type: "prune",
|
|
166
|
-
boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
167
|
-
acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl),
|
|
168
175
|
})
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
cause,
|
|
172
|
-
reason: mainHotUpdate.reason,
|
|
173
|
-
instructions,
|
|
174
|
-
})
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
name: "jsenv:sse_server",
|
|
179
|
-
appliesDuring: { dev: true },
|
|
180
|
-
serve: (request) => {
|
|
176
|
+
},
|
|
177
|
+
serve: (request, { rootDirectoryUrl, urlGraph }) => {
|
|
181
178
|
if (request.ressource === "/__graph__") {
|
|
182
179
|
const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl))
|
|
183
180
|
return {
|
|
@@ -189,15 +186,7 @@ export const jsenvPluginDevSSEServer = ({
|
|
|
189
186
|
body: graphJson,
|
|
190
187
|
}
|
|
191
188
|
}
|
|
192
|
-
const { accept } = request.headers
|
|
193
|
-
if (accept && accept.includes("text/event-stream")) {
|
|
194
|
-
const room = sseService.getOrCreateSSERoom(request)
|
|
195
|
-
return room.join(request)
|
|
196
|
-
}
|
|
197
189
|
return null
|
|
198
190
|
},
|
|
199
|
-
destroy: () => {
|
|
200
|
-
sseService.destroy()
|
|
201
|
-
},
|
|
202
191
|
}
|
|
203
192
|
}
|
|
@@ -3,8 +3,6 @@ import { jsenvPluginDevSSEClient } from "./dev_sse/jsenv_plugin_dev_sse_client.j
|
|
|
3
3
|
import { jsenvPluginDevSSEServer } from "./dev_sse/jsenv_plugin_dev_sse_server.js"
|
|
4
4
|
|
|
5
5
|
export const jsenvPluginAutoreload = ({
|
|
6
|
-
rootDirectoryUrl,
|
|
7
|
-
urlGraph,
|
|
8
6
|
scenario,
|
|
9
7
|
clientFileChangeCallbackList,
|
|
10
8
|
clientFilesPruneCallbackList,
|
|
@@ -16,8 +14,6 @@ export const jsenvPluginAutoreload = ({
|
|
|
16
14
|
jsenvPluginHmr(),
|
|
17
15
|
jsenvPluginDevSSEClient(),
|
|
18
16
|
jsenvPluginDevSSEServer({
|
|
19
|
-
rootDirectoryUrl,
|
|
20
|
-
urlGraph,
|
|
21
17
|
clientFileChangeCallbackList,
|
|
22
18
|
clientFilesPruneCallbackList,
|
|
23
19
|
}),
|