arcane-os 0.52.1 → 0.54.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/CHANGELOG.md +42 -0
- package/NOTICE +4 -1
- package/README.md +1 -1
- package/bin/arcane-test.mjs +2 -1
- package/browser-runtime/ai/browser-decisions.mjs +405 -0
- package/browser-runtime/ai/decision-runtime.mjs +281 -0
- package/browser-runtime/ai/decision-worker.mjs +67 -0
- package/browser-runtime/dependencies/event-pubsub/dependencies/strong-type/index.js +1151 -0
- package/browser-runtime/dependencies/event-pubsub/dependencies/strong-type/licence +21 -0
- package/browser-runtime/dependencies/event-pubsub/dependencies/strong-type/package.json +61 -0
- package/browser-runtime/dependencies/event-pubsub/index.js +2 -2
- package/browser-runtime/dependencies/event-pubsub/package.json +11 -4
- package/browser-runtime/dependencies/ws-share/WS.js +128 -0
- package/browser-runtime/dependencies/ws-share/licence.md +27 -0
- package/browser-runtime/dependencies/ws-share/package.json +64 -0
- package/browser-runtime/websocket-client.mjs +1 -0
- package/docs/event-manager.md +7 -4
- package/docs/reference/ai/browser-decisions.md +184 -0
- package/docs/reference/inventory/package-api.json +44 -2
- package/docs/reference/inventory/runtime-modules.json +17 -4
- package/docs/reference/protocols.md +76 -1
- package/docs/reference/runtime-modules.md +45 -2
- package/docs/reference/sdk-api.md +280 -6
- package/docs/reference/websocket-client.md +132 -0
- package/node_modules/event-pubsub/CHANGELOG.md +12 -1
- package/node_modules/event-pubsub/MIGRATION.md +8 -5
- package/node_modules/event-pubsub/README.md +75 -19
- package/node_modules/event-pubsub/SECURITY.md +3 -3
- package/node_modules/event-pubsub/index.js +2 -2
- package/node_modules/event-pubsub/package.json +11 -4
- package/package.json +9 -5
- package/runtime/arcane/modules/HTMLImport.js +81 -26
- package/runtime/arcane/modules/HTMLImportScript.js +3 -0
- package/src/import-map.mjs +416 -59
- package/src/index.mjs +2 -0
- package/src/packager/core.mjs +24 -6
- package/src/packager/native-modules.mjs +458 -0
- package/src/testing-loader.mjs +41 -20
- package/src/websocket.mjs +479 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Shared WebSocket clients
|
|
2
|
+
|
|
3
|
+
`arcane-os/websocket-client` exposes the published `ws-share` constructor as
|
|
4
|
+
both `default` and `WS`. Node also exports the same `WS` binding from
|
|
5
|
+
`arcane-os`. Browser modules use the focused entry through the generated SDK
|
|
6
|
+
import map. These entries reuse the upstream implementation rather than
|
|
7
|
+
creating another pool or event bus.
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import WS from 'arcane-os/websocket-client';
|
|
11
|
+
|
|
12
|
+
const airlock=new WS('wss://moon.example/airlock',['moon-control']);
|
|
13
|
+
const oxygenPanel=new WS('wss://moon.example/airlock',['moon-control']);
|
|
14
|
+
console.log(airlock===oxygenPanel); // true while connecting or open
|
|
15
|
+
|
|
16
|
+
function showAirlockMessage(event){
|
|
17
|
+
console.log(event.data);
|
|
18
|
+
}
|
|
19
|
+
airlock.addEventListener('message',showAirlockMessage);
|
|
20
|
+
|
|
21
|
+
// When this panel goes away, release only its listener.
|
|
22
|
+
function disposePanel(){
|
|
23
|
+
airlock.removeEventListener('message',showAirlockMessage);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Replace the example URL with your application's WebSocket endpoint. The exact
|
|
28
|
+
URI string and ordered protocol list select a shared connection. Repeated
|
|
29
|
+
construction reuses a connecting or open socket. A closing or closed socket
|
|
30
|
+
gets a new physical connection and a new ID; the predecessor's eventual close
|
|
31
|
+
cannot remove its replacement.
|
|
32
|
+
|
|
33
|
+
The returned object is the native `WebSocket`, with its native `send`,
|
|
34
|
+
`close`, `binaryType`, properties and per-socket events. Complete messages pass
|
|
35
|
+
through unchanged. Upstream `on`/`off` and `addListener`/`removeListener`
|
|
36
|
+
aliases retain native listener semantics, rather than Node EventEmitter
|
|
37
|
+
semantics. Importing the SDK entry starts no connection and does not replace
|
|
38
|
+
`globalThis.WebSocket`.
|
|
39
|
+
|
|
40
|
+
## Observe all managed connections
|
|
41
|
+
|
|
42
|
+
`await WS.observe()` returns one lazy `event-pubsub` observer per loaded
|
|
43
|
+
implementation. Repeated or concurrent calls return that same observer.
|
|
44
|
+
Enabling observation opens no socket. Register handlers after the await, then
|
|
45
|
+
read `WS.getConnections()` synchronously without another await between them.
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
import {WS} from 'arcane-os/websocket-client';
|
|
49
|
+
|
|
50
|
+
const events=await WS.observe();
|
|
51
|
+
const liveConnections=new Map();
|
|
52
|
+
|
|
53
|
+
function trackConnection(type,connection){
|
|
54
|
+
if(type==='close')liveConnections.delete(connection.id);
|
|
55
|
+
else liveConnections.set(connection.id,connection);
|
|
56
|
+
console.log(type,connection.id,connection.url,connection.readyState);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
events.on('*',trackConnection);
|
|
60
|
+
for(const connection of WS.getConnections()){
|
|
61
|
+
liveConnections.set(connection.id,connection);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function disposeConnectionPanel(){
|
|
65
|
+
events.off('*',trackConnection);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The typed events `created`, `open`, `error` and `close` each receive one record.
|
|
70
|
+
The wildcard handler receives `(type,record)`. Each record contains:
|
|
71
|
+
|
|
72
|
+
| Field | Meaning |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `id` | Numeric physical-connection identity within this loaded implementation. |
|
|
75
|
+
| `socket` | The exact native socket. |
|
|
76
|
+
| `url` | The native socket's URL. |
|
|
77
|
+
| `protocols` | A fresh copy of the requested, normalized protocol list. |
|
|
78
|
+
| `readyState` | Native state when the record is produced. |
|
|
79
|
+
| `event` | Original native event; `created` has `undefined`. |
|
|
80
|
+
|
|
81
|
+
`WS.getConnections()` returns fresh records with the first five fields. It
|
|
82
|
+
includes tracked sockets until their native close event, including a closing
|
|
83
|
+
predecessor after its replacement exists. Records are snapshots; the `socket`
|
|
84
|
+
remains live. Read a new snapshot when current state is needed.
|
|
85
|
+
|
|
86
|
+
`created` is queued in a microtask only when observation was enabled at
|
|
87
|
+
construction. Reusing a connection emits no second `created` event. A snapshot
|
|
88
|
+
can include a connection before its queued `created` notification arrives, so
|
|
89
|
+
reconcile by `id` rather than appending duplicates. Native close removes the
|
|
90
|
+
connection and its internal lifecycle listeners before global close handlers
|
|
91
|
+
run. Applications may still use native socket listeners alongside the global
|
|
92
|
+
observer; there is no second per-socket event bus.
|
|
93
|
+
|
|
94
|
+
## Ownership and lifetime
|
|
95
|
+
|
|
96
|
+
Every caller shares the same socket, including changes to `binaryType`, a
|
|
97
|
+
property handler, or a call to `close()`. A component that only owns a listener
|
|
98
|
+
removes that exact listener. The application decides when the shared socket
|
|
99
|
+
should close; construction does not acquire an independent reference-counted
|
|
100
|
+
lifetime. Remove only your own observer handlers instead of resetting the
|
|
101
|
+
shared observer. Observe asynchronous handler failures at their owning caller.
|
|
102
|
+
|
|
103
|
+
All modules that should share connections use the same SDK module URL in
|
|
104
|
+
their realm. Separate package copies, browser realms, Workers, processes, and
|
|
105
|
+
upstream classic-script versus ESM loads have separate pools. The observer
|
|
106
|
+
reports actual native lifecycle events; it provides no closed-event history
|
|
107
|
+
or delivery after the realm/process ends. It adds no automatic reconnect,
|
|
108
|
+
heartbeat, message envelope, storage, or application routing.
|
|
109
|
+
|
|
110
|
+
## Runtime and package delivery
|
|
111
|
+
|
|
112
|
+
The SDK's Node baseline supplies native `WebSocket`; browsers need their native
|
|
113
|
+
WebSocket capability. The focused entry is portable JavaScript, with the host
|
|
114
|
+
owning networking and native errors. Browser Workers need module resolution
|
|
115
|
+
provided by their host because document import maps do not apply to Workers.
|
|
116
|
+
|
|
117
|
+
The SDK selects `ws-share@3.1.0` and `event-pubsub@6.1.1`. npm resolves the
|
|
118
|
+
latter's `strong-type@2.0.0`, while the SDK's own direct `strong-type@2.0.1`
|
|
119
|
+
remains unchanged. The canonical browser projection generator copies the
|
|
120
|
+
installed public runtime files unchanged. Managed maps resolve the shared
|
|
121
|
+
constructor and event package to one URL each, and a dependency scope selects
|
|
122
|
+
the event package's own strong-type version. Physical, direct-installed,
|
|
123
|
+
packaged-document and managed test maps preserve that scope. Applications
|
|
124
|
+
regenerate their managed maps/runtime through the ordinary public SDK flow;
|
|
125
|
+
they do not copy the upstream implementation into application source.
|
|
126
|
+
|
|
127
|
+
`acceptWebSocket` remains the separate Node server-side API at
|
|
128
|
+
`arcane-os/websocket`. It owns accepted server connections, not this client
|
|
129
|
+
pool. Existing native clients and server Upgrade handling remain available.
|
|
130
|
+
|
|
131
|
+
Upstream details: [ws-share 3.1.0 release](https://github.com/RIAEvangelist/ws-share/releases/tag/3.1.0)
|
|
132
|
+
and [observer documentation](https://riaevangelist.github.io/ws-share/#observe).
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.1.1 — 2026-08-23
|
|
4
|
+
|
|
5
|
+
- Replaced the consumer-root-relative `../strong-type/index.js` import with the bare `strong-type` package name so Node selects event-pubsub's declared nested exact dependency under a root version conflict.
|
|
6
|
+
- Declared the shared `index.js` source as the explicit browser entry and made bundled plus no-build unbundled support explicit, including normal and conflict-scoped import maps.
|
|
7
|
+
- Added a packed-consumer regression that installs `strong-type` 1.1.0 at the consumer root, poisons that copy, instruments event-pubsub's nested 2.0.0, and proves both ESM and CommonJS execute the nested validator.
|
|
8
|
+
- Added packed real-Chrome consumers for the normal and conflict-scoped import maps plus a Rollup 4.62.5/node-resolve 16.0.3 bundle of the poisoned conflict layout.
|
|
9
|
+
- Staged the exact validator beneath event-pubsub and made the shared Chrome suite and live playgrounds resolve the bare `event-pubsub` and `strong-type` names through explicit maps.
|
|
10
|
+
- Added a 12-scenario Behavioral suite with Given/When/Then consumer workflows for audited delivery, nested events, lifecycle teardown, routing, synchronous replies, shared payloads, failure propagation, asynchronous side effects, live subscriber changes, and hub isolation.
|
|
11
|
+
- Expanded the shared host-neutral Node/Chrome registry to 131 checks and added the focused `npm run test:behavioral` command.
|
|
12
|
+
- Added a focused Behavioral inventory page and carried the 131-check total through CI, coverage, status, and deployment validation.
|
|
13
|
+
|
|
3
14
|
## 6.1.0 — 2026-08-21
|
|
4
15
|
|
|
5
|
-
Published to npm
|
|
16
|
+
Published to npm and GitHub from the same verified source commit.
|
|
6
17
|
|
|
7
18
|
- Added direct CommonJS `require('event-pubsub')` support while keeping one native ESM implementation for both module systems.
|
|
8
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Migrating from event-pubsub 5.x to 6.x
|
|
2
2
|
|
|
3
|
-
Version 6 preserves the public method names and synchronous wildcard-first model while formalizing previously inconsistent edge behavior. The 6.1.0 npm release
|
|
3
|
+
Version 6 preserves the public method names and synchronous wildcard-first model while formalizing previously inconsistent edge behavior. The 6.1.0 npm release restored delegated validation and shared-source CommonJS consumption. The 6.1.1 correction makes Node resolve that validator through event-pubsub's declared dependency boundary.
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ Version 6 preserves the public method names and synchronous wildcard-first model
|
|
|
23
23
|
|
|
24
24
|
### Package layout
|
|
25
25
|
|
|
26
|
-
The package keeps its historical ESM entry at `event-pubsub/index.js` without a restrictive export map. Applications should normally import `event-pubsub`; repository-only paths are not part of the supported API.
|
|
26
|
+
The package keeps its historical ESM entry at `event-pubsub/index.js` without a restrictive export map and declares that same source as its browser entry. Applications should normally import `event-pubsub`; repository-only paths are not part of the supported API.
|
|
27
27
|
|
|
28
28
|
## Behavior to review
|
|
29
29
|
|
|
@@ -53,15 +53,18 @@ Public argument checks again come from `strong-type` 2.0.0. Invalid inputs still
|
|
|
53
53
|
|
|
54
54
|
Each `list` access creates a null-prototype object with copied handler arrays. Mutating or deleting snapshot values no longer mutates the live registry. Use `Object.hasOwn(snapshot, type)` instead of calling `snapshot.hasOwnProperty(...)`. The wildcard entry remains available through `Symbol.for('event-pubsub-all')`.
|
|
55
55
|
|
|
56
|
-
###
|
|
56
|
+
### Package dependency resolution
|
|
57
57
|
|
|
58
|
-
The 6.1.0
|
|
58
|
+
The 6.1.0 entry reached `strong-type` through `../strong-type/index.js`. In a consumer with an incompatible root validator and event-pubsub's exact 2.0.0 nested beneath it, that relative path could execute the root package. The 6.1.1 entry uses the bare `strong-type` name, so Node and bundlers resolve from event-pubsub outward and select its nested declared dependency first.
|
|
59
|
+
|
|
60
|
+
Browser support is explicit in both modes: bundlers resolve both package names normally, while unbundled native ESM runs the same source directly with an import map and no build step. Native browsers do not read the npm `browser` field. Put the map before the first module script, serve the app over HTTP(S), and map both `event-pubsub` and `strong-type`. When npm nests event-pubsub's validator because the root version conflicts, add an import-map scope for `./node_modules/event-pubsub/` that maps `strong-type` to `./node_modules/event-pubsub/node_modules/strong-type/index.js`. The README contains complete hoisted and conflicting-layout examples, both exercised from a packed install in real Chrome.
|
|
59
61
|
|
|
60
62
|
## Tooling cleanup
|
|
61
63
|
|
|
62
64
|
- `vanilla-test` is now pinned exactly at 2.1.1.
|
|
65
|
+
- Rollup 4.62.5 with node-resolve 16.0.3 is exact-pinned and configured only for JavaScript as the bundled-browser conformance probe.
|
|
63
66
|
- Native Node and Chrome coverage replaces c8.
|
|
64
|
-
- The old `copyfiles` dependency is gone; a dependency-free staging script now verifies the
|
|
67
|
+
- The old `copyfiles` dependency is gone; a dependency-free staging script now verifies the nested exact dependency in Node and maps that same copy for browser coverage.
|
|
65
68
|
- `copyfiles`, `c8`, and the test-only `node-http-server` dependency are removed.
|
|
66
69
|
- Production installs contain exactly one dependency: `strong-type` 2.0.0. They do not install `copyfiles` or the development-only `vanilla-test`.
|
|
67
70
|
|
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
[](https://riaevangelist.github.io/event-pubsub/reports/chrome/)
|
|
23
23
|
[](https://riaevangelist.github.io/event-pubsub/reports/chrome/)
|
|
24
24
|
|
|
25
|
-
Small, synchronous, extensible publish/subscribe events for
|
|
25
|
+
Small, synchronous, extensible publish/subscribe events for Node.js plus bundled and unbundled browsers.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
**It works with bundlers and without a bundler.** Both paths execute the same native ESM source; direct browser use needs only a standard import map, not a build or transpilation step.
|
|
28
|
+
|
|
29
|
+
> **Release status:** `6.1.1` is the current npm and GitHub release.
|
|
28
30
|
|
|
29
31
|

|
|
30
32
|
|
|
@@ -44,6 +46,8 @@ events.on('ready', (payload) => {
|
|
|
44
46
|
events.emit('ready', {fast: true});
|
|
45
47
|
```
|
|
46
48
|
|
|
49
|
+
That bare import is also the bundler entry. In a native browser application with no bundler, keep the same import and add the complete [import map shown below](#browser-use-bundled-and-unbundled).
|
|
50
|
+
|
|
47
51
|
The same source is available directly to CommonJS on Node.js 22.12 or newer:
|
|
48
52
|
|
|
49
53
|
```js
|
|
@@ -64,8 +68,8 @@ Bars show median nanoseconds per emit, whiskers show p25–p75, and dots show al
|
|
|
64
68
|
- Subscriber arrays remain live during an emit: additions can run in that emit, and specifically removed handlers are skipped before their turn. Removing a whole bucket or resetting the registry detaches it from future lookup while an already-active array finishes.
|
|
65
69
|
- Safe event names, including `__proto__`, `constructor`, and `toString`.
|
|
66
70
|
- Isolated `list` snapshots that cannot mutate the live registry.
|
|
67
|
-
- One native ESM source for
|
|
68
|
-
- One explicit production validator: `strong-type` 2.0.0,
|
|
71
|
+
- One native ESM source for Node.js `import`/`require()`, bundled browser applications, and unbundled browser modules, without transpilation or a duplicate build.
|
|
72
|
+
- One explicit production validator: `strong-type` 2.0.0, resolved through the package dependency boundary with an explicit browser entry and import map.
|
|
69
73
|
|
|
70
74
|
## API
|
|
71
75
|
|
|
@@ -96,15 +100,19 @@ The wildcard list entry is exposed at `Symbol.for('event-pubsub-all')`.
|
|
|
96
100
|
|
|
97
101
|
Only the exact public string `*` maps to the internal wildcard Symbol. The ordinary string `Symbol(event-pubsub-all)` remains an exact typed event name and never aliases wildcard removal.
|
|
98
102
|
|
|
99
|
-
### Browser
|
|
103
|
+
### Browser use: bundled and unbundled
|
|
104
|
+
|
|
105
|
+
The 6.1.1 package imports `strong-type` by package name. Bundlers may use its explicit `browser` entry; native browsers do not read npm package metadata, so the import map selects `index.js` directly.
|
|
100
106
|
|
|
101
|
-
|
|
107
|
+
- With a standards-compatible bundler, both package names resolve normally. The release gate bundles and executes a packed conflicting-dependency consumer with Rollup 4.62.5 and node-resolve 16.0.3, configured only for JavaScript.
|
|
108
|
+
- Without a bundler, a modern browser runs the same files directly through native ESM. Put this import map before the first module script that starts the graph and serve the directory over HTTP(S):
|
|
102
109
|
|
|
103
110
|
```html
|
|
104
111
|
<script type="importmap">
|
|
105
112
|
{
|
|
106
113
|
"imports": {
|
|
107
|
-
"event-pubsub": "./node_modules/event-pubsub/index.js"
|
|
114
|
+
"event-pubsub": "./node_modules/event-pubsub/index.js",
|
|
115
|
+
"strong-type": "./node_modules/strong-type/index.js"
|
|
108
116
|
}
|
|
109
117
|
}
|
|
110
118
|
</script>
|
|
@@ -113,30 +121,57 @@ The 6.1.0 runtime imports `strong-type` 2.0.0 through `../strong-type/index.js`.
|
|
|
113
121
|
</script>
|
|
114
122
|
```
|
|
115
123
|
|
|
124
|
+
That example is non-bundled browser code: the browser fetches both files from the mapped URLs and executes them directly. The paths are relative to the HTML document, so the static server must expose the shown `node_modules` files. Open the application through HTTP(S), not `file://`.
|
|
125
|
+
|
|
126
|
+
If the application uses a strict Content Security Policy, configure it to authorize the inline import-map and module scripts—for example, with an allowed nonce or hash.
|
|
127
|
+
|
|
128
|
+
If the application intentionally installs an incompatible `strong-type` at its root, npm keeps event-pubsub's exact 2.0.0 dependency nested. Scope the validator mapping to the event-pubsub referrer so the browser preserves that same dependency boundary:
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<script type="importmap">
|
|
132
|
+
{
|
|
133
|
+
"imports": {
|
|
134
|
+
"event-pubsub": "./node_modules/event-pubsub/index.js",
|
|
135
|
+
"strong-type": "./node_modules/strong-type/index.js"
|
|
136
|
+
},
|
|
137
|
+
"scopes": {
|
|
138
|
+
"./node_modules/event-pubsub/": {
|
|
139
|
+
"strong-type": "./node_modules/event-pubsub/node_modules/strong-type/index.js"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
</script>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Adjust the URLs to the package layout exposed by your static server. The release gate installs the packed tarball twice and executes both maps in real Chrome; the conflict fixture poisons the root validator so the scoped nested mapping cannot pass accidentally.
|
|
147
|
+
|
|
116
148
|
## Complete verification summary
|
|
117
149
|
|
|
118
|
-
The shared host-neutral registry contains **
|
|
150
|
+
The shared host-neutral registry contains **131 unique checks**. `vanilla-test` 2.1.1 executes the same inventory in Node and real Google Chrome.
|
|
119
151
|
|
|
120
152
|
| Suite | Cases | Focus |
|
|
121
153
|
| --- | ---: | --- |
|
|
122
154
|
| Unit | 16 | Exports, state, fluent identity, validation, and list shape |
|
|
123
155
|
| Functional | 26 | Registration, dispatch, wildcard, once, removal, reset, and chaining |
|
|
124
156
|
| Integration | 14 | Subclassing, routing, isolation, namespaces, lifecycle, and errors |
|
|
157
|
+
| Behavioral | 12 | Given/When/Then workflows, lifecycle boundaries, routing, failures, async effects, and live membership |
|
|
125
158
|
| Regression | 43 | Mutation, reentrancy, snapshots, safe names, throws, and registration-local once state |
|
|
126
159
|
| Interface | 20 | Playground parsing, safe display, bounded state, benchmark evidence, units, and chart scaling |
|
|
127
|
-
| **Total** | **
|
|
160
|
+
| **Total** | **131** | One registry used by direct tests and both coverage runtimes |
|
|
128
161
|
|
|
129
162
|
### Runtime and CI matrix
|
|
130
163
|
|
|
131
164
|
| Verification | Runtime | Hosts | Result requirement |
|
|
132
165
|
| --- | --- | --- | --- |
|
|
133
|
-
| Direct shared suite | Node 22.12.0 and Node 24 | Ubuntu, macOS, Windows |
|
|
134
|
-
| Node coverage | Node 24.18.0 | Ubuntu |
|
|
135
|
-
| Browser coverage | Google Chrome Stable | Ubuntu |
|
|
136
|
-
| Packed consumer | Node 24 | Ubuntu | Exact tarball contents
|
|
166
|
+
| Direct shared suite | Node 22.12.0 and Node 24 | Ubuntu, macOS, Windows | 131/131 on every matrix job |
|
|
167
|
+
| Node coverage | Node 24.18.0 | Ubuntu | 131/131 and every native V8 gate at 100% |
|
|
168
|
+
| Browser coverage | Google Chrome Stable | Ubuntu | 131/131 and every native V8 gate at 100% |
|
|
169
|
+
| Packed consumer | Node 24 | Ubuntu | Exact tarball contents plus ESM/CommonJS execution of nested `strong-type` 2.0.0 under a poisoned root conflict |
|
|
170
|
+
| Packed unbundled browser | Chrome Stable | Ubuntu and local release host | Normal and scoped-conflict import maps execute the tarball directly over HTTP |
|
|
171
|
+
| Packed bundled browser | Rollup 4.62.5 + Chrome Stable | Ubuntu and local release host | A bundle resolves nested `strong-type` 2.0.0 and runs representative behavior under a poisoned root conflict |
|
|
137
172
|
| Shared-source package smoke | Node 22.12.0 | Ubuntu | The same packed `index.js` through ESM `import` and direct CommonJS `require()` |
|
|
138
173
|
| Execution benchmark | Node 24.18.0 | Ubuntu | Eight validated scenarios with execution-only timing boundaries |
|
|
139
|
-
| GitHub Pages | Node 24 | Ubuntu |
|
|
174
|
+
| GitHub Pages | Node 24 | Ubuntu | 22 pages, both runtime reports, badges, benchmark JSON, scripts, links, and licenses |
|
|
140
175
|
|
|
141
176
|
### Coverage gates
|
|
142
177
|
|
|
@@ -151,25 +186,27 @@ These are native V8 executable/block/function range and executable-line totals f
|
|
|
151
186
|
|
|
152
187
|
| Command | Purpose |
|
|
153
188
|
| --- | --- |
|
|
154
|
-
| `npm test` | Stage
|
|
189
|
+
| `npm test` | Stage event-pubsub with its nested exact validator and run all 131 checks in Node. |
|
|
155
190
|
| `npm run test:unit` | Run the 16 Unit cases. |
|
|
156
191
|
| `npm run test:functional` | Run the 26 Functional cases. |
|
|
157
192
|
| `npm run test:integration` | Run the 14 Integration cases. |
|
|
193
|
+
| `npm run test:behavioral` | Run the 12 Behavioral scenarios. |
|
|
158
194
|
| `npm run test:regression` | Run the 43 Regression cases. |
|
|
159
195
|
| `npm run test:interface` | Run the 20 Interface cases. |
|
|
160
|
-
| `npm run coverage` | Run all
|
|
196
|
+
| `npm run coverage` | Run all 131 checks independently in Node and real Chrome with 100% gates. |
|
|
161
197
|
| `npm run coverage:node` | Generate only the Node native V8 report. |
|
|
162
198
|
| `npm run coverage:chrome` | Generate only the real-Chrome native V8 report. |
|
|
163
199
|
| `npm run benchmark` | Record seven fixed-count latency samples for eight scenarios. |
|
|
164
200
|
| `npm run benchmark:smoke` | Validate the benchmark quickly without replacing published results. |
|
|
165
201
|
| `npm run test:package` | Pack, inspect, install, and exercise a clean consumer. |
|
|
202
|
+
| `npm run test:browser-consumer` | Pack and execute normal-map, scoped-conflict-map, and Rollup browser consumers in real Chrome. |
|
|
166
203
|
| `npm run site:check` | Validate all focused pages, exact test inventories, scripts, links, forms, and assets. |
|
|
167
204
|
| `npm run verify` | Run the complete local release gate. |
|
|
168
205
|
|
|
169
206
|
### Published evidence
|
|
170
207
|
|
|
171
208
|
- [Testing strategy and suite totals](https://riaevangelist.github.io/event-pubsub/testing.html)
|
|
172
|
-
- [Live execution of all
|
|
209
|
+
- [Live execution of all 131 checks](https://riaevangelist.github.io/event-pubsub/live.html)
|
|
173
210
|
- [Node test-result JSON](https://riaevangelist.github.io/event-pubsub/reports/node/test-results.json)
|
|
174
211
|
- [Chrome test-result JSON](https://riaevangelist.github.io/event-pubsub/reports/chrome/test-results.json)
|
|
175
212
|
- [Node HTML coverage](https://riaevangelist.github.io/event-pubsub/reports/node/)
|
|
@@ -256,6 +293,24 @@ Every test name below is sourced from the shared registry. The focused Pages sit
|
|
|
256
293
|
|
|
257
294
|
</details>
|
|
258
295
|
|
|
296
|
+
<details>
|
|
297
|
+
<summary><strong>Behavioral — 12 scenarios</strong></summary>
|
|
298
|
+
|
|
299
|
+
1. given an audited order retry with one-time reservation and persistent projection, when the same order is published twice, then the audit leads both deliveries while reservation happens once
|
|
300
|
+
2. given an order handler that publishes the next workflow stage, when an order is created, then the nested fulfillment stage completes before outer delivery continues
|
|
301
|
+
3. given a one-time readiness gate that reenters its own topic, when the outer readiness signal arrives, then the gate is consumed before the nested signal
|
|
302
|
+
4. given a mounted subscriber that observes application updates, when the subscriber unmounts, then later updates no longer reach it
|
|
303
|
+
5. given listeners from an authenticated session, when logout resets the event hub and a new session starts, then only the new session observes later activity
|
|
304
|
+
6. given a bridge that forwards only public topics to another hub, when private and public messages are published, then only public messages cross the boundary
|
|
305
|
+
7. given a request carrying a reply callback, when a subscriber handles the request, then the caller receives the reply before publish returns
|
|
306
|
+
8. given a wildcard normalizer and a typed consumer sharing a payload, when the payload is published, then the consumer and caller observe the normalized object
|
|
307
|
+
9. given a one-time preflight followed by a failing persistent subscriber, when delivery is retried after the failure, then preflight stays consumed and the exact failure keeps reaching the publisher
|
|
308
|
+
10. given an asynchronous side effect beside a synchronous projection, when the event is published, then publish returns after starting both without awaiting the side effect
|
|
309
|
+
11. given subscriber membership that changes during a notification, when the current delivery adds one subscriber and removes another, then the added subscriber joins immediately and the removed one is skipped
|
|
310
|
+
12. given two tenant hubs with the same topic names, when each tenant publishes an update, then each update stays within its originating tenant
|
|
311
|
+
|
|
312
|
+
</details>
|
|
313
|
+
|
|
259
314
|
<details>
|
|
260
315
|
<summary><strong>Regression — 43 cases</strong></summary>
|
|
261
316
|
|
|
@@ -343,7 +398,7 @@ The benchmark reports median **execution latency**—nanoseconds per named opera
|
|
|
343
398
|
- [Examples](https://riaevangelist.github.io/event-pubsub/examples.html)
|
|
344
399
|
- [Event console playground](https://riaevangelist.github.io/event-pubsub/playground.html)
|
|
345
400
|
- [Mutation playground scenarios](https://riaevangelist.github.io/event-pubsub/playground-scenarios.html)
|
|
346
|
-
- [All
|
|
401
|
+
- [All 131 tests](https://riaevangelist.github.io/event-pubsub/testing.html)
|
|
347
402
|
- [Node and Chrome coverage](https://riaevangelist.github.io/event-pubsub/coverage.html)
|
|
348
403
|
- [Benchmark overview](https://riaevangelist.github.io/event-pubsub/benchmarks.html)
|
|
349
404
|
- [Dispatch latency chart](https://riaevangelist.github.io/event-pubsub/benchmarks-dispatch.html)
|
|
@@ -356,7 +411,8 @@ The benchmark reports median **execution latency**—nanoseconds per named opera
|
|
|
356
411
|
## Runtime support
|
|
357
412
|
|
|
358
413
|
- Node.js 22.12.0 or newer for production, development, and direct CommonJS `require()` of the native ESM source.
|
|
359
|
-
-
|
|
414
|
+
- Bundled browser applications; the bundler resolves `event-pubsub` and `strong-type` from package metadata normally.
|
|
415
|
+
- Unbundled modern browsers with native modules, private class fields, `Symbol`, and import maps; no build step is required. Map both package names, with a scoped validator mapping when npm nests it.
|
|
360
416
|
|
|
361
417
|
## License
|
|
362
418
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Supported |
|
|
6
6
|
| --- | --- |
|
|
7
|
-
| 6.1.
|
|
8
|
-
| 6.0.0 | Superseded
|
|
7
|
+
| 6.1.1 on npm and GitHub | Current supported release |
|
|
8
|
+
| 6.0.0 through 6.1.0 | Superseded 6.x releases |
|
|
9
9
|
| 5.x and older | No planned security fixes |
|
|
10
10
|
|
|
11
|
-
Version 6.1.
|
|
11
|
+
Version 6.1.1 is the current npm and GitHub release and requires Node.js 22.12 or newer. Earlier 6.x versions remain available for provenance, but users should install the latest available 6.x release.
|
|
12
12
|
|
|
13
13
|
## Reporting a vulnerability
|
|
14
14
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
import Is from '
|
|
1
|
+
// Preserve the package manager's dependency boundary instead of reaching for a consumer-root sibling.
|
|
2
|
+
import Is from 'strong-type';
|
|
3
3
|
|
|
4
4
|
const is = new Is();
|
|
5
5
|
const ALL_EVENTS = Symbol.for('event-pubsub-all');
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "event-pubsub",
|
|
3
|
-
"version": "6.1.
|
|
4
|
-
"description": "Small, synchronous
|
|
3
|
+
"version": "6.1.1",
|
|
4
|
+
"description": "Small, synchronous publish/subscribe events for Node.js plus bundled and unbundled browsers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
7
|
+
"browser": "./index.js",
|
|
7
8
|
"engines": {
|
|
8
9
|
"node": ">=22.12.0"
|
|
9
10
|
},
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"test:unit": "npm run stage && node ./test-runtime/event-pubsub/test/node.js unit",
|
|
14
15
|
"test:functional": "npm run stage && node ./test-runtime/event-pubsub/test/node.js functional",
|
|
15
16
|
"test:integration": "npm run stage && node ./test-runtime/event-pubsub/test/node.js integration",
|
|
17
|
+
"test:behavioral": "npm run stage && node ./test-runtime/event-pubsub/test/node.js behavioral",
|
|
16
18
|
"test:regression": "npm run stage && node ./test-runtime/event-pubsub/test/node.js regression",
|
|
17
19
|
"test:interface": "npm run stage && node ./test-runtime/event-pubsub/test/node.js interface",
|
|
18
20
|
"coverage": "npm run stage && vanilla-test coverage all",
|
|
@@ -23,11 +25,12 @@
|
|
|
23
25
|
"benchmark:chart": "node ./scripts/benchmark-chart.js",
|
|
24
26
|
"benchmark:chart:check": "node ./scripts/benchmark-chart.js --check",
|
|
25
27
|
"test:package": "node ./scripts/package-smoke.js",
|
|
28
|
+
"test:browser-consumer": "node ./scripts/browser-consumer-smoke.js",
|
|
26
29
|
"site:check": "npm run stage && npm run benchmark:chart:check && node ./scripts/site-check.js",
|
|
27
30
|
"site:assemble": "node ./scripts/assemble-site.js _site",
|
|
28
31
|
"site:deployment-check": "node ./scripts/deployment-check.js _site",
|
|
29
32
|
"start": "node ./scripts/serve.js",
|
|
30
|
-
"verify": "npm test && npm run coverage && npm run benchmark:smoke && npm run test:package && npm run site:check && npm run site:assemble && npm run site:deployment-check"
|
|
33
|
+
"verify": "npm test && npm run coverage && npm run benchmark:smoke && npm run test:package && npm run test:browser-consumer && npm run site:check && npm run site:assemble && npm run site:deployment-check"
|
|
31
34
|
},
|
|
32
35
|
"repository": {
|
|
33
36
|
"type": "git",
|
|
@@ -46,7 +49,9 @@
|
|
|
46
49
|
"event-emitter",
|
|
47
50
|
"node",
|
|
48
51
|
"browser",
|
|
49
|
-
"esm"
|
|
52
|
+
"esm",
|
|
53
|
+
"import-map",
|
|
54
|
+
"unbundled"
|
|
50
55
|
],
|
|
51
56
|
"author": "Brandon Nozaki Miller",
|
|
52
57
|
"license": "MIT",
|
|
@@ -54,6 +59,8 @@
|
|
|
54
59
|
"strong-type": "2.0.0"
|
|
55
60
|
},
|
|
56
61
|
"devDependencies": {
|
|
62
|
+
"@rollup/plugin-node-resolve": "16.0.3",
|
|
63
|
+
"rollup": "4.62.5",
|
|
57
64
|
"vanilla-test": "2.1.1"
|
|
58
65
|
}
|
|
59
66
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcane-os",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.mjs",
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
".": "./src/index.mjs",
|
|
13
13
|
"./toolchain": "./src/toolchain.mjs",
|
|
14
14
|
"./events": "./src/events.mjs",
|
|
15
|
+
"./websocket": "./src/websocket.mjs",
|
|
16
|
+
"./websocket-client": "./browser-runtime/websocket-client.mjs",
|
|
15
17
|
"./event-manager": "./src/event-manager.mjs",
|
|
16
18
|
"./modules/*": "./runtime/arcane/modules/*",
|
|
17
19
|
"./entities/*": "./runtime/arcane/entities/*",
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
"./speech-playback": "./runtime/arcane/modules/SpeechPlayback.js",
|
|
38
40
|
"./speech-text": "./browser-runtime/speech-text.mjs",
|
|
39
41
|
"./ai/browser-wasm": "./browser-runtime/ai/browser-wasm.mjs",
|
|
42
|
+
"./ai/browser-decisions": "./browser-runtime/ai/browser-decisions.mjs",
|
|
40
43
|
"./ai/tool-text-stream": "./browser-runtime/ai/tool-text-stream.mjs",
|
|
41
44
|
"./ai/twin-cloud": "./browser-runtime/ai/twin-cloud.mjs",
|
|
42
45
|
"./ai/browser-speech": "./browser-runtime/ai/browser-speech.mjs",
|
|
@@ -86,9 +89,9 @@
|
|
|
86
89
|
"test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
|
|
87
90
|
"test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
|
|
88
91
|
"test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/app-selection.test.mjs test/contracts.test.mjs test/conversation-closing-report.test.mjs test/doctor.test.mjs test/mail-credentials.test.mjs test/mail-outbox.test.mjs test/mail-public-api.test.mjs test/mail-send.test.mjs test/mail-transport.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
|
|
89
|
-
"test:functional": "node ./bin/arcane-test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
92
|
+
"test:functional": "node ./bin/arcane-test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-decisions.test.mjs test/browser-speech-providers.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
90
93
|
"test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-plan.test.mjs test/native-provider-loader.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
91
|
-
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
94
|
+
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/html-import-packaged-script.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
92
95
|
"check": "node tools/check-source.mjs && npm test",
|
|
93
96
|
"check:release": "node tools/check-source.mjs --package-only && npm run test:release",
|
|
94
97
|
"pack:local": "npm pack --ignore-scripts",
|
|
@@ -123,11 +126,12 @@
|
|
|
123
126
|
"tag": "latest"
|
|
124
127
|
},
|
|
125
128
|
"dependencies": {
|
|
126
|
-
"event-pubsub": "6.1.
|
|
129
|
+
"event-pubsub": "6.1.1",
|
|
127
130
|
"js-queue": "3.1.1",
|
|
128
131
|
"node-http-server": "10.0.0",
|
|
129
132
|
"strong-type": "2.0.1",
|
|
130
|
-
"vanilla-test": "2.1.3"
|
|
133
|
+
"vanilla-test": "2.1.3",
|
|
134
|
+
"ws-share": "3.1.0"
|
|
131
135
|
},
|
|
132
136
|
"bundleDependencies": [
|
|
133
137
|
"event-pubsub",
|