@vielzeug/pulse 2.4.0 → 26.10.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.
Files changed (64) hide show
  1. package/README.md +12 -20
  2. package/dist/_connection.cjs +1 -1
  3. package/dist/_connection.cjs.map +1 -1
  4. package/dist/_connection.js +1 -106
  5. package/dist/_connection.js.map +1 -1
  6. package/dist/_store.cjs +2 -0
  7. package/dist/_store.cjs.map +1 -0
  8. package/dist/_store.d.ts +6 -0
  9. package/dist/_store.d.ts.map +1 -0
  10. package/dist/_store.js +2 -0
  11. package/dist/_store.js.map +1 -0
  12. package/dist/_utils.cjs +1 -1
  13. package/dist/_utils.cjs.map +1 -1
  14. package/dist/_utils.js +1 -24
  15. package/dist/_utils.js.map +1 -1
  16. package/dist/_wait.cjs +1 -1
  17. package/dist/_wait.cjs.map +1 -1
  18. package/dist/_wait.js +1 -27
  19. package/dist/_wait.js.map +1 -1
  20. package/dist/channel.cjs +1 -1
  21. package/dist/channel.cjs.map +1 -1
  22. package/dist/channel.js +1 -56
  23. package/dist/channel.js.map +1 -1
  24. package/dist/errors.cjs +1 -1
  25. package/dist/errors.cjs.map +1 -1
  26. package/dist/errors.js +1 -37
  27. package/dist/errors.js.map +1 -1
  28. package/dist/heartbeat.cjs +1 -1
  29. package/dist/heartbeat.cjs.map +1 -1
  30. package/dist/heartbeat.js +1 -35
  31. package/dist/heartbeat.js.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +1 -3
  35. package/dist/protocol.cjs +1 -1
  36. package/dist/protocol.cjs.map +1 -1
  37. package/dist/protocol.js +1 -121
  38. package/dist/protocol.js.map +1 -1
  39. package/dist/pulse.cjs +1 -1
  40. package/dist/pulse.cjs.map +1 -1
  41. package/dist/pulse.d.ts.map +1 -1
  42. package/dist/pulse.iife.js +1 -1
  43. package/dist/pulse.iife.js.map +1 -1
  44. package/dist/pulse.js +1 -1
  45. package/dist/pulse.js.map +1 -1
  46. package/dist/room.cjs +1 -1
  47. package/dist/room.cjs.map +1 -1
  48. package/dist/room.d.ts +2 -2
  49. package/dist/room.d.ts.map +1 -1
  50. package/dist/room.js +1 -255
  51. package/dist/room.js.map +1 -1
  52. package/dist/testing/index.d.ts +10 -0
  53. package/dist/testing/index.d.ts.map +1 -0
  54. package/dist/testing/mock-websocket.cjs +2 -0
  55. package/dist/testing/mock-websocket.cjs.map +1 -0
  56. package/dist/testing/mock-websocket.d.ts +48 -0
  57. package/dist/testing/mock-websocket.d.ts.map +1 -0
  58. package/dist/testing/mock-websocket.js +2 -0
  59. package/dist/testing/mock-websocket.js.map +1 -0
  60. package/dist/testing.cjs +1 -0
  61. package/dist/testing.js +1 -0
  62. package/dist/types.d.ts +8 -4
  63. package/dist/types.d.ts.map +1 -1
  64. package/package.json +20 -8
