@jsenv/core 27.3.2 → 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/controllable_child_process.mjs +1 -0
- package/dist/controllable_worker_thread.mjs +1 -0
- package/dist/js/event_source_client.js +45 -24
- package/dist/js/execute_using_dynamic_import.js +5 -3
- package/dist/js/html_supervisor_installer.js +368 -139
- package/dist/main.js +668 -471
- package/package.json +5 -6
- package/src/build/build.js +6 -4
- package/src/build/graph_utils.js +14 -11
- package/src/execute/run.js +29 -28
- package/src/execute/runtimes/browsers/from_playwright.js +90 -92
- package/src/execute/runtimes/node/execute_using_dynamic_import.js +8 -2
- package/src/execute/runtimes/node/node_child_process.js +2 -0
- package/src/execute/runtimes/node/node_worker_thread.js +11 -6
- 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/omega/url_graph/url_graph_report.js +2 -4
- package/src/omega/url_graph.js +29 -16
- 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 -172
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +0 -4
- package/src/plugins/bundling/js_module/bundle_js_module.js +0 -1
- 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/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +1 -2
- package/src/plugins/plugins.js +0 -2
- package/src/plugins/url_analysis/js/js_urls.js +0 -9
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +3 -1
- package/src/test/coverage/report_to_coverage.js +16 -11
- package/src/test/execute_plan.js +3 -2
- package/src/test/execute_test_plan.js +3 -1
- package/src/test/logs_file_execution.js +60 -27
- package/src/test/logs_file_execution.test.mjs +41 -0
package/README.md
CHANGED
|
@@ -4,18 +4,30 @@ Jsenv was first created to write tests that could be executed in different runti
|
|
|
4
4
|
|
|
5
5
|
- :exploding_head: Directly execute HTML files as tests
|
|
6
6
|
- :relieved: Consistent and integral developer experience (dev + test + build)
|
|
7
|
-
- :
|
|
7
|
+
- :sparkles: Same dev experience for source and test files
|
|
8
8
|
- :ok_hand: Seamless integration with standard HTML, CSS and JS
|
|
9
9
|
|
|
10
|
+
Jsenv is NOT a tool for fullstack projects where client and server code are in the same files.<br />
|
|
11
|
+
Jsenv is designed for projects where client and server codebases are independent.
|
|
12
|
+
|
|
10
13
|
# Demo
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
The following command can be used to create a jsenv project on a machine.
|
|
13
16
|
|
|
14
17
|
```console
|
|
15
18
|
npm create jsenv@latest
|
|
16
19
|
```
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
These demos are showing how jsenv can be integrated with preconfigured scripts such as:
|
|
22
|
+
|
|
23
|
+
- `npm run dev`: starts a dev server with autoreload.
|
|
24
|
+
- `npm run test`: execute test files on browsers(s) and/or Node.js.
|
|
25
|
+
- `npm run build`: generate files optimized for production.
|
|
26
|
+
|
|
27
|
+
> **Info**
|
|
28
|
+
> Executing "npm install" in web demos can take time. It is because in these demos tests are runned in headless browsers that needs to be installed.
|
|
29
|
+
|
|
30
|
+
See also [packages/create-jsenv](./packages/create-jsenv).
|
|
19
31
|
|
|
20
32
|
# Installation
|
|
21
33
|
|
|
@@ -23,7 +35,7 @@ npm create jsenv@latest
|
|
|
23
35
|
npm install --save-dev @jsenv/core
|
|
24
36
|
```
|
|
25
37
|
|
|
26
|
-
_@jsenv/core_ is tested on Mac, Windows, Linux
|
|
38
|
+
_@jsenv/core_ is tested on Mac, Windows, Linux with Node.js 18.5.0. Other operating systems and Node.js versions are not tested.
|
|
27
39
|
|
|
28
40
|
# Documentation
|
|
29
41
|
|
|
@@ -2,7 +2,12 @@ import { urlHotMetas } from "./import_meta_hot.js";
|
|
|
2
2
|
import { parseSrcSet, stringifySrcSet } from "@jsenv/ast/src/html/html_src_set.js";
|
|
3
3
|
|
|
4
4
|
/* eslint-env browser */
|
|
5
|
-
const
|
|
5
|
+
const STATUSES = {
|
|
6
|
+
CONNECTING: "connecting",
|
|
7
|
+
CONNECTED: "connected",
|
|
8
|
+
DISCONNECTED: "disconnected"
|
|
9
|
+
};
|
|
10
|
+
const createEventSourceConnection = (eventSourceUrl, {
|
|
6
11
|
retryMaxAttempt = Infinity,
|
|
7
12
|
retryAllocatedMs = Infinity,
|
|
8
13
|
lastEventId
|
|
@@ -15,20 +20,31 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
15
20
|
return () => {};
|
|
16
21
|
}
|
|
17
22
|
|
|
23
|
+
let eventSource;
|
|
24
|
+
const events = {};
|
|
18
25
|
const eventSourceOrigin = new URL(eventSourceUrl).origin;
|
|
19
|
-
Object.keys(events).forEach(eventName => {
|
|
20
|
-
const eventCallback = events[eventName];
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
const addEventCallbacks = eventCallbacks => {
|
|
28
|
+
Object.keys(eventCallbacks).forEach(eventName => {
|
|
29
|
+
const eventCallback = eventCallbacks[eventName];
|
|
30
|
+
|
|
31
|
+
events[eventName] = e => {
|
|
32
|
+
if (e.origin === eventSourceOrigin) {
|
|
33
|
+
if (e.lastEventId) {
|
|
34
|
+
lastEventId = e.lastEventId;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
eventCallback(e);
|
|
26
38
|
}
|
|
39
|
+
};
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
if (eventSource) {
|
|
42
|
+
eventSource.addEventListener(eventName, events[eventName]);
|
|
29
43
|
}
|
|
30
|
-
};
|
|
31
|
-
}
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
addEventCallbacks(events);
|
|
32
48
|
const status = {
|
|
33
49
|
value: "default",
|
|
34
50
|
goTo: value => {
|
|
@@ -45,12 +61,12 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
45
61
|
let _disconnect = () => {};
|
|
46
62
|
|
|
47
63
|
const attemptConnection = url => {
|
|
48
|
-
|
|
64
|
+
eventSource = new EventSource(url, {
|
|
49
65
|
withCredentials: true
|
|
50
66
|
});
|
|
51
67
|
|
|
52
68
|
_disconnect = () => {
|
|
53
|
-
if (status.value !==
|
|
69
|
+
if (status.value !== STATUSES.CONNECTING && status.value !== STATUSES.CONNECTED) {
|
|
54
70
|
console.warn(`disconnect() ignored because connection is ${status.value}`);
|
|
55
71
|
return;
|
|
56
72
|
}
|
|
@@ -60,7 +76,8 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
60
76
|
Object.keys(events).forEach(eventName => {
|
|
61
77
|
eventSource.removeEventListener(eventName, events[eventName]);
|
|
62
78
|
});
|
|
63
|
-
|
|
79
|
+
eventSource = null;
|
|
80
|
+
status.goTo(STATUSES.DISCONNECTED);
|
|
64
81
|
};
|
|
65
82
|
|
|
66
83
|
let retryCount = 0;
|
|
@@ -91,7 +108,7 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
retryCount++;
|
|
94
|
-
status.goTo(
|
|
111
|
+
status.goTo(STATUSES.CONNECTING);
|
|
95
112
|
return;
|
|
96
113
|
}
|
|
97
114
|
|
|
@@ -103,7 +120,7 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
103
120
|
};
|
|
104
121
|
|
|
105
122
|
eventSource.onopen = () => {
|
|
106
|
-
status.goTo(
|
|
123
|
+
status.goTo(STATUSES.CONNECTED);
|
|
107
124
|
};
|
|
108
125
|
|
|
109
126
|
Object.keys(events).forEach(eventName => {
|
|
@@ -118,7 +135,7 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
118
135
|
});
|
|
119
136
|
}
|
|
120
137
|
|
|
121
|
-
status.goTo(
|
|
138
|
+
status.goTo(STATUSES.CONNECTING);
|
|
122
139
|
};
|
|
123
140
|
|
|
124
141
|
let connect = () => {
|
|
@@ -130,7 +147,7 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
130
147
|
};
|
|
131
148
|
|
|
132
149
|
const removePageUnloadListener = listenPageUnload(() => {
|
|
133
|
-
if (status.value ===
|
|
150
|
+
if (status.value === STATUSES.CONNECTING || status.value === STATUSES.CONNECTED) {
|
|
134
151
|
_disconnect();
|
|
135
152
|
}
|
|
136
153
|
});
|
|
@@ -144,6 +161,7 @@ const createEventSourceConnection = (eventSourceUrl, events = {}, {
|
|
|
144
161
|
return {
|
|
145
162
|
status,
|
|
146
163
|
connect,
|
|
164
|
+
addEventCallbacks,
|
|
147
165
|
disconnect: () => _disconnect(),
|
|
148
166
|
destroy
|
|
149
167
|
};
|
|
@@ -492,23 +510,26 @@ const addReloadMessage = reloadMessage => {
|
|
|
492
510
|
};
|
|
493
511
|
|
|
494
512
|
const eventsourceConnection = createEventSourceConnection(document.location.href, {
|
|
495
|
-
reload: ({
|
|
496
|
-
data
|
|
497
|
-
}) => {
|
|
498
|
-
const reloadMessage = JSON.parse(data);
|
|
499
|
-
addReloadMessage(reloadMessage);
|
|
500
|
-
}
|
|
501
|
-
}, {
|
|
502
513
|
retryMaxAttempt: Infinity,
|
|
503
514
|
retryAllocatedMs: 20 * 1000
|
|
504
515
|
});
|
|
505
516
|
const {
|
|
506
517
|
status,
|
|
507
518
|
connect,
|
|
519
|
+
addEventCallbacks,
|
|
508
520
|
disconnect
|
|
509
521
|
} = eventsourceConnection;
|
|
522
|
+
eventsourceConnection.addEventCallbacks({
|
|
523
|
+
reload: ({
|
|
524
|
+
data
|
|
525
|
+
}) => {
|
|
526
|
+
const reloadMessage = JSON.parse(data);
|
|
527
|
+
addReloadMessage(reloadMessage);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
510
530
|
connect();
|
|
511
531
|
window.__jsenv_event_source_client__ = {
|
|
532
|
+
addEventCallbacks,
|
|
512
533
|
status,
|
|
513
534
|
connect,
|
|
514
535
|
disconnect,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
1
2
|
import { Session } from "node:inspector";
|
|
2
3
|
import { performance, PerformanceObserver } from "node:perf_hooks";
|
|
3
4
|
|
|
@@ -122,9 +123,10 @@ const executeUsingDynamicImport = async ({
|
|
|
122
123
|
collectPerformance,
|
|
123
124
|
coverageEnabled,
|
|
124
125
|
coverageConfig,
|
|
125
|
-
coverageMethodForNodeJs
|
|
126
|
+
coverageMethodForNodeJs,
|
|
127
|
+
coverageFileUrl
|
|
126
128
|
}) => {
|
|
127
|
-
|
|
129
|
+
const result = {};
|
|
128
130
|
const afterImportCallbacks = [];
|
|
129
131
|
|
|
130
132
|
if (coverageEnabled && coverageMethodForNodeJs === "Profiler") {
|
|
@@ -140,7 +142,7 @@ const executeUsingDynamicImport = async ({
|
|
|
140
142
|
rootDirectoryUrl,
|
|
141
143
|
coverageConfig
|
|
142
144
|
});
|
|
143
|
-
|
|
145
|
+
writeFileSync(new URL(coverageFileUrl), JSON.stringify(coverageLight, null, " "));
|
|
144
146
|
});
|
|
145
147
|
}
|
|
146
148
|
|