@vielzeug/pulse 2.1.2 → 2.2.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/dist/room.js ADDED
@@ -0,0 +1,256 @@
1
+ import { PulseAbortError as e, PulseConnectionError as t, PulseDisposedError as n, PulseError as r, PulseRoomTimeoutError as i } from "./errors.js";
2
+ import { combineSignals as a, deriveAbortController as o } from "./_utils.js";
3
+ import { encode as s } from "./protocol.js";
4
+ import { signal as c } from "@vielzeug/ripple";
5
+ //#region src/room.ts
6
+ function l(l) {
7
+ let f = c(/* @__PURE__ */ new Set()), p = /* @__PURE__ */ new Map();
8
+ function m(e) {
9
+ let t = p.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
+ }, p.set(e, t)), t;
18
+ }
19
+ function h(e, t) {
20
+ let n = new Set(f.value);
21
+ t ? n.add(e) : n.delete(e), f.value = n;
22
+ }
23
+ function g(e) {
24
+ l.send(s({
25
+ room: e,
26
+ type: "join"
27
+ }));
28
+ }
29
+ function _(e) {
30
+ l.send(s({
31
+ room: e,
32
+ type: "leave"
33
+ }));
34
+ }
35
+ function v(e, r) {
36
+ let i = p.get(e);
37
+ if (!i) throw new n(`Room "${e}"`);
38
+ if (!l.isOpen()) throw new t("Connection is not open", e);
39
+ l.send(s({
40
+ room: e,
41
+ state: r,
42
+ type: "presence"
43
+ })), i.localPresence = r;
44
+ }
45
+ function y(e, t) {
46
+ let n = p.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, h(e, !1), l.isOpen() && _(e), p.delete(e)) : n.joinSent ? n.leaveAfterJoin = !0 : p.delete(e)));
48
+ }
49
+ return {
50
+ createScope(s, f, p) {
51
+ if (l.disposalSignal.aborted) return d(s, f);
52
+ let h = m(s), _ = o(l.disposalSignal), b, x, S = !1, C = new Promise((e, t) => {
53
+ b = () => {
54
+ S || (S = !0, clearTimeout(w), E.removeEventListener("abort", M), e());
55
+ }, x = (e) => {
56
+ S || (S = !0, clearTimeout(w), E.removeEventListener("abort", M), t(e));
57
+ };
58
+ });
59
+ C.catch(() => {});
60
+ let w, T = [_.signal];
61
+ if (p?.signal && T.push(p.signal), p?.timeout !== void 0) {
62
+ let e = new AbortController();
63
+ w = setTimeout(() => e.abort(new i(s)), p.timeout), T.push(e.signal);
64
+ }
65
+ let E = T.length === 1 ? T[0] : a(T[0], ...T.slice(1)), D, O, k = /* @__PURE__ */ new Set(), A = /* @__PURE__ */ new Set();
66
+ f && (D = c(/* @__PURE__ */ new Map()), O = {
67
+ onJoin(e, t) {
68
+ let n = new Map(D.value);
69
+ n.set(e, t), D.value = n;
70
+ for (let n of k) n(e, t);
71
+ },
72
+ onLeave(e) {
73
+ let t = new Map(D.value);
74
+ t.delete(e), D.value = t;
75
+ for (let t of A) 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
+ D.value = t;
81
+ },
82
+ reset() {
83
+ D.value = /* @__PURE__ */ new Map();
84
+ }
85
+ });
86
+ let j = {
87
+ isSettled: () => S,
88
+ joined: C,
89
+ name: s,
90
+ presenceHandlers: O,
91
+ rejectJoined: x,
92
+ resolveJoined: b
93
+ }, M = () => {
94
+ clearTimeout(w), _.abort();
95
+ let t = E.reason, n = t instanceof r ? t : new e();
96
+ j.rejectJoined(n), y(s, j);
97
+ };
98
+ if (h.refs++, h.scopes.add(j), E.aborted) return M(), u(j, _.signal, D, k, A, s, v);
99
+ if (E.addEventListener("abort", M, { once: !0 }), h.confirmed) j.resolveJoined();
100
+ else if (!h.joinSent && l.isOpen()) {
101
+ h.joinSent = !0;
102
+ try {
103
+ g(s);
104
+ } catch (e) {
105
+ h.joinSent = !1, j.rejectJoined(e instanceof r ? e : new t("Failed to send join", s));
106
+ }
107
+ }
108
+ return u(j, _.signal, D, k, A, s, v, () => {
109
+ _.signal.aborted || (clearTimeout(w), E.removeEventListener("abort", M), _.abort(), S || j.rejectJoined(new n(`Room "${s}"`)), y(s, j));
110
+ });
111
+ },
112
+ dispose() {
113
+ f.value = /* @__PURE__ */ new Set(), p.clear();
114
+ },
115
+ handleJoined(e) {
116
+ let t = p.get(e);
117
+ if (t) {
118
+ if (t.confirmed = !0, t.joinSent = !1, h(e, !0), t.leaveAfterJoin) {
119
+ t.leaveAfterJoin = !1, t.confirmed = !1, h(e, !1), l.isOpen() && _(e), p.delete(e);
120
+ return;
121
+ }
122
+ for (let e of t.scopes) e.isSettled() || e.resolveJoined();
123
+ }
124
+ },
125
+ handleLeft(e) {
126
+ let t = p.get(e);
127
+ t && (t.confirmed = !1, t.joinSent = !1, h(e, !1));
128
+ },
129
+ handlePresenceJoin(e, t, n) {
130
+ let r = p.get(e);
131
+ if (r) for (let e of r.scopes) e.presenceHandlers?.onJoin(t, n);
132
+ },
133
+ handlePresenceLeave(e, t) {
134
+ let n = p.get(e);
135
+ if (n) for (let e of n.scopes) e.presenceHandlers?.onLeave(t);
136
+ },
137
+ handlePresenceState(e, t) {
138
+ let n = p.get(e);
139
+ if (n) for (let e of n.scopes) e.presenceHandlers?.onState(t);
140
+ },
141
+ rejectAll(e) {
142
+ for (let t of p.values()) for (let n of t.scopes) n.isSettled() || n.rejectJoined(e);
143
+ },
144
+ reset() {
145
+ f.value = /* @__PURE__ */ new Set();
146
+ for (let [e, t] of p) {
147
+ if (t.refs === 0) {
148
+ p.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 p) if (t.refs !== 0) {
157
+ t.confirmed = !1, t.joinSent = !0;
158
+ try {
159
+ g(e);
160
+ } catch {
161
+ t.joinSent = !1;
162
+ }
163
+ if (t.localPresence !== void 0) try {
164
+ l.send(s({
165
+ room: e,
166
+ state: t.localPresence,
167
+ type: "presence"
168
+ }));
169
+ } catch {}
170
+ }
171
+ },
172
+ rooms: f
173
+ };
174
+ }
175
+ function u(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 d(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: c(/* @__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 { l as createRoomRegistry };
255
+
256
+ //# sourceMappingURL=room.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room.js","names":[],"sources":["../src/room.ts"],"sourcesContent":["import { type Signal, signal } from '@vielzeug/ripple';\nimport { combineSignals, 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 = signals.length === 1 ? signals[0]! : combineSignals(signals[0]!, ...signals.slice(1));\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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"}
package/dist/types.d.ts CHANGED
@@ -1,10 +1,41 @@
1
1
  import type { Readable } from '@vielzeug/ripple';
2
- /** A map of event name → payload type. Use as the generic parameter for Pulse. */
2
+ import type { PulseError } from './errors';
3
+ /** A map of event name → payload type. */
3
4
  export type MessageMap = Record<string, unknown>;
4
5
  /** Extract valid event keys from a MessageMap. */
5
6
  export type EventKey<T extends MessageMap> = keyof T & string;
6
7
  /** A function that removes a listener subscription. */
7
8
  export type Unsubscribe = () => void;
9
+ /**
10
+ * Declare server events, client events, channel schemas, and room schemas once
11
+ * at construction. All named scopes infer their types from this schema.
12
+ */
13
+ export type PulseSchema = {
14
+ /** Root events the server sends to the client. */
15
+ server?: MessageMap;
16
+ /** Root events the client sends to the server. */
17
+ client?: MessageMap;
18
+ /** Named channel schemas. */
19
+ channels?: ChannelDefinitions;
20
+ /** Named room schemas with optional presence state. */
21
+ rooms?: RoomDefinitions;
22
+ };
23
+ /** Extract server events from a schema, defaulting to an empty map. */
24
+ export type ServerEvents<S extends PulseSchema> = S extends {
25
+ server: infer M extends MessageMap;
26
+ } ? M : MessageMap;
27
+ /** Extract client events from a schema, defaulting to an empty map. */
28
+ export type ClientEvents<S extends PulseSchema> = S extends {
29
+ client: infer M extends MessageMap;
30
+ } ? M : MessageMap;
31
+ /** Extract channel definitions from a schema, defaulting to an empty map. */
32
+ export type ChannelMap<S extends PulseSchema> = S extends {
33
+ channels: infer C extends ChannelDefinitions;
34
+ } ? C : ChannelDefinitions;
35
+ /** Extract room definitions from a schema, defaulting to an empty map. */
36
+ export type RoomMap<S extends PulseSchema> = S extends {
37
+ rooms: infer R extends RoomDefinitions;
38
+ } ? R : RoomDefinitions;
8
39
  /** Lifecycle state of a Pulse connection. */
9
40
  export type PulseStatus = 'connecting' | 'open' | 'reconnecting' | 'closed';
10
41
  export type ReconnectOptions = {
@@ -39,8 +70,17 @@ export type ChannelDefinition = {
39
70
  };
40
71
  /** Named channel schemas supplied when creating Pulse. */
41
72
  export type ChannelDefinitions = Record<string, ChannelDefinition>;
42
- /** Named presence-state schemas supplied when creating Pulse. */
43
- export type PresenceDefinitions = Record<string, unknown>;
73
+ /** A room definition with optional presence state type. */
74
+ export type RoomDefinition = {
75
+ presence?: unknown;
76
+ };
77
+ /** Named room schemas supplied when creating Pulse. */
78
+ export type RoomDefinitions = Record<string, RoomDefinition>;
79
+ /** Options for creating a room scope. */
80
+ export type RoomOptions = {
81
+ signal?: AbortSignal;
82
+ timeout?: number;
83
+ };
44
84
  export type PulseOptions = {
45
85
  /**
46
86
  * Heartbeat ping/pong keep-alive.
@@ -48,7 +88,7 @@ export type PulseOptions = {
48
88
  */
49
89
  heartbeat?: boolean | HeartbeatOptions;
50
90
  /** Receives typed transport and protocol failures. */
51
- onError?: (error: import('./errors').PulseError) => void;
91
+ onError?: (error: PulseError) => void;
52
92
  /** Sub-protocols to pass to the WebSocket constructor. */
53
93
  protocols?: string | string[];
54
94
  /**
@@ -101,45 +141,48 @@ export type PulseChannel<TServer extends MessageMap = MessageMap, TClient extend
101
141
  timeout?: number;
102
142
  }): Promise<TServer[K]>;
103
143
  };
104
- /**
105
- * A reactive presence channel that tracks members' state in a room.
106
- * Obtain one via `pulse.presence(room)`.
107
- *
108
- * @example
109
- * const lobby = pulse.presence('lobby');
110
- * effect(() => console.log('Online:', [...lobby.state.value.keys()]));
111
- * lobby.update({ name: 'Alice', status: 'online' });
112
- */
113
- export type PresenceChannel<T = unknown> = {
144
+ /** Base room scope: ref-counted server membership with explicit disposal. */
145
+ export type RoomScopeBase = {
114
146
  /** Delegates to `dispose()`. Enables `using` declarations. */
115
147
  [Symbol.dispose](): void;
116
148
  /** `AbortSignal` aborted when `dispose()` is called. */
117
149
  readonly disposalSignal: AbortSignal;
118
- /** Releases this scope's listeners and room reference. */
150
+ /** Releases this scope's room reference and listeners. */
119
151
  dispose(): void;
120
- /** Whether this presence channel has been disposed. */
152
+ /** Whether this room scope has been disposed. */
121
153
  readonly disposed: boolean;
154
+ /** Room name passed to `pulse.room()`. */
155
+ readonly name: string;
122
156
  /**
123
- * Register a handler called whenever a new member joins with their initial state.
124
- * Returns an unsubscribe function.
125
- */
126
- onJoin(handler: (memberId: string, state: T) => void): Unsubscribe;
127
- /**
128
- * Register a handler called whenever a member leaves.
129
- * Returns an unsubscribe function.
157
+ * Resolves when the server confirms membership with a `joined` frame.
158
+ * Rejects on transport close, timeout, abort, or disposal.
159
+ * For post-reconnect membership, read `pulse.rooms` instead.
130
160
  */
131
- onLeave(handler: (memberId: string) => void): Unsubscribe;
132
- /** Room name passed to `pulse.presence()`. */
133
- readonly room: string;
161
+ readonly joined: Promise<void>;
162
+ };
163
+ /** Room scope with reactive presence state tracking. */
164
+ export type PresenceRoomScope<T = unknown> = RoomScopeBase & {
134
165
  /** Reactive map of `memberId → state`. Updates whenever any member joins, leaves, or updates. */
135
- readonly state: Readable<ReadonlyMap<string, T>>;
166
+ readonly presence: Readable<ReadonlyMap<string, T>>;
136
167
  /**
137
168
  * Broadcast this client's presence state to all room members.
138
169
  * Throws `PulseConnectionError` unless the connection is open.
139
170
  */
140
- update(state: T): void;
171
+ updatePresence(state: T): void;
172
+ /** Register a handler called whenever a new member joins with their initial state. */
173
+ onJoin(handler: (memberId: string, state: T) => void): Unsubscribe;
174
+ /** Register a handler called whenever a member leaves. */
175
+ onLeave(handler: (memberId: string) => void): Unsubscribe;
141
176
  };
142
- export type Pulse<TServer extends MessageMap = MessageMap, TClient extends MessageMap = MessageMap, TChannels extends ChannelDefinitions = ChannelDefinitions, TPresence extends PresenceDefinitions = PresenceDefinitions> = {
177
+ /**
178
+ * A room scope. When the room definition includes `presence`, the scope
179
+ * exposes reactive presence state, join/leave handlers, and `updatePresence()`.
180
+ * Otherwise it is a plain ref-counted room membership.
181
+ */
182
+ export type RoomScope<R extends RoomDefinition = RoomDefinition> = R extends {
183
+ presence: infer P;
184
+ } ? P extends undefined ? RoomScopeBase : PresenceRoomScope<P> : RoomScopeBase;
185
+ export type Pulse<S extends PulseSchema = PulseSchema> = {
143
186
  /** Delegates to `dispose()`. Enables `using` declarations. */
144
187
  [Symbol.dispose](): void;
145
188
  /**
@@ -147,7 +190,7 @@ export type Pulse<TServer extends MessageMap = MessageMap, TClient extends Messa
147
190
  * Each call returns an independently disposable scope. The server subscription
148
191
  * remains active until every scope for this name is disposed.
149
192
  */
150
- channel<K extends keyof TChannels & string>(name: K): PulseChannel<TChannels[K]['server'], TChannels[K]['client']>;
193
+ channel<K extends keyof ChannelMap<S> & string>(name: K): PulseChannel<ChannelMap<S>[K]['server'], ChannelMap<S>[K]['client']>;
151
194
  /**
152
195
  * Explicitly open the connection. Resolves after session restoration completes.
153
196
  * Rejects if the connection closes before opening.
@@ -165,51 +208,35 @@ export type Pulse<TServer extends MessageMap = MessageMap, TClient extends Messa
165
208
  dispose(): void;
166
209
  /** Whether the instance has been permanently disposed. */
167
210
  readonly disposed: boolean;
168
- /**
169
- * Request to join a room. Resolves when the server confirms with a `joined` frame.
170
- * Rejects if the pulse is disposed, the signal aborts, or the timeout elapses.
171
- */
172
- join(room: string, opts?: {
173
- signal?: AbortSignal;
174
- timeout?: number;
175
- }): Promise<void>;
176
- /**
177
- * Request to leave a room. Resolves when the server confirms with a `left` frame.
178
- * Rejects if the pulse is disposed, the signal aborts, or the timeout elapses.
179
- */
180
- leave(room: string, opts?: {
181
- signal?: AbortSignal;
182
- timeout?: number;
183
- }): Promise<void>;
184
211
  /**
185
212
  * Subscribe to a typed server event. Returns an unsubscribe function.
186
213
  * The same handler can be registered multiple times independently.
187
214
  */
188
- on<K extends EventKey<TServer>>(event: K, handler: (payload: TServer[K]) => void): Unsubscribe;
215
+ on<K extends EventKey<ServerEvents<S>>>(event: K, handler: (payload: ServerEvents<S>[K]) => void): Unsubscribe;
189
216
  /** Subscribe once — auto-removes after first invocation. */
190
- once<K extends EventKey<TServer>>(event: K, handler: (payload: TServer[K]) => void): Unsubscribe;
217
+ once<K extends EventKey<ServerEvents<S>>>(event: K, handler: (payload: ServerEvents<S>[K]) => void): Unsubscribe;
191
218
  /**
192
- * Create a presence scope that tracks all members' state in a room.
193
- * Each call returns an independently disposable scope. The room remains joined
194
- * until every scope for this name is disposed.
219
+ * Create a ref-counted room scope. The first scope for a room sends a `join`
220
+ * frame; the last disposal sends a `leave` frame. When the room definition
221
+ * includes `presence`, the scope exposes reactive presence state.
195
222
  */
196
- presence<K extends keyof TPresence & string>(room: K): PresenceChannel<TPresence[K]>;
197
- /** Reactive set of rooms the client is currently a member of. */
223
+ room<K extends keyof RoomMap<S> & string>(name: K, opts?: RoomOptions): RoomScope<RoomMap<S>[K]>;
224
+ /** Reactive set of rooms the client is currently a confirmed member of. */
198
225
  readonly rooms: Readable<ReadonlySet<string>>;
199
226
  /**
200
227
  * Send a typed event to the server.
201
228
  * Throws `PulseConnectionError` unless the connection is open.
202
229
  */
203
- send<K extends EventKey<TClient>>(event: K, payload: TClient[K]): void;
230
+ send<K extends EventKey<ClientEvents<S>>>(event: K, payload: ClientEvents<S>[K]): void;
204
231
  /** Reactive connection status. */
205
232
  readonly status: Readable<PulseStatus>;
206
233
  /**
207
234
  * Resolve on the next emission of the given server event.
208
235
  * Rejects when `opts.signal` aborts or the instance is disposed.
209
236
  */
210
- wait<K extends EventKey<TServer>>(event: K, opts?: {
237
+ wait<K extends EventKey<ServerEvents<S>>>(event: K, opts?: {
211
238
  signal?: AbortSignal;
212
239
  timeout?: number;
213
- }): Promise<TServer[K]>;
240
+ }): Promise<ServerEvents<S>[K]>;
214
241
  };
215
242
  //# sourceMappingURL=types.d.ts.map
@@ -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,12 @@
1
1
  {
2
2
  "name": "@vielzeug/pulse",
3
- "version": "2.1.2",
3
+ "version": "2.2.0",
4
4
  "description": "Typed WebSocket client with channel multiplexing, presence tracking, auto-reconnect, and heartbeat",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/helmuthdu/vielzeug",
8
+ "directory": "packages/pulse"
9
+ },
5
10
  "type": "module",
6
11
  "engines": {
7
12
  "node": ">=22"
@@ -34,7 +39,7 @@
34
39
  "test": "vitest"
35
40
  },
36
41
  "dependencies": {
37
- "@vielzeug/ripple": "2.2.0"
42
+ "@vielzeug/ripple": "2.2.1"
38
43
  },
39
44
  "devDependencies": {
40
45
  "@types/node": "^26.2.0",
package/dist/presence.cjs DELETED
@@ -1,2 +0,0 @@
1
- const e=require("./errors.cjs"),t=require("./_utils.cjs");let n=require("@vielzeug/ripple");function r(r,i,a,o,s,c){let l=t.deriveAbortController(o),u=l.signal.aborted;l.signal.addEventListener(`abort`,()=>{u=!0},{once:!0});let d=(0,n.signal)(new Map);s?.(()=>{d.value=new Map});let f=new Set,p=new Set,m=[a.onState(e=>{if(e.room!==r)return;let t=new Map;for(let[n,r]of Object.entries(e.members))t.set(n,r);d.value=t}),a.onJoin(e=>{if(e.room!==r)return;let t=new Map(d.value);t.set(e.id,e.state),d.value=t;for(let t of f)t(e.id,e.state)}),a.onLeave(e=>{if(e.room!==r)return;let t=new Map(d.value);t.delete(e.id),d.value=t;for(let t of p)t(e.id)})];return{get disposalSignal(){return l.signal},dispose(){if(!u){u=!0,l.abort();for(let e of m)e();m.length=0,f.clear(),p.clear(),c?.()}},get disposed(){return u},onJoin(t){if(u)throw new e.PulseDisposedError(`Presence "${r}"`);return f.add(t),()=>f.delete(t)},onLeave(t){if(u)throw new e.PulseDisposedError(`Presence "${r}"`);return p.add(t),()=>p.delete(t)},get room(){return r},get state(){return d},[Symbol.dispose](){this.dispose()},update(t){if(u)throw new e.PulseDisposedError(`Presence "${r}"`);i(r,t)}}}exports.createPresence=r;
2
- //# sourceMappingURL=presence.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presence.cjs","names":[],"sources":["../src/presence.ts"],"sourcesContent":["import { type Signal, signal } from '@vielzeug/ripple';\nimport { deriveAbortController } from './_utils';\nimport { PulseDisposedError } from './errors';\nimport type { InPresenceJoinFrame, InPresenceLeaveFrame, InPresenceStateFrame } from './protocol';\nimport type { PresenceChannel, Unsubscribe } from './types';\n\ntype UpdateFn<T> = (room: string, state: T) => void;\n\nexport type PresenceEvents = {\n onJoin(handler: (frame: InPresenceJoinFrame) => void): Unsubscribe;\n onLeave(handler: (frame: InPresenceLeaveFrame) => void): Unsubscribe;\n onState(handler: (frame: InPresenceStateFrame) => void): Unsubscribe;\n};\n\n/**\n * Create a presence channel that reactively tracks room member states.\n * @internal\n */\nexport function createPresence<T>(\n room: string,\n update: UpdateFn<T>,\n events: PresenceEvents,\n disposalSignal: AbortSignal,\n registerReset?: (reset: () => void) => void,\n onDispose?: () => void,\n): PresenceChannel<T> {\n const ctrl = deriveAbortController(disposalSignal);\n\n let disposed = ctrl.signal.aborted;\n\n ctrl.signal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const members: Signal<Map<string, T>> = signal(new Map<string, T>());\n\n registerReset?.(() => {\n members.value = new Map<string, T>();\n });\n\n const joinHandlers = new Set<(memberId: string, state: T) => void>();\n const leaveHandlers = new Set<(memberId: string) => void>();\n\n const unsubs: Array<() => void> = [\n events.onState((frame) => {\n if (frame.room !== room) return;\n\n const next = new Map<string, T>();\n\n for (const [id, state] of Object.entries(frame.members)) {\n next.set(id, state as T);\n }\n\n members.value = next;\n }),\n events.onJoin((frame) => {\n if (frame.room !== room) return;\n\n const next = new Map(members.value);\n\n next.set(frame.id, frame.state as T);\n members.value = next;\n\n for (const handler of joinHandlers) {\n handler(frame.id, frame.state as T);\n }\n }),\n events.onLeave((frame) => {\n if (frame.room !== room) return;\n\n const next = new Map(members.value);\n\n next.delete(frame.id);\n members.value = next;\n\n for (const handler of leaveHandlers) {\n handler(frame.id);\n }\n }),\n ];\n\n const presence: PresenceChannel<T> = {\n get disposalSignal() {\n return ctrl.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n ctrl.abort();\n\n for (const unsub of unsubs) unsub();\n\n unsubs.length = 0;\n joinHandlers.clear();\n leaveHandlers.clear();\n onDispose?.();\n },\n\n get disposed() {\n return disposed;\n },\n\n onJoin(handler: (memberId: string, state: T) => void): Unsubscribe {\n if (disposed) {\n throw new PulseDisposedError(`Presence \"${room}\"`);\n }\n\n joinHandlers.add(handler);\n\n return () => joinHandlers.delete(handler);\n },\n\n onLeave(handler: (memberId: string) => void): Unsubscribe {\n if (disposed) {\n throw new PulseDisposedError(`Presence \"${room}\"`);\n }\n\n leaveHandlers.add(handler);\n\n return () => leaveHandlers.delete(handler);\n },\n\n get room() {\n return room;\n },\n\n get state() {\n return members;\n },\n\n [Symbol.dispose]() {\n this.dispose();\n },\n\n update(state: T): void {\n if (disposed) throw new PulseDisposedError(`Presence \"${room}\"`);\n\n update(room, state);\n },\n };\n\n return presence;\n}\n"],"mappings":"4FAkBA,SAAgB,EACd,EACA,EACA,EACA,EACA,EACA,EACoB,CACpB,IAAM,EAAO,EAAA,sBAAsB,CAAc,EAE7C,EAAW,EAAK,OAAO,QAE3B,EAAK,OAAO,iBACV,YACM,CACJ,EAAW,EACb,EACA,CAAE,KAAM,EAAK,CACf,EAEA,IAAM,GAAA,EAAkC,EAAA,OAAA,CAAO,IAAI,GAAgB,EAEnE,QAAsB,CACpB,EAAQ,MAAQ,IAAI,GACtB,CAAC,EAED,IAAM,EAAe,IAAI,IACnB,EAAgB,IAAI,IAEpB,EAA4B,CAChC,EAAO,QAAS,GAAU,CACxB,GAAI,EAAM,OAAS,EAAM,OAEzB,IAAM,EAAO,IAAI,IAEjB,IAAK,GAAM,CAAC,EAAI,KAAU,OAAO,QAAQ,EAAM,OAAO,EACpD,EAAK,IAAI,EAAI,CAAU,EAGzB,EAAQ,MAAQ,CAClB,CAAC,EACD,EAAO,OAAQ,GAAU,CACvB,GAAI,EAAM,OAAS,EAAM,OAEzB,IAAM,EAAO,IAAI,IAAI,EAAQ,KAAK,EAElC,EAAK,IAAI,EAAM,GAAI,EAAM,KAAU,EACnC,EAAQ,MAAQ,EAEhB,IAAK,IAAM,KAAW,EACpB,EAAQ,EAAM,GAAI,EAAM,KAAU,CAEtC,CAAC,EACD,EAAO,QAAS,GAAU,CACxB,GAAI,EAAM,OAAS,EAAM,OAEzB,IAAM,EAAO,IAAI,IAAI,EAAQ,KAAK,EAElC,EAAK,OAAO,EAAM,EAAE,EACpB,EAAQ,MAAQ,EAEhB,IAAK,IAAM,KAAW,EACpB,EAAQ,EAAM,EAAE,CAEpB,CAAC,CACH,EAgEA,MAAO,CA7DL,IAAI,gBAAiB,CACnB,OAAO,EAAK,MACd,EAEA,SAAU,CACJ,MAGJ,CADA,EAAW,GACX,EAAK,MAAM,EAEX,IAAK,IAAM,KAAS,EAAQ,EAAM,EAElC,EAAO,OAAS,EAChB,EAAa,MAAM,EACnB,EAAc,MAAM,EACpB,IAAY,CAPD,CAQb,EAEA,IAAI,UAAW,CACb,OAAO,CACT,EAEA,OAAO,EAA4D,CACjE,GAAI,EACF,MAAM,IAAI,EAAA,mBAAmB,aAAa,EAAK,EAAE,EAKnD,OAFA,EAAa,IAAI,CAAO,MAEX,EAAa,OAAO,CAAO,CAC1C,EAEA,QAAQ,EAAkD,CACxD,GAAI,EACF,MAAM,IAAI,EAAA,mBAAmB,aAAa,EAAK,EAAE,EAKnD,OAFA,EAAc,IAAI,CAAO,MAEZ,EAAc,OAAO,CAAO,CAC3C,EAEA,IAAI,MAAO,CACT,OAAO,CACT,EAEA,IAAI,OAAQ,CACV,OAAO,CACT,EAEA,CAAC,OAAO,UAAW,CACjB,KAAK,QAAQ,CACf,EAEA,OAAO,EAAgB,CACrB,GAAI,EAAU,MAAM,IAAI,EAAA,mBAAmB,aAAa,EAAK,EAAE,EAE/D,EAAO,EAAM,CAAK,CACpB,CAGK,CACT"}
@@ -1,8 +0,0 @@
1
- import type { InPresenceJoinFrame, InPresenceLeaveFrame, InPresenceStateFrame } from './protocol';
2
- import type { Unsubscribe } from './types';
3
- export type PresenceEvents = {
4
- onJoin(handler: (frame: InPresenceJoinFrame) => void): Unsubscribe;
5
- onLeave(handler: (frame: InPresenceLeaveFrame) => void): Unsubscribe;
6
- onState(handler: (frame: InPresenceStateFrame) => void): Unsubscribe;
7
- };
8
- //# sourceMappingURL=presence.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,SAAS,CAAC;AAI5D,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,WAAW,CAAC;IACnE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,WAAW,CAAC;IACrE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,WAAW,CAAC;CACtE,CAAC"}