@vielzeug/pulse 2.2.2 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,7 +29,10 @@ type Schema = {
29
29
 
30
30
  const pulse = createPulse<Schema>('wss://api.example.com/ws', {
31
31
  reconnect: true,
32
- onError: (error) => console.error(error),
32
+ });
33
+ pulse.tap((event) => {
34
+ if (event.type === 'error') console.error(event.error);
35
+ if (event.type === 'status-change') console.log('status:', event.status);
33
36
  });
34
37
 
35
38
  const chat = pulse.channel('chat');
@@ -55,7 +58,7 @@ pulse.dispose();
55
58
  - Reconnect restores channels, room memberships, and the last successfully published local presence state.
56
59
  - `send()` throws `PulseConnectionError` while disconnected; Pulse never silently drops or buffers application messages.
57
60
  - `room()` returns a `RoomScope` with a `joined` promise. When the room definition includes `presence`, the scope also exposes reactive presence state, `updatePresence()`, and `onJoin()`/`onLeave()` handlers.
58
- - `onError` receives typed transport and protocol errors.
61
+ - Call `tap()` to observe lifecycle events; Pulse reports transport and protocol errors there rather than throwing asynchronously.
59
62
 
60
63
  ## Migration
61
64
 
package/dist/_utils.cjs CHANGED
@@ -1,2 +1,2 @@
1
- function e(e,...n){return n.length===0?e:n.reduce(t,e)}function t(e,t){if(e.aborted)return e;if(t.aborted)return t;let n=new AbortController,r=()=>n.abort(e.reason),i=()=>n.abort(t.reason);return e.addEventListener(`abort`,r,{once:!0}),t.addEventListener(`abort`,i,{once:!0}),n.signal.addEventListener(`abort`,()=>{e.removeEventListener(`abort`,r),t.removeEventListener(`abort`,i)},{once:!0}),n.signal}function n(e){let t=new AbortController;return e.aborted?t.abort(e.reason):e.addEventListener(`abort`,()=>t.abort(e.reason),{once:!0}),t}function r(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=setTimeout(n,e);t?.addEventListener(`abort`,()=>{clearTimeout(r),n()},{once:!0})})}function i(e,t=3e4){let n=Math.min(1e3*2**e,t);return Math.random()*n}exports.combineSignals=e,exports.defaultReconnectDelay=i,exports.deriveAbortController=n,exports.sleep=r;
1
+ function e(e){let t=new AbortController;return e.aborted?t.abort(e.reason):e.addEventListener(`abort`,()=>t.abort(e.reason),{once:!0}),t}function t(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=setTimeout(n,e);t?.addEventListener(`abort`,()=>{clearTimeout(r),n()},{once:!0})})}function n(e,t=3e4){let n=Math.min(1e3*2**e,t);return Math.random()*n}exports.defaultReconnectDelay=n,exports.deriveAbortController=e,exports.sleep=t;
2
2
  //# sourceMappingURL=_utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_utils.cjs","names":[],"sources":["../src/_utils.ts"],"sourcesContent":["/**\n * Returns a signal that aborts as soon as any of the provided signals abort.\n * With a single argument, returns it directly (no allocation).\n * Cleanup listeners are registered to prevent leaks.\n *\n * @internal\n */\nexport function combineSignals(first: AbortSignal, ...rest: AbortSignal[]): AbortSignal {\n if (rest.length === 0) return first;\n\n return rest.reduce(mergeTwo, first);\n}\n\nfunction mergeTwo(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a;\n\n if (b.aborted) return b;\n\n const ctrl = new AbortController();\n const onA = (): void => ctrl.abort(a.reason);\n const onB = (): void => ctrl.abort(b.reason);\n\n a.addEventListener('abort', onA, { once: true });\n b.addEventListener('abort', onB, { once: true });\n ctrl.signal.addEventListener(\n 'abort',\n () => {\n a.removeEventListener('abort', onA);\n b.removeEventListener('abort', onB);\n },\n { once: true },\n );\n\n return ctrl.signal;\n}\n\n/**\n * Create a child `AbortController` that aborts as soon as `parent` does.\n * Handles the case where `parent` is already aborted at call time — a plain\n * `addEventListener('abort', ...)` would miss that, since the event already fired.\n *\n * @internal\n */\nexport function deriveAbortController(parent: AbortSignal): AbortController {\n const ctrl = new AbortController();\n\n if (parent.aborted) {\n ctrl.abort(parent.reason);\n } else {\n parent.addEventListener('abort', () => ctrl.abort(parent.reason), { once: true });\n }\n\n return ctrl;\n}\n\n/**\n * Sleep for `ms` milliseconds, aborting early when the signal fires.\n * Resolves (does not reject) on abort — callers check `signal.aborted`.\n *\n * @internal\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n\n return;\n }\n\n const id = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(id);\n resolve();\n },\n { once: true },\n );\n });\n}\n\n/**\n * Full-jitter exponential backoff in ms, capped at `maxMs`.\n * `attempt` is zero-based.\n *\n * @internal\n */\nexport function defaultReconnectDelay(attempt: number, maxMs = 30_000): number {\n const base = Math.min(1000 * 2 ** attempt, maxMs);\n\n return Math.random() * base;\n}\n"],"mappings":"AAOA,SAAgB,EAAe,EAAoB,GAAG,EAAkC,CAGtF,OAFI,EAAK,SAAW,EAAU,EAEvB,EAAK,OAAO,EAAU,CAAK,CACpC,CAEA,SAAS,EAAS,EAAgB,EAA6B,CAC7D,GAAI,EAAE,QAAS,OAAO,EAEtB,GAAI,EAAE,QAAS,OAAO,EAEtB,IAAM,EAAO,IAAI,gBACX,MAAkB,EAAK,MAAM,EAAE,MAAM,EACrC,MAAkB,EAAK,MAAM,EAAE,MAAM,EAa3C,OAXA,EAAE,iBAAiB,QAAS,EAAK,CAAE,KAAM,EAAK,CAAC,EAC/C,EAAE,iBAAiB,QAAS,EAAK,CAAE,KAAM,EAAK,CAAC,EAC/C,EAAK,OAAO,iBACV,YACM,CACJ,EAAE,oBAAoB,QAAS,CAAG,EAClC,EAAE,oBAAoB,QAAS,CAAG,CACpC,EACA,CAAE,KAAM,EAAK,CACf,EAEO,EAAK,MACd,CASA,SAAgB,EAAsB,EAAsC,CAC1E,IAAM,EAAO,IAAI,gBAQjB,OANI,EAAO,QACT,EAAK,MAAM,EAAO,MAAM,EAExB,EAAO,iBAAiB,YAAe,EAAK,MAAM,EAAO,MAAM,EAAG,CAAE,KAAM,EAAK,CAAC,EAG3E,CACT,CAQA,SAAgB,EAAM,EAAY,EAAqC,CACrE,OAAO,IAAI,QAAS,GAAY,CAC9B,GAAI,GAAQ,QAAS,CACnB,EAAQ,EAER,MACF,CAEA,IAAM,EAAK,WAAW,EAAS,CAAE,EAEjC,GAAQ,iBACN,YACM,CACJ,aAAa,CAAE,EACf,EAAQ,CACV,EACA,CAAE,KAAM,EAAK,CACf,CACF,CAAC,CACH,CAQA,SAAgB,EAAsB,EAAiB,EAAQ,IAAgB,CAC7E,IAAM,EAAO,KAAK,IAAI,IAAO,GAAK,EAAS,CAAK,EAEhD,OAAO,KAAK,OAAO,EAAI,CACzB"}
1
+ {"version":3,"file":"_utils.cjs","names":[],"sources":["../src/_utils.ts"],"sourcesContent":["/**\n * Create a child `AbortController` that aborts as soon as `parent` does.\n * Handles the case where `parent` is already aborted at call time — a plain\n * `addEventListener('abort', ...)` would miss that, since the event already fired.\n *\n * @internal\n */\nexport function deriveAbortController(parent: AbortSignal): AbortController {\n const ctrl = new AbortController();\n\n if (parent.aborted) {\n ctrl.abort(parent.reason);\n } else {\n parent.addEventListener('abort', () => ctrl.abort(parent.reason), { once: true });\n }\n\n return ctrl;\n}\n\n/**\n * Sleep for `ms` milliseconds, aborting early when the signal fires.\n * Resolves (does not reject) on abort — callers check `signal.aborted`.\n *\n * @internal\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n\n return;\n }\n\n const id = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(id);\n resolve();\n },\n { once: true },\n );\n });\n}\n\n/**\n * Full-jitter exponential backoff in ms, capped at `maxMs`.\n * `attempt` is zero-based.\n *\n * @internal\n */\nexport function defaultReconnectDelay(attempt: number, maxMs = 30_000): number {\n const base = Math.min(1000 * 2 ** attempt, maxMs);\n\n return Math.random() * base;\n}\n"],"mappings":"AAOA,SAAgB,EAAsB,EAAsC,CAC1E,IAAM,EAAO,IAAI,gBAQjB,OANI,EAAO,QACT,EAAK,MAAM,EAAO,MAAM,EAExB,EAAO,iBAAiB,YAAe,EAAK,MAAM,EAAO,MAAM,EAAG,CAAE,KAAM,EAAK,CAAC,EAG3E,CACT,CAQA,SAAgB,EAAM,EAAY,EAAqC,CACrE,OAAO,IAAI,QAAS,GAAY,CAC9B,GAAI,GAAQ,QAAS,CACnB,EAAQ,EAER,MACF,CAEA,IAAM,EAAK,WAAW,EAAS,CAAE,EAEjC,GAAQ,iBACN,YACM,CACJ,aAAa,CAAE,EACf,EAAQ,CACV,EACA,CAAE,KAAM,EAAK,CACf,CACF,CAAC,CACH,CAQA,SAAgB,EAAsB,EAAiB,EAAQ,IAAgB,CAC7E,IAAM,EAAO,KAAK,IAAI,IAAO,GAAK,EAAS,CAAK,EAEhD,OAAO,KAAK,OAAO,EAAI,CACzB"}
package/dist/_utils.js CHANGED
@@ -1,20 +1,9 @@
1
1
  //#region src/_utils.ts
