@maxtroost/use-websocket 1.0.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/index.js ADDED
@@ -0,0 +1,595 @@
1
+ import { Store as e, useStore as t } from "@tanstack/react-store";
2
+ import { Store as n } from "@tanstack/store";
3
+ import { deepEqual as r } from "fast-equals";
4
+ import { createElement as i, useEffect as a, useId as o, useRef as s, useState as c } from "react";
5
+ import { useIsomorphicLayoutEffect as l } from "usehooks-ts";
6
+ import { closeSnackbar as u, enqueueSnackbar as d } from "notistack";
7
+ import { v4 as f } from "uuid";
8
+ //#region src/lib/types.ts
9
+ var p = /* @__PURE__ */ function(e) {
10
+ return e[e.UNINSTANTIATED = -1] = "UNINSTANTIATED", e[e.CONNECTING = 0] = "CONNECTING", e[e.OPEN = 1] = "OPEN", e[e.CLOSING = 2] = "CLOSING", e[e.CLOSED = 3] = "CLOSED", e;
11
+ }({});
12
+ function m() {
13
+ return {
14
+ message: void 0,
15
+ subscribed: !1,
16
+ pendingSubscription: !1,
17
+ subscribedAt: void 0,
18
+ receivedAt: void 0,
19
+ connected: !1,
20
+ messageError: void 0,
21
+ serverError: void 0
22
+ };
23
+ }
24
+ //#endregion
25
+ //#region src/lib/websocketStores.ts
26
+ var h = new e(/* @__PURE__ */ new Map()), g = new e(/* @__PURE__ */ new Map()), _ = () => {
27
+ h.state.forEach((e) => {
28
+ e.reconnect();
29
+ });
30
+ }, v = (e) => new Promise((t) => setTimeout(t, e)), y = {
31
+ NORMAL_CLOSURE: 1e3,
32
+ GOING_AWAY: 1001,
33
+ INTERNAL_ERROR: 1011,
34
+ SERVICE_RESTART: 1012,
35
+ TRY_AGAIN_LATER: 1013,
36
+ ABNORMAL_CLOSURE: 1006
37
+ }, b = {
38
+ MAX_RETRY_ATTEMPTS: 20,
39
+ NOTIFICATION_THRESHOLD: 10,
40
+ TRY_AGAIN_LATER_DELAY_MS: 3e4,
41
+ DELAYS: {
42
+ FIRST_PHASE: 4e3,
43
+ SECOND_PHASE: 3e4,
44
+ THIRD_PHASE: 9e4
45
+ },
46
+ PHASE_THRESHOLDS: {
47
+ FIRST: 5,
48
+ SECOND: 10
49
+ }
50
+ }, x = {
51
+ PRODUCTION_MS: 3e3,
52
+ TEST_MS: 10
53
+ }, S = { PONG_TIMEOUT_MS: 1e4 }, C = { enabled: !0 }, w = 1e4, T = (e) => e < b.PHASE_THRESHOLDS.FIRST ? b.DELAYS.FIRST_PHASE : e < b.PHASE_THRESHOLDS.SECOND ? b.DELAYS.SECOND_PHASE : b.DELAYS.THIRD_PHASE, E = () => 40 * 1e3, D = (e) => typeof e == "object" && !!e && "uri" in e && typeof e.uri == "string", O = (e) => e ? [
54
+ "error",
55
+ "conflict",
56
+ "exception"
57
+ ].includes(e) : !1, k = () => typeof window < "u" && window.navigator.onLine, A = (e) => typeof window < "u" && window.navigator.onLine && e !== void 0 && e.readyState === WebSocket.OPEN, j = (e, t, n) => {
58
+ t > b.NOTIFICATION_THRESHOLD && d(`trying to reconnect to ${e} in ${n / 1e3} seconds.`, {
59
+ key: `${e}-offline`,
60
+ variant: "error",
61
+ preventDuplicate: !0
62
+ });
63
+ }, M = (e, t) => {
64
+ let n = `${e}-max-retries`;
65
+ d(`Connection to ${e} failed after maximum retries.`, {
66
+ key: n,
67
+ variant: "error",
68
+ preventDuplicate: !0,
69
+ action: (e) => i("button", {
70
+ onClick: () => {
71
+ t(), u(e);
72
+ },
73
+ style: {
74
+ marginLeft: 8,
75
+ padding: "4px 12px",
76
+ background: "rgba(255,255,255,0.2)",
77
+ border: "none",
78
+ borderRadius: 4,
79
+ color: "inherit",
80
+ cursor: "pointer",
81
+ fontSize: 14,
82
+ fontWeight: 500
83
+ }
84
+ }, "Retry")
85
+ });
86
+ }, N = (e, t) => {
87
+ t > b.NOTIFICATION_THRESHOLD && d(`trying to reconnect to ${e}...`, {
88
+ key: `${e}-reconnecting`,
89
+ variant: "info",
90
+ preventDuplicate: !0
91
+ });
92
+ }, P = () => JSON.stringify({
93
+ method: "post",
94
+ uri: "ping",
95
+ body: Date.now(),
96
+ correlation: f()
97
+ }), F = (e) => e?.readyState === WebSocket.OPEN || e?.readyState === WebSocket.CONNECTING, I = (e) => e !== y.NORMAL_CLOSURE, L = class e {
98
+ static setCustomLogger(t) {
99
+ e._logger = t;
100
+ }
101
+ constructor(t) {
102
+ this._listeners = /* @__PURE__ */ new Map(), this.reconnectTries = 0, this._isReconnecting = !1, this._maxRetriesExceeded = !1, this.cachedMessages = [], this.getSocket = () => this._socket, this.getUriApiByKey = (e) => {
103
+ let t = this._listeners.get(e);
104
+ if (t && "uri" in t) return t;
105
+ }, this.addListener = (e) => (e.setSendToConnection(this.handleSendMessage), this.connect(), this._listeners.set(e.key, e), clearTimeout(this.closeConnectionTimeOut), this._socket?.readyState === WebSocket.OPEN && e.onOpen && e.onOpen(), e), this.removeListener = (e) => {
106
+ let t = this._listeners.get(e.key);
107
+ t && (t.setSendToConnection(null), this._listeners.delete(t.key)), clearTimeout(this.closeConnectionTimeOut), this.scheduleConnectionCleanup();
108
+ }, this.scheduleConnectionCleanup = () => {
109
+ this.closeConnectionTimeOut = setTimeout(() => {
110
+ this._listeners.size === 0 && this._socket?.close();
111
+ }, x.PRODUCTION_MS);
112
+ }, this.replaceUrl = async (e) => {
113
+ this._url !== e && (this._url = e, await this.teardownAndReconnect());
114
+ }, this.reconnect = async () => {
115
+ await this.teardownAndReconnect();
116
+ }, this.resetRetriesAndReconnect = () => {
117
+ this.reconnectTries = 0, this._maxRetriesExceeded = !1, u(`${this._name}-max-retries`), this.connect();
118
+ }, this.connect = () => {
119
+ let t = Array.from(this._listeners.values()).some((e) => e.isEnabled);
120
+ F(this._socket) || !t || (e._logger?.log?.("info", "ws-connect", {
121
+ url: this._url,
122
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri)
123
+ }), this._socket = new WebSocket(this._url), this._socket.addEventListener("close", this.handleClose), this._socket.addEventListener("message", this.handleMessage), this._socket.addEventListener("open", this.handleOpen), this._socket.addEventListener("error", this.handleError));
124
+ }, this.teardownSocket = () => {
125
+ this.clearAllTimers(), this.removeListeners(), this._socket?.close(), this._socket = void 0;
126
+ }, this.teardownAndReconnect = async () => {
127
+ if (!this._isReconnecting) {
128
+ this._isReconnecting = !0;
129
+ try {
130
+ this.teardownSocket(), this._listeners.forEach((e) => e.reset()), this.reconnectTries = 0, this._maxRetriesExceeded = !1, u(`${this._name}-max-retries`), await v(1e3), this.connect();
131
+ } finally {
132
+ this._isReconnecting = !1;
133
+ }
134
+ }
135
+ }, this.cleanupConnection = () => {
136
+ this._listeners.size === 0 && (e._logger?.log?.("info", "ws-closed", {
137
+ url: this._url,
138
+ subscriptions: this._listeners.size
139
+ }), this.removeListeners(), this._socket = void 0);
140
+ }, this.clearAllTimers = () => {
141
+ clearTimeout(this.pingTimeOut), clearTimeout(this.pongTimeOut), clearTimeout(this.closeConnectionTimeOut);
142
+ }, this.removeListeners = () => {
143
+ this._socket?.removeEventListener("message", this.handleMessage), this._socket?.removeEventListener("close", this.handleClose), this._socket?.removeEventListener("open", this.handleOpen), this._socket?.removeEventListener("error", this.handleError), typeof window < "u" && (window.removeEventListener("online", this.handleOnline), window.removeEventListener("online", this.handleOnlineForReconnection), window.removeEventListener("offline", this.handleOffline));
144
+ }, this.attemptReconnection = async (t) => {
145
+ if (this.reconnectTries >= b.MAX_RETRY_ATTEMPTS) {
146
+ this._maxRetriesExceeded = !0, e._logger?.connectionFailed?.(this._url, this.reconnectTries, this._listeners.size), M(this._name, this.resetRetriesAndReconnect);
147
+ return;
148
+ }
149
+ if (this.deferReconnectionUntilOnline() || t === y.TRY_AGAIN_LATER && (j(this._name, this.reconnectTries, b.TRY_AGAIN_LATER_DELAY_MS), await v(b.TRY_AGAIN_LATER_DELAY_MS), this.deferReconnectionUntilOnline())) return;
150
+ this.reconnectTries++, e._logger?.log?.("info", "ws-reconnect", {
151
+ url: this._url,
152
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri),
153
+ retries: this.reconnectTries
154
+ });
155
+ let n = T(this.reconnectTries);
156
+ j(this._name, this.reconnectTries, n), await v(n), !this.deferReconnectionUntilOnline() && (N(this._name, this.reconnectTries), this.connect());
157
+ }, this.deferReconnectionUntilOnline = () => k() ? !1 : (typeof window < "u" && window.addEventListener("online", this.handleOnlineForReconnection, { once: !0 }), !0), this.handleClose = async (t) => {
158
+ this.clearAllTimers(), e._logger?.log?.("info", "ws-close", {
159
+ url: this._url,
160
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri),
161
+ code: t.code,
162
+ reason: t.reason,
163
+ wasClean: t.wasClean,
164
+ online: typeof window < "u" && window.navigator.onLine
165
+ });
166
+ let n = I(t.code), r = this._listeners.size > 0;
167
+ n && r && await this.attemptReconnection(t.code), this.cleanupConnection();
168
+ }, this.handleOpen = () => {
169
+ typeof window < "u" && window.addEventListener("offline", this.handleOffline), u(`${this._name}-offline`), u(`${this._name}-reconnecting`), this.reconnectTries > b.NOTIFICATION_THRESHOLD && d(`reconnected to ${this._name}.`, {
170
+ key: `${this._name}-online`,
171
+ variant: "success",
172
+ preventDuplicate: !0
173
+ }), this.reconnectTries = 0;
174
+ let t = this._socket;
175
+ t && (this._listeners.forEach((e) => e.onOpen?.()), e._logger?.log?.("info", "ws-on-open", {
176
+ url: this._url,
177
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri)
178
+ }), this.cachedMessages.forEach((e) => t.send(this.serializeMessage(e)))), this.cachedMessages = [], this.schedulePing();
179
+ }, this.handleMessage = (t) => {
180
+ try {
181
+ let n = JSON.parse(t.data);
182
+ if (!D(n)) {
183
+ e._logger?.log?.("error", "ws-invalid-message", {
184
+ url: this._url,
185
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri),
186
+ message: n
187
+ }), this._listeners.forEach((e) => e.onError({
188
+ type: "transport",
189
+ event: t
190
+ }));
191
+ return;
192
+ }
193
+ if (n.uri === "ping") {
194
+ this.clearPongTimeout(), this.schedulePing();
195
+ return;
196
+ }
197
+ if (O(n.method)) {
198
+ e._logger?.log?.("error", "ws-message-error", {
199
+ url: this._url,
200
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri),
201
+ message: n
202
+ }), this.forEachMatchingListener(n.uri, (e) => e.onMessageError({
203
+ type: "server",
204
+ message: n
205
+ }));
206
+ return;
207
+ }
208
+ this.forEachMatchingListener(n.uri, (e) => {
209
+ e.uri === n.uri ? e.onMessage?.(n.body) : e.deliverMessage?.(n.uri, n.body);
210
+ });
211
+ } catch (n) {
212
+ e._logger?.log?.("error", "ws-message-parse-error", {
213
+ url: this._url,
214
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri),
215
+ message: t.data,
216
+ error: n
217
+ }), this._listeners.forEach((e) => e.onError({
218
+ type: "transport",
219
+ event: t
220
+ }));
221
+ }
222
+ }, this.handleError = (t) => {
223
+ this._listeners.forEach((e) => e.onError({
224
+ type: "transport",
225
+ event: t
226
+ })), e._logger?.log?.("error", "ws-error", {
227
+ url: this._url,
228
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri),
229
+ event: t
230
+ });
231
+ }, this.handleOnline = () => {
232
+ typeof window < "u" && window.removeEventListener("online", this.handleOnline), this.connect();
233
+ }, this.handleOnlineForReconnection = () => {
234
+ typeof window < "u" && window.removeEventListener("online", this.handleOnlineForReconnection), this.reconnectTries--, this.attemptReconnection();
235
+ }, this.handleOffline = () => {
236
+ typeof window < "u" && window.removeEventListener("offline", this.handleOffline), this._socket && this._listeners.forEach((e) => e.onClose(new CloseEvent("offline"))), this.teardownSocket(), typeof window < "u" && window.addEventListener("online", this.handleOnline);
237
+ }, this.handleSendMessage = (t) => {
238
+ if (this._socket?.readyState === WebSocket.OPEN) {
239
+ e._logger?.log?.("info", `ws-${t.method}: ${t.uri}`, {
240
+ url: this._url,
241
+ message: t.body
242
+ }), this._socket.send(this.serializeMessage(t));
243
+ return;
244
+ }
245
+ t.method !== "subscribe" && this.cachedMessages.push(t), this.connect();
246
+ }, this.sendPing = () => {
247
+ A(this._socket) && (this._socket?.send(P()), this.schedulePongTimeout());
248
+ }, this.clearPongTimeout = () => {
249
+ clearTimeout(this.pongTimeOut), this.pongTimeOut = void 0;
250
+ }, this.schedulePongTimeout = () => {
251
+ this.clearPongTimeout(), this.pongTimeOut = setTimeout(() => {
252
+ e._logger?.log?.("info", "ws-pong-timeout", {
253
+ url: this._url,
254
+ uriApis: Array.from(this._listeners).filter(([e, t]) => "uri" in t).map(([e, t]) => t.uri)
255
+ }), this.teardownSocket(), this.attemptReconnection();
256
+ }, S.PONG_TIMEOUT_MS);
257
+ }, this.schedulePing = () => {
258
+ this.pingTimeOut = setTimeout(() => {
259
+ this.sendPing();
260
+ }, E());
261
+ }, this.serializeMessage = (e) => JSON.stringify({
262
+ ...e,
263
+ correlation: f()
264
+ }), this.forEachMatchingListener = (e, t) => {
265
+ this._listeners.forEach((n) => {
266
+ (n.uri === e || n.hasWaitingUri?.(e)) && t(n);
267
+ });
268
+ }, this._url = t, this._name = new URL(t).pathname;
269
+ }
270
+ get readyState() {
271
+ return this._socket?.readyState;
272
+ }
273
+ get url() {
274
+ return this._url;
275
+ }
276
+ }, R = class {
277
+ constructor(e) {
278
+ this._sendToConnection = null, this._pendingByUri = /* @__PURE__ */ new Map(), this._pendingMessages = [], this._registeredHooks = /* @__PURE__ */ new Set(), this.hasWaitingUri = (e) => this._pendingByUri.has(e), this.registerHook = (e) => {
279
+ this._clearHookRemovalTimeout(), this._registeredHooks.add(e);
280
+ }, this.unregisterHook = (e, t) => {
281
+ this._registeredHooks.delete(e), this._scheduleHookRemoval(t);
282
+ }, this.disconnect = (e) => {
283
+ this._clearHookRemovalTimeout(), this._hookRemovalTimeout = setTimeout(() => {
284
+ this._hookRemovalTimeout = void 0, e();
285
+ }, 200);
286
+ }, this.setSendToConnection = (e) => {
287
+ this._sendToConnection = e, e ? this._flushPendingMessages(e) : (this._clearHookRemovalTimeout(), this._pendingMessages = [], this._cancelAllPending());
288
+ }, this.deliverMessage = (e, t) => {
289
+ let n = this._pendingByUri.get(e);
290
+ n && (clearTimeout(n.timeoutId), this._pendingByUri.delete(e), n.resolve(t));
291
+ }, this.onError = (e) => {
292
+ this._options.onError?.(e);
293
+ }, this.onMessageError = (e) => {
294
+ this._options.onMessageError?.(e);
295
+ }, this.onClose = (e) => {
296
+ this._cancelAllPending(), this._options.onClose?.(e);
297
+ }, this.reset = () => {
298
+ this._clearHookRemovalTimeout(), this._cancelAllPending();
299
+ }, this._options = {
300
+ enabled: !0,
301
+ responseTimeoutMs: w,
302
+ ...e
303
+ };
304
+ }
305
+ get key() {
306
+ return this._options.key;
307
+ }
308
+ get url() {
309
+ return this._options.url;
310
+ }
311
+ get isEnabled() {
312
+ return this._options.enabled ?? !0;
313
+ }
314
+ sendMessage(e, t, n, r) {
315
+ if (!this.isEnabled) return Promise.reject(/* @__PURE__ */ Error("WebsocketMessageApi is disabled"));
316
+ this._cancelPendingForUri(e);
317
+ let i = r?.timeout ?? this._options.responseTimeoutMs ?? 1e4;
318
+ return new Promise((r, a) => {
319
+ let o = setTimeout(() => {
320
+ this._pendingByUri.get(e)?.timeoutId === o && (this._pendingByUri.delete(e), a(/* @__PURE__ */ Error(`WebSocket response timeout for URI: ${e}`)));
321
+ }, i);
322
+ this._pendingByUri.set(e, {
323
+ resolve: (e) => r(e),
324
+ reject: a,
325
+ timeoutId: o
326
+ });
327
+ let s = {
328
+ uri: e,
329
+ method: t,
330
+ body: n,
331
+ correlation: f()
332
+ };
333
+ this._sendOrQueue(s);
334
+ });
335
+ }
336
+ sendMessageNoWait(e, t, n) {
337
+ if (!this.isEnabled) return;
338
+ let r = {
339
+ uri: e,
340
+ method: t,
341
+ body: n,
342
+ correlation: f()
343
+ };
344
+ this._sendOrQueue(r);
345
+ }
346
+ _clearHookRemovalTimeout() {
347
+ this._hookRemovalTimeout !== void 0 && (clearTimeout(this._hookRemovalTimeout), this._hookRemovalTimeout = void 0);
348
+ }
349
+ _scheduleHookRemoval(e) {
350
+ this._clearHookRemovalTimeout(), this._hookRemovalTimeout = setTimeout(() => {
351
+ this._hookRemovalTimeout = void 0, this._registeredHooks.size === 0 && e();
352
+ }, 200);
353
+ }
354
+ _flushPendingMessages(e) {
355
+ this._pendingMessages.length !== 0 && (this._pendingMessages.forEach((t) => e(t)), this._pendingMessages = []);
356
+ }
357
+ _sendOrQueue(e) {
358
+ this._sendToConnection ? this._sendToConnection(e) : this._pendingMessages.push(e);
359
+ }
360
+ _cancelPendingForUri(e) {
361
+ let t = this._pendingByUri.get(e);
362
+ t && (clearTimeout(t.timeoutId), this._pendingByUri.delete(e), t.reject(/* @__PURE__ */ Error(`WebSocket request overwritten for URI: ${e}`)));
363
+ }
364
+ _cancelAllPending() {
365
+ this._pendingByUri.forEach((e) => {
366
+ clearTimeout(e.timeoutId), e.reject(/* @__PURE__ */ Error("WebSocket connection closed"));
367
+ }), this._pendingByUri.clear();
368
+ }
369
+ }, z = class {
370
+ constructor(t) {
371
+ this._state = new e(m()), this._registeredHooks = /* @__PURE__ */ new Set(), this._sendToConnection = null, this._pendingMessages = [], this.setSendToConnection = (e) => {
372
+ this._sendToConnection = e, e ? this._flushPendingMessages(e) : (this._clearPendingTimeouts(), this._pendingMessages = []);
373
+ }, this.registerHook = (e) => {
374
+ this._clearPendingTimeouts(), this._registeredHooks.add(e), this._registeredHooks.size > 1 && console.warn(`the uri ${this.uri} has more than one initiator, multiple initiators could cause unexpected behavior`);
375
+ }, this.unregisterHook = (e, t) => {
376
+ this._registeredHooks.delete(e), this._scheduleHookRemoval(t);
377
+ }, this.disconnect = (e) => {
378
+ this._clearPendingTimeouts(), this.unsubscribe(), this._disconnectTimeout = setTimeout(() => {
379
+ this._disconnectTimeout = void 0, this._state.setState((e) => ({
380
+ ...e,
381
+ connected: !1,
382
+ subscribed: !1,
383
+ pendingSubscription: !1
384
+ })), e();
385
+ }, 200);
386
+ }, this.reset = () => {
387
+ this._state.state.connected && (this._state.setState((e) => ({
388
+ ...e,
389
+ connected: !1,
390
+ subscribed: !1,
391
+ pendingSubscription: !1,
392
+ message: void 0
393
+ })), this._clearPendingTimeouts());
394
+ }, this.sendMessage = (e) => {
395
+ if (!this.isEnabled) return;
396
+ this._clearPendingTimeouts();
397
+ let t = {
398
+ ...e,
399
+ uri: this.uri,
400
+ method: e.method ?? this._options.method ?? "post"
401
+ };
402
+ this._sendOrQueue(t);
403
+ }, this.subscribe = (e) => {
404
+ this.isEnabled && (this._clearPendingTimeouts(), this._state.setState((e) => ({
405
+ ...e,
406
+ subscribed: !0,
407
+ pendingSubscription: !0,
408
+ subscribedAt: Date.now()
409
+ })), this._sendOrQueue({
410
+ body: e,
411
+ uri: this.uri,
412
+ method: "subscribe"
413
+ }), this._options.onSubscribe?.({
414
+ uri: this.uri,
415
+ body: this._options.body,
416
+ uriApi: this
417
+ }));
418
+ }, this.unsubscribe = () => {
419
+ this._state.state.subscribed && (this._state.setState((e) => ({
420
+ ...e,
421
+ subscribed: !1,
422
+ pendingSubscription: !1,
423
+ message: void 0
424
+ })), this._sendOrQueue({
425
+ uri: this.uri,
426
+ method: "unsubscribe"
427
+ }));
428
+ }, this.onOpen = () => {
429
+ this._state.state.connected || (this._state.setState((e) => ({
430
+ ...e,
431
+ connected: !0
432
+ })), this.subscribe(this._options.body));
433
+ }, this.onMessage = (e) => {
434
+ this._state.setState((t) => ({
435
+ ...t,
436
+ message: e,
437
+ pendingSubscription: !1,
438
+ receivedAt: Date.now()
439
+ })), this._options.onMessage?.({
440
+ data: e,
441
+ uriApi: this
442
+ });
443
+ }, this.onError = (e) => {
444
+ this._state.setState((e) => ({
445
+ ...e,
446
+ pendingSubscription: !1
447
+ })), this._options.onError?.(e);
448
+ }, this.onMessageError = (e) => {
449
+ this._state.setState((e) => ({
450
+ ...e,
451
+ pendingSubscription: !1
452
+ })), this._options.onMessageError?.(e);
453
+ }, this.onClose = (e) => {
454
+ this._state.setState((e) => ({
455
+ ...e,
456
+ subscribed: !1,
457
+ pendingSubscription: !1
458
+ })), this._options.onClose?.(e);
459
+ }, this._options = {
460
+ ...C,
461
+ ...t
462
+ };
463
+ }
464
+ get key() {
465
+ return this._options.key;
466
+ }
467
+ get uri() {
468
+ return this._options.uri;
469
+ }
470
+ get url() {
471
+ return this._options.url;
472
+ }
473
+ get options() {
474
+ return this._options;
475
+ }
476
+ get data() {
477
+ return this._state.state.message;
478
+ }
479
+ get store() {
480
+ return this._state;
481
+ }
482
+ get isEnabled() {
483
+ return this._options.enabled ?? !0;
484
+ }
485
+ set options(e) {
486
+ let t = {
487
+ ...C,
488
+ ...this._options,
489
+ ...e
490
+ };
491
+ if (r(this._options, t)) return;
492
+ let n = this._options;
493
+ this._options = t, this._handleSubscriptionUpdates(n, t), this._handleUnsubscribeOnDisable(n, t);
494
+ }
495
+ _clearPendingTimeouts() {
496
+ this._disconnectTimeout !== void 0 && (clearTimeout(this._disconnectTimeout), this._disconnectTimeout = void 0), this._hookRemovalTimeout !== void 0 && (clearTimeout(this._hookRemovalTimeout), this._hookRemovalTimeout = void 0);
497
+ }
498
+ _scheduleHookRemoval(e) {
499
+ this._clearPendingTimeouts(), this._hookRemovalTimeout = setTimeout(() => {
500
+ this._hookRemovalTimeout = void 0, this._registeredHooks.size === 0 && (this._state.setState((e) => ({
501
+ ...e,
502
+ connected: !1
503
+ })), this.unsubscribe(), e());
504
+ }, 200);
505
+ }
506
+ _flushPendingMessages(e) {
507
+ this._pendingMessages.length !== 0 && (this._pendingMessages.forEach((t) => e({
508
+ ...t,
509
+ uri: this.uri,
510
+ method: t.method ?? this._options.method ?? "post"
511
+ })), this._pendingMessages = []);
512
+ }
513
+ _sendOrQueue(e) {
514
+ this._sendToConnection ? this._sendToConnection(e) : this._pendingMessages.push(e);
515
+ }
516
+ _handleSubscriptionUpdates(e, t) {
517
+ let n = !r(e.body, t.body), i = !e.enabled && t.enabled;
518
+ (n || i) && this.subscribe(t.body);
519
+ }
520
+ _handleUnsubscribeOnDisable(e, t) {
521
+ let n = !t.enabled, r = e.enabled;
522
+ n && r && this._state.state.subscribed && this.unsubscribe();
523
+ }
524
+ }, B = (e, t) => {
525
+ let n = V(e);
526
+ if (n) return n;
527
+ let r = new L(t);
528
+ return h.setState((t) => new Map(t).set(e, r)), r;
529
+ }, V = (e) => h.state.get(e), H = (e) => {
530
+ let t = g.state.get(e);
531
+ if (t && "uri" in t) return t;
532
+ }, U = (e, t) => {
533
+ let n = H(e);
534
+ if (n) return n;
535
+ let r = new z(t);
536
+ return g.setState((t) => new Map(t).set(e, r)), r;
537
+ }, W = (e) => {
538
+ let t = g.state.get(e);
539
+ if (t && "hasWaitingUri" in t) return t;
540
+ }, G = (e, t) => {
541
+ let n = W(e);
542
+ if (n) return n;
543
+ let r = new R(t);
544
+ return g.setState((t) => new Map(t).set(e, r)), r;
545
+ }, K = (e) => {
546
+ V(e.url)?.removeListener(e), g.setState((t) => {
547
+ let n = new Map(t);
548
+ return n.delete(e.key), n;
549
+ });
550
+ };
551
+ //#endregion
552
+ //#region src/lib/WebsocketHook.ts
553
+ function q(e) {
554
+ let t = s(e);
555
+ return r(t.current, e) || (t.current = e), t.current;
556
+ }
557
+ function J(e, t, n) {
558
+ let r = o();
559
+ l(() => {
560
+ n === !1 ? e.disconnect(() => K(e)) : B(e.url, t).addListener(e);
561
+ }, [n, e]), l(() => {
562
+ V(t)?.replaceUrl(t);
563
+ }, [t, t]), a(() => {
564
+ let t = r;
565
+ return n !== !1 && e.registerHook(r), () => {
566
+ e.unregisterHook(t, () => K(e));
567
+ };
568
+ }, [
569
+ n,
570
+ r,
571
+ e
572
+ ]);
573
+ }
574
+ function Y(e) {
575
+ let [t] = c(() => U(e.key, e));
576
+ J(t, e.url, e.enabled);
577
+ let n = q(e);
578
+ return l(() => {
579
+ t.options = n;
580
+ }, [n, t]), t;
581
+ }
582
+ var X = (e) => {
583
+ let r = t(g, (t) => {
584
+ let n = t.get(e);
585
+ if (n && "uri" in n) return n;
586
+ }), [i] = c(() => new n(m()));
587
+ return r?.store ?? i;
588
+ }, Z = (e) => {
589
+ let [t] = c(() => G(e.key, e));
590
+ return J(t, e.url, e.enabled), t;
591
+ };
592
+ //#endregion
593
+ export { p as ReadyState, L as WebsocketConnection, R as WebsocketMessageApi, z as WebsocketSubscriptionApi, m as createInitialWebsocketSubscriptionStore, Z as useWebsocketMessage, Y as useWebsocketSubscription, X as useWebsocketSubscriptionByKey, _ as websocketConnectionsReconnect };
594
+
595
+ //# sourceMappingURL=index.js.map