@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 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
- - :relieved: Same dev experience for source and test files
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
- Run the following command to create a demo of a jsenv project on your machine.
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
- > "web" demos are running tests in headless browsers. If you never have installed playwright on your machine npm install can take a bit of time.
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 on Node.js 18.5.0. Other operating systems and Node.js versions are not tested.
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 createEventSourceConnection = (eventSourceUrl, events = {}, {
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
- events[eventName] = e => {
23
- if (e.origin === eventSourceOrigin) {
24
- if (e.lastEventId) {
25
- lastEventId = e.lastEventId;
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
- eventCallback(e);
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
- const eventSource = new EventSource(url, {
64
+ eventSource = new EventSource(url, {
49
65
  withCredentials: true
50
66
  });
51
67
 
52
68
  _disconnect = () => {
53
- if (status.value !== "connecting" && status.value !== "connected") {
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
- status.goTo("disconnected");
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("connecting");
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("connected");
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("connecting");
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 === "connecting" || status.value === "connected") {
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,