package/dist/room.js CHANGED
@@ -1,256 +1,2 @@
1
- import { PulseAbortError as e, PulseConnectionError as t, PulseDisposedError as n, PulseError as r, PulseRoomTimeoutError as i } from "./errors.js";
2
- import { deriveAbortController as a } from "./_utils.js";
3
- import { encode as o } from "./protocol.js";
4
- import { signal as s } from "@vielzeug/ripple";
5
- //#region src/room.ts
6
- function c(c) {
7
- let d = s(/* @__PURE__ */ new Set()), f = /* @__PURE__ */ new Map();
8
- function p(e) {
9
- let t = f.get(e);
10
- return t || (t = {
11
- confirmed: !1,
12
- joinSent: !1,
13
- leaveAfterJoin: !1,
14
- localPresence: void 0,
15
- refs: 0,
16
- scopes: /* @__PURE__ */ new Set()
17
- }, f.set(e, t)), t;
18
- }
19
- function m(e, t) {
20
- let n = new Set(d.value);
21
- t ? n.add(e) : n.delete(e), d.value = n;
22
- }
23
- function h(e) {
24
- c.send(o({
25
- room: e,
26
- type: "join"
27
- }));
28
- }
29
- function g(e) {
30
- c.send(o({
31
- room: e,
32
- type: "leave"
33
- }));
34
- }
35
- function _(e, r) {
36
- let i = f.get(e);
37
- if (!i) throw new n(`Room "${e}"`);
38
- if (!c.isOpen()) throw new t("Connection is not open", e);
39
- c.send(o({
40
- room: e,
41
- state: r,
42
- type: "presence"
43
- })), i.localPresence = r;
44
- }
45
- function v(e, t) {
46
- let n = f.get(e);
47
- !n || !n.scopes.has(t) || (n.scopes.delete(t), n.refs--, n.refs === 0 && (n.confirmed ? (n.confirmed = !1, n.localPresence = void 0, m(e, !1), c.isOpen() && g(e), f.delete(e)) : n.joinSent ? n.leaveAfterJoin = !0 : f.delete(e)));
48
- }
49
- return {
50
- createScope(o, d, f) {
51
- if (c.disposalSignal.aborted) return u(o, d);
52
- let m = p(o), g = a(c.disposalSignal), y, b, x = !1, S = new Promise((e, t) => {
53
- y = () => {
54
- x || (x = !0, clearTimeout(C), T.removeEventListener("abort", j), e());
55
- }, b = (e) => {
56
- x || (x = !0, clearTimeout(C), T.removeEventListener("abort", j), t(e));
57
- };
58
- });
59
- S.catch(() => {});
60
- let C, w = [g.signal];
61
- if (f?.signal && w.push(f.signal), f?.timeout !== void 0) {
62
- let e = new AbortController();
63
- C = setTimeout(() => e.abort(new i(o)), f.timeout), w.push(e.signal);
64
- }
65
- let T = AbortSignal.any(w), E, D, O = /* @__PURE__ */ new Set(), k = /* @__PURE__ */ new Set();
66
- d && (E = s(/* @__PURE__ */ new Map()), D = {
67
- onJoin(e, t) {
68
- let n = new Map(E.value);
69
- n.set(e, t), E.value = n;
70
- for (let n of O) n(e, t);
71
- },
72
- onLeave(e) {
73
- let t = new Map(E.value);
74
- t.delete(e), E.value = t;
75
- for (let t of k) t(e);
76
- },
77
- onState(e) {
78
- let t = /* @__PURE__ */ new Map();
79
- for (let [n, r] of Object.entries(e)) t.set(n, r);
80
- E.value = t;
81
- },
82
- reset() {
83
- E.value = /* @__PURE__ */ new Map();
84
- }
85
- });
86
- let A = {
87
- isSettled: () => x,
88
- joined: S,
89
- name: o,
90
- presenceHandlers: D,
91
- rejectJoined: b,
92
- resolveJoined: y
93
- }, j = () => {
94
- clearTimeout(C), g.abort();
95
- let t = T.reason, n = t instanceof r ? t : new e();
96
- A.rejectJoined(n), v(o, A);
97
- };
98
- if (m.refs++, m.scopes.add(A), T.aborted) return j(), l(A, g.signal, E, O, k, o, _);
99
- if (T.addEventListener("abort", j, { once: !0 }), m.confirmed) A.resolveJoined();
100
- else if (!m.joinSent && c.isOpen()) {
101
- m.joinSent = !0;
102
- try {
103
- h(o);
104
- } catch (e) {
105
- m.joinSent = !1, A.rejectJoined(e instanceof r ? e : new t("Failed to send join", o));
106
- }
107
- }
108
- return l(A, g.signal, E, O, k, o, _, () => {
109
- g.signal.aborted || (clearTimeout(C), T.removeEventListener("abort", j), g.abort(), x || A.rejectJoined(new n(`Room "${o}"`)), v(o, A));
110
- });
111
- },
112
- dispose() {
113
- d.value = /* @__PURE__ */ new Set(), f.clear();
114
- },
115
- handleJoined(e) {
116
- let t = f.get(e);
117
- if (t) {
118
- if (t.confirmed = !0, t.joinSent = !1, m(e, !0), t.leaveAfterJoin) {
119
- t.leaveAfterJoin = !1, t.confirmed = !1, m(e, !1), c.isOpen() && g(e), f.delete(e);
120
- return;
121
- }
122
- for (let e of t.scopes) e.isSettled() || e.resolveJoined();
123
- }
124
- },
125
- handleLeft(e) {
126
- let t = f.get(e);
127
- t && (t.confirmed = !1, t.joinSent = !1, m(e, !1));
128
- },
129
- handlePresenceJoin(e, t, n) {
130
- let r = f.get(e);
131
- if (r) for (let e of r.scopes) e.presenceHandlers?.onJoin(t, n);
132
- },
133
- handlePresenceLeave(e, t) {
134
- let n = f.get(e);
135
- if (n) for (let e of n.scopes) e.presenceHandlers?.onLeave(t);
136
- },
137
- handlePresenceState(e, t) {
138
- let n = f.get(e);
139
- if (n) for (let e of n.scopes) e.presenceHandlers?.onState(t);
140
- },
141
- rejectAll(e) {
142
- for (let t of f.values()) for (let n of t.scopes) n.isSettled() || n.rejectJoined(e);
143
- },
144
- reset() {
145
- d.value = /* @__PURE__ */ new Set();
146
- for (let [e, t] of f) {
147
- if (t.refs === 0) {
148
- f.delete(e);
149
- continue;
150
- }
151
- t.confirmed = !1, t.joinSent = !1;
152
- for (let e of t.scopes) e.presenceHandlers?.reset();
153
- }
154
- },
155
- restore() {
156
- for (let [e, t] of f) if (t.refs !== 0) {
157
- t.confirmed = !1, t.joinSent = !0;
158
- try {
159
- h(e);
160
- } catch {
161
- t.joinSent = !1;
162
- }
163
- if (t.localPresence !== void 0) try {
164
- c.send(o({
165
- room: e,
166
- state: t.localPresence,
167
- type: "presence"
168
- }));
169
- } catch {}
170
- }
171
- },
172
- rooms: d
173
- };
174
- }
175
- function l(e, t, r, i, a, o, s, c) {
176
- let l = c ?? (() => {});
177
- return r ? {
178
- get disposalSignal() {
179
- return t;
180
- },
181
- dispose: l,
182
- get disposed() {
183
- return t.aborted;
184
- },
185
- get joined() {
186
- return e.joined;
187
- },
188
- get name() {
189
- return e.name;
190
- },
191
- onJoin(e) {
192
- if (t.aborted) throw new n(`Room "${o}"`);
193
- return i.add(e), () => i.delete(e);
194
- },
195
- onLeave(e) {
196
- if (t.aborted) throw new n(`Room "${o}"`);
197
- return a.add(e), () => a.delete(e);
198
- },
199
- get presence() {
200
- return r;
201
- },
202
- updatePresence(e) {
203
- s(o, e);
204
- },
205
- [Symbol.dispose]: l
206
- } : {
207
- get disposalSignal() {
208
- return t;
209
- },
210
- dispose: l,
211
- get disposed() {
212
- return t.aborted;
213
- },
214
- get joined() {
215
- return e.joined;
216
- },
217
- get name() {
218
- return e.name;
219
- },
220
- [Symbol.dispose]: l
221
- };
222
- }
223
- function u(e, t) {
224
- let r = new AbortController();
225
- r.abort(new n());
226
- let i = Promise.reject(new n(`Room "${e}"`));
227
- return i.catch(() => {}), t ? {
228
- disposalSignal: r.signal,
229
- dispose() {},
230
- disposed: !0,
231
- joined: i,
232
- name: e,
233
- onJoin() {
234
- throw new n(`Room "${e}"`);
235
- },
236
- onLeave() {
237
- throw new n(`Room "${e}"`);
238
- },
239
- presence: s(/* @__PURE__ */ new Map()),
240
- updatePresence() {
241
- throw new n(`Room "${e}"`);
242
- },
243
- [Symbol.dispose]() {}
244
- } : {
245
- disposalSignal: r.signal,
246
- dispose() {},
247
- disposed: !0,
248
- joined: i,
249
- name: e,
250
- [Symbol.dispose]() {}
251
- };
252
- }
253
- //#endregion
254
- export { c as createRoomRegistry };
255
-
1
+ import{PulseAbortError as e,PulseConnectionError as t,PulseDisposedError as n,PulseError as r,PulseRoomTimeoutError as i}from"./errors.js";import{deriveAbortController as a}from"./_utils.js";import{createStore as o}from"./_store.js";import{encode as s}from"./protocol.js";function createRoomRegistry(c){let l=o(new Set,c.onStoreError),u=new Map;function getOrCreate(e){let t=u.get(e);return t||(t={confirmed:!1,joinSent:!1,leaveAfterJoin:!1,localPresence:void 0,refs:0,scopes:new Set},u.set(e,t)),t}function setRoom(e,t){let n=new Set(l.getSnapshot());t?n.add(e):n.delete(e),l.set(n)}function sendJoin(e){c.send(s({room:e,type:`join`}))}function sendLeave(e){c.send(s({room:e,type:`leave`}))}function updatePresence(e,r){let i=u.get(e);if(!i)throw new n(`Room "${e}"`);if(!c.isOpen())throw new t(`Connection is not open`,e);c.send(s({room:e,state:r,type:`presence`})),i.localPresence=r}function releaseScope(e,t){let n=u.get(e);n&&n.scopes.has(t)&&(n.scopes.delete(t),n.refs--,n.refs===0&&(n.confirmed?(n.confirmed=!1,n.localPresence=void 0,setRoom(e,!1),c.isOpen()&&sendLeave(e),u.delete(e)):n.joinSent?n.leaveAfterJoin=!0:u.delete(e)))}return{createScope(s,l,u){if(c.disposalSignal.aborted)return createDeadScope(s,l);let d=getOrCreate(s),f=a(c.disposalSignal),resolveJoined,rejectJoined,p=!1,m=new Promise((e,t)=>{resolveJoined=()=>{p||(p=!0,clearTimeout(h),_.removeEventListener(`abort`,onAbort),e())},rejectJoined=e=>{p||(p=!0,clearTimeout(h),_.removeEventListener(`abort`,onAbort),t(e))}});m.catch(()=>{});let h,g=[f.signal];if(u?.signal&&g.push(u.signal),u?.timeout!==void 0){let e=new AbortController;h=setTimeout(()=>e.abort(new i(s)),u.timeout),g.push(e.signal)}let _=AbortSignal.any(g),v,y,b=new Set,x=new Set;l&&(v=o(new Map,c.onStoreError),y={onJoin(e,t){let n=new Map(v.getSnapshot());n.set(e,t),v.set(n);for(let n of b)n(e,t)},onLeave(e){let t=new Map(v.getSnapshot());t.delete(e),v.set(t);for(let t of x)t(e)},onState(e){let t=new Map;for(let[n,r]of Object.entries(e))t.set(n,r);v.set(t)},reset(){v.set(new Map)}});let S={isSettled:()=>p,joined:m,name:s,presenceHandlers:y,rejectJoined,resolveJoined},onAbort=()=>{clearTimeout(h),f.abort();let t=_.reason,n=t instanceof r?t:new e;S.rejectJoined(n),releaseScope(s,S)};if(d.refs++,d.scopes.add(S),_.aborted)return onAbort(),buildPublicScope(S,f.signal,v,b,x,s,updatePresence);if(_.addEventListener(`abort`,onAbort,{once:!0}),d.confirmed)S.resolveJoined();else if(!d.joinSent&&c.isOpen()){d.joinSent=!0;try{sendJoin(s)}catch(e){d.joinSent=!1,S.rejectJoined(e instanceof r?e:new t(`Failed to send join`,s))}}let disposeScope=()=>{f.signal.aborted||(clearTimeout(h),_.removeEventListener(`abort`,onAbort),f.abort(),p||S.rejectJoined(new n(`Room "${s}"`)),releaseScope(s,S))};return buildPublicScope(S,f.signal,v,b,x,s,updatePresence,disposeScope)},dispose(){l.set(new Set),u.clear()},handleJoined(e){let t=u.get(e);if(t){if(t.confirmed=!0,t.joinSent=!1,setRoom(e,!0),t.leaveAfterJoin){t.leaveAfterJoin=!1,t.confirmed=!1,setRoom(e,!1),c.isOpen()&&sendLeave(e),u.delete(e);return}for(let e of t.scopes)e.isSettled()||e.resolveJoined()}},handleLeft(e){let t=u.get(e);t&&(t.confirmed=!1,t.joinSent=!1,setRoom(e,!1))},handlePresenceJoin(e,t,n){let r=u.get(e);if(r)for(let e of r.scopes)e.presenceHandlers?.onJoin(t,n)},handlePresenceLeave(e,t){let n=u.get(e);if(n)for(let e of n.scopes)e.presenceHandlers?.onLeave(t)},handlePresenceState(e,t){let n=u.get(e);if(n)for(let e of n.scopes)e.presenceHandlers?.onState(t)},rejectAll(e){for(let t of u.values())for(let n of t.scopes)n.isSettled()||n.rejectJoined(e)},reset(){l.set(new Set);for(let[e,t]of u){if(t.refs===0){u.delete(e);continue}t.confirmed=!1,t.joinSent=!1;for(let e of t.scopes)e.presenceHandlers?.reset()}},restore(){for(let[e,t]of u)if(t.refs!==0){t.confirmed=!1,t.joinSent=!0;try{sendJoin(e)}catch{t.joinSent=!1}if(t.localPresence!==void 0)try{c.send(s({room:e,state:t.localPresence,type:`presence`}))}catch{}}},rooms:l}}function buildPublicScope(e,t,r,i,a,o,s,c){let l=c??(()=>{});return r?{get disposalSignal(){return t},dispose:l,get disposed(){return t.aborted},get joined(){return e.joined},get name(){return e.name},onJoin(e){if(t.aborted)throw new n(`Room "${o}"`);return i.add(e),()=>i.delete(e)},onLeave(e){if(t.aborted)throw new n(`Room "${o}"`);return a.add(e),()=>a.delete(e)},get presence(){return r},updatePresence(e){s(o,e)},[Symbol.dispose]:l}:{get disposalSignal(){return t},dispose:l,get disposed(){return t.aborted},get joined(){return e.joined},get name(){return e.name},[Symbol.dispose]:l}}function createDeadScope(e,t){let r=new AbortController;r.abort(new n);let i=Promise.reject(new n(`Room "${e}"`));return i.catch(()=>{}),t?{disposalSignal:r.signal,dispose(){},disposed:!0,joined:i,name:e,onJoin(){throw new n(`Room "${e}"`)},onLeave(){throw new n(`Room "${e}"`)},presence:o(new Map,()=>{}),updatePresence(){throw new n(`Room "${e}"`)},[Symbol.dispose](){}}:{disposalSignal:r.signal,dispose(){},disposed:!0,joined:i,name:e,[Symbol.dispose](){}}}export{createRoomRegistry};
256
2
  //# sourceMappingURL=room.js.map
