@jsenv/core 27.0.0-alpha.13 → 27.0.0-alpha.16
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/main.js +1 -1
- package/package.json +7 -8
- package/src/build/build.js +29 -17
- package/src/build/start_build_server.js +176 -0
- package/src/dev/start_dev_server.js +9 -20
- package/src/execute/execute.js +9 -2
- package/src/omega/kitchen.js +7 -3
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +41 -0
- package/src/{dev/plugins/autoreload/jsenv_plugin_autoreload.js → plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js} +23 -174
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +25 -0
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +3 -4
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +0 -0
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +98 -0
- package/src/plugins/minification/jsenv_plugin_minification.js +2 -1
- package/src/plugins/plugins.js +23 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +13 -0
- package/src/test/execute_plan.js +6 -1
- package/src/test/execute_test_plan.js +4 -0
- package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
- package/src/dev/plugins/autoreload/sse_service.js +0 -169
- package/src/preview/preview.js +0 -3
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
export const createEventSourceConnection = (
|
|
2
|
-
eventSourceUrl,
|
|
3
|
-
events = {},
|
|
4
|
-
{ retryMaxAttempt = Infinity, retryAllocatedMs = Infinity, lastEventId } = {},
|
|
5
|
-
) => {
|
|
6
|
-
const { EventSource } = window
|
|
7
|
-
if (typeof EventSource !== "function") {
|
|
8
|
-
return () => {}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const eventSourceOrigin = new URL(eventSourceUrl).origin
|
|
12
|
-
Object.keys(events).forEach((eventName) => {
|
|
13
|
-
const eventCallback = events[eventName]
|
|
14
|
-
events[eventName] = (e) => {
|
|
15
|
-
if (e.origin === eventSourceOrigin) {
|
|
16
|
-
if (e.lastEventId) {
|
|
17
|
-
lastEventId = e.lastEventId
|
|
18
|
-
}
|
|
19
|
-
eventCallback(e)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const status = {
|
|
25
|
-
value: "default",
|
|
26
|
-
goTo: (value) => {
|
|
27
|
-
if (value === status.value) {
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
status.value = value
|
|
31
|
-
status.onchange()
|
|
32
|
-
},
|
|
33
|
-
onchange: () => {},
|
|
34
|
-
}
|
|
35
|
-
let _disconnect = () => {}
|
|
36
|
-
|
|
37
|
-
const attemptConnection = (url) => {
|
|
38
|
-
const eventSource = new EventSource(url, {
|
|
39
|
-
withCredentials: true,
|
|
40
|
-
})
|
|
41
|
-
_disconnect = () => {
|
|
42
|
-
if (status.value !== "connecting" && status.value !== "connected") {
|
|
43
|
-
console.warn(
|
|
44
|
-
`disconnect() ignored because connection is ${status.value}`,
|
|
45
|
-
)
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
eventSource.onerror = undefined
|
|
49
|
-
eventSource.close()
|
|
50
|
-
Object.keys(events).forEach((eventName) => {
|
|
51
|
-
eventSource.removeEventListener(eventName, events[eventName])
|
|
52
|
-
})
|
|
53
|
-
status.goTo("disconnected")
|
|
54
|
-
}
|
|
55
|
-
let retryCount = 0
|
|
56
|
-
let firstRetryMs = Date.now()
|
|
57
|
-
eventSource.onerror = (errorEvent) => {
|
|
58
|
-
if (errorEvent.target.readyState === EventSource.CONNECTING) {
|
|
59
|
-
if (retryCount > retryMaxAttempt) {
|
|
60
|
-
console.info(`could not connect after ${retryMaxAttempt} attempt`)
|
|
61
|
-
_disconnect()
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (retryCount === 0) {
|
|
66
|
-
firstRetryMs = Date.now()
|
|
67
|
-
} else {
|
|
68
|
-
const allRetryDuration = Date.now() - firstRetryMs
|
|
69
|
-
if (retryAllocatedMs && allRetryDuration > retryAllocatedMs) {
|
|
70
|
-
console.info(
|
|
71
|
-
`could not connect in less than ${retryAllocatedMs} ms`,
|
|
72
|
-
)
|
|
73
|
-
_disconnect()
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
retryCount++
|
|
79
|
-
status.goTo("connecting")
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (errorEvent.target.readyState === EventSource.CLOSED) {
|
|
84
|
-
_disconnect()
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
eventSource.onopen = () => {
|
|
89
|
-
status.goTo("connected")
|
|
90
|
-
}
|
|
91
|
-
Object.keys(events).forEach((eventName) => {
|
|
92
|
-
eventSource.addEventListener(eventName, events[eventName])
|
|
93
|
-
})
|
|
94
|
-
if (!events.hasOwnProperty("welcome")) {
|
|
95
|
-
eventSource.addEventListener("welcome", (e) => {
|
|
96
|
-
if (e.origin === eventSourceOrigin && e.lastEventId) {
|
|
97
|
-
lastEventId = e.lastEventId
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
status.goTo("connecting")
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let connect = () => {
|
|
105
|
-
attemptConnection(eventSourceUrl)
|
|
106
|
-
connect = () => {
|
|
107
|
-
attemptConnection(
|
|
108
|
-
lastEventId
|
|
109
|
-
? addLastEventIdIntoUrlSearchParams(eventSourceUrl, lastEventId)
|
|
110
|
-
: eventSourceUrl,
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const removePageUnloadListener = listenPageUnload(() => {
|
|
116
|
-
if (status.value === "connecting" || status.value === "connected") {
|
|
117
|
-
_disconnect()
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
const destroy = () => {
|
|
122
|
-
removePageUnloadListener()
|
|
123
|
-
_disconnect()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
status,
|
|
128
|
-
connect,
|
|
129
|
-
disconnect: () => _disconnect(),
|
|
130
|
-
destroy,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const addLastEventIdIntoUrlSearchParams = (url, lastEventId) => {
|
|
135
|
-
if (url.indexOf("?") === -1) {
|
|
136
|
-
url += "?"
|
|
137
|
-
} else {
|
|
138
|
-
url += "&"
|
|
139
|
-
}
|
|
140
|
-
return `${url}last-event-id=${encodeURIComponent(lastEventId)}`
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// const listenPageMightFreeze = (callback) => {
|
|
144
|
-
// const removePageHideListener = listenEvent(window, "pagehide", (pageHideEvent) => {
|
|
145
|
-
// if (pageHideEvent.persisted === true) {
|
|
146
|
-
// callback(pageHideEvent)
|
|
147
|
-
// }
|
|
148
|
-
// })
|
|
149
|
-
// return removePageHideListener
|
|
150
|
-
// }
|
|
151
|
-
|
|
152
|
-
// const listenPageFreeze = (callback) => {
|
|
153
|
-
// const removeFreezeListener = listenEvent(document, "freeze", (freezeEvent) => {
|
|
154
|
-
// callback(freezeEvent)
|
|
155
|
-
// })
|
|
156
|
-
// return removeFreezeListener
|
|
157
|
-
// }
|
|
158
|
-
|
|
159
|
-
// const listenPageIsRestored = (callback) => {
|
|
160
|
-
// const removeResumeListener = listenEvent(document, "resume", (resumeEvent) => {
|
|
161
|
-
// removePageshowListener()
|
|
162
|
-
// callback(resumeEvent)
|
|
163
|
-
// })
|
|
164
|
-
// const removePageshowListener = listenEvent(window, "pageshow", (pageshowEvent) => {
|
|
165
|
-
// if (pageshowEvent.persisted === true) {
|
|
166
|
-
// removePageshowListener()
|
|
167
|
-
// removeResumeListener()
|
|
168
|
-
// callback(pageshowEvent)
|
|
169
|
-
// }
|
|
170
|
-
// })
|
|
171
|
-
// return () => {
|
|
172
|
-
// removeResumeListener()
|
|
173
|
-
// removePageshowListener()
|
|
174
|
-
// }
|
|
175
|
-
// }
|
|
176
|
-
|
|
177
|
-
const listenPageUnload = (callback) => {
|
|
178
|
-
const removePageHideListener = listenEvent(
|
|
179
|
-
window,
|
|
180
|
-
"pagehide",
|
|
181
|
-
(pageHideEvent) => {
|
|
182
|
-
if (pageHideEvent.persisted !== true) {
|
|
183
|
-
callback(pageHideEvent)
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
)
|
|
187
|
-
return removePageHideListener
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const listenEvent = (emitter, event, callback) => {
|
|
191
|
-
emitter.addEventListener(event, callback)
|
|
192
|
-
return () => {
|
|
193
|
-
emitter.removeEventListener(event, callback)
|
|
194
|
-
}
|
|
195
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { createSSERoom } from "@jsenv/server"
|
|
2
|
-
import { registerDirectoryLifecycle } from "@jsenv/filesystem"
|
|
3
|
-
import {
|
|
4
|
-
createCallbackList,
|
|
5
|
-
createCallbackListNotifiedOnce,
|
|
6
|
-
} from "@jsenv/abort"
|
|
7
|
-
|
|
8
|
-
export const createSSEService = ({
|
|
9
|
-
rootDirectoryUrl,
|
|
10
|
-
autoreloadPatterns,
|
|
11
|
-
onFileChange,
|
|
12
|
-
hotUpdateCallbackList,
|
|
13
|
-
cooldownBetweenFileEvents = 0,
|
|
14
|
-
}) => {
|
|
15
|
-
const destroyCallbackList = createCallbackListNotifiedOnce()
|
|
16
|
-
const projectFileModified = createCallbackList()
|
|
17
|
-
const projectFileRemoved = createCallbackList()
|
|
18
|
-
const projectFileAdded = createCallbackList()
|
|
19
|
-
const watchProjectFiles = (callback) => {
|
|
20
|
-
const removeModifiedCallback = projectFileModified.add((relativeUrl) => {
|
|
21
|
-
callback({
|
|
22
|
-
event: "modified",
|
|
23
|
-
relativeUrl,
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
const removeRemovedCallback = projectFileRemoved.add((relativeUrl) => {
|
|
27
|
-
callback({
|
|
28
|
-
event: "removed",
|
|
29
|
-
relativeUrl,
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
const removeAddedCallback = projectFileRemoved.add((relativeUrl) => {
|
|
33
|
-
callback({
|
|
34
|
-
event: "added",
|
|
35
|
-
relativeUrl,
|
|
36
|
-
})
|
|
37
|
-
})
|
|
38
|
-
return () => {
|
|
39
|
-
removeModifiedCallback()
|
|
40
|
-
removeRemovedCallback()
|
|
41
|
-
removeAddedCallback()
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
// wait 100ms to actually start watching
|
|
45
|
-
// otherwise server starting is delayed by the filesystem scan done in
|
|
46
|
-
// registerDirectoryLifecycle
|
|
47
|
-
const timeout = setTimeout(() => {
|
|
48
|
-
const unregisterDirectoryLifecyle = registerDirectoryLifecycle(
|
|
49
|
-
rootDirectoryUrl,
|
|
50
|
-
{
|
|
51
|
-
watchDescription: {
|
|
52
|
-
...autoreloadPatterns,
|
|
53
|
-
".jsenv/": false,
|
|
54
|
-
},
|
|
55
|
-
updated: ({ relativeUrl }) => {
|
|
56
|
-
projectFileModified.notify(relativeUrl)
|
|
57
|
-
},
|
|
58
|
-
removed: ({ relativeUrl }) => {
|
|
59
|
-
projectFileRemoved.notify(relativeUrl)
|
|
60
|
-
},
|
|
61
|
-
added: ({ relativeUrl }) => {
|
|
62
|
-
projectFileAdded.notify(relativeUrl)
|
|
63
|
-
},
|
|
64
|
-
keepProcessAlive: false,
|
|
65
|
-
recursive: true,
|
|
66
|
-
},
|
|
67
|
-
)
|
|
68
|
-
destroyCallbackList.add(unregisterDirectoryLifecyle)
|
|
69
|
-
}, 100)
|
|
70
|
-
destroyCallbackList.add(() => {
|
|
71
|
-
clearTimeout(timeout)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
const cache = []
|
|
75
|
-
const sseRoomLimit = 100
|
|
76
|
-
const getOrCreateSSERoom = (request) => {
|
|
77
|
-
const htmlFileRelativeUrl = request.ressource.slice(1)
|
|
78
|
-
const cacheEntry = cache.find(
|
|
79
|
-
(cacheEntryCandidate) =>
|
|
80
|
-
cacheEntryCandidate.htmlFileRelativeUrl === htmlFileRelativeUrl,
|
|
81
|
-
)
|
|
82
|
-
if (cacheEntry) {
|
|
83
|
-
return cacheEntry.sseRoom
|
|
84
|
-
}
|
|
85
|
-
const sseRoom = createSSERoom({
|
|
86
|
-
retryDuration: 2000,
|
|
87
|
-
historyLength: 100,
|
|
88
|
-
welcomeEventEnabled: true,
|
|
89
|
-
effect: () => {
|
|
90
|
-
const removeHotUpdateCallback = hotUpdateCallbackList.add(
|
|
91
|
-
(hotUpdate) => {
|
|
92
|
-
if (hotUpdate.declined) {
|
|
93
|
-
sseRoom.sendEvent({
|
|
94
|
-
type: "reload",
|
|
95
|
-
data: JSON.stringify({
|
|
96
|
-
cause: hotUpdate.cause,
|
|
97
|
-
type: "full",
|
|
98
|
-
typeReason: hotUpdate.reason,
|
|
99
|
-
declinedBy: hotUpdate.declinedBy,
|
|
100
|
-
}),
|
|
101
|
-
})
|
|
102
|
-
} else {
|
|
103
|
-
sseRoom.sendEvent({
|
|
104
|
-
type: "reload",
|
|
105
|
-
data: JSON.stringify({
|
|
106
|
-
cause: hotUpdate.cause,
|
|
107
|
-
type: "hot",
|
|
108
|
-
typeReason: hotUpdate.reason,
|
|
109
|
-
hotInstructions: hotUpdate.instructions,
|
|
110
|
-
}),
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
)
|
|
115
|
-
const stopWatching = watchProjectFiles(
|
|
116
|
-
cooldownBetweenFileEvents
|
|
117
|
-
? guardTooFastSecondCall(onFileChange, cooldownBetweenFileEvents)
|
|
118
|
-
: onFileChange,
|
|
119
|
-
)
|
|
120
|
-
return () => {
|
|
121
|
-
removeHotUpdateCallback()
|
|
122
|
-
stopWatching()
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
const removeSSECleanupCallback = destroyCallbackList.add(() => {
|
|
128
|
-
removeSSECleanupCallback()
|
|
129
|
-
sseRoom.close()
|
|
130
|
-
})
|
|
131
|
-
cache.push({
|
|
132
|
-
htmlFileRelativeUrl,
|
|
133
|
-
sseRoom,
|
|
134
|
-
cleanup: () => {
|
|
135
|
-
removeSSECleanupCallback()
|
|
136
|
-
sseRoom.close()
|
|
137
|
-
},
|
|
138
|
-
})
|
|
139
|
-
if (cache.length >= sseRoomLimit) {
|
|
140
|
-
const firstCacheEntry = cache.shift()
|
|
141
|
-
firstCacheEntry.cleanup()
|
|
142
|
-
}
|
|
143
|
-
return sseRoom
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
getOrCreateSSERoom,
|
|
148
|
-
destroy: () => {
|
|
149
|
-
destroyCallbackList.notify()
|
|
150
|
-
},
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const guardTooFastSecondCall = (callback, cooldownBetweenFileEvents = 40) => {
|
|
155
|
-
const previousCallMsMap = new Map()
|
|
156
|
-
return ({ relativeUrl, event }) => {
|
|
157
|
-
const previousCallMs = previousCallMsMap.get(relativeUrl)
|
|
158
|
-
const nowMs = Date.now()
|
|
159
|
-
if (previousCallMs) {
|
|
160
|
-
const msEllapsed = nowMs - previousCallMs
|
|
161
|
-
if (msEllapsed < cooldownBetweenFileEvents) {
|
|
162
|
-
previousCallMsMap.delete(relativeUrl)
|
|
163
|
-
return
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
previousCallMsMap.set(relativeUrl, nowMs)
|
|
167
|
-
callback({ relativeUrl, event })
|
|
168
|
-
}
|
|
169
|
-
}
|
package/src/preview/preview.js
DELETED