2
- function e(e, ...n) {
3
- return n.length === 0 ? e : n.reduce(t, e);
4
- }
5
- function t(e, t) {
6
- if (e.aborted) return e;
7
- if (t.aborted) return t;
8
- let n = new AbortController(), r = () => n.abort(e.reason), i = () => n.abort(t.reason);
9
- return e.addEventListener("abort", r, { once: !0 }), t.addEventListener("abort", i, { once: !0 }), n.signal.addEventListener("abort", () => {
10
- e.removeEventListener("abort", r), t.removeEventListener("abort", i);
11
- }, { once: !0 }), n.signal;
12
- }
13
- function n(e) {
2
+ function e(e) {
14
3
  let t = new AbortController();
15
4
  return e.aborted ? t.abort(e.reason) : e.addEventListener("abort", () => t.abort(e.reason), { once: !0 }), t;
16
5
  }
17
- function r(e, t) {
6
+ function t(e, t) {
18
7
  return new Promise((n) => {
19
8
  if (t?.aborted) {
20
9
  n();
@@ -26,11 +15,11 @@ function r(e, t) {
26
15
  }, { once: !0 });
27
16
  });
28
17
  }
29
- function i(e, t = 3e4) {
18
+ function n(e, t = 3e4) {
30
19
  let n = Math.min(1e3 * 2 ** e, t);
31
20
  return Math.random() * n;
32
21
  }
33
22
  //#endregion
34
- export { e as combineSignals, i as defaultReconnectDelay, n as deriveAbortController, r as sleep };
23
+ export { n as defaultReconnectDelay, e as deriveAbortController, t as sleep };
35
24
 
36
25
  //# sourceMappingURL=_utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"_utils.js","names":[],"sources":["../src/_utils.ts"],"sourcesContent":["/**\n * Returns a signal that aborts as soon as any of the provided signals abort.\n * With a single argument, returns it directly (no allocation).\n * Cleanup listeners are registered to prevent leaks.\n *\n * @internal\n */\nexport function combineSignals(first: AbortSignal, ...rest: AbortSignal[]): AbortSignal {\n if (rest.length === 0) return first;\n\n return rest.reduce(mergeTwo, first);\n}\n\nfunction mergeTwo(a: AbortSignal, b: AbortSignal): AbortSignal {\n if (a.aborted) return a;\n\n if (b.aborted) return b;\n\n const ctrl = new AbortController();\n const onA = (): void => ctrl.abort(a.reason);\n const onB = (): void => ctrl.abort(b.reason);\n\n a.addEventListener('abort', onA, { once: true });\n b.addEventListener('abort', onB, { once: true });\n ctrl.signal.addEventListener(\n 'abort',\n () => {\n a.removeEventListener('abort', onA);\n b.removeEventListener('abort', onB);\n },\n { once: true },\n );\n\n return ctrl.signal;\n}\n\n/**\n * Create a child `AbortController` that aborts as soon as `parent` does.\n * Handles the case where `parent` is already aborted at call time — a plain\n * `addEventListener('abort', ...)` would miss that, since the event already fired.\n *\n * @internal\n */\nexport function deriveAbortController(parent: AbortSignal): AbortController {\n const ctrl = new AbortController();\n\n if (parent.aborted) {\n ctrl.abort(parent.reason);\n } else {\n parent.addEventListener('abort', () => ctrl.abort(parent.reason), { once: true });\n }\n\n return ctrl;\n}\n\n/**\n * Sleep for `ms` milliseconds, aborting early when the signal fires.\n * Resolves (does not reject) on abort — callers check `signal.aborted`.\n *\n * @internal\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n\n return;\n }\n\n const id = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(id);\n resolve();\n },\n { once: true },\n );\n });\n}\n\n/**\n * Full-jitter exponential backoff in ms, capped at `maxMs`.\n * `attempt` is zero-based.\n *\n * @internal\n */\nexport function defaultReconnectDelay(attempt: number, maxMs = 30_000): number {\n const base = Math.min(1000 * 2 ** attempt, maxMs);\n\n return Math.random() * base;\n}\n"],"mappings":";AAOA,SAAgB,EAAe,GAAoB,GAAG,GAAkC;CAGtF,OAFI,EAAK,WAAW,IAAU,IAEvB,EAAK,OAAO,GAAU,CAAK;AACpC;AAEA,SAAS,EAAS,GAAgB,GAA6B;CAC7D,IAAI,EAAE,SAAS,OAAO;CAEtB,IAAI,EAAE,SAAS,OAAO;CAEtB,IAAM,IAAO,IAAI,gBAAgB,GAC3B,UAAkB,EAAK,MAAM,EAAE,MAAM,GACrC,UAAkB,EAAK,MAAM,EAAE,MAAM;CAa3C,OAXA,EAAE,iBAAiB,SAAS,GAAK,EAAE,MAAM,GAAK,CAAC,GAC/C,EAAE,iBAAiB,SAAS,GAAK,EAAE,MAAM,GAAK,CAAC,GAC/C,EAAK,OAAO,iBACV,eACM;EAEJ,AADA,EAAE,oBAAoB,SAAS,CAAG,GAClC,EAAE,oBAAoB,SAAS,CAAG;CACpC,GACA,EAAE,MAAM,GAAK,CACf,GAEO,EAAK;AACd;AASA,SAAgB,EAAsB,GAAsC;CAC1E,IAAM,IAAO,IAAI,gBAAgB;CAQjC,OANI,EAAO,UACT,EAAK,MAAM,EAAO,MAAM,IAExB,EAAO,iBAAiB,eAAe,EAAK,MAAM,EAAO,MAAM,GAAG,EAAE,MAAM,GAAK,CAAC,GAG3E;AACT;AAQA,SAAgB,EAAM,GAAY,GAAqC;CACrE,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAI,GAAQ,SAAS;GACnB,EAAQ;GAER;EACF;EAEA,IAAM,IAAK,WAAW,GAAS,CAAE;EAEjC,GAAQ,iBACN,eACM;GAEJ,AADA,aAAa,CAAE,GACf,EAAQ;EACV,GACA,EAAE,MAAM,GAAK,CACf;CACF,CAAC;AACH;AAQA,SAAgB,EAAsB,GAAiB,IAAQ,KAAgB;CAC7E,IAAM,IAAO,KAAK,IAAI,MAAO,KAAK,GAAS,CAAK;CAEhD,OAAO,KAAK,OAAO,IAAI;AACzB"}
1
+ {"version":3,"file":"_utils.js","names":[],"sources":["../src/_utils.ts"],"sourcesContent":["/**\n * Create a child `AbortController` that aborts as soon as `parent` does.\n * Handles the case where `parent` is already aborted at call time — a plain\n * `addEventListener('abort', ...)` would miss that, since the event already fired.\n *\n * @internal\n */\nexport function deriveAbortController(parent: AbortSignal): AbortController {\n const ctrl = new AbortController();\n\n if (parent.aborted) {\n ctrl.abort(parent.reason);\n } else {\n parent.addEventListener('abort', () => ctrl.abort(parent.reason), { once: true });\n }\n\n return ctrl;\n}\n\n/**\n * Sleep for `ms` milliseconds, aborting early when the signal fires.\n * Resolves (does not reject) on abort — callers check `signal.aborted`.\n *\n * @internal\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n\n return;\n }\n\n const id = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(id);\n resolve();\n },\n { once: true },\n );\n });\n}\n\n/**\n * Full-jitter exponential backoff in ms, capped at `maxMs`.\n * `attempt` is zero-based.\n *\n * @internal\n */\nexport function defaultReconnectDelay(attempt: number, maxMs = 30_000): number {\n const base = Math.min(1000 * 2 ** attempt, maxMs);\n\n return Math.random() * base;\n}\n"],"mappings":";AAOA,SAAgB,EAAsB,GAAsC;CAC1E,IAAM,IAAO,IAAI,gBAAgB;CAQjC,OANI,EAAO,UACT,EAAK,MAAM,EAAO,MAAM,IAExB,EAAO,iBAAiB,eAAe,EAAK,MAAM,EAAO,MAAM,GAAG,EAAE,MAAM,GAAK,CAAC,GAG3E;AACT;AAQA,SAAgB,EAAM,GAAY,GAAqC;CACrE,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAI,GAAQ,SAAS;GACnB,EAAQ;GAER;EACF;EAEA,IAAM,IAAK,WAAW,GAAS,CAAE;EAEjC,GAAQ,iBACN,eACM;GAEJ,AADA,aAAa,CAAE,GACf,EAAQ;EACV,GACA,EAAE,MAAM,GAAK,CACf;CACF,CAAC;AACH;AAQA,SAAgB,EAAsB,GAAiB,IAAQ,KAAgB;CAC7E,IAAM,IAAO,KAAK,IAAI,MAAO,KAAK,GAAS,CAAK;CAEhD,OAAO,KAAK,OAAO,IAAI;AACzB"}
package/dist/_wait.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./_utils.cjs");function n(n,r,i,a){return new Promise((o,s)=>{let c=[r],l;if(i?.signal&&c.push(i.signal),i?.timeout!==void 0){let t=new AbortController;l=setTimeout(()=>{t.abort(new e.PulseTimeoutError(n))},i.timeout),c.push(t.signal)}let u=c.length===1?c[0]:t.combineSignals(c[0],...c.slice(1));if(u.aborted){clearTimeout(l),s(u.reason instanceof e.PulseTimeoutError?u.reason:new e.PulseAbortError);return}let d=()=>{},f=()=>{clearTimeout(l),d(),s(u.reason instanceof e.PulseTimeoutError?u.reason:new e.PulseAbortError)};u.addEventListener(`abort`,f,{once:!0}),d=a(n,e=>{clearTimeout(l),u.removeEventListener(`abort`,f),o(e)})})}exports.createWaitPromise=n;
1
+ const e=require("./errors.cjs");function t(t,n,r,i){return new Promise((a,o)=>{let s=[n],c;if(r?.signal&&s.push(r.signal),r?.timeout!==void 0){let n=new AbortController;c=setTimeout(()=>{n.abort(new e.PulseTimeoutError(t))},r.timeout),s.push(n.signal)}let l=AbortSignal.any(s);if(l.aborted){clearTimeout(c),o(l.reason instanceof e.PulseTimeoutError?l.reason:new e.PulseAbortError);return}let u=()=>{},d=()=>{clearTimeout(c),u(),o(l.reason instanceof e.PulseTimeoutError?l.reason:new e.PulseAbortError)};l.addEventListener(`abort`,d,{once:!0}),u=i(t,e=>{clearTimeout(c),l.removeEventListener(`abort`,d),a(e)})})}exports.createWaitPromise=t;
2
2
  //# sourceMappingURL=_wait.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"_wait.cjs","names":[],"sources":["../src/_wait.ts"],"sourcesContent":["import { combineSignals } from './_utils';\nimport { PulseAbortError, PulseTimeoutError } from './errors';\nimport type { Unsubscribe } from './types';\n\n/**\n * Shared implementation for `pulse.wait()` and `channel.wait()`.\n * Resolves on the next event dispatched via `subscribe`, or rejects when\n * the combined signal aborts or the optional timeout elapses.\n *\n * @internal\n */\nexport function createWaitPromise<T>(\n event: string,\n baseSignal: AbortSignal,\n opts: { signal?: AbortSignal; timeout?: number } | undefined,\n subscribe: (event: string, handler: (payload: unknown) => void) => Unsubscribe,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const signals: AbortSignal[] = [baseSignal];\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (opts?.signal) signals.push(opts.signal);\n\n if (opts?.timeout !== undefined) {\n const timeoutCtrl = new AbortController();\n\n timeoutId = setTimeout(() => {\n timeoutCtrl.abort(new PulseTimeoutError(event));\n }, opts.timeout);\n signals.push(timeoutCtrl.signal);\n }\n\n const combined = signals.length === 1 ? signals[0]! : combineSignals(signals[0]!, ...signals.slice(1));\n\n if (combined.aborted) {\n clearTimeout(timeoutId);\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n\n return;\n }\n\n let unsub: Unsubscribe = () => {};\n\n const onAbort = (): void => {\n clearTimeout(timeoutId);\n unsub();\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n };\n\n combined.addEventListener('abort', onAbort, { once: true });\n\n unsub = subscribe(event, (payload) => {\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n resolve(payload as T);\n });\n });\n}\n"],"mappings":"0DAWA,SAAgB,EACd,EACA,EACA,EACA,EACY,CACZ,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAyB,CAAC,CAAU,EAEtC,EAIJ,GAFI,GAAM,QAAQ,EAAQ,KAAK,EAAK,MAAM,EAEtC,GAAM,UAAY,IAAA,GAAW,CAC/B,IAAM,EAAc,IAAI,gBAExB,EAAY,eAAiB,CAC3B,EAAY,MAAM,IAAI,EAAA,kBAAkB,CAAK,CAAC,CAChD,EAAG,EAAK,OAAO,EACf,EAAQ,KAAK,EAAY,MAAM,CACjC,CAEA,IAAM,EAAW,EAAQ,SAAW,EAAI,EAAQ,GAAM,EAAA,eAAe,EAAQ,GAAK,GAAG,EAAQ,MAAM,CAAC,CAAC,EAErG,GAAI,EAAS,QAAS,CACpB,aAAa,CAAS,EACtB,EAAO,EAAS,kBAAkB,EAAA,kBAAoB,EAAS,OAAS,IAAI,EAAA,eAAiB,EAE7F,MACF,CAEA,IAAI,MAA2B,CAAC,EAE1B,MAAsB,CAC1B,aAAa,CAAS,EACtB,EAAM,EACN,EAAO,EAAS,kBAAkB,EAAA,kBAAoB,EAAS,OAAS,IAAI,EAAA,eAAiB,CAC/F,EAEA,EAAS,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,EAE1D,EAAQ,EAAU,EAAQ,GAAY,CACpC,aAAa,CAAS,EACtB,EAAS,oBAAoB,QAAS,CAAO,EAC7C,EAAQ,CAAY,CACtB,CAAC,CACH,CAAC,CACH"}
1
+ {"version":3,"file":"_wait.cjs","names":[],"sources":["../src/_wait.ts"],"sourcesContent":["import { PulseAbortError, PulseTimeoutError } from './errors';\nimport type { Unsubscribe } from './types';\n\n/**\n * Shared implementation for `pulse.wait()` and `channel.wait()`.\n * Resolves on the next event dispatched via `subscribe`, or rejects when\n * the combined signal aborts or the optional timeout elapses.\n *\n * @internal\n */\nexport function createWaitPromise<T>(\n event: string,\n baseSignal: AbortSignal,\n opts: { signal?: AbortSignal; timeout?: number } | undefined,\n subscribe: (event: string, handler: (payload: unknown) => void) => Unsubscribe,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const signals: AbortSignal[] = [baseSignal];\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (opts?.signal) signals.push(opts.signal);\n\n if (opts?.timeout !== undefined) {\n const timeoutCtrl = new AbortController();\n\n timeoutId = setTimeout(() => {\n timeoutCtrl.abort(new PulseTimeoutError(event));\n }, opts.timeout);\n signals.push(timeoutCtrl.signal);\n }\n\n const combined = AbortSignal.any(signals);\n\n if (combined.aborted) {\n clearTimeout(timeoutId);\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n\n return;\n }\n\n let unsub: Unsubscribe = () => {};\n\n const onAbort = (): void => {\n clearTimeout(timeoutId);\n unsub();\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n };\n\n combined.addEventListener('abort', onAbort, { once: true });\n\n unsub = subscribe(event, (payload) => {\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n resolve(payload as T);\n });\n });\n}\n"],"mappings":"gCAUA,SAAgB,EACd,EACA,EACA,EACA,EACY,CACZ,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAyB,CAAC,CAAU,EAEtC,EAIJ,GAFI,GAAM,QAAQ,EAAQ,KAAK,EAAK,MAAM,EAEtC,GAAM,UAAY,IAAA,GAAW,CAC/B,IAAM,EAAc,IAAI,gBAExB,EAAY,eAAiB,CAC3B,EAAY,MAAM,IAAI,EAAA,kBAAkB,CAAK,CAAC,CAChD,EAAG,EAAK,OAAO,EACf,EAAQ,KAAK,EAAY,MAAM,CACjC,CAEA,IAAM,EAAW,YAAY,IAAI,CAAO,EAExC,GAAI,EAAS,QAAS,CACpB,aAAa,CAAS,EACtB,EAAO,EAAS,kBAAkB,EAAA,kBAAoB,EAAS,OAAS,IAAI,EAAA,eAAiB,EAE7F,MACF,CAEA,IAAI,MAA2B,CAAC,EAE1B,MAAsB,CAC1B,aAAa,CAAS,EACtB,EAAM,EACN,EAAO,EAAS,kBAAkB,EAAA,kBAAoB,EAAS,OAAS,IAAI,EAAA,eAAiB,CAC/F,EAEA,EAAS,iBAAiB,QAAS,EAAS,CAAE,KAAM,EAAK,CAAC,EAE1D,EAAQ,EAAU,EAAQ,GAAY,CACpC,aAAa,CAAS,EACtB,EAAS,oBAAoB,QAAS,CAAO,EAC7C,EAAQ,CAAY,CACtB,CAAC,CACH,CAAC,CACH"}
package/dist/_wait.js CHANGED
@@ -1,29 +1,28 @@
1
1
  import { PulseAbortError as e, PulseTimeoutError as t } from "./errors.js";
2
- import { combineSignals as n } from "./_utils.js";
3
2
  //#region src/_wait.ts
4
- function r(r, i, a, o) {
5
- return new Promise((s, c) => {
6
- let l = [i], u;
7
- if (a?.signal && l.push(a.signal), a?.timeout !== void 0) {
3
+ function n(n, r, i, a) {
4
+ return new Promise((o, s) => {
5
+ let c = [r], l;
6
+ if (i?.signal && c.push(i.signal), i?.timeout !== void 0) {
8
7
  let e = new AbortController();
9
- u = setTimeout(() => {
10
- e.abort(new t(r));
11
- }, a.timeout), l.push(e.signal);
8
+ l = setTimeout(() => {
9
+ e.abort(new t(n));
10
+ }, i.timeout), c.push(e.signal);
12
11
  }
13
- let d = l.length === 1 ? l[0] : n(l[0], ...l.slice(1));
14
- if (d.aborted) {
15
- clearTimeout(u), c(d.reason instanceof t ? d.reason : new e());
12
+ let u = AbortSignal.any(c);
13
+ if (u.aborted) {
14
+ clearTimeout(l), s(u.reason instanceof t ? u.reason : new e());
16
15
  return;
17
16
  }
18
- let f = () => {}, p = () => {
19
- clearTimeout(u), f(), c(d.reason instanceof t ? d.reason : new e());
17
+ let d = () => {}, f = () => {
18
+ clearTimeout(l), d(), s(u.reason instanceof t ? u.reason : new e());
20
19
  };
21
- d.addEventListener("abort", p, { once: !0 }), f = o(r, (e) => {
22
- clearTimeout(u), d.removeEventListener("abort", p), s(e);
20
+ u.addEventListener("abort", f, { once: !0 }), d = a(n, (e) => {
21
+ clearTimeout(l), u.removeEventListener("abort", f), o(e);
23
22
  });
24
23
  });
25
24
  }
26
25
  //#endregion
27
- export { r as createWaitPromise };
26
+ export { n as createWaitPromise };
28
27
 
29
28
  //# sourceMappingURL=_wait.js.map
package/dist/_wait.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"_wait.js","names":[],"sources":["../src/_wait.ts"],"sourcesContent":["import { combineSignals } from './_utils';\nimport { PulseAbortError, PulseTimeoutError } from './errors';\nimport type { Unsubscribe } from './types';\n\n/**\n * Shared implementation for `pulse.wait()` and `channel.wait()`.\n * Resolves on the next event dispatched via `subscribe`, or rejects when\n * the combined signal aborts or the optional timeout elapses.\n *\n * @internal\n */\nexport function createWaitPromise<T>(\n event: string,\n baseSignal: AbortSignal,\n opts: { signal?: AbortSignal; timeout?: number } | undefined,\n subscribe: (event: string, handler: (payload: unknown) => void) => Unsubscribe,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const signals: AbortSignal[] = [baseSignal];\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (opts?.signal) signals.push(opts.signal);\n\n if (opts?.timeout !== undefined) {\n const timeoutCtrl = new AbortController();\n\n timeoutId = setTimeout(() => {\n timeoutCtrl.abort(new PulseTimeoutError(event));\n }, opts.timeout);\n signals.push(timeoutCtrl.signal);\n }\n\n const combined = signals.length === 1 ? signals[0]! : combineSignals(signals[0]!, ...signals.slice(1));\n\n if (combined.aborted) {\n clearTimeout(timeoutId);\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n\n return;\n }\n\n let unsub: Unsubscribe = () => {};\n\n const onAbort = (): void => {\n clearTimeout(timeoutId);\n unsub();\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n };\n\n combined.addEventListener('abort', onAbort, { once: true });\n\n unsub = subscribe(event, (payload) => {\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n resolve(payload as T);\n });\n });\n}\n"],"mappings":";;;AAWA,SAAgB,EACd,GACA,GACA,GACA,GACY;CACZ,OAAO,IAAI,SAAS,GAAS,MAAW;EACtC,IAAM,IAAyB,CAAC,CAAU,GAEtC;EAIJ,IAFI,GAAM,UAAQ,EAAQ,KAAK,EAAK,MAAM,GAEtC,GAAM,YAAY,KAAA,GAAW;GAC/B,IAAM,IAAc,IAAI,gBAAgB;GAKxC,AAHA,IAAY,iBAAiB;IAC3B,EAAY,MAAM,IAAI,EAAkB,CAAK,CAAC;GAChD,GAAG,EAAK,OAAO,GACf,EAAQ,KAAK,EAAY,MAAM;EACjC;EAEA,IAAM,IAAW,EAAQ,WAAW,IAAI,EAAQ,KAAM,EAAe,EAAQ,IAAK,GAAG,EAAQ,MAAM,CAAC,CAAC;EAErG,IAAI,EAAS,SAAS;GAEpB,AADA,aAAa,CAAS,GACtB,EAAO,EAAS,kBAAkB,IAAoB,EAAS,SAAS,IAAI,EAAgB,CAAC;GAE7F;EACF;EAEA,IAAI,UAA2B,CAAC,GAE1B,UAAsB;GAG1B,AAFA,aAAa,CAAS,GACtB,EAAM,GACN,EAAO,EAAS,kBAAkB,IAAoB,EAAS,SAAS,IAAI,EAAgB,CAAC;EAC/F;EAIA,AAFA,EAAS,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC,GAE1D,IAAQ,EAAU,IAAQ,MAAY;GAGpC,AAFA,aAAa,CAAS,GACtB,EAAS,oBAAoB,SAAS,CAAO,GAC7C,EAAQ,CAAY;EACtB,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"_wait.js","names":[],"sources":["../src/_wait.ts"],"sourcesContent":["import { PulseAbortError, PulseTimeoutError } from './errors';\nimport type { Unsubscribe } from './types';\n\n/**\n * Shared implementation for `pulse.wait()` and `channel.wait()`.\n * Resolves on the next event dispatched via `subscribe`, or rejects when\n * the combined signal aborts or the optional timeout elapses.\n *\n * @internal\n */\nexport function createWaitPromise<T>(\n event: string,\n baseSignal: AbortSignal,\n opts: { signal?: AbortSignal; timeout?: number } | undefined,\n subscribe: (event: string, handler: (payload: unknown) => void) => Unsubscribe,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const signals: AbortSignal[] = [baseSignal];\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (opts?.signal) signals.push(opts.signal);\n\n if (opts?.timeout !== undefined) {\n const timeoutCtrl = new AbortController();\n\n timeoutId = setTimeout(() => {\n timeoutCtrl.abort(new PulseTimeoutError(event));\n }, opts.timeout);\n signals.push(timeoutCtrl.signal);\n }\n\n const combined = AbortSignal.any(signals);\n\n if (combined.aborted) {\n clearTimeout(timeoutId);\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n\n return;\n }\n\n let unsub: Unsubscribe = () => {};\n\n const onAbort = (): void => {\n clearTimeout(timeoutId);\n unsub();\n reject(combined.reason instanceof PulseTimeoutError ? combined.reason : new PulseAbortError());\n };\n\n combined.addEventListener('abort', onAbort, { once: true });\n\n unsub = subscribe(event, (payload) => {\n clearTimeout(timeoutId);\n combined.removeEventListener('abort', onAbort);\n resolve(payload as T);\n });\n });\n}\n"],"mappings":";;AAUA,SAAgB,EACd,GACA,GACA,GACA,GACY;CACZ,OAAO,IAAI,SAAS,GAAS,MAAW;EACtC,IAAM,IAAyB,CAAC,CAAU,GAEtC;EAIJ,IAFI,GAAM,UAAQ,EAAQ,KAAK,EAAK,MAAM,GAEtC,GAAM,YAAY,KAAA,GAAW;GAC/B,IAAM,IAAc,IAAI,gBAAgB;GAKxC,AAHA,IAAY,iBAAiB;IAC3B,EAAY,MAAM,IAAI,EAAkB,CAAK,CAAC;GAChD,GAAG,EAAK,OAAO,GACf,EAAQ,KAAK,EAAY,MAAM;EACjC;EAEA,IAAM,IAAW,YAAY,IAAI,CAAO;EAExC,IAAI,EAAS,SAAS;GAEpB,AADA,aAAa,CAAS,GACtB,EAAO,EAAS,kBAAkB,IAAoB,EAAS,SAAS,IAAI,EAAgB,CAAC;GAE7F;EACF;EAEA,IAAI,UAA2B,CAAC,GAE1B,UAAsB;GAG1B,AAFA,aAAa,CAAS,GACtB,EAAM,GACN,EAAO,EAAS,kBAAkB,IAAoB,EAAS,SAAS,IAAI,EAAgB,CAAC;EAC/F;EAIA,AAFA,EAAS,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC,GAE1D,IAAQ,EAAU,IAAQ,MAAY;GAGpC,AAFA,aAAa,CAAS,GACtB,EAAS,oBAAoB,SAAS,CAAO,GAC7C,EAAQ,CAAY;EACtB,CAAC;CACH,CAAC;AACH"}
package/dist/errors.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},t=class extends e{url;constructor(e,t,n){super(e,n),this.url=t}},n=class extends e{event;constructor(e,t){super(`Timed out waiting for "${e}"`,t),this.event=e}},r=class extends e{room;constructor(e,t){super(`Timed out waiting for room "${e}"`,t),this.room=e}},i=class extends e{constructor(e){super(`Aborted`,e)}},a=class extends e{constructor(e=`Pulse`,t){super(`${e} instance is disposed`,t)}},o=class extends e{raw;constructor(e,t,n){super(e,n),this.raw=t}};exports.PulseAbortError=i,exports.PulseConnectionError=t,exports.PulseDisposedError=a,exports.PulseError=e,exports.PulseProtocolError=o,exports.PulseRoomTimeoutError=r,exports.PulseTimeoutError=n;
1
+ var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{url;constructor(e,t,n){super(e,n),this.url=t}},n=class extends e{event;constructor(e,t){super(`Timed out waiting for "${e}"`,t),this.event=e}},r=class extends e{room;constructor(e,t){super(`Timed out waiting for room "${e}"`,t),this.room=e}},i=class extends e{constructor(e){super(`Aborted`,e)}},a=class extends e{constructor(e=`Pulse`,t){super(`${e} instance is disposed`,t)}},o=class extends e{raw;constructor(e,t,n){super(e,n),this.raw=t}};exports.PulseAbortError=i,exports.PulseConnectionError=t,exports.PulseDisposedError=a,exports.PulseError=e,exports.PulseProtocolError=o,exports.PulseRoomTimeoutError=r,exports.PulseTimeoutError=n;
2
2
  //# sourceMappingURL=errors.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all pulse errors.\n * Use `instanceof PulseError` to catch any pulse-originated error in one branch.\n */\nexport class PulseError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is PulseError {\n return err instanceof PulseError;\n }\n}\n\n/**\n * Thrown when a WebSocket connection cannot be established or is lost\n * without triggering auto-reconnect (budget exhausted, or reconnect disabled).\n */\nexport class PulseConnectionError extends PulseError {\n readonly url: string;\n\n constructor(message: string, url: string, opts?: ErrorOptions) {\n super(message, opts);\n this.url = url;\n }\n}\n\n/**\n * Thrown when `wait()` times out before the server event arrives.\n */\nexport class PulseTimeoutError extends PulseError {\n readonly event: string;\n\n constructor(event: string, opts?: ErrorOptions) {\n super(`Timed out waiting for \"${event}\"`, opts);\n this.event = event;\n }\n}\n\n/**\n * Thrown when a room scope's `joined` promise times out before the server\n * confirms membership, or when an AbortSignal fires before confirmation.\n */\nexport class PulseRoomTimeoutError extends PulseError {\n readonly room: string;\n\n constructor(room: string, opts?: ErrorOptions) {\n super(`Timed out waiting for room \"${room}\"`, opts);\n this.room = room;\n }\n}\n\n/**\n * Thrown when `wait()` is aborted via an AbortSignal before the event fires,\n * or when a room scope's join is aborted before the server confirms.\n */\nexport class PulseAbortError extends PulseError {\n constructor(opts?: ErrorOptions) {\n super('Aborted', opts);\n }\n}\n\n/**\n * Thrown when a method is called on a disposed Pulse instance or channel.\n */\nexport class PulseDisposedError extends PulseError {\n constructor(target = 'Pulse', opts?: ErrorOptions) {\n super(`${target} instance is disposed`, opts);\n }\n}\n\n/**\n * Thrown when the server sends a frame that cannot be parsed or violates\n * the wire protocol schema.\n */\nexport class PulseProtocolError extends PulseError {\n readonly raw: unknown;\n\n constructor(message: string, raw?: unknown, opts?: ErrorOptions) {\n super(message, opts);\n this.raw = raw;\n }\n}\n"],"mappings":"AAIA,IAAa,EAAb,MAAa,UAAmB,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CAEA,OAAO,GAAG,EAAiC,CACzC,OAAO,aAAe,CACxB,CACF,EAMa,EAAb,cAA0C,CAAW,CACnD,IAEA,YAAY,EAAiB,EAAa,EAAqB,CAC7D,MAAM,EAAS,CAAI,EACnB,KAAK,IAAM,CACb,CACF,EAKa,EAAb,cAAuC,CAAW,CAChD,MAEA,YAAY,EAAe,EAAqB,CAC9C,MAAM,0BAA0B,EAAM,GAAI,CAAI,EAC9C,KAAK,MAAQ,CACf,CACF,EAMa,EAAb,cAA2C,CAAW,CACpD,KAEA,YAAY,EAAc,EAAqB,CAC7C,MAAM,+BAA+B,EAAK,GAAI,CAAI,EAClD,KAAK,KAAO,CACd,CACF,EAMa,EAAb,cAAqC,CAAW,CAC9C,YAAY,EAAqB,CAC/B,MAAM,UAAW,CAAI,CACvB,CACF,EAKa,EAAb,cAAwC,CAAW,CACjD,YAAY,EAAS,QAAS,EAAqB,CACjD,MAAM,GAAG,EAAO,uBAAwB,CAAI,CAC9C,CACF,EAMa,EAAb,cAAwC,CAAW,CACjD,IAEA,YAAY,EAAiB,EAAe,EAAqB,CAC/D,MAAM,EAAS,CAAI,EACnB,KAAK,IAAM,CACb,CACF"}
1
+ {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all pulse errors.\n * Use `instanceof PulseError` to catch any pulse-originated error in one branch.\n */\nexport class PulseError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown when a WebSocket connection cannot be established or is lost\n * without triggering auto-reconnect (budget exhausted, or reconnect disabled).\n */\nexport class PulseConnectionError extends PulseError {\n readonly url: string;\n\n constructor(message: string, url: string, opts?: ErrorOptions) {\n super(message, opts);\n this.url = url;\n }\n}\n\n/**\n * Thrown when `wait()` times out before the server event arrives.\n */\nexport class PulseTimeoutError extends PulseError {\n readonly event: string;\n\n constructor(event: string, opts?: ErrorOptions) {\n super(`Timed out waiting for \"${event}\"`, opts);\n this.event = event;\n }\n}\n\n/**\n * Thrown when a room scope's `joined` promise times out before the server\n * confirms membership, or when an AbortSignal fires before confirmation.\n */\nexport class PulseRoomTimeoutError extends PulseError {\n readonly room: string;\n\n constructor(room: string, opts?: ErrorOptions) {\n super(`Timed out waiting for room \"${room}\"`, opts);\n this.room = room;\n }\n}\n\n/**\n * Thrown when `wait()` is aborted via an AbortSignal before the event fires,\n * or when a room scope's join is aborted before the server confirms.\n */\nexport class PulseAbortError extends PulseError {\n constructor(opts?: ErrorOptions) {\n super('Aborted', opts);\n }\n}\n\n/**\n * Thrown when a method is called on a disposed Pulse instance or channel.\n */\nexport class PulseDisposedError extends PulseError {\n constructor(target = 'Pulse', opts?: ErrorOptions) {\n super(`${target} instance is disposed`, opts);\n }\n}\n\n/**\n * Thrown when the server sends a frame that cannot be parsed or violates\n * the wire protocol schema.\n */\nexport class PulseProtocolError extends PulseError {\n readonly raw: unknown;\n\n constructor(message: string, raw?: unknown, opts?: ErrorOptions) {\n super(message, opts);\n this.raw = raw;\n }\n}\n"],"mappings":"AAIA,IAAa,EAAb,cAAgC,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAMa,EAAb,cAA0C,CAAW,CACnD,IAEA,YAAY,EAAiB,EAAa,EAAqB,CAC7D,MAAM,EAAS,CAAI,EACnB,KAAK,IAAM,CACb,CACF,EAKa,EAAb,cAAuC,CAAW,CAChD,MAEA,YAAY,EAAe,EAAqB,CAC9C,MAAM,0BAA0B,EAAM,GAAI,CAAI,EAC9C,KAAK,MAAQ,CACf,CACF,EAMa,EAAb,cAA2C,CAAW,CACpD,KAEA,YAAY,EAAc,EAAqB,CAC7C,MAAM,+BAA+B,EAAK,GAAI,CAAI,EAClD,KAAK,KAAO,CACd,CACF,EAMa,EAAb,cAAqC,CAAW,CAC9C,YAAY,EAAqB,CAC/B,MAAM,UAAW,CAAI,CACvB,CACF,EAKa,EAAb,cAAwC,CAAW,CACjD,YAAY,EAAS,QAAS,EAAqB,CACjD,MAAM,GAAG,EAAO,uBAAwB,CAAI,CAC9C,CACF,EAMa,EAAb,cAAwC,CAAW,CACjD,IAEA,YAAY,EAAiB,EAAe,EAAqB,CAC/D,MAAM,EAAS,CAAI,EACnB,KAAK,IAAM,CACb,CACF"}
package/dist/errors.d.ts CHANGED
@@ -4,7 +4,6 @@
4
4
  */
5
5
  export declare class PulseError extends Error {
6
6
  constructor(message: string, opts?: ErrorOptions);
7
- static is(err: unknown): err is PulseError;
8
7
  }
9
8
  /**
10
9
  * Thrown when a WebSocket connection cannot be established or is lost
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAMhD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,UAAU;CAG3C;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAET,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAI9D;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAI/C;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAI9C;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,UAAU;gBACjC,IAAI,CAAC,EAAE,YAAY;CAGhC;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,MAAM,SAAU,EAAE,IAAI,CAAC,EAAE,YAAY;CAGlD;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,YAAY;CAIhE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAKjD;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAET,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAI9D;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAI/C;AAED;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAI9C;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,UAAU;gBACjC,IAAI,CAAC,EAAE,YAAY;CAGhC;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,MAAM,SAAU,EAAE,IAAI,CAAC,EAAE,YAAY;CAGlD;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,YAAY;CAIhE"}
package/dist/errors.js CHANGED
@@ -1,11 +1,8 @@
1
1
  //#region src/errors.ts
2
- var e = class e extends Error {
2
+ var e = class extends Error {
3
3
  constructor(e, t) {
4
4
  super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
5
5
  }
6
- static is(t) {
7
- return t instanceof e;
8
- }
9
6
  }, t = class extends e {
10
7
  url;
11
8
  constructor(e, t, n) {
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all pulse errors.\n * Use `instanceof PulseError` to catch any pulse-originated error in one branch.\n */\nexport class PulseError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is PulseError {\n return err instanceof PulseError;\n }\n}\n\n/**\n * Thrown when a WebSocket connection cannot be established or is lost\n * without triggering auto-reconnect (budget exhausted, or reconnect disabled).\n */\nexport class PulseConnectionError extends PulseError {\n readonly url: string;\n\n constructor(message: string, url: string, opts?: ErrorOptions) {\n super(message, opts);\n this.url = url;\n }\n}\n\n/**\n * Thrown when `wait()` times out before the server event arrives.\n */\nexport class PulseTimeoutError extends PulseError {\n readonly event: string;\n\n constructor(event: string, opts?: ErrorOptions) {\n super(`Timed out waiting for \"${event}\"`, opts);\n this.event = event;\n }\n}\n\n/**\n * Thrown when a room scope's `joined` promise times out before the server\n * confirms membership, or when an AbortSignal fires before confirmation.\n */\nexport class PulseRoomTimeoutError extends PulseError {\n readonly room: string;\n\n constructor(room: string, opts?: ErrorOptions) {\n super(`Timed out waiting for room \"${room}\"`, opts);\n this.room = room;\n }\n}\n\n/**\n * Thrown when `wait()` is aborted via an AbortSignal before the event fires,\n * or when a room scope's join is aborted before the server confirms.\n */\nexport class PulseAbortError extends PulseError {\n constructor(opts?: ErrorOptions) {\n super('Aborted', opts);\n }\n}\n\n/**\n * Thrown when a method is called on a disposed Pulse instance or channel.\n */\nexport class PulseDisposedError extends PulseError {\n constructor(target = 'Pulse', opts?: ErrorOptions) {\n super(`${target} instance is disposed`, opts);\n }\n}\n\n/**\n * Thrown when the server sends a frame that cannot be parsed or violates\n * the wire protocol schema.\n */\nexport class PulseProtocolError extends PulseError {\n readonly raw: unknown;\n\n constructor(message: string, raw?: unknown, opts?: ErrorOptions) {\n super(message, opts);\n this.raw = raw;\n }\n}\n"],"mappings":";AAIA,IAAa,IAAb,MAAa,UAAmB,MAAM;CACpC,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,WAAW,MACvB,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;CAEA,OAAO,GAAG,GAAiC;EACzC,OAAO,aAAe;CACxB;AACF,GAMa,IAAb,cAA0C,EAAW;CACnD;CAEA,YAAY,GAAiB,GAAa,GAAqB;EAE7D,AADA,MAAM,GAAS,CAAI,GACnB,KAAK,MAAM;CACb;AACF,GAKa,IAAb,cAAuC,EAAW;CAChD;CAEA,YAAY,GAAe,GAAqB;EAE9C,AADA,MAAM,0BAA0B,EAAM,IAAI,CAAI,GAC9C,KAAK,QAAQ;CACf;AACF,GAMa,IAAb,cAA2C,EAAW;CACpD;CAEA,YAAY,GAAc,GAAqB;EAE7C,AADA,MAAM,+BAA+B,EAAK,IAAI,CAAI,GAClD,KAAK,OAAO;CACd;AACF,GAMa,IAAb,cAAqC,EAAW;CAC9C,YAAY,GAAqB;EAC/B,MAAM,WAAW,CAAI;CACvB;AACF,GAKa,IAAb,cAAwC,EAAW;CACjD,YAAY,IAAS,SAAS,GAAqB;EACjD,MAAM,GAAG,EAAO,wBAAwB,CAAI;CAC9C;AACF,GAMa,IAAb,cAAwC,EAAW;CACjD;CAEA,YAAY,GAAiB,GAAe,GAAqB;EAE/D,AADA,MAAM,GAAS,CAAI,GACnB,KAAK,MAAM;CACb;AACF"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all pulse errors.\n * Use `instanceof PulseError` to catch any pulse-originated error in one branch.\n */\nexport class PulseError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown when a WebSocket connection cannot be established or is lost\n * without triggering auto-reconnect (budget exhausted, or reconnect disabled).\n */\nexport class PulseConnectionError extends PulseError {\n readonly url: string;\n\n constructor(message: string, url: string, opts?: ErrorOptions) {\n super(message, opts);\n this.url = url;\n }\n}\n\n/**\n * Thrown when `wait()` times out before the server event arrives.\n */\nexport class PulseTimeoutError extends PulseError {\n readonly event: string;\n\n constructor(event: string, opts?: ErrorOptions) {\n super(`Timed out waiting for \"${event}\"`, opts);\n this.event = event;\n }\n}\n\n/**\n * Thrown when a room scope's `joined` promise times out before the server\n * confirms membership, or when an AbortSignal fires before confirmation.\n */\nexport class PulseRoomTimeoutError extends PulseError {\n readonly room: string;\n\n constructor(room: string, opts?: ErrorOptions) {\n super(`Timed out waiting for room \"${room}\"`, opts);\n this.room = room;\n }\n}\n\n/**\n * Thrown when `wait()` is aborted via an AbortSignal before the event fires,\n * or when a room scope's join is aborted before the server confirms.\n */\nexport class PulseAbortError extends PulseError {\n constructor(opts?: ErrorOptions) {\n super('Aborted', opts);\n }\n}\n\n/**\n * Thrown when a method is called on a disposed Pulse instance or channel.\n */\nexport class PulseDisposedError extends PulseError {\n constructor(target = 'Pulse', opts?: ErrorOptions) {\n super(`${target} instance is disposed`, opts);\n }\n}\n\n/**\n * Thrown when the server sends a frame that cannot be parsed or violates\n * the wire protocol schema.\n */\nexport class PulseProtocolError extends PulseError {\n readonly raw: unknown;\n\n constructor(message: string, raw?: unknown, opts?: ErrorOptions) {\n super(message, opts);\n this.raw = raw;\n }\n}\n"],"mappings":";AAIA,IAAa,IAAb,cAAgC,MAAM;CACpC,YAAY,GAAiB,GAAqB;EAGhD,AAFA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,WAAW,MACvB,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAMa,IAAb,cAA0C,EAAW;CACnD;CAEA,YAAY,GAAiB,GAAa,GAAqB;EAE7D,AADA,MAAM,GAAS,CAAI,GACnB,KAAK,MAAM;CACb;AACF,GAKa,IAAb,cAAuC,EAAW;CAChD;CAEA,YAAY,GAAe,GAAqB;EAE9C,AADA,MAAM,0BAA0B,EAAM,IAAI,CAAI,GAC9C,KAAK,QAAQ;CACf;AACF,GAMa,IAAb,cAA2C,EAAW;CACpD;CAEA,YAAY,GAAc,GAAqB;EAE7C,AADA,MAAM,+BAA+B,EAAK,IAAI,CAAI,GAClD,KAAK,OAAO;CACd;AACF,GAMa,IAAb,cAAqC,EAAW;CAC9C,YAAY,GAAqB;EAC/B,MAAM,WAAW,CAAI;CACvB;AACF,GAKa,IAAb,cAAwC,EAAW;CACjD,YAAY,IAAS,SAAS,GAAqB;EACjD,MAAM,GAAG,EAAO,wBAAwB,CAAI;CAC9C;AACF,GAMa,IAAb,cAAwC,EAAW;CACjD;CAEA,YAAY,GAAiB,GAAe,GAAqB;EAE/D,AADA,MAAM,GAAS,CAAI,GACnB,KAAK,MAAM;CACb;AACF"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { PulseAbortError, PulseConnectionError, PulseDisposedError, PulseError, PulseProtocolError, PulseRoomTimeoutError, PulseTimeoutError, } from './errors';
2
2
  export { createPulse } from './pulse';
3
- export type { ChannelDefinition, ChannelDefinitions, ClientEvents, EventKey, HeartbeatOptions, MessageMap, OutgoingMessage, OutgoingTransform, PresenceRoomScope, Pulse, PulseChannel, PulseOptions, PulseSchema, PulseStatus, ReconnectOptions, RoomDefinition, RoomDefinitions, RoomMap, RoomOptions, RoomScope, RoomScopeBase, ServerEvents, Unsubscribe, } from './types';
3
+ export type { ChannelDefinition, ChannelDefinitions, ClientEvents, EventKey, HeartbeatOptions, MessageMap, OutgoingMessage, OutgoingTransform, PresenceRoomScope, Pulse, PulseChannel, PulseEvent, PulseOptions, PulseSchema, PulseStatus, ReconnectOptions, RoomDefinition, RoomDefinitions, RoomMap, RoomOptions, RoomScope, RoomScopeBase, ServerEvents, Unsubscribe, } from './types';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,OAAO,EACP,WAAW,EACX,SAAS,EACT,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,EACL,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,OAAO,EACP,WAAW,EACX,SAAS,EACT,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC"}
package/dist/pulse.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/ripple");var t=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},n=class extends t{url;constructor(e,t,n){super(e,n),this.url=t}},r=class extends t{event;constructor(e,t){super(`Timed out waiting for "${e}"`,t),this.event=e}},i=class extends t{room;constructor(e,t){super(`Timed out waiting for room "${e}"`,t),this.room=e}},a=class extends t{constructor(e){super(`Aborted`,e)}},o=class extends t{constructor(e=`Pulse`,t){super(`${e} instance is disposed`,t)}},s=class extends t{raw;constructor(e,t,n){super(e,n),this.raw=t}};function c(e,...t){return t.length===0?e:t.reduce(l,e)}function l(e,t){if(e.aborted)return e;if(t.aborted)return t;let n=new AbortController,r=()=>n.abort(e.reason),i=()=>n.abort(t.reason);return e.addEventListener(`abort`,r,{once:!0}),t.addEventListener(`abort`,i,{once:!0}),n.signal.addEventListener(`abort`,()=>{e.removeEventListener(`abort`,r),t.removeEventListener(`abort`,i)},{once:!0}),n.signal}function u(e){let t=new AbortController;return e.aborted?t.abort(e.reason):e.addEventListener(`abort`,()=>t.abort(e.reason),{once:!0}),t}function d(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=setTimeout(n,e);t?.addEventListener(`abort`,()=>{clearTimeout(r),n()},{once:!0})})}function f(e,t=3e4){let n=Math.min(1e3*2**e,t);return Math.random()*n}var p=5;function m(e,t,r,i){let a=r===!0?{}:r||void 0,s=a?a.maxAttempts??p:0,c=a?.delay,l=typeof c==`function`?c:typeof c==`number`?()=>c:f,u=!1,m=!1,h=!1,g,_,v,y=new Set;function b(e){i.onStatus(e)}function x(e){for(let t of y)t.reject(e);y.clear()}function S(){for(let e of y)e.resolve();y.clear()}function C(e,t){v?.socket===e&&(v.reject(t),v=void 0)}function w(){if(_?.readyState===WebSocket.OPEN)return Promise.resolve();if(v)return v.promise;let r=new WebSocket(e,t);_=r;let a,o,s=new Promise((e,t)=>{a=e,o=t});return v={promise:s,reject:o,resolve:a,socket:r},r.onopen=()=>{if(_!==r||!m){r.close(1e3,`stale connection`);return}v?.socket===r&&(v.resolve(),v=void 0),b(`open`),i.onOpen(),S()},r.onmessage=e=>{_===r&&i.onMessage(e)},r.onerror=()=>{if(_!==r)return;let t=new n(`WebSocket error`,e);i.onError(t),C(r,t),x(t)},r.onclose=()=>{if(_!==r)return;_=void 0,i.onClose();let t=new n(`Connection closed`,e);if(C(r,t),!m||u){b(`closed`);return}h||T()},s}async function T(){if(h||u||!m)return;h=!0;let t=new AbortController;g=t,b(`reconnecting`);let r;for(let i=0;i<s&&m&&!u&&(await d(l(i),t.signal),!(t.signal.aborted||!m||u));i++)try{await w(),h=!1;return}catch(t){r=t instanceof n?t:new n(`Reconnect failed`,e)}!t.signal.aborted&&m&&!u&&(m=!1,b(`closed`),i.onError(r??new n(`Reconnect budget exhausted`,e)),x(r??new n(`Reconnect budget exhausted`,e))),g===t&&(g=void 0),h=!1}function E(){g?.abort(),g=void 0,h=!1}return{connect(){if(u)return Promise.reject(new o);if(m=!0,_?.readyState===WebSocket.OPEN)return Promise.resolve();let e=new Promise((e,t)=>{y.add({reject:t,resolve:e})});return!v&&!h&&(b(`connecting`),w().catch(()=>{})),e},disconnect(t=1e3,r=``){m=!1,E(),x(new n(`Connection closed`,e)),b(`closed`),_?.close(t,r)},dispose(){u||(u=!0,m=!1,E(),x(new o),_?.close(1e3,`disposed`),_=void 0,v=void 0,b(`closed`))},forceReconnect(e,t){m&&_?.readyState===WebSocket.OPEN&&_.close(e,t)},get open(){return _?.readyState===WebSocket.OPEN},send(t){if(_?.readyState!==WebSocket.OPEN)throw new n(`Connection is not open`,e);_.send(t)}}}function h(e,t,n,i){return new Promise((o,s)=>{let l=[t],u;if(n?.signal&&l.push(n.signal),n?.timeout!==void 0){let t=new AbortController;u=setTimeout(()=>{t.abort(new r(e))},n.timeout),l.push(t.signal)}let d=l.length===1?l[0]:c(l[0],...l.slice(1));if(d.aborted){clearTimeout(u),s(d.reason instanceof r?d.reason:new a);return}let f=()=>{},p=()=>{clearTimeout(u),f(),s(d.reason instanceof r?d.reason:new a)};d.addEventListener(`abort`,p,{once:!0}),f=i(e,e=>{clearTimeout(u),d.removeEventListener(`abort`,p),o(e)})})}function g(e,t,n,r,i){let a=u(r),s=new Set,c=a.signal.aborted;return a.signal.addEventListener(`abort`,()=>{c=!0},{once:!0}),{get disposalSignal(){return a.signal},dispose(){if(!c){c=!0,a.abort();for(let e of s)e();s.clear(),i?.()}},get disposed(){return c},get name(){return e},on(t,r){if(c)throw new o(`Channel "${e}"`);let i=n(e,t,r);return s.add(i),()=>{i(),s.delete(i)}},once(t,r){if(c)throw new o(`Channel "${e}"`);let i=()=>{};return i=n(e,t,e=>{s.delete(i),i(),r(e)}),s.add(i),()=>{s.delete(i),i()}},send(n,r){if(c)throw new o(`Channel "${e}"`);t(e,n,r)},[Symbol.dispose](){this.dispose()},wait(t,r){return h(t,a.signal,r,(t,r)=>n(e,t,r))}}}function _(e){return JSON.stringify(e)}function v(e){if(typeof e!=`string`)throw new s(`Expected string message data`,e);let t;try{t=JSON.parse(e)}catch{throw new s(`JSON parse error`,e)}if(typeof t!=`object`||!t||!(`type`in t)||typeof t.type!=`string`)throw new s(`Missing or invalid "type" field`,t);return t}function y(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function b(e,t){if(!y(e))return null;let n=e[t];return typeof n==`string`?n:null}function x(e){return b(e,`room`)!==null}function S(e){return b(e,`code`)!==null&&b(e,`message`)!==null}function C(e){return!y(e)||b(e,`event`)===null||!(`payload`in e)?!1:e.channel===void 0||typeof e.channel==`string`}function w(e){return y(e)&&typeof e.ts==`number`}function T(e){return y(e)&&b(e,`id`)!==null&&b(e,`room`)!==null&&`state`in e}function E(e){return b(e,`id`)!==null&&b(e,`room`)!==null}function D(e){return y(e)&&b(e,`room`)!==null&&y(e.members)}function O(e){return b(e,`channel`)!==null}function k(e){let t=v(e);switch(t.type){case`error`:if(S(t))return{frame:t,kind:`known`};break;case`joined`:if(x(t))return{frame:t,kind:`known`};break;case`left`:if(x(t))return{frame:t,kind:`known`};break;case`message`:if(C(t))return{frame:t,kind:`known`};break;case`pong`:if(w(t))return{frame:t,kind:`known`};break;case`presence_join`:if(T(t))return{frame:t,kind:`known`};break;case`presence_leave`:if(E(t))return{frame:t,kind:`known`};break;case`presence_state`:if(D(t))return{frame:t,kind:`known`};break;case`subscribed`:if(O(t))return{frame:t,kind:`known`};break;case`unsubscribed`:if(O(t))return{frame:t,kind:`known`};break;default:return{kind:`unknown`,type:t.type}}throw new s(`Malformed "${t.type}" frame`,t)}var A=3e4,j=5e3;function M(e,t,n){if(!e)return{onPong(){},start(){},stop(){}};let r=e===!0?{}:e,i=r.interval??A,a=r.timeout??j,o,s,c=!1;function l(){o=setTimeout(()=>{t(_({ts:Date.now(),type:`ping`})),s=setTimeout(()=>{n()},a)},i)}return{onPong(){clearTimeout(s),s=void 0,c&&l()},start(){c=!0,clearTimeout(o),clearTimeout(s),s=void 0,l()},stop(){c=!1,clearTimeout(o),clearTimeout(s),o=void 0,s=void 0}}}function N(r){let s=(0,e.signal)(new Set),l=new Map;function d(e){let t=l.get(e);return t||(t={confirmed:!1,joinSent:!1,leaveAfterJoin:!1,localPresence:void 0,refs:0,scopes:new Set},l.set(e,t)),t}function f(e,t){let n=new Set(s.value);t?n.add(e):n.delete(e),s.value=n}function p(e){r.send(_({room:e,type:`join`}))}function m(e){r.send(_({room:e,type:`leave`}))}function h(e,t){let i=l.get(e);if(!i)throw new o(`Room "${e}"`);if(!r.isOpen())throw new n(`Connection is not open`,e);r.send(_({room:e,state:t,type:`presence`})),i.localPresence=t}function g(e,t){let n=l.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,f(e,!1),r.isOpen()&&m(e),l.delete(e)):n.joinSent?n.leaveAfterJoin=!0:l.delete(e)))}return{createScope(s,l,f){if(r.disposalSignal.aborted)return F(s,l);let m=d(s),_=u(r.disposalSignal),v,y,b=!1,x=new Promise((e,t)=>{v=()=>{b||(b=!0,clearTimeout(S),w.removeEventListener(`abort`,A),e())},y=e=>{b||(b=!0,clearTimeout(S),w.removeEventListener(`abort`,A),t(e))}});x.catch(()=>{});let S,C=[_.signal];if(f?.signal&&C.push(f.signal),f?.timeout!==void 0){let e=new AbortController;S=setTimeout(()=>e.abort(new i(s)),f.timeout),C.push(e.signal)}let w=C.length===1?C[0]:c(C[0],...C.slice(1)),T,E,D=new Set,O=new Set;l&&(T=(0,e.signal)(new Map),E={onJoin(e,t){let n=new Map(T.value);n.set(e,t),T.value=n;for(let n of D)n(e,t)},onLeave(e){let t=new Map(T.value);t.delete(e),T.value=t;for(let t of O)t(e)},onState(e){let t=new Map;for(let[n,r]of Object.entries(e))t.set(n,r);T.value=t},reset(){T.value=new Map}});let k={isSettled:()=>b,joined:x,name:s,presenceHandlers:E,rejectJoined:y,resolveJoined:v},A=()=>{clearTimeout(S),_.abort();let e=w.reason,n=e instanceof t?e:new a;k.rejectJoined(n),g(s,k)};if(m.refs++,m.scopes.add(k),w.aborted)return A(),P(k,_.signal,T,D,O,s,h);if(w.addEventListener(`abort`,A,{once:!0}),m.confirmed)k.resolveJoined();else if(!m.joinSent&&r.isOpen()){m.joinSent=!0;try{p(s)}catch(e){m.joinSent=!1,k.rejectJoined(e instanceof t?e:new n(`Failed to send join`,s))}}return P(k,_.signal,T,D,O,s,h,()=>{_.signal.aborted||(clearTimeout(S),w.removeEventListener(`abort`,A),_.abort(),b||k.rejectJoined(new o(`Room "${s}"`)),g(s,k))})},dispose(){s.value=new Set,l.clear()},handleJoined(e){let t=l.get(e);if(t){if(t.confirmed=!0,t.joinSent=!1,f(e,!0),t.leaveAfterJoin){t.leaveAfterJoin=!1,t.confirmed=!1,f(e,!1),r.isOpen()&&m(e),l.delete(e);return}for(let e of t.scopes)e.isSettled()||e.resolveJoined()}},handleLeft(e){let t=l.get(e);t&&(t.confirmed=!1,t.joinSent=!1,f(e,!1))},handlePresenceJoin(e,t,n){let r=l.get(e);if(r)for(let e of r.scopes)e.presenceHandlers?.onJoin(t,n)},handlePresenceLeave(e,t){let n=l.get(e);if(n)for(let e of n.scopes)e.presenceHandlers?.onLeave(t)},handlePresenceState(e,t){let n=l.get(e);if(n)for(let e of n.scopes)e.presenceHandlers?.onState(t)},rejectAll(e){for(let t of l.values())for(let n of t.scopes)n.isSettled()||n.rejectJoined(e)},reset(){s.value=new Set;for(let[e,t]of l){if(t.refs===0){l.delete(e);continue}t.confirmed=!1,t.joinSent=!1;for(let e of t.scopes)e.presenceHandlers?.reset()}},restore(){for(let[e,t]of l)if(t.refs!==0){t.confirmed=!1,t.joinSent=!0;try{p(e)}catch{t.joinSent=!1}if(t.localPresence!==void 0)try{r.send(_({room:e,state:t.localPresence,type:`presence`}))}catch{}}},rooms:s}}function P(e,t,n,r,i,a,s,c){let l=c??(()=>{});return n?{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 o(`Room "${a}"`);return r.add(e),()=>r.delete(e)},onLeave(e){if(t.aborted)throw new o(`Room "${a}"`);return i.add(e),()=>i.delete(e)},get presence(){return n},updatePresence(e){s(a,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 F(t,n){let r=new AbortController;r.abort(new o);let i=Promise.reject(new o(`Room "${t}"`));return i.catch(()=>{}),n?{disposalSignal:r.signal,dispose(){},disposed:!0,joined:i,name:t,onJoin(){throw new o(`Room "${t}"`)},onLeave(){throw new o(`Room "${t}"`)},presence:(0,e.signal)(new Map),updatePresence(){throw new o(`Room "${t}"`)},[Symbol.dispose](){}}:{disposalSignal:r.signal,dispose(){},disposed:!0,joined:i,name:t,[Symbol.dispose](){}}}var I=class{map=new Map;add(e,t,n){let r=this.map.get(e);r||(r=new Map,this.map.set(e,r));let i=r.get(t);return i||(i=new Set,r.set(t,i)),i.add(n),()=>{i.delete(n),i.size===0&&r.delete(t),r.size===0&&this.map.delete(e)}}clear(){this.map.clear()}dispatch(e,t,n){for(let r of this.map.get(e)?.get(t)??[])r(n)}};function L(r,i={}){let a=new AbortController,c=(0,e.signal)(`closed`),l=new I,u=new Map,d=!1,f=!0;function p(e){i.onError?.(e)}function v(e){C.send(e)}let y=N({disposalSignal:a.signal,isOpen:()=>C.open,send:v});function b(){for(let e of u.keys())v(_({channel:e,type:`subscribe`}));y.restore()}function x(){y.reset()}function S(){f||(f=!0,w.stop(),x(),y.rejectAll(new n(`Connection closed before room confirmation`,r)))}let C=m(r,i.protocols,i.reconnect,{onClose(){S()},onError:p,onMessage(e){let t;try{t=k(e.data)}catch(t){p(t instanceof s?t:new s(`Failed to decode frame`,e.data));return}if(t.kind===`unknown`){p(new s(`Unknown frame type "${t.type}"`,e.data));return}try{T(t)}catch(e){p(new s(`Frame handler threw`,t.frame,{cause:e}))}},onOpen(){f=!1;try{b(),w.start()}catch(e){p(e instanceof t?e:new n(`Session restore failed`,r))}},onStatus(e){c.value=e}}),w=M(i.heartbeat,e=>{C.open&&v(e)},()=>C.forceReconnect(4e3,`heartbeat timeout`));function T(e){let t=e.frame;switch(t.type){case`error`:p(new s(`Server error [${t.code}]: ${t.message}`,t));break;case`joined`:y.handleJoined(t.room);break;case`left`:y.handleLeft(t.room);break;case`message`:l.dispatch(t.channel??null,t.event,t.payload);break;case`pong`:w.onPong();break;case`presence_join`:y.handlePresenceJoin(t.room,t.id,t.state);break;case`presence_leave`:y.handlePresenceLeave(t.room,t.id);break;case`presence_state`:y.handlePresenceState(t.room,t.members)}}function E(e){let t=u.get(e)??0;u.set(e,t+1),t===0&&C.open&&v(_({channel:e,type:`subscribe`}))}function D(e){let t=u.get(e);if(t){if(t>1){u.set(e,t-1);return}u.delete(e),C.open&&v(_({channel:e,type:`unsubscribe`}))}}return{channel(e){if(d)throw new o;return E(e),g(e,(e,t,n)=>{let r=i.transform?i.transform({channel:e,event:t,payload:n}):{channel:e,event:t,payload:n};r!==null&&v(_({...r,type:`message`}))},(e,t,n)=>l.add(e,t,n),a.signal,()=>D(e))},connect(){return d?Promise.reject(new o):C.connect()},disconnect(e=1e3,t=``){d||(S(),C.disconnect(e,t))},get disposalSignal(){return a.signal},dispose(){d||(d=!0,w.stop(),f=!0,y.reset(),y.rejectAll(new o),C.dispose(),u.clear(),y.dispose(),l.clear(),a.abort())},get disposed(){return d},on(e,t){if(d)throw new o;return l.add(null,e,t)},once(e,t){if(d)throw new o;let n=()=>{};return n=l.add(null,e,e=>{n(),t(e)}),n},room(e,t){if(d)throw new o;return y.createScope(e,!0,t)},get rooms(){return y.rooms},send(e,t){if(d)throw new o;let n=i.transform?i.transform({event:e,payload:t}):{event:e,payload:t};n!==null&&v(_({...n,type:`message`}))},get status(){return c},[Symbol.dispose](){this.dispose()},wait(e,t){return h(e,a.signal,t,(e,t)=>l.add(null,e,t))}}}exports.PulseAbortError=a,exports.PulseConnectionError=n,exports.PulseDisposedError=o,exports.PulseError=t,exports.PulseProtocolError=s,exports.PulseRoomTimeoutError=i,exports.PulseTimeoutError=r,exports.createPulse=L;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/ripple");var t=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{url;constructor(e,t,n){super(e,n),this.url=t}},r=class extends t{event;constructor(e,t){super(`Timed out waiting for "${e}"`,t),this.event=e}},i=class extends t{room;constructor(e,t){super(`Timed out waiting for room "${e}"`,t),this.room=e}},a=class extends t{constructor(e){super(`Aborted`,e)}},o=class extends t{constructor(e=`Pulse`,t){super(`${e} instance is disposed`,t)}},s=class extends t{raw;constructor(e,t,n){super(e,n),this.raw=t}};function c(e){let t=new AbortController;return e.aborted?t.abort(e.reason):e.addEventListener(`abort`,()=>t.abort(e.reason),{once:!0}),t}function l(e,t){return new Promise(n=>{if(t?.aborted){n();return}let r=setTimeout(n,e);t?.addEventListener(`abort`,()=>{clearTimeout(r),n()},{once:!0})})}function u(e,t=3e4){let n=Math.min(1e3*2**e,t);return Math.random()*n}var d=5;function f(e,t,r,i){let a=r===!0?{}:r||void 0,s=a?a.maxAttempts??d:0,c=a?.delay,f=typeof c==`function`?c:typeof c==`number`?()=>c:u,p=!1,m=!1,h=!1,g,_,v,y=new Set;function b(e){i.onStatus(e)}function x(e){for(let t of y)t.reject(e);y.clear()}function S(){for(let e of y)e.resolve();y.clear()}function C(e,t){v?.socket===e&&(v.reject(t),v=void 0)}function w(){if(_?.readyState===WebSocket.OPEN)return Promise.resolve();if(v)return v.promise;let r=new WebSocket(e,t);_=r;let a,o,s=new Promise((e,t)=>{a=e,o=t});return v={promise:s,reject:o,resolve:a,socket:r},r.onopen=()=>{if(_!==r||!m){r.close(1e3,`stale connection`);return}v?.socket===r&&(v.resolve(),v=void 0),b(`open`),i.onOpen(),S()},r.onmessage=e=>{_===r&&i.onMessage(e)},r.onerror=()=>{if(_!==r)return;let t=new n(`WebSocket error`,e);i.onError(t),C(r,t),x(t)},r.onclose=()=>{if(_!==r)return;_=void 0,i.onClose();let t=new n(`Connection closed`,e);if(C(r,t),!m||p){b(`closed`);return}h||T()},s}async function T(){if(h||p||!m)return;h=!0;let t=new AbortController;g=t,b(`reconnecting`);let r;for(let i=0;i<s&&m&&!p&&(await l(f(i),t.signal),!(t.signal.aborted||!m||p));i++)try{await w(),h=!1;return}catch(t){r=t instanceof n?t:new n(`Reconnect failed`,e)}!t.signal.aborted&&m&&!p&&(m=!1,b(`closed`),i.onError(r??new n(`Reconnect budget exhausted`,e)),x(r??new n(`Reconnect budget exhausted`,e))),g===t&&(g=void 0),h=!1}function E(){g?.abort(),g=void 0,h=!1}return{connect(){if(p)return Promise.reject(new o);if(m=!0,_?.readyState===WebSocket.OPEN)return Promise.resolve();let e=new Promise((e,t)=>{y.add({reject:t,resolve:e})});return!v&&!h&&(b(`connecting`),w().catch(()=>{})),e},disconnect(t=1e3,r=``){m=!1,E(),x(new n(`Connection closed`,e)),b(`closed`),_?.close(t,r)},dispose(){p||(p=!0,m=!1,E(),x(new o),_?.close(1e3,`disposed`),_=void 0,v=void 0,b(`closed`))},forceReconnect(e,t){m&&_?.readyState===WebSocket.OPEN&&_.close(e,t)},get open(){return _?.readyState===WebSocket.OPEN},send(t){if(_?.readyState!==WebSocket.OPEN)throw new n(`Connection is not open`,e);_.send(t)}}}function p(e,t,n,i){return new Promise((o,s)=>{let c=[t],l;if(n?.signal&&c.push(n.signal),n?.timeout!==void 0){let t=new AbortController;l=setTimeout(()=>{t.abort(new r(e))},n.timeout),c.push(t.signal)}let u=AbortSignal.any(c);if(u.aborted){clearTimeout(l),s(u.reason instanceof r?u.reason:new a);return}let d=()=>{},f=()=>{clearTimeout(l),d(),s(u.reason instanceof r?u.reason:new a)};u.addEventListener(`abort`,f,{once:!0}),d=i(e,e=>{clearTimeout(l),u.removeEventListener(`abort`,f),o(e)})})}function m(e,t,n,r,i){let a=c(r),s=new Set,l=a.signal.aborted;return a.signal.addEventListener(`abort`,()=>{l=!0},{once:!0}),{get disposalSignal(){return a.signal},dispose(){if(!l){l=!0,a.abort();for(let e of s)e();s.clear(),i?.()}},get disposed(){return l},get name(){return e},on(t,r){if(l)throw new o(`Channel "${e}"`);let i=n(e,t,r);return s.add(i),()=>{i(),s.delete(i)}},once(t,r){if(l)throw new o(`Channel "${e}"`);let i=()=>{};return i=n(e,t,e=>{s.delete(i),i(),r(e)}),s.add(i),()=>{s.delete(i),i()}},send(n,r){if(l)throw new o(`Channel "${e}"`);t(e,n,r)},[Symbol.dispose](){this.dispose()},wait(t,r){return p(t,a.signal,r,(t,r)=>n(e,t,r))}}}function h(e){return JSON.stringify(e)}function g(e){if(typeof e!=`string`)throw new s(`Expected string message data`,e);let t;try{t=JSON.parse(e)}catch{throw new s(`JSON parse error`,e)}if(typeof t!=`object`||!t||!(`type`in t)||typeof t.type!=`string`)throw new s(`Missing or invalid "type" field`,t);return t}function _(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function v(e,t){if(!_(e))return null;let n=e[t];return typeof n==`string`?n:null}function y(e){return v(e,`room`)!==null}function b(e){return v(e,`code`)!==null&&v(e,`message`)!==null}function x(e){return!_(e)||v(e,`event`)===null||!(`payload`in e)?!1:e.channel===void 0||typeof e.channel==`string`}function S(e){return _(e)&&typeof e.ts==`number`}function C(e){return _(e)&&v(e,`id`)!==null&&v(e,`room`)!==null&&`state`in e}function w(e){return v(e,`id`)!==null&&v(e,`room`)!==null}function T(e){return _(e)&&v(e,`room`)!==null&&_(e.members)}function E(e){return v(e,`channel`)!==null}function D(e){let t=g(e);switch(t.type){case`error`:if(b(t))return{frame:t,kind:`known`};break;case`joined`:if(y(t))return{frame:t,kind:`known`};break;case`left`:if(y(t))return{frame:t,kind:`known`};break;case`message`:if(x(t))return{frame:t,kind:`known`};break;case`pong`:if(S(t))return{frame:t,kind:`known`};break;case`presence_join`:if(C(t))return{frame:t,kind:`known`};break;case`presence_leave`:if(w(t))return{frame:t,kind:`known`};break;case`presence_state`:if(T(t))return{frame:t,kind:`known`};break;case`subscribed`:if(E(t))return{frame:t,kind:`known`};break;case`unsubscribed`:if(E(t))return{frame:t,kind:`known`};break;default:return{kind:`unknown`,type:t.type}}throw new s(`Malformed "${t.type}" frame`,t)}var O=3e4,k=5e3;function A(e,t,n){if(!e)return{onPong(){},start(){},stop(){}};let r=e===!0?{}:e,i=r.interval??O,a=r.timeout??k,o,s,c=!1;function l(){o=setTimeout(()=>{t(h({ts:Date.now(),type:`ping`})),s=setTimeout(()=>{n()},a)},i)}return{onPong(){clearTimeout(s),s=void 0,c&&l()},start(){c=!0,clearTimeout(o),clearTimeout(s),s=void 0,l()},stop(){c=!1,clearTimeout(o),clearTimeout(s),o=void 0,s=void 0}}}function j(r){let s=(0,e.signal)(new Set),l=new Map;function u(e){let t=l.get(e);return t||(t={confirmed:!1,joinSent:!1,leaveAfterJoin:!1,localPresence:void 0,refs:0,scopes:new Set},l.set(e,t)),t}function d(e,t){let n=new Set(s.value);t?n.add(e):n.delete(e),s.value=n}function f(e){r.send(h({room:e,type:`join`}))}function p(e){r.send(h({room:e,type:`leave`}))}function m(e,t){let i=l.get(e);if(!i)throw new o(`Room "${e}"`);if(!r.isOpen())throw new n(`Connection is not open`,e);r.send(h({room:e,state:t,type:`presence`})),i.localPresence=t}function g(e,t){let n=l.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,d(e,!1),r.isOpen()&&p(e),l.delete(e)):n.joinSent?n.leaveAfterJoin=!0:l.delete(e)))}return{createScope(s,l,d){if(r.disposalSignal.aborted)return N(s,l);let p=u(s),h=c(r.disposalSignal),_,v,y=!1,b=new Promise((e,t)=>{_=()=>{y||(y=!0,clearTimeout(x),C.removeEventListener(`abort`,k),e())},v=e=>{y||(y=!0,clearTimeout(x),C.removeEventListener(`abort`,k),t(e))}});b.catch(()=>{});let x,S=[h.signal];if(d?.signal&&S.push(d.signal),d?.timeout!==void 0){let e=new AbortController;x=setTimeout(()=>e.abort(new i(s)),d.timeout),S.push(e.signal)}let C=AbortSignal.any(S),w,T,E=new Set,D=new Set;l&&(w=(0,e.signal)(new Map),T={onJoin(e,t){let n=new Map(w.value);n.set(e,t),w.value=n;for(let n of E)n(e,t)},onLeave(e){let t=new Map(w.value);t.delete(e),w.value=t;for(let t of D)t(e)},onState(e){let t=new Map;for(let[n,r]of Object.entries(e))t.set(n,r);w.value=t},reset(){w.value=new Map}});let O={isSettled:()=>y,joined:b,name:s,presenceHandlers:T,rejectJoined:v,resolveJoined:_},k=()=>{clearTimeout(x),h.abort();let e=C.reason,n=e instanceof t?e:new a;O.rejectJoined(n),g(s,O)};if(p.refs++,p.scopes.add(O),C.aborted)return k(),M(O,h.signal,w,E,D,s,m);if(C.addEventListener(`abort`,k,{once:!0}),p.confirmed)O.resolveJoined();else if(!p.joinSent&&r.isOpen()){p.joinSent=!0;try{f(s)}catch(e){p.joinSent=!1,O.rejectJoined(e instanceof t?e:new n(`Failed to send join`,s))}}return M(O,h.signal,w,E,D,s,m,()=>{h.signal.aborted||(clearTimeout(x),C.removeEventListener(`abort`,k),h.abort(),y||O.rejectJoined(new o(`Room "${s}"`)),g(s,O))})},dispose(){s.value=new Set,l.clear()},handleJoined(e){let t=l.get(e);if(t){if(t.confirmed=!0,t.joinSent=!1,d(e,!0),t.leaveAfterJoin){t.leaveAfterJoin=!1,t.confirmed=!1,d(e,!1),r.isOpen()&&p(e),l.delete(e);return}for(let e of t.scopes)e.isSettled()||e.resolveJoined()}},handleLeft(e){let t=l.get(e);t&&(t.confirmed=!1,t.joinSent=!1,d(e,!1))},handlePresenceJoin(e,t,n){let r=l.get(e);if(r)for(let e of r.scopes)e.presenceHandlers?.onJoin(t,n)},handlePresenceLeave(e,t){let n=l.get(e);if(n)for(let e of n.scopes)e.presenceHandlers?.onLeave(t)},handlePresenceState(e,t){let n=l.get(e);if(n)for(let e of n.scopes)e.presenceHandlers?.onState(t)},rejectAll(e){for(let t of l.values())for(let n of t.scopes)n.isSettled()||n.rejectJoined(e)},reset(){s.value=new Set;for(let[e,t]of l){if(t.refs===0){l.delete(e);continue}t.confirmed=!1,t.joinSent=!1;for(let e of t.scopes)e.presenceHandlers?.reset()}},restore(){for(let[e,t]of l)if(t.refs!==0){t.confirmed=!1,t.joinSent=!0;try{f(e)}catch{t.joinSent=!1}if(t.localPresence!==void 0)try{r.send(h({room:e,state:t.localPresence,type:`presence`}))}catch{}}},rooms:s}}function M(e,t,n,r,i,a,s,c){let l=c??(()=>{});return n?{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 o(`Room "${a}"`);return r.add(e),()=>r.delete(e)},onLeave(e){if(t.aborted)throw new o(`Room "${a}"`);return i.add(e),()=>i.delete(e)},get presence(){return n},updatePresence(e){s(a,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 N(t,n){let r=new AbortController;r.abort(new o);let i=Promise.reject(new o(`Room "${t}"`));return i.catch(()=>{}),n?{disposalSignal:r.signal,dispose(){},disposed:!0,joined:i,name:t,onJoin(){throw new o(`Room "${t}"`)},onLeave(){throw new o(`Room "${t}"`)},presence:(0,e.signal)(new Map),updatePresence(){throw new o(`Room "${t}"`)},[Symbol.dispose](){}}:{disposalSignal:r.signal,dispose(){},disposed:!0,joined:i,name:t,[Symbol.dispose](){}}}var P=class{map=new Map;add(e,t,n){let r=this.map.get(e);r||(r=new Map,this.map.set(e,r));let i=r.get(t);return i||(i=new Set,r.set(t,i)),i.add(n),()=>{i.delete(n),i.size===0&&r.delete(t),r.size===0&&this.map.delete(e)}}clear(){this.map.clear()}dispatch(e,t,n){for(let r of this.map.get(e)?.get(t)??[])r(n)}};function F(r,i={}){let a=new AbortController,c=(0,e.signal)(`closed`),l=new P,u=new Map,d=new Set,g=!1,_=!0,v=`closed`;function y(e){if(d.size!==0)for(let t of d)try{t(e)}catch{}}function b(e){y({error:e,type:`error`})}function x(e){E.send(e)}let S=j({disposalSignal:a.signal,isOpen:()=>E.open,send:x});function C(){for(let e of u.keys())x(h({channel:e,type:`subscribe`}));S.restore()}function w(){S.reset()}function T(){_||(_=!0,O.stop(),w(),S.rejectAll(new n(`Connection closed before room confirmation`,r)))}let E=f(r,i.protocols,i.reconnect,{onClose(){T()},onError:b,onMessage(e){let t;try{t=D(e.data)}catch(t){b(t instanceof s?t:new s(`Failed to decode frame`,e.data));return}if(t.kind===`unknown`){b(new s(`Unknown frame type "${t.type}"`,e.data));return}try{k(t)}catch(e){b(new s(`Frame handler threw`,t.frame,{cause:e}))}},onOpen(){_=!1;try{C(),O.start()}catch(e){b(e instanceof t?e:new n(`Session restore failed`,r))}},onStatus(e){c.value=e,e!==v&&(v=e,y({status:e,type:`status-change`}))}}),O=A(i.heartbeat,e=>{E.open&&x(e)},()=>E.forceReconnect(4e3,`heartbeat timeout`));function k(e){let t=e.frame;switch(t.type){case`error`:b(new s(`Server error [${t.code}]: ${t.message}`,t));break;case`joined`:S.handleJoined(t.room);break;case`left`:S.handleLeft(t.room);break;case`message`:l.dispatch(t.channel??null,t.event,t.payload);break;case`pong`:O.onPong();break;case`presence_join`:S.handlePresenceJoin(t.room,t.id,t.state);break;case`presence_leave`:S.handlePresenceLeave(t.room,t.id);break;case`presence_state`:S.handlePresenceState(t.room,t.members)}}function M(e){let t=u.get(e)??0;u.set(e,t+1),t===0&&E.open&&x(h({channel:e,type:`subscribe`}))}function N(e){let t=u.get(e);if(t){if(t>1){u.set(e,t-1);return}u.delete(e),E.open&&x(h({channel:e,type:`unsubscribe`}))}}return{channel(e){if(g)throw new o;return M(e),m(e,(e,t,n)=>{let r=i.transform?i.transform({channel:e,event:t,payload:n}):{channel:e,event:t,payload:n};r!==null&&x(h({...r,type:`message`}))},(e,t,n)=>l.add(e,t,n),a.signal,()=>N(e))},connect(){return g?Promise.reject(new o):E.connect()},disconnect(e=1e3,t=``){g||(T(),E.disconnect(e,t))},get disposalSignal(){return a.signal},dispose(){g||(g=!0,O.stop(),_=!0,S.reset(),S.rejectAll(new o),E.dispose(),u.clear(),S.dispose(),l.clear(),y({type:`dispose`}),d.clear(),a.abort())},get disposed(){return g},on(e,t){if(g)throw new o;return l.add(null,e,t)},once(e,t){if(g)throw new o;let n=()=>{};return n=l.add(null,e,e=>{n(),t(e)}),n},room(e,t){if(g)throw new o;return S.createScope(e,!0,t)},get rooms(){return S.rooms},send(e,t){if(g)throw new o;let n=i.transform?i.transform({event:e,payload:t}):{event:e,payload:t};n!==null&&x(h({...n,type:`message`}))},get status(){return c},tap(e,t){if(g)throw new o;if(d.add(e),t?.signal){if(t.signal.aborted)return d.delete(e),()=>{};let n=()=>d.delete(e);return t.signal.addEventListener(`abort`,n,{once:!0}),()=>{d.delete(e),t.signal?.removeEventListener(`abort`,n)}}return()=>d.delete(e)},[Symbol.dispose](){this.dispose()},wait(e,t){return p(e,a.signal,t,(e,t)=>l.add(null,e,t))}}}exports.PulseAbortError=a,exports.PulseConnectionError=n,exports.PulseDisposedError=o,exports.PulseError=t,exports.PulseProtocolError=s,exports.PulseRoomTimeoutError=i,exports.PulseTimeoutError=r,exports.createPulse=F;
2
2
  //# sourceMappingURL=pulse.cjs.map