package/dist/room.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"room.js","names":[],"sources":["../src/room.ts"],"sourcesContent":["import { type Signal, signal } from '@vielzeug/ripple';\nimport { deriveAbortController } from './_utils';\nimport { PulseAbortError, PulseConnectionError, PulseDisposedError, PulseError, PulseRoomTimeoutError } from './errors';\nimport { encode } from './protocol';\nimport type { PresenceRoomScope, RoomOptions, RoomScopeBase, Unsubscribe } from './types';\n\ntype PresenceHandlers = {\n onState(members: Record<string, unknown>): void;\n onJoin(id: string, state: unknown): void;\n onLeave(id: string): void;\n reset(): void;\n};\n\ntype RoomState = {\n refs: number;\n confirmed: boolean;\n joinSent: boolean;\n leaveAfterJoin: boolean;\n localPresence: unknown | undefined;\n scopes: Set<ScopeInternal>;\n};\n\ntype ScopeInternal = {\n readonly name: string;\n readonly joined: Promise<void>;\n resolveJoined(): void;\n rejectJoined(error: PulseError): void;\n isSettled(): boolean;\n presenceHandlers?: PresenceHandlers;\n};\n\ntype RegistryOptions = {\n isOpen: () => boolean;\n send: (frame: string) => void;\n disposalSignal: AbortSignal;\n};\n\nexport type RoomRegistry = {\n readonly rooms: Signal<ReadonlySet<string>>;\n createScope(name: string, hasPresence: boolean, opts: RoomOptions | undefined): RoomScopeBase | PresenceRoomScope;\n handleJoined(room: string): void;\n handleLeft(room: string): void;\n handlePresenceState(room: string, members: Record<string, unknown>): void;\n handlePresenceJoin(room: string, id: string, state: unknown): void;\n handlePresenceLeave(room: string, id: string): void;\n restore(): void;\n reset(): void;\n rejectAll(error: PulseError): void;\n dispose(): void;\n};\n\n/**\n * Manages ref-counted room memberships, pending join tracking, and presence state.\n * @internal\n */\nexport function createRoomRegistry(opts: RegistryOptions): RoomRegistry {\n const rooms = signal<ReadonlySet<string>>(new Set());\n const states = new Map<string, RoomState>();\n\n function getOrCreate(name: string): RoomState {\n let state = states.get(name);\n\n if (!state) {\n state = {\n confirmed: false,\n joinSent: false,\n leaveAfterJoin: false,\n localPresence: undefined,\n refs: 0,\n scopes: new Set(),\n };\n states.set(name, state);\n }\n\n return state;\n }\n\n function setRoom(name: string, joined: boolean): void {\n const next = new Set(rooms.value);\n if (joined) next.add(name);\n else next.delete(name);\n rooms.value = next;\n }\n\n function sendJoin(name: string): void {\n opts.send(encode({ room: name, type: 'join' }));\n }\n\n function sendLeave(name: string): void {\n opts.send(encode({ room: name, type: 'leave' }));\n }\n\n function updatePresence(name: string, state: unknown): void {\n const roomState = states.get(name);\n if (!roomState) throw new PulseDisposedError(`Room \"${name}\"`);\n if (!opts.isOpen()) throw new PulseConnectionError('Connection is not open', name);\n opts.send(encode({ room: name, state, type: 'presence' }));\n roomState.localPresence = state;\n }\n\n function releaseScope(name: string, scope: ScopeInternal): void {\n const state = states.get(name);\n if (!state || !state.scopes.has(scope)) return;\n\n state.scopes.delete(scope);\n state.refs--;\n\n if (state.refs === 0) {\n if (state.confirmed) {\n state.confirmed = false;\n state.localPresence = undefined;\n setRoom(name, false);\n if (opts.isOpen()) sendLeave(name);\n states.delete(name);\n } else if (state.joinSent) {\n state.leaveAfterJoin = true;\n // Keep state alive until handleJoined processes the compensating leave\n } else {\n states.delete(name);\n }\n }\n }\n\n return {\n createScope(name, hasPresence, joinOpts) {\n if (opts.disposalSignal.aborted) {\n return createDeadScope(name, hasPresence);\n }\n\n const state = getOrCreate(name);\n const ctrl = deriveAbortController(opts.disposalSignal);\n\n let resolveJoined!: () => void;\n let rejectJoined!: (error: PulseError) => void;\n let settled = false;\n\n const joined = new Promise<void>((resolve, reject) => {\n resolveJoined = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n resolve();\n };\n rejectJoined = (error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n reject(error);\n };\n });\n // Suppress unhandled rejection when joined is never awaited\n joined.catch(() => {});\n\n // Timeout + abort handling\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const signals: AbortSignal[] = [ctrl.signal];\n\n if (joinOpts?.signal) signals.push(joinOpts.signal);\n\n if (joinOpts?.timeout !== undefined) {\n const timeoutCtrl = new AbortController();\n timeoutId = setTimeout(() => timeoutCtrl.abort(new PulseRoomTimeoutError(name)), joinOpts.timeout);\n signals.push(timeoutCtrl.signal);\n }\n\n const combined = AbortSignal.any(signals);\n\n // Presence state\n let presenceSignal: Signal<Map<string, unknown>> | undefined;\n let presenceHandlers: PresenceHandlers | undefined;\n const joinHandlers = new Set<(memberId: string, state: unknown) => void>();\n const leaveHandlers = new Set<(memberId: string) => void>();\n\n if (hasPresence) {\n presenceSignal = signal(new Map<string, unknown>());\n presenceHandlers = {\n onJoin(id, memberState) {\n const next = new Map(presenceSignal!.value);\n next.set(id, memberState);\n presenceSignal!.value = next;\n for (const handler of joinHandlers) handler(id, memberState);\n },\n onLeave(id) {\n const next = new Map(presenceSignal!.value);\n next.delete(id);\n presenceSignal!.value = next;\n for (const handler of leaveHandlers) handler(id);\n },\n onState(members) {\n const next = new Map<string, unknown>();\n for (const [id, memberState] of Object.entries(members)) next.set(id, memberState);\n presenceSignal!.value = next;\n },\n reset() {\n presenceSignal!.value = new Map();\n },\n };\n }\n\n const scope: ScopeInternal = {\n isSettled: () => settled,\n joined,\n name,\n presenceHandlers,\n rejectJoined,\n resolveJoined,\n };\n\n // Abort handler — rejects joined and auto-disposes\n const onAbort = (): void => {\n clearTimeout(timeoutId);\n ctrl.abort();\n const reason = combined.reason;\n const error = reason instanceof PulseError ? reason : new PulseAbortError();\n scope.rejectJoined(error);\n releaseScope(name, scope);\n };\n\n // Register scope BEFORE setting up abort, so releaseScope is safe\n state.refs++;\n state.scopes.add(scope);\n\n if (combined.aborted) {\n onAbort();\n return buildPublicScope(scope, ctrl.signal, presenceSignal, joinHandlers, leaveHandlers, name, updatePresence);\n }\n\n combined.addEventListener('abort', onAbort, { once: true });\n\n // Start join\n if (state.confirmed) {\n scope.resolveJoined();\n } else if (!state.joinSent && opts.isOpen()) {\n state.joinSent = true;\n try {\n sendJoin(name);\n } catch (error) {\n state.joinSent = false;\n scope.rejectJoined(\n error instanceof PulseError ? error : new PulseConnectionError('Failed to send join', name),\n );\n }\n }\n\n // Build dispose function\n const disposeScope = (): void => {\n if (ctrl.signal.aborted) return;\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n ctrl.abort();\n if (!settled) scope.rejectJoined(new PulseDisposedError(`Room \"${name}\"`));\n releaseScope(name, scope);\n };\n\n return buildPublicScope(\n scope,\n ctrl.signal,\n presenceSignal,\n joinHandlers,\n leaveHandlers,\n name,\n updatePresence,\n disposeScope,\n );\n },\n\n dispose() {\n rooms.value = new Set();\n states.clear();\n },\n\n handleJoined(room) {\n const state = states.get(room);\n if (!state) return;\n\n state.confirmed = true;\n state.joinSent = false;\n setRoom(room, true);\n\n if (state.leaveAfterJoin) {\n state.leaveAfterJoin = false;\n state.confirmed = false;\n setRoom(room, false);\n if (opts.isOpen()) sendLeave(room);\n states.delete(room);\n return;\n }\n\n for (const scope of state.scopes) {\n if (!scope.isSettled()) scope.resolveJoined();\n }\n },\n\n handleLeft(room) {\n const state = states.get(room);\n if (!state) return;\n\n state.confirmed = false;\n state.joinSent = false;\n setRoom(room, false);\n },\n\n handlePresenceJoin(room, id, memberState) {\n const state = states.get(room);\n if (!state) return;\n for (const scope of state.scopes) scope.presenceHandlers?.onJoin(id, memberState);\n },\n\n handlePresenceLeave(room, id) {\n const state = states.get(room);\n if (!state) return;\n for (const scope of state.scopes) scope.presenceHandlers?.onLeave(id);\n },\n\n handlePresenceState(room, members) {\n const state = states.get(room);\n if (!state) return;\n for (const scope of state.scopes) scope.presenceHandlers?.onState(members);\n },\n\n rejectAll(error) {\n for (const state of states.values()) {\n for (const scope of state.scopes) {\n if (!scope.isSettled()) scope.rejectJoined(error);\n }\n }\n },\n\n reset() {\n rooms.value = new Set();\n for (const [name, state] of states) {\n if (state.refs === 0) {\n states.delete(name);\n continue;\n }\n state.confirmed = false;\n state.joinSent = false;\n for (const scope of state.scopes) scope.presenceHandlers?.reset();\n }\n },\n\n restore() {\n for (const [name, state] of states) {\n if (state.refs === 0) continue;\n\n state.confirmed = false;\n state.joinSent = true;\n\n try {\n sendJoin(name);\n } catch {\n state.joinSent = false;\n }\n\n if (state.localPresence !== undefined) {\n try {\n opts.send(encode({ room: name, state: state.localPresence, type: 'presence' }));\n } catch {\n // non-fatal; next updatePresence retries\n }\n }\n }\n },\n rooms,\n };\n}\n\nfunction buildPublicScope(\n scope: ScopeInternal,\n disposalSignal: AbortSignal,\n presenceSignal: Signal<Map<string, unknown>> | undefined,\n joinHandlers: Set<(memberId: string, state: unknown) => void>,\n leaveHandlers: Set<(memberId: string) => void>,\n name: string,\n updatePresence: (name: string, state: unknown) => void,\n disposeFn?: () => void,\n): RoomScopeBase | PresenceRoomScope {\n const dispose = disposeFn ?? (() => {});\n\n if (presenceSignal) {\n const publicScope: PresenceRoomScope = {\n get disposalSignal() {\n return disposalSignal;\n },\n dispose,\n get disposed() {\n return disposalSignal.aborted;\n },\n get joined() {\n return scope.joined;\n },\n get name() {\n return scope.name;\n },\n onJoin(handler: (memberId: string, state: unknown) => void): Unsubscribe {\n if (disposalSignal.aborted) throw new PulseDisposedError(`Room \"${name}\"`);\n joinHandlers.add(handler);\n return () => joinHandlers.delete(handler);\n },\n onLeave(handler: (memberId: string) => void): Unsubscribe {\n if (disposalSignal.aborted) throw new PulseDisposedError(`Room \"${name}\"`);\n leaveHandlers.add(handler);\n return () => leaveHandlers.delete(handler);\n },\n get presence() {\n return presenceSignal;\n },\n updatePresence(state: unknown) {\n updatePresence(name, state);\n },\n [Symbol.dispose]: dispose,\n };\n return publicScope;\n }\n\n const publicScope: RoomScopeBase = {\n get disposalSignal() {\n return disposalSignal;\n },\n dispose,\n get disposed() {\n return disposalSignal.aborted;\n },\n get joined() {\n return scope.joined;\n },\n get name() {\n return scope.name;\n },\n [Symbol.dispose]: dispose,\n };\n return publicScope;\n}\n\nfunction createDeadScope(name: string, hasPresence: boolean): RoomScopeBase | PresenceRoomScope {\n const disposalCtrl = new AbortController();\n disposalCtrl.abort(new PulseDisposedError());\n\n const joined = Promise.reject(new PulseDisposedError(`Room \"${name}\"`));\n joined.catch(() => {});\n\n if (hasPresence) {\n return {\n disposalSignal: disposalCtrl.signal,\n dispose() {},\n disposed: true,\n joined,\n name,\n onJoin() {\n throw new PulseDisposedError(`Room \"${name}\"`);\n },\n onLeave() {\n throw new PulseDisposedError(`Room \"${name}\"`);\n },\n presence: signal(new Map()),\n updatePresence() {\n throw new PulseDisposedError(`Room \"${name}\"`);\n },\n [Symbol.dispose]() {},\n };\n }\n\n return {\n disposalSignal: disposalCtrl.signal,\n dispose() {},\n disposed: true,\n joined,\n name,\n [Symbol.dispose]() {},\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"room.js","names":[],"sources":["../src/room.ts"],"sourcesContent":["import { createStore, type MutableStore } from './_store';\nimport { deriveAbortController } from './_utils';\nimport { PulseAbortError, PulseConnectionError, PulseDisposedError, PulseError, PulseRoomTimeoutError } from './errors';\nimport { encode } from './protocol';\nimport type { PresenceRoomScope, RoomOptions, RoomScopeBase, Unsubscribe } from './types';\n\ntype PresenceHandlers = {\n onState(members: Record<string, unknown>): void;\n onJoin(id: string, state: unknown): void;\n onLeave(id: string): void;\n reset(): void;\n};\n\ntype RoomState = {\n refs: number;\n confirmed: boolean;\n joinSent: boolean;\n leaveAfterJoin: boolean;\n localPresence: unknown | undefined;\n scopes: Set<ScopeInternal>;\n};\n\ntype ScopeInternal = {\n readonly name: string;\n readonly joined: Promise<void>;\n resolveJoined(): void;\n rejectJoined(error: PulseError): void;\n isSettled(): boolean;\n presenceHandlers?: PresenceHandlers;\n};\n\ntype RegistryOptions = {\n isOpen: () => boolean;\n onStoreError: (error: unknown) => void;\n send: (frame: string) => void;\n disposalSignal: AbortSignal;\n};\n\nexport type RoomRegistry = {\n readonly rooms: MutableStore<ReadonlySet<string>>;\n createScope(name: string, hasPresence: boolean, opts: RoomOptions | undefined): RoomScopeBase | PresenceRoomScope;\n handleJoined(room: string): void;\n handleLeft(room: string): void;\n handlePresenceState(room: string, members: Record<string, unknown>): void;\n handlePresenceJoin(room: string, id: string, state: unknown): void;\n handlePresenceLeave(room: string, id: string): void;\n restore(): void;\n reset(): void;\n rejectAll(error: PulseError): void;\n dispose(): void;\n};\n\n/**\n * Manages ref-counted room memberships, pending join tracking, and presence state.\n * @internal\n */\nexport function createRoomRegistry(opts: RegistryOptions): RoomRegistry {\n const rooms = createStore<ReadonlySet<string>>(new Set(), opts.onStoreError);\n const states = new Map<string, RoomState>();\n\n function getOrCreate(name: string): RoomState {\n let state = states.get(name);\n\n if (!state) {\n state = {\n confirmed: false,\n joinSent: false,\n leaveAfterJoin: false,\n localPresence: undefined,\n refs: 0,\n scopes: new Set(),\n };\n states.set(name, state);\n }\n\n return state;\n }\n\n function setRoom(name: string, joined: boolean): void {\n const next = new Set(rooms.getSnapshot());\n if (joined) next.add(name);\n else next.delete(name);\n rooms.set(next);\n }\n\n function sendJoin(name: string): void {\n opts.send(encode({ room: name, type: 'join' }));\n }\n\n function sendLeave(name: string): void {\n opts.send(encode({ room: name, type: 'leave' }));\n }\n\n function updatePresence(name: string, state: unknown): void {\n const roomState = states.get(name);\n if (!roomState) throw new PulseDisposedError(`Room \"${name}\"`);\n if (!opts.isOpen()) throw new PulseConnectionError('Connection is not open', name);\n opts.send(encode({ room: name, state, type: 'presence' }));\n roomState.localPresence = state;\n }\n\n function releaseScope(name: string, scope: ScopeInternal): void {\n const state = states.get(name);\n if (!state || !state.scopes.has(scope)) return;\n\n state.scopes.delete(scope);\n state.refs--;\n\n if (state.refs === 0) {\n if (state.confirmed) {\n state.confirmed = false;\n state.localPresence = undefined;\n setRoom(name, false);\n if (opts.isOpen()) sendLeave(name);\n states.delete(name);\n } else if (state.joinSent) {\n state.leaveAfterJoin = true;\n // Keep state alive until handleJoined processes the compensating leave\n } else {\n states.delete(name);\n }\n }\n }\n\n return {\n createScope(name, hasPresence, joinOpts) {\n if (opts.disposalSignal.aborted) {\n return createDeadScope(name, hasPresence);\n }\n\n const state = getOrCreate(name);\n const ctrl = deriveAbortController(opts.disposalSignal);\n\n let resolveJoined!: () => void;\n let rejectJoined!: (error: PulseError) => void;\n let settled = false;\n\n const joined = new Promise<void>((resolve, reject) => {\n resolveJoined = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n resolve();\n };\n rejectJoined = (error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n reject(error);\n };\n });\n // Suppress unhandled rejection when joined is never awaited\n joined.catch(() => {});\n\n // Timeout + abort handling\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const signals: AbortSignal[] = [ctrl.signal];\n\n if (joinOpts?.signal) signals.push(joinOpts.signal);\n\n if (joinOpts?.timeout !== undefined) {\n const timeoutCtrl = new AbortController();\n timeoutId = setTimeout(() => timeoutCtrl.abort(new PulseRoomTimeoutError(name)), joinOpts.timeout);\n signals.push(timeoutCtrl.signal);\n }\n\n const combined = AbortSignal.any(signals);\n\n // Presence state\n let presenceSignal: MutableStore<Map<string, unknown>> | undefined;\n let presenceHandlers: PresenceHandlers | undefined;\n const joinHandlers = new Set<(memberId: string, state: unknown) => void>();\n const leaveHandlers = new Set<(memberId: string) => void>();\n\n if (hasPresence) {\n presenceSignal = createStore(new Map<string, unknown>(), opts.onStoreError);\n presenceHandlers = {\n onJoin(id, memberState) {\n const next = new Map(presenceSignal!.getSnapshot());\n next.set(id, memberState);\n presenceSignal!.set(next);\n for (const handler of joinHandlers) handler(id, memberState);\n },\n onLeave(id) {\n const next = new Map(presenceSignal!.getSnapshot());\n next.delete(id);\n presenceSignal!.set(next);\n for (const handler of leaveHandlers) handler(id);\n },\n onState(members) {\n const next = new Map<string, unknown>();\n for (const [id, memberState] of Object.entries(members)) next.set(id, memberState);\n presenceSignal!.set(next);\n },\n reset() {\n presenceSignal!.set(new Map());\n },\n };\n }\n\n const scope: ScopeInternal = {\n isSettled: () => settled,\n joined,\n name,\n presenceHandlers,\n rejectJoined,\n resolveJoined,\n };\n\n // Abort handler — rejects joined and auto-disposes\n const onAbort = (): void => {\n clearTimeout(timeoutId);\n ctrl.abort();\n const reason = combined.reason;\n const error = reason instanceof PulseError ? reason : new PulseAbortError();\n scope.rejectJoined(error);\n releaseScope(name, scope);\n };\n\n // Register scope BEFORE setting up abort, so releaseScope is safe\n state.refs++;\n state.scopes.add(scope);\n\n if (combined.aborted) {\n onAbort();\n return buildPublicScope(scope, ctrl.signal, presenceSignal, joinHandlers, leaveHandlers, name, updatePresence);\n }\n\n combined.addEventListener('abort', onAbort, { once: true });\n\n // Start join\n if (state.confirmed) {\n scope.resolveJoined();\n } else if (!state.joinSent && opts.isOpen()) {\n state.joinSent = true;\n try {\n sendJoin(name);\n } catch (error) {\n state.joinSent = false;\n scope.rejectJoined(\n error instanceof PulseError ? error : new PulseConnectionError('Failed to send join', name),\n );\n }\n }\n\n // Build dispose function\n const disposeScope = (): void => {\n if (ctrl.signal.aborted) return;\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n ctrl.abort();\n if (!settled) scope.rejectJoined(new PulseDisposedError(`Room \"${name}\"`));\n releaseScope(name, scope);\n };\n\n return buildPublicScope(\n scope,\n ctrl.signal,\n presenceSignal,\n joinHandlers,\n leaveHandlers,\n name,\n updatePresence,\n disposeScope,\n );\n },\n\n dispose() {\n rooms.set(new Set());\n states.clear();\n },\n\n handleJoined(room) {\n const state = states.get(room);\n if (!state) return;\n\n state.confirmed = true;\n state.joinSent = false;\n setRoom(room, true);\n\n if (state.leaveAfterJoin) {\n state.leaveAfterJoin = false;\n state.confirmed = false;\n setRoom(room, false);\n if (opts.isOpen()) sendLeave(room);\n states.delete(room);\n return;\n }\n\n for (const scope of state.scopes) {\n if (!scope.isSettled()) scope.resolveJoined();\n }\n },\n\n handleLeft(room) {\n const state = states.get(room);\n if (!state) return;\n\n state.confirmed = false;\n state.joinSent = false;\n setRoom(room, false);\n },\n\n handlePresenceJoin(room, id, memberState) {\n const state = states.get(room);\n if (!state) return;\n for (const scope of state.scopes) scope.presenceHandlers?.onJoin(id, memberState);\n },\n\n handlePresenceLeave(room, id) {\n const state = states.get(room);\n if (!state) return;\n for (const scope of state.scopes) scope.presenceHandlers?.onLeave(id);\n },\n\n handlePresenceState(room, members) {\n const state = states.get(room);\n if (!state) return;\n for (const scope of state.scopes) scope.presenceHandlers?.onState(members);\n },\n\n rejectAll(error) {\n for (const state of states.values()) {\n for (const scope of state.scopes) {\n if (!scope.isSettled()) scope.rejectJoined(error);\n }\n }\n },\n\n reset() {\n rooms.set(new Set());\n for (const [name, state] of states) {\n if (state.refs === 0) {\n states.delete(name);\n continue;\n }\n state.confirmed = false;\n state.joinSent = false;\n for (const scope of state.scopes) scope.presenceHandlers?.reset();\n }\n },\n\n restore() {\n for (const [name, state] of states) {\n if (state.refs === 0) continue;\n\n state.confirmed = false;\n state.joinSent = true;\n\n try {\n sendJoin(name);\n } catch {\n state.joinSent = false;\n }\n\n if (state.localPresence !== undefined) {\n try {\n opts.send(encode({ room: name, state: state.localPresence, type: 'presence' }));\n } catch {\n // non-fatal; next updatePresence retries\n }\n }\n }\n },\n rooms,\n };\n}\n\nfunction buildPublicScope(\n scope: ScopeInternal,\n disposalSignal: AbortSignal,\n presenceSignal: MutableStore<Map<string, unknown>> | undefined,\n joinHandlers: Set<(memberId: string, state: unknown) => void>,\n leaveHandlers: Set<(memberId: string) => void>,\n name: string,\n updatePresence: (name: string, state: unknown) => void,\n disposeFn?: () => void,\n): RoomScopeBase | PresenceRoomScope {\n const dispose = disposeFn ?? (() => {});\n\n if (presenceSignal) {\n const publicScope: PresenceRoomScope = {\n get disposalSignal() {\n return disposalSignal;\n },\n dispose,\n get disposed() {\n return disposalSignal.aborted;\n },\n get joined() {\n return scope.joined;\n },\n get name() {\n return scope.name;\n },\n onJoin(handler: (memberId: string, state: unknown) => void): Unsubscribe {\n if (disposalSignal.aborted) throw new PulseDisposedError(`Room \"${name}\"`);\n joinHandlers.add(handler);\n return () => joinHandlers.delete(handler);\n },\n onLeave(handler: (memberId: string) => void): Unsubscribe {\n if (disposalSignal.aborted) throw new PulseDisposedError(`Room \"${name}\"`);\n leaveHandlers.add(handler);\n return () => leaveHandlers.delete(handler);\n },\n get presence() {\n return presenceSignal;\n },\n updatePresence(state: unknown) {\n updatePresence(name, state);\n },\n [Symbol.dispose]: dispose,\n };\n return publicScope;\n }\n\n const publicScope: RoomScopeBase = {\n get disposalSignal() {\n return disposalSignal;\n },\n dispose,\n get disposed() {\n return disposalSignal.aborted;\n },\n get joined() {\n return scope.joined;\n },\n get name() {\n return scope.name;\n },\n [Symbol.dispose]: dispose,\n };\n return publicScope;\n}\n\nfunction createDeadScope(name: string, hasPresence: boolean): RoomScopeBase | PresenceRoomScope {\n const disposalCtrl = new AbortController();\n disposalCtrl.abort(new PulseDisposedError());\n\n const joined = Promise.reject(new PulseDisposedError(`Room \"${name}\"`));\n joined.catch(() => {});\n\n if (hasPresence) {\n return {\n disposalSignal: disposalCtrl.signal,\n dispose() {},\n disposed: true,\n joined,\n name,\n onJoin() {\n throw new PulseDisposedError(`Room \"${name}\"`);\n },\n onLeave() {\n throw new PulseDisposedError(`Room \"${name}\"`);\n },\n presence: createStore(new Map(), () => {}),\n updatePresence() {\n throw new PulseDisposedError(`Room \"${name}\"`);\n },\n [Symbol.dispose]() {},\n };\n }\n\n return {\n disposalSignal: disposalCtrl.signal,\n dispose() {},\n disposed: true,\n joined,\n name,\n [Symbol.dispose]() {},\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Testing utilities for Pulse
3
+ *
4
+ * ⚠️ Requires a browser-like environment (browser / jsdom / happy-dom) for the
5
+ * `CloseEvent`/`MessageEvent` globals the socket dispatches.
6
+ *
7
+ * This is the package's only public testing entry point.
8
+ */
9
+ export { frames, MockWebSocket, type MockWebSocketOptions } from './mock-websocket';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ var e=class MockWebSocket{static CLOSED=3;static CLOSING=2;static CONNECTING=0;static deferClose=!1;static OPEN=1;static instances=[];CLOSED=MockWebSocket.CLOSED;CLOSING=MockWebSocket.CLOSING;CONNECTING=MockWebSocket.CONNECTING;OPEN=MockWebSocket.OPEN;onclose=null;onerror=null;onmessage=null;onopen=null;readyState=MockWebSocket.CONNECTING;sentMessages=[];url;protocols;constructor(e,t,n={}){this.url=e,this.protocols=t,MockWebSocket.instances.push(this),n.autoOpen&&setTimeout(()=>this.open(),0)}close(e=1e3,t=``){if(MockWebSocket.deferClose){this.readyState=MockWebSocket.CLOSING;return}this.finishClose(e,t)}finishClose(e=1e3,t=``){this.readyState=MockWebSocket.CLOSED,this.onclose?.({code:e,reason:t})}drop(e=1006,t=`network error`){this.close(e,t)}error(){this.onerror?.(new Event(`error`))}open(){this.readyState=MockWebSocket.OPEN,this.onopen?.(new Event(`open`))}receive(e){this.onmessage?.({data:JSON.stringify(e)})}send(e){this.sentMessages.push(e)}};function frames(e){return e.sentMessages.map(e=>JSON.parse(e))}exports.MockWebSocket=e,exports.frames=frames;
2
+ //# sourceMappingURL=mock-websocket.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-websocket.cjs","names":[],"sources":["../../src/testing/mock-websocket.ts"],"sourcesContent":["export type MockWebSocketOptions = {\n /**\n * Open the socket automatically on the next macrotask instead of waiting for an\n * explicit `open()` call. Useful for consumers (demos, app-level tests) that\n * install the class as `globalThis.WebSocket` and never touch the instance.\n * @default false\n */\n readonly autoOpen?: boolean;\n};\n\n/**\n * A wire-protocol-accurate `WebSocket` stand-in for tests and demos: pulse dials it through\n * `new WebSocket(url, protocols)`, tests drive it through `open()`, `receive()`, `drop()`,\n * and `error()`, and every outbound frame lands in `sentMessages` for `frames()` to decode.\n *\n * Instances register on the static `instances` array in construction order, so a test can\n * grab the socket pulse just created without reaching into the client.\n */\nexport class MockWebSocket {\n static CLOSED = 3;\n static CLOSING = 2;\n static CONNECTING = 0;\n static deferClose = false;\n static OPEN = 1;\n static instances: MockWebSocket[] = [];\n\n readonly CLOSED = MockWebSocket.CLOSED;\n readonly CLOSING = MockWebSocket.CLOSING;\n readonly CONNECTING = MockWebSocket.CONNECTING;\n readonly OPEN = MockWebSocket.OPEN;\n\n onclose: ((event: CloseEvent) => void) | null = null;\n onerror: ((event: Event) => void) | null = null;\n onmessage: ((event: MessageEvent) => void) | null = null;\n onopen: ((event: Event) => void) | null = null;\n readyState = MockWebSocket.CONNECTING;\n readonly sentMessages: string[] = [];\n readonly url: string;\n readonly protocols?: string | string[];\n\n constructor(url: string, protocols?: string | string[], options: MockWebSocketOptions = {}) {\n this.url = url;\n this.protocols = protocols;\n MockWebSocket.instances.push(this);\n if (options.autoOpen) setTimeout(() => this.open(), 0);\n }\n\n close(code = 1000, reason = ''): void {\n if (MockWebSocket.deferClose) {\n this.readyState = MockWebSocket.CLOSING;\n return;\n }\n\n this.finishClose(code, reason);\n }\n\n finishClose(code = 1000, reason = ''): void {\n this.readyState = MockWebSocket.CLOSED;\n this.onclose?.({ code, reason } as CloseEvent);\n }\n\n drop(code = 1006, reason = 'network error'): void {\n this.close(code, reason);\n }\n\n error(): void {\n this.onerror?.(new Event('error'));\n }\n\n open(): void {\n this.readyState = MockWebSocket.OPEN;\n this.onopen?.(new Event('open'));\n }\n\n receive(frame: unknown): void {\n this.onmessage?.({ data: JSON.stringify(frame) } as MessageEvent);\n }\n\n send(frame: string): void {\n this.sentMessages.push(frame);\n }\n}\n\n/** Decodes every frame the socket sent, in order. */\nexport function frames(socket: MockWebSocket): Array<Record<string, unknown>> {\n return socket.sentMessages.map((frame) => JSON.parse(frame) as Record<string, unknown>);\n}\n"],"mappings":"AAkBA,IAAa,EAAb,MAAa,aAAc,CACzB,OAAO,OAAS,EAChB,OAAO,QAAU,EACjB,OAAO,WAAa,EACpB,OAAO,WAAa,GACpB,OAAO,KAAO,EACd,OAAO,UAA6B,CAAC,EAErC,OAAkB,cAAc,OAChC,QAAmB,cAAc,QACjC,WAAsB,cAAc,WACpC,KAAgB,cAAc,KAE9B,QAAgD,KAChD,QAA2C,KAC3C,UAAoD,KACpD,OAA0C,KAC1C,WAAa,cAAc,WAC3B,aAAkC,CAAC,EACnC,IACA,UAEA,YAAY,EAAa,EAA+B,EAAgC,CAAC,EAAG,CAC1F,KAAK,IAAM,EACX,KAAK,UAAY,EACjB,cAAc,UAAU,KAAK,IAAI,EAC7B,EAAQ,UAAU,eAAiB,KAAK,KAAK,EAAG,CAAC,CACvD,CAEA,MAAM,EAAO,IAAM,EAAS,GAAU,CACpC,GAAI,cAAc,WAAY,CAC5B,KAAK,WAAa,cAAc,QAChC,MACF,CAEA,KAAK,YAAY,EAAM,CAAM,CAC/B,CAEA,YAAY,EAAO,IAAM,EAAS,GAAU,CAC1C,KAAK,WAAa,cAAc,OAChC,KAAK,UAAU,CAAE,OAAM,QAAO,CAAe,CAC/C,CAEA,KAAK,EAAO,KAAM,EAAS,gBAAuB,CAChD,KAAK,MAAM,EAAM,CAAM,CACzB,CAEA,OAAc,CACZ,KAAK,UAAU,IAAI,MAAM,OAAO,CAAC,CACnC,CAEA,MAAa,CACX,KAAK,WAAa,cAAc,KAChC,KAAK,SAAS,IAAI,MAAM,MAAM,CAAC,CACjC,CAEA,QAAQ,EAAsB,CAC5B,KAAK,YAAY,CAAE,KAAM,KAAK,UAAU,CAAK,CAAE,CAAiB,CAClE,CAEA,KAAK,EAAqB,CACxB,KAAK,aAAa,KAAK,CAAK,CAC9B,CACF,EAGA,SAAgB,OAAO,EAAuD,CAC5E,OAAO,EAAO,aAAa,IAAK,GAAU,KAAK,MAAM,CAAK,CAA4B,CACxF"}
@@ -0,0 +1,48 @@
1
+ export type MockWebSocketOptions = {
2
+ /**
3
+ * Open the socket automatically on the next macrotask instead of waiting for an
4
+ * explicit `open()` call. Useful for consumers (demos, app-level tests) that
5
+ * install the class as `globalThis.WebSocket` and never touch the instance.
6
+ * @default false
7
+ */
8
+ readonly autoOpen?: boolean;
9
+ };
10
+ /**
11
+ * A wire-protocol-accurate `WebSocket` stand-in for tests and demos: pulse dials it through
12
+ * `new WebSocket(url, protocols)`, tests drive it through `open()`, `receive()`, `drop()`,
13
+ * and `error()`, and every outbound frame lands in `sentMessages` for `frames()` to decode.
14
+ *
15
+ * Instances register on the static `instances` array in construction order, so a test can
16
+ * grab the socket pulse just created without reaching into the client.
17
+ */
18
+ export declare class MockWebSocket {
19
+ static CLOSED: number;
20
+ static CLOSING: number;
21
+ static CONNECTING: number;
22
+ static deferClose: boolean;
23
+ static OPEN: number;
24
+ static instances: MockWebSocket[];
25
+ readonly CLOSED: number;
26
+ readonly CLOSING: number;
27
+ readonly CONNECTING: number;
28
+ readonly OPEN: number;
29
+ onclose: ((event: CloseEvent) => void) | null;
30
+ onerror: ((event: Event) => void) | null;
31
+ onmessage: ((event: MessageEvent) => void) | null;
32
+ onopen: ((event: Event) => void) | null;
33
+ readyState: number;
34
+ readonly sentMessages: string[];
35
+ readonly url: string;
36
+ readonly protocols?: string | string[];
37
+ constructor(url: string, protocols?: string | string[], options?: MockWebSocketOptions);
38
+ close(code?: number, reason?: string): void;
39
+ finishClose(code?: number, reason?: string): void;
40
+ drop(code?: number, reason?: string): void;
41
+ error(): void;
42
+ open(): void;
43
+ receive(frame: unknown): void;
44
+ send(frame: string): void;
45
+ }
46
+ /** Decodes every frame the socket sent, in order. */
47
+ export declare function frames(socket: MockWebSocket): Array<Record<string, unknown>>;
48
+ //# sourceMappingURL=mock-websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-websocket.d.ts","sourceRoot":"","sources":["../../src/testing/mock-websocket.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,MAAM,CAAC,MAAM,SAAK;IAClB,MAAM,CAAC,OAAO,SAAK;IACnB,MAAM,CAAC,UAAU,SAAK;IACtB,MAAM,CAAC,UAAU,UAAS;IAC1B,MAAM,CAAC,IAAI,SAAK;IAChB,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,CAAM;IAEvC,QAAQ,CAAC,MAAM,SAAwB;IACvC,QAAQ,CAAC,OAAO,SAAyB;IACzC,QAAQ,CAAC,UAAU,SAA4B;IAC/C,QAAQ,CAAC,IAAI,SAAsB;IAEnC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACrD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAChD,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACzD,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC/C,UAAU,SAA4B;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAM;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;gBAE3B,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,GAAE,oBAAyB;IAO1F,KAAK,CAAC,IAAI,SAAO,EAAE,MAAM,SAAK,GAAG,IAAI;IASrC,WAAW,CAAC,IAAI,SAAO,EAAE,MAAM,SAAK,GAAG,IAAI;IAK3C,IAAI,CAAC,IAAI,SAAO,EAAE,MAAM,SAAkB,GAAG,IAAI;IAIjD,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI;IAKZ,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI7B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAG1B;AAED,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAE5E"}
@@ -0,0 +1,2 @@
1
+ var e=class MockWebSocket{static CLOSED=3;static CLOSING=2;static CONNECTING=0;static deferClose=!1;static OPEN=1;static instances=[];CLOSED=MockWebSocket.CLOSED;CLOSING=MockWebSocket.CLOSING;CONNECTING=MockWebSocket.CONNECTING;OPEN=MockWebSocket.OPEN;onclose=null;onerror=null;onmessage=null;onopen=null;readyState=MockWebSocket.CONNECTING;sentMessages=[];url;protocols;constructor(e,t,n={}){this.url=e,this.protocols=t,MockWebSocket.instances.push(this),n.autoOpen&&setTimeout(()=>this.open(),0)}close(e=1e3,t=``){if(MockWebSocket.deferClose){this.readyState=MockWebSocket.CLOSING;return}this.finishClose(e,t)}finishClose(e=1e3,t=``){this.readyState=MockWebSocket.CLOSED,this.onclose?.({code:e,reason:t})}drop(e=1006,t=`network error`){this.close(e,t)}error(){this.onerror?.(new Event(`error`))}open(){this.readyState=MockWebSocket.OPEN,this.onopen?.(new Event(`open`))}receive(e){this.onmessage?.({data:JSON.stringify(e)})}send(e){this.sentMessages.push(e)}};function frames(e){return e.sentMessages.map(e=>JSON.parse(e))}export{e as MockWebSocket,frames};
2
+ //# sourceMappingURL=mock-websocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-websocket.js","names":[],"sources":["../../src/testing/mock-websocket.ts"],"sourcesContent":["export type MockWebSocketOptions = {\n /**\n * Open the socket automatically on the next macrotask instead of waiting for an\n * explicit `open()` call. Useful for consumers (demos, app-level tests) that\n * install the class as `globalThis.WebSocket` and never touch the instance.\n * @default false\n */\n readonly autoOpen?: boolean;\n};\n\n/**\n * A wire-protocol-accurate `WebSocket` stand-in for tests and demos: pulse dials it through\n * `new WebSocket(url, protocols)`, tests drive it through `open()`, `receive()`, `drop()`,\n * and `error()`, and every outbound frame lands in `sentMessages` for `frames()` to decode.\n *\n * Instances register on the static `instances` array in construction order, so a test can\n * grab the socket pulse just created without reaching into the client.\n */\nexport class MockWebSocket {\n static CLOSED = 3;\n static CLOSING = 2;\n static CONNECTING = 0;\n static deferClose = false;\n static OPEN = 1;\n static instances: MockWebSocket[] = [];\n\n readonly CLOSED = MockWebSocket.CLOSED;\n readonly CLOSING = MockWebSocket.CLOSING;\n readonly CONNECTING = MockWebSocket.CONNECTING;\n readonly OPEN = MockWebSocket.OPEN;\n\n onclose: ((event: CloseEvent) => void) | null = null;\n onerror: ((event: Event) => void) | null = null;\n onmessage: ((event: MessageEvent) => void) | null = null;\n onopen: ((event: Event) => void) | null = null;\n readyState = MockWebSocket.CONNECTING;\n readonly sentMessages: string[] = [];\n readonly url: string;\n readonly protocols?: string | string[];\n\n constructor(url: string, protocols?: string | string[], options: MockWebSocketOptions = {}) {\n this.url = url;\n this.protocols = protocols;\n MockWebSocket.instances.push(this);\n if (options.autoOpen) setTimeout(() => this.open(), 0);\n }\n\n close(code = 1000, reason = ''): void {\n if (MockWebSocket.deferClose) {\n this.readyState = MockWebSocket.CLOSING;\n return;\n }\n\n this.finishClose(code, reason);\n }\n\n finishClose(code = 1000, reason = ''): void {\n this.readyState = MockWebSocket.CLOSED;\n this.onclose?.({ code, reason } as CloseEvent);\n }\n\n drop(code = 1006, reason = 'network error'): void {\n this.close(code, reason);\n }\n\n error(): void {\n this.onerror?.(new Event('error'));\n }\n\n open(): void {\n this.readyState = MockWebSocket.OPEN;\n this.onopen?.(new Event('open'));\n }\n\n receive(frame: unknown): void {\n this.onmessage?.({ data: JSON.stringify(frame) } as MessageEvent);\n }\n\n send(frame: string): void {\n this.sentMessages.push(frame);\n }\n}\n\n/** Decodes every frame the socket sent, in order. */\nexport function frames(socket: MockWebSocket): Array<Record<string, unknown>> {\n return socket.sentMessages.map((frame) => JSON.parse(frame) as Record<string, unknown>);\n}\n"],"mappings":"AAkBA,IAAa,EAAb,MAAa,aAAc,CACzB,OAAO,OAAS,EAChB,OAAO,QAAU,EACjB,OAAO,WAAa,EACpB,OAAO,WAAa,GACpB,OAAO,KAAO,EACd,OAAO,UAA6B,CAAC,EAErC,OAAkB,cAAc,OAChC,QAAmB,cAAc,QACjC,WAAsB,cAAc,WACpC,KAAgB,cAAc,KAE9B,QAAgD,KAChD,QAA2C,KAC3C,UAAoD,KACpD,OAA0C,KAC1C,WAAa,cAAc,WAC3B,aAAkC,CAAC,EACnC,IACA,UAEA,YAAY,EAAa,EAA+B,EAAgC,CAAC,EAAG,CAC1F,KAAK,IAAM,EACX,KAAK,UAAY,EACjB,cAAc,UAAU,KAAK,IAAI,EAC7B,EAAQ,UAAU,eAAiB,KAAK,KAAK,EAAG,CAAC,CACvD,CAEA,MAAM,EAAO,IAAM,EAAS,GAAU,CACpC,GAAI,cAAc,WAAY,CAC5B,KAAK,WAAa,cAAc,QAChC,MACF,CAEA,KAAK,YAAY,EAAM,CAAM,CAC/B,CAEA,YAAY,EAAO,IAAM,EAAS,GAAU,CAC1C,KAAK,WAAa,cAAc,OAChC,KAAK,UAAU,CAAE,OAAM,QAAO,CAAe,CAC/C,CAEA,KAAK,EAAO,KAAM,EAAS,gBAAuB,CAChD,KAAK,MAAM,EAAM,CAAM,CACzB,CAEA,OAAc,CACZ,KAAK,UAAU,IAAI,MAAM,OAAO,CAAC,CACnC,CAEA,MAAa,CACX,KAAK,WAAa,cAAc,KAChC,KAAK,SAAS,IAAI,MAAM,MAAM,CAAC,CACjC,CAEA,QAAQ,EAAsB,CAC5B,KAAK,YAAY,CAAE,KAAM,KAAK,UAAU,CAAK,CAAE,CAAiB,CAClE,CAEA,KAAK,EAAqB,CACxB,KAAK,aAAa,KAAK,CAAK,CAC9B,CACF,EAGA,SAAgB,OAAO,EAAuD,CAC5E,OAAO,EAAO,aAAa,IAAK,GAAU,KAAK,MAAM,CAAK,CAA4B,CACxF"}
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./testing/mock-websocket.cjs");exports.MockWebSocket=e.MockWebSocket,exports.frames=e.frames;
@@ -0,0 +1 @@
1
+ import{MockWebSocket as e,frames as t}from"./testing/mock-websocket.js";export{e as MockWebSocket,t as frames};
package/dist/types.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { Readable } from '@vielzeug/ripple';
2
1
  import type { PulseError } from './errors';
3
2
  /** A map of event name → payload type. */
4
3
  export type MessageMap = Record<string, unknown>;
@@ -6,6 +5,11 @@ export type MessageMap = Record<string, unknown>;
6
5
  export type EventKey<T extends MessageMap> = keyof T & string;
7
6
  /** A function that removes a listener subscription. */
8
7
  export type Unsubscribe = () => void;
8
+ /** Framework-neutral snapshot/subscription state source. */
9
+ export interface Subscribable<T> {
10
+ getSnapshot(): T;
11
+ subscribe(listener: () => void): Unsubscribe;
12
+ }
9
13
  /**
10
14
  * Declare server events, client events, channel schemas, and room schemas once
11
15
  * at construction. All named scopes infer their types from this schema.
@@ -174,7 +178,7 @@ export type RoomScopeBase = {
174
178
  /** Room scope with reactive presence state tracking. */
175
179
  export type PresenceRoomScope<T = unknown> = RoomScopeBase & {
176
180
  /** Reactive map of `memberId → state`. Updates whenever any member joins, leaves, or updates. */
177
- readonly presence: Readable<ReadonlyMap<string, T>>;
181
+ readonly presence: Subscribable<ReadonlyMap<string, T>>;
178
182
  /**
179
183
  * Broadcast this client's presence state to all room members.
180
184
  * Throws `PulseConnectionError` unless the connection is open.
@@ -233,14 +237,14 @@ export type Pulse<S extends PulseSchema = PulseSchema> = {
233
237
  */
234
238
  room<K extends keyof RoomMap<S> & string>(name: K, opts?: RoomOptions): RoomScope<RoomMap<S>[K]>;
235
239
  /** Reactive set of rooms the client is currently a confirmed member of. */
236
- readonly rooms: Readable<ReadonlySet<string>>;
240
+ readonly rooms: Subscribable<ReadonlySet<string>>;
237
241
  /**
238
242
  * Send a typed event to the server.
239
243
  * Throws `PulseConnectionError` unless the connection is open.
240
244
  */
241
245
  send<K extends EventKey<ClientEvents<S>>>(event: K, payload: ClientEvents<S>[K]): void;
242
246
  /** Reactive connection status. */
243
- readonly status: Readable<PulseStatus>;
247
+ readonly status: Subscribable<PulseStatus>;
244
248
  /**
245
249
  * Observe runtime events (status-change, error, dispose) without affecting
246
250
  * pulse behavior. Handler errors are swallowed. Returns an unsubscribe function.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vielzeug/pulse",
3
- "version": "2.4.0",
4
- "description": "Typed WebSocket client with channel multiplexing, presence tracking, auto-reconnect, and heartbeat",
3
+ "version": "26.10.0",
4
+ "description": "Typed WebSocket client with channels, rooms, presence, reconnect",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/helmuthdu/vielzeug",
@@ -22,6 +22,18 @@
22
22
  "import": "./dist/index.js",
23
23
  "require": "./dist/index.cjs",
24
24
  "types": "./dist/index.d.ts"
25
+ },
26
+ "./testing": {
27
+ "import": "./dist/testing.js",
28
+ "require": "./dist/testing.cjs",
29
+ "types": "./dist/testing/index.d.ts"
30
+ }
31
+ },
32
+ "typesVersions": {
33
+ "*": {
34
+ "testing": [
35
+ "dist/testing/index.d.ts"
36
+ ]
25
37
  }
26
38
  },
27
39
  "sideEffects": false,
@@ -30,22 +42,22 @@
30
42
  "registry": "https://registry.npmjs.org/"
31
43
  },
32
44
  "scripts": {
33
- "build": "vite build && pnpm run build:bundle && pnpm run build:types",
45
+ "build": "vite build && pnpm --silent run build:bundle && pnpm --silent run build:types",
34
46
  "build:bundle": "vite build --config vite.bundle.config.ts",
35
47
  "build:types": "tsc -p tsconfig.declarations.json",
36
48
  "fix": "biome check --write src",
37
49
  "lint": "biome ci src",
38
- "prepublishOnly": "pnpm run build",
50
+ "prepublishOnly": "pnpm --silent run build",
39
51
  "preview": "vite preview",
40
52
  "test": "vitest"
41
53
  },
42
54
  "dependencies": {
43
- "@vielzeug/ripple": "2.3.0"
55
+ "@vielzeug/arsenal": "26.10.0"
44
56
  },
45
57
  "devDependencies": {
46
- "@types/node": "^26.2.0",
58
+ "@types/node": "^26.6.2",
47
59
  "typescript": "^6.0.3",
48
- "vite": "^8.2.1",
49
- "vitest": "^4.1.10"
60
+ "vite": "^8.3.0",
61
+ "vitest": "^5.0.1"
50
62
  }
51
63
  }