@ancon/wildcat-utils 1.53.6 → 1.53.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ancon/wildcat-utils",
3
- "version": "1.53.6",
3
+ "version": "1.53.8",
4
4
  "main": "index.js",
5
5
  "module": "index.mjs",
6
6
  "types": "index.d.ts",
@@ -13,14 +13,19 @@ declare class SignalR {
13
13
  private shouldReconnect;
14
14
  private isReconnecting;
15
15
  private pendingJoins;
16
+ private initialReconnectDelayMs;
16
17
  groups: string[];
17
18
  constructor(options: SignalRConfig);
18
19
  info: (message: string, data?: any) => void;
19
20
  private generateBackoff;
20
21
  private getNextBackoffMs;
22
+ private getInitialReconnectDelayMs;
21
23
  /**
22
24
  * Keep trying to connect, with backoff, until connected or `disconnect()` is called.
23
25
  * Only one reconnect loop runs at a time.
26
+ *
27
+ * @param withInitialDelay Wait a random `initialReconnectDelayMs` before the
28
+ * first attempt, so clients dropped at the same moment don't all reconnect at once.
24
29
  */
25
30
  private reconnect;
26
31
  private buildInitialListeners;
@@ -1 +1 @@
1
- "use strict";var l=Object.defineProperty;var f=(r,e,n)=>e in r?l(r,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):r[e]=n;var t=(r,e,n)=>(f(r,typeof e!="symbol"?e+"":e,n),n);const h=require("@microsoft/signalr"),a=require("@ancon/wildcat-types"),d=require("../shared/wait.js"),u=require("../api/generateBackoffWithEqualJitter.js");require("axios");require("../number/randomIntFromInterval.js");class g{constructor(e){t(this,"internalEvents");t(this,"signalREvents");t(this,"hubConnection");t(this,"clientId");t(this,"logger");t(this,"backoff",[]);t(this,"reconnectAttempt",0);t(this,"shouldReconnect",!0);t(this,"isReconnecting",!1);t(this,"pendingJoins",new Map);t(this,"groups");t(this,"info",(e,n)=>{var i;(i=this.logger)==null||i.info(e,n)});t(this,"generateBackoff",()=>{this.backoff=u(50,500,5e3),this.info("Generated new backoff")});t(this,"getNextBackoffMs",()=>{this.backoff[this.reconnectAttempt]==null&&(this.reconnectAttempt>0&&this.info("Ran out of backoff intervals, restarting backoff..."),this.reconnectAttempt=0,this.generateBackoff());const e=this.backoff[this.reconnectAttempt];if(e==null)throw new Error("Could not resolve ms from backoff");return e});t(this,"reconnect",async()=>{if(!this.isReconnecting){this.isReconnecting=!0;try{for(;this.shouldReconnect;)try{this.info("Attempting to reconnect...",{attempt:this.reconnectAttempt+1}),await this.connect(!0),this.info("Reconnected"),this.reconnectAttempt=0;return}catch{if(!this.shouldReconnect)break;await d(this.getNextBackoffMs()),this.reconnectAttempt+=1}}finally{this.isReconnecting=!1}}});t(this,"buildInitialListeners",()=>{this.hubConnection.onclose(()=>{this.groups=[],this.info("Hub connection closed"),this.emitEvent("disconnected"),this.reconnect()}),this.hubConnection.onreconnected(()=>this.emitEvent("reconnected"))});t(this,"emitEvent",(e,...n)=>{if(this.internalEvents.has(e)){this.info(`Emitting event "${e}"`);const i=this.internalEvents.get(e);i&&i.forEach(s=>s(...n))}else this.info(`Failed to emit event "${e}". There were no listeners.`)});t(this,"skipSignal",(e,n)=>{this.info(`Skipped signal "${e}"`,n)});t(this,"enhanceListener",(e,n,i)=>s=>{const o=JSON.parse(s),c=i&&o.clientId&&o.clientId===this.clientId;return c||this.info(`Received signal "${e}"`,s),c?this.skipSignal(e,s):n(o)});t(this,"setClientId",e=>{this.clientId=e});t(this,"connect",async(e=!1)=>{try{this.info("Connecting..."),await this.hubConnection.start(),this.info("Connected"),this.emitEvent("connected")}catch(n){if(this.info("Failed to connect"),e)throw n;this.shouldReconnect&&(this.emitEvent("disconnected"),await this.reconnect())}});t(this,"disconnect",async()=>{try{this.shouldReconnect=!1,this.info("Disconnecting..."),await this.hubConnection.stop(),this.info("Disconnected"),this.emitEvent("disconnected")}catch{this.info("Failed to disconnect")}});t(this,"addEventListener",(e,n)=>{this.internalEvents.has(e)||this.internalEvents.set(e,[]);const i=this.internalEvents.get(e);return i&&i.push(n),()=>this.removeEventListener(e,n)});t(this,"removeEventListener",(e,n)=>{var i;if(this.internalEvents.has(e)){const s=this.internalEvents.get(e),o=((i=s==null?void 0:s.indexOf)==null?void 0:i.call(s,n))??-1;o>=0?(s.splice(o,1),this.info(`Removed event listener for event "${e}"`)):this.info(`Failed to remove event listener for event "${e}". Specified listener was not found.`)}else this.info(`Failed to remove event listener for event "${e}". Event doesn't have any listeners.`)});t(this,"addSignalListener",(e,n,i=!0)=>{this.signalREvents.has(e)||this.signalREvents.set(e,[]);const s=this.signalREvents.get(e),o=this.enhanceListener(e,n,i);return s&&s.push(o),this.hubConnection.on(e,o),this.info(`Added signal listener for signal "${e}"`),()=>this.removeSignalListener(e,o)});t(this,"removeSignalListener",(e,n)=>{var i;if(this.signalREvents.has(e)){const s=this.signalREvents.get(e),o=((i=s==null?void 0:s.indexOf)==null?void 0:i.call(s,n))??-1;o>=0?(this.hubConnection.off(e,n),s.splice(o,1),this.info(`Removed signal listener for signal "${e}"`)):this.info(`Failed to remove signal listener for signal "${e}". Specified listener was not found.`)}else this.info(`Failed to remove signal listener for signal "${e}". Signal doesn't have any listeners.`)});t(this,"joinGroup",async e=>{const n=this.pendingJoins.get(e);if(n)return n;if(this.groups.includes(e))return!0;const i=this.invokeJoinGroup(e).finally(()=>{this.pendingJoins.delete(e)});return this.pendingJoins.set(e,i),i});t(this,"invokeJoinGroup",async e=>{this.info(`Joining group "${e}"...`),this.groups.push(e);try{return await this.hubConnection.invoke(a.SignalRMethodName.JoinGroup,e),this.info(`Joined group "${e}"`),!0}catch(n){this.info(`Failed to join group "${e}"`,n);const i=this.groups.indexOf(e);return i>=0&&this.groups.splice(i,1),!1}});t(this,"leaveGroup",async e=>{this.info(`Leaving group "${e}"...`);const n=this.groups.indexOf(e);n>=0&&this.groups.splice(n,1);try{await this.hubConnection.invoke(a.SignalRMethodName.LeaveGroup,e),this.info(`Left group "${e}"`)}catch(i){this.groups.indexOf(e)<0&&this.groups.push(e),this.info(`Failed to leave group "${e}"`,i)}});t(this,"leaveAllGroups",async()=>{this.info(`Leaving all (${this.groups.length}) groups...`);const e=[...this.groups].map(n=>this.leaveGroup(n));await Promise.all(e),this.info("Left all groups")});t(this,"getHubConnectionId",()=>this.hubConnection.connectionId);this.internalEvents=new Map,this.signalREvents=new Map,this.groups=[],e.enableLogging&&(this.logger=e.logger),this.hubConnection=new h.HubConnectionBuilder().withUrl(`${e.signalRApiUrl}/${e.hub}`).configureLogging(h.LogLevel.None).build(),e.serverTimeoutInMilliseconds!=null&&(this.hubConnection.serverTimeoutInMilliseconds=e.serverTimeoutInMilliseconds),e.keepAliveIntervalInMilliseconds!=null&&(this.hubConnection.keepAliveIntervalInMilliseconds=e.keepAliveIntervalInMilliseconds),this.buildInitialListeners()}}module.exports=g;
1
+ "use strict";var f=Object.defineProperty;var d=(c,e,n)=>e in c?f(c,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):c[e]=n;var t=(c,e,n)=>(d(c,typeof e!="symbol"?e+"":e,n),n);const h=require("@microsoft/signalr"),a=require("@ancon/wildcat-types"),l=require("../shared/wait.js"),u=require("../api/generateBackoffWithEqualJitter.js"),g=require("../number/randomIntFromInterval.js");require("axios");const v={min:500,max:5e3};class p{constructor(e){t(this,"internalEvents");t(this,"signalREvents");t(this,"hubConnection");t(this,"clientId");t(this,"logger");t(this,"backoff",[]);t(this,"reconnectAttempt",0);t(this,"shouldReconnect",!0);t(this,"isReconnecting",!1);t(this,"pendingJoins",new Map);t(this,"initialReconnectDelayMs");t(this,"groups");t(this,"info",(e,n)=>{var i;(i=this.logger)==null||i.info(e,n)});t(this,"generateBackoff",()=>{this.backoff=u(50,500,5e3),this.info("Generated new backoff")});t(this,"getNextBackoffMs",()=>{this.backoff[this.reconnectAttempt]==null&&(this.reconnectAttempt>0&&this.info("Ran out of backoff intervals, restarting backoff..."),this.reconnectAttempt=0,this.generateBackoff());const e=this.backoff[this.reconnectAttempt];if(e==null)throw new Error("Could not resolve ms from backoff");return e});t(this,"getInitialReconnectDelayMs",()=>{const e=Math.max(0,this.initialReconnectDelayMs.min),n=Math.max(e,this.initialReconnectDelayMs.max);return g(e,n)});t(this,"reconnect",async(e=!1)=>{if(!this.isReconnecting){this.isReconnecting=!0;try{if(e){const n=this.getInitialReconnectDelayMs();this.info("Waiting before reconnecting...",{delayMs:n}),await l(n)}for(;this.shouldReconnect;)try{this.info("Attempting to reconnect...",{attempt:this.reconnectAttempt+1}),await this.connect(!0),this.info("Reconnected"),this.reconnectAttempt=0;return}catch{if(!this.shouldReconnect)break;await l(this.getNextBackoffMs()),this.reconnectAttempt+=1}}finally{this.isReconnecting=!1}}});t(this,"buildInitialListeners",()=>{this.hubConnection.onclose(()=>{this.groups=[],this.info("Hub connection closed"),this.emitEvent("disconnected"),this.reconnect(!0)}),this.hubConnection.onreconnected(()=>this.emitEvent("reconnected"))});t(this,"emitEvent",(e,...n)=>{if(this.internalEvents.has(e)){this.info(`Emitting event "${e}"`);const i=this.internalEvents.get(e);i&&i.forEach(s=>s(...n))}else this.info(`Failed to emit event "${e}". There were no listeners.`)});t(this,"skipSignal",(e,n)=>{this.info(`Skipped signal "${e}"`,n)});t(this,"enhanceListener",(e,n,i)=>s=>{const o=JSON.parse(s),r=i&&o.clientId&&o.clientId===this.clientId;return r||this.info(`Received signal "${e}"`,s),r?this.skipSignal(e,s):n(o)});t(this,"setClientId",e=>{this.clientId=e});t(this,"connect",async(e=!1)=>{try{this.info("Connecting..."),await this.hubConnection.start(),this.info("Connected"),this.emitEvent("connected")}catch(n){if(this.info("Failed to connect"),e)throw n;this.shouldReconnect&&(this.emitEvent("disconnected"),await this.reconnect())}});t(this,"disconnect",async()=>{try{this.shouldReconnect=!1,this.info("Disconnecting..."),await this.hubConnection.stop(),this.info("Disconnected"),this.emitEvent("disconnected")}catch{this.info("Failed to disconnect")}});t(this,"addEventListener",(e,n)=>{this.internalEvents.has(e)||this.internalEvents.set(e,[]);const i=this.internalEvents.get(e);return i&&i.push(n),()=>this.removeEventListener(e,n)});t(this,"removeEventListener",(e,n)=>{var i;if(this.internalEvents.has(e)){const s=this.internalEvents.get(e),o=((i=s==null?void 0:s.indexOf)==null?void 0:i.call(s,n))??-1;o>=0?(s.splice(o,1),this.info(`Removed event listener for event "${e}"`)):this.info(`Failed to remove event listener for event "${e}". Specified listener was not found.`)}else this.info(`Failed to remove event listener for event "${e}". Event doesn't have any listeners.`)});t(this,"addSignalListener",(e,n,i=!0)=>{this.signalREvents.has(e)||this.signalREvents.set(e,[]);const s=this.signalREvents.get(e),o=this.enhanceListener(e,n,i);return s&&s.push(o),this.hubConnection.on(e,o),this.info(`Added signal listener for signal "${e}"`),()=>this.removeSignalListener(e,o)});t(this,"removeSignalListener",(e,n)=>{var i;if(this.signalREvents.has(e)){const s=this.signalREvents.get(e),o=((i=s==null?void 0:s.indexOf)==null?void 0:i.call(s,n))??-1;o>=0?(this.hubConnection.off(e,n),s.splice(o,1),this.info(`Removed signal listener for signal "${e}"`)):this.info(`Failed to remove signal listener for signal "${e}". Specified listener was not found.`)}else this.info(`Failed to remove signal listener for signal "${e}". Signal doesn't have any listeners.`)});t(this,"joinGroup",async e=>{const n=this.pendingJoins.get(e);if(n)return n;if(this.groups.includes(e))return!0;const i=this.invokeJoinGroup(e).finally(()=>{this.pendingJoins.delete(e)});return this.pendingJoins.set(e,i),i});t(this,"invokeJoinGroup",async e=>{this.info(`Joining group "${e}"...`),this.groups.push(e);try{return await this.hubConnection.invoke(a.SignalRMethodName.JoinGroup,e),this.info(`Joined group "${e}"`),!0}catch(n){this.info(`Failed to join group "${e}"`,n);const i=this.groups.indexOf(e);return i>=0&&this.groups.splice(i,1),!1}});t(this,"leaveGroup",async e=>{this.info(`Leaving group "${e}"...`);const n=this.groups.indexOf(e);n>=0&&this.groups.splice(n,1);try{await this.hubConnection.invoke(a.SignalRMethodName.LeaveGroup,e),this.info(`Left group "${e}"`)}catch(i){this.groups.indexOf(e)<0&&this.groups.push(e),this.info(`Failed to leave group "${e}"`,i)}});t(this,"leaveAllGroups",async()=>{this.info(`Leaving all (${this.groups.length}) groups...`);const e=[...this.groups].map(n=>this.leaveGroup(n));await Promise.all(e),this.info("Left all groups")});t(this,"getHubConnectionId",()=>this.hubConnection.connectionId);this.internalEvents=new Map,this.signalREvents=new Map,this.groups=[],this.initialReconnectDelayMs=e.initialReconnectDelayMs??v,e.enableLogging&&(this.logger=e.logger),this.hubConnection=new h.HubConnectionBuilder().withUrl(`${e.signalRApiUrl}/${e.hub}`).configureLogging(h.LogLevel.None).build(),e.serverTimeoutInMilliseconds!=null&&(this.hubConnection.serverTimeoutInMilliseconds=e.serverTimeoutInMilliseconds),e.keepAliveIntervalInMilliseconds!=null&&(this.hubConnection.keepAliveIntervalInMilliseconds=e.keepAliveIntervalInMilliseconds),this.buildInitialListeners()}}module.exports=p;
@@ -1,12 +1,16 @@
1
1
  var l = Object.defineProperty;
2
- var a = (r, e, n) => e in r ? l(r, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : r[e] = n;
3
- var t = (r, e, n) => (a(r, typeof e != "symbol" ? e + "" : e, n), n);
4
- import { HubConnectionBuilder as f, LogLevel as d } from "@microsoft/signalr";
2
+ var f = (c, e, n) => e in c ? l(c, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : c[e] = n;
3
+ var t = (c, e, n) => (f(c, typeof e != "symbol" ? e + "" : e, n), n);
4
+ import { HubConnectionBuilder as d, LogLevel as u } from "@microsoft/signalr";
5
5
  import { SignalRMethodName as h } from "@ancon/wildcat-types";
6
- import u from "../shared/wait.mjs";
6
+ import a from "../shared/wait.mjs";
7
7
  import g from "../api/generateBackoffWithEqualJitter.mjs";
8
+ import v from "../number/randomIntFromInterval.mjs";
8
9
  import "axios";
9
- import "../number/randomIntFromInterval.mjs";
10
+ const m = {
11
+ min: 500,
12
+ max: 5e3
13
+ };
10
14
  class w {
11
15
  constructor(e) {
12
16
  t(this, "internalEvents");
@@ -19,6 +23,7 @@ class w {
19
23
  t(this, "shouldReconnect", !0);
20
24
  t(this, "isReconnecting", !1);
21
25
  t(this, "pendingJoins", /* @__PURE__ */ new Map());
26
+ t(this, "initialReconnectDelayMs");
22
27
  t(this, "groups");
23
28
  t(this, "info", (e, n) => {
24
29
  var i;
@@ -34,14 +39,25 @@ class w {
34
39
  throw new Error("Could not resolve ms from backoff");
35
40
  return e;
36
41
  });
42
+ t(this, "getInitialReconnectDelayMs", () => {
43
+ const e = Math.max(0, this.initialReconnectDelayMs.min), n = Math.max(e, this.initialReconnectDelayMs.max);
44
+ return v(e, n);
45
+ });
37
46
  /**
38
47
  * Keep trying to connect, with backoff, until connected or `disconnect()` is called.
39
48
  * Only one reconnect loop runs at a time.
49
+ *
50
+ * @param withInitialDelay Wait a random `initialReconnectDelayMs` before the
51
+ * first attempt, so clients dropped at the same moment don't all reconnect at once.
40
52
  */
41
- t(this, "reconnect", async () => {
53
+ t(this, "reconnect", async (e = !1) => {
42
54
  if (!this.isReconnecting) {
43
55
  this.isReconnecting = !0;
44
56
  try {
57
+ if (e) {
58
+ const n = this.getInitialReconnectDelayMs();
59
+ this.info("Waiting before reconnecting...", { delayMs: n }), await a(n);
60
+ }
45
61
  for (; this.shouldReconnect; )
46
62
  try {
47
63
  this.info("Attempting to reconnect...", {
@@ -51,7 +67,7 @@ class w {
51
67
  } catch {
52
68
  if (!this.shouldReconnect)
53
69
  break;
54
- await u(this.getNextBackoffMs()), this.reconnectAttempt += 1;
70
+ await a(this.getNextBackoffMs()), this.reconnectAttempt += 1;
55
71
  }
56
72
  } finally {
57
73
  this.isReconnecting = !1;
@@ -60,7 +76,7 @@ class w {
60
76
  });
61
77
  t(this, "buildInitialListeners", () => {
62
78
  this.hubConnection.onclose(() => {
63
- this.groups = [], this.info("Hub connection closed"), this.emitEvent("disconnected"), this.reconnect();
79
+ this.groups = [], this.info("Hub connection closed"), this.emitEvent("disconnected"), this.reconnect(!0);
64
80
  }), this.hubConnection.onreconnected(() => this.emitEvent("reconnected"));
65
81
  });
66
82
  /**
@@ -80,8 +96,8 @@ class w {
80
96
  this.info(`Skipped signal "${e}"`, n);
81
97
  });
82
98
  t(this, "enhanceListener", (e, n, i) => (s) => {
83
- const o = JSON.parse(s), c = i && o.clientId && o.clientId === this.clientId;
84
- return c || this.info(`Received signal "${e}"`, s), c ? this.skipSignal(e, s) : n(o);
99
+ const o = JSON.parse(s), r = i && o.clientId && o.clientId === this.clientId;
100
+ return r || this.info(`Received signal "${e}"`, s), r ? this.skipSignal(e, s) : n(o);
85
101
  });
86
102
  t(this, "setClientId", (e) => {
87
103
  this.clientId = e;
@@ -209,7 +225,7 @@ class w {
209
225
  await Promise.all(e), this.info("Left all groups");
210
226
  });
211
227
  t(this, "getHubConnectionId", () => this.hubConnection.connectionId);
212
- this.internalEvents = /* @__PURE__ */ new Map(), this.signalREvents = /* @__PURE__ */ new Map(), this.groups = [], e.enableLogging && (this.logger = e.logger), this.hubConnection = new f().withUrl(`${e.signalRApiUrl}/${e.hub}`).configureLogging(d.None).build(), e.serverTimeoutInMilliseconds != null && (this.hubConnection.serverTimeoutInMilliseconds = e.serverTimeoutInMilliseconds), e.keepAliveIntervalInMilliseconds != null && (this.hubConnection.keepAliveIntervalInMilliseconds = e.keepAliveIntervalInMilliseconds), this.buildInitialListeners();
228
+ this.internalEvents = /* @__PURE__ */ new Map(), this.signalREvents = /* @__PURE__ */ new Map(), this.groups = [], this.initialReconnectDelayMs = e.initialReconnectDelayMs ?? m, e.enableLogging && (this.logger = e.logger), this.hubConnection = new d().withUrl(`${e.signalRApiUrl}/${e.hub}`).configureLogging(u.None).build(), e.serverTimeoutInMilliseconds != null && (this.hubConnection.serverTimeoutInMilliseconds = e.serverTimeoutInMilliseconds), e.keepAliveIntervalInMilliseconds != null && (this.hubConnection.keepAliveIntervalInMilliseconds = e.keepAliveIntervalInMilliseconds), this.buildInitialListeners();
213
229
  }
214
230
  }
215
231
  export {
@@ -1 +1 @@
1
- "use strict";const n=require("react"),I=require("react-redux"),h=require("../noop-7ea3b37b.js"),J=l=>Object.freeze(Object.defineProperty({__proto__:null,default:l},Symbol.toStringTag,{value:"Module"}));function K(l,_,j,q){const{logger:w,enableLogging:D,serverTimeoutInMilliseconds:M,keepAliveIntervalInMilliseconds:m}=l;let{signalRApiUrl:v}=l;const{clientIdSelector:x,isSignalROnlineSelector:c}=_??{},{setIsSignalROnlineAction:a}=j??{},{useAppStore:G=I.useStore,useAppDispatch:P=I.useDispatch,useAppSelector:T=I.useSelector}=q??{},b=new Set;function z(o){const[f,N]=n.useState(v),[e,B]=n.useState(null),d=G(),p=P(),C=T(x??(()=>{})),[u,F]=n.useState(!1),[r,E]=n.useState(!1),k=n.useRef(u),S=n.useCallback(()=>{(c==null?void 0:c(d.getState()))===!1&&a&&p(a({isSignalROnline:!0})),r||E(!0)},[p,r,d]),A=S,H=n.useCallback(()=>{(c==null?void 0:c(d.getState()))===!0&&a&&p(a({isSignalROnline:!1})),r&&E(!1)},[p,r,d]),O=n.useCallback(async t=>e?e.joinGroup(t):!1,[e]),y=n.useCallback(async t=>{e&&e.groups.indexOf(t)>=0&&await(e==null?void 0:e.leaveGroup(t))},[e]),L=n.useCallback((t,s,i)=>e?e==null?void 0:e.addSignalListener(t,s,i):h.noop,[e]),U=n.useCallback((t,s)=>{e&&e.removeSignalListener(t,s)},[e]),g=n.useCallback(()=>e?e.getHubConnectionId():null,[e]);return n.useEffect(()=>{let t=!1;return Promise.resolve().then(()=>J(require("./SignalR.js"))).then(({default:s})=>{t||B(new s({signalRApiUrl:f,hub:o,logger:w,enableLogging:D,serverTimeoutInMilliseconds:M,keepAliveIntervalInMilliseconds:m}))}),()=>{t=!0}},[o,f]),n.useEffect(()=>{function t(s){N(s)}return b.add(t),()=>{b.delete(t)}},[]),n.useEffect(()=>{k.current=u},[u]),n.useEffect(()=>{const t=e==null?void 0:e.addEventListener("connected",S),s=e==null?void 0:e.addEventListener("reconnected",A),i=e==null?void 0:e.addEventListener("disconnected",H);return e&&!k.current&&F(!0),()=>{t==null||t(),s==null||s(),i==null||i()}},[e,S,H,A]),n.useEffect(()=>{e==null||e.setClientId(C||void 0)},[e,C]),n.useEffect(()=>{async function t(){await(e==null?void 0:e.connect())}u&&t()},[e,u]),n.useEffect(()=>()=>{e==null||e.leaveAllGroups().then(()=>{e==null||e.disconnect()}).catch(h.noop).finally(()=>{e==null||e.disconnect().catch(h.noop)})},[e]),n.useMemo(()=>({isHubConnected:r,join:O,leave:y,subscribe:L,unsubscribe:U,getHubConnectionId:g}),[r,O,y,L,U,g])}return{useSignalR:z,setUrl(o){v=o,b.forEach(f=>{f(o)})}}}module.exports=K;
1
+ "use strict";const n=require("react"),I=require("react-redux"),h=require("../noop-7ea3b37b.js"),K=l=>Object.freeze(Object.defineProperty({__proto__:null,default:l},Symbol.toStringTag,{value:"Module"}));function Q(l,D,M,_){const{logger:j,enableLogging:q,serverTimeoutInMilliseconds:w,keepAliveIntervalInMilliseconds:m,initialReconnectDelayMs:x}=l;let{signalRApiUrl:v}=l;const{clientIdSelector:G,isSignalROnlineSelector:c}=D??{},{setIsSignalROnlineAction:a}=M??{},{useAppStore:P=I.useStore,useAppDispatch:T=I.useDispatch,useAppSelector:z=I.useSelector}=_??{},b=new Set;function N(o){const[f,B]=n.useState(v),[e,F]=n.useState(null),d=P(),p=T(),C=z(G??(()=>{})),[u,J]=n.useState(!1),[r,E]=n.useState(!1),k=n.useRef(u),S=n.useCallback(()=>{(c==null?void 0:c(d.getState()))===!1&&a&&p(a({isSignalROnline:!0})),r||E(!0)},[p,r,d]),y=S,A=n.useCallback(()=>{(c==null?void 0:c(d.getState()))===!0&&a&&p(a({isSignalROnline:!1})),r&&E(!1)},[p,r,d]),H=n.useCallback(async t=>e?e.joinGroup(t):!1,[e]),O=n.useCallback(async t=>{e&&e.groups.indexOf(t)>=0&&await(e==null?void 0:e.leaveGroup(t))},[e]),L=n.useCallback((t,s,i)=>e?e==null?void 0:e.addSignalListener(t,s,i):h.noop,[e]),U=n.useCallback((t,s)=>{e&&e.removeSignalListener(t,s)},[e]),g=n.useCallback(()=>e?e.getHubConnectionId():null,[e]);return n.useEffect(()=>{let t=!1;return Promise.resolve().then(()=>K(require("./SignalR.js"))).then(({default:s})=>{t||F(new s({signalRApiUrl:f,hub:o,logger:j,enableLogging:q,serverTimeoutInMilliseconds:w,keepAliveIntervalInMilliseconds:m,initialReconnectDelayMs:x}))}),()=>{t=!0}},[o,f]),n.useEffect(()=>{function t(s){B(s)}return b.add(t),()=>{b.delete(t)}},[]),n.useEffect(()=>{k.current=u},[u]),n.useEffect(()=>{const t=e==null?void 0:e.addEventListener("connected",S),s=e==null?void 0:e.addEventListener("reconnected",y),i=e==null?void 0:e.addEventListener("disconnected",A);return e&&!k.current&&J(!0),()=>{t==null||t(),s==null||s(),i==null||i()}},[e,S,A,y]),n.useEffect(()=>{e==null||e.setClientId(C||void 0)},[e,C]),n.useEffect(()=>{async function t(){await(e==null?void 0:e.connect())}u&&t()},[e,u]),n.useEffect(()=>()=>{e==null||e.leaveAllGroups().then(()=>{e==null||e.disconnect()}).catch(h.noop).finally(()=>{e==null||e.disconnect().catch(h.noop)})},[e]),n.useMemo(()=>({isHubConnected:r,join:H,leave:O,subscribe:L,unsubscribe:U,getHubConnectionId:g}),[r,H,O,L,U,g])}return{useSignalR:N,setUrl(o){v=o,b.forEach(f=>{f(o)})}}}module.exports=Q;
@@ -1,72 +1,74 @@
1
- import { useState as I, useRef as Q, useCallback as r, useEffect as s, useMemo as V } from "react";
2
- import { useStore as W, useDispatch as X, useSelector as Y } from "react-redux";
1
+ import { useState as I, useRef as V, useCallback as s, useEffect as r, useMemo as W } from "react";
2
+ import { useStore as X, useDispatch as Y, useSelector as Z } from "react-redux";
3
3
  import { n as h } from "../noop-378485d5.mjs";
4
- function ee(v, k, D, G) {
4
+ function te(v, D, M, k) {
5
5
  const {
6
- logger: M,
6
+ logger: G,
7
7
  enableLogging: j,
8
8
  serverTimeoutInMilliseconds: x,
9
- keepAliveIntervalInMilliseconds: T
9
+ keepAliveIntervalInMilliseconds: T,
10
+ initialReconnectDelayMs: q
10
11
  } = v;
11
12
  let { signalRApiUrl: A } = v;
12
- const { clientIdSelector: q, isSignalROnlineSelector: c } = k ?? {}, { setIsSignalROnlineAction: a } = D ?? {}, {
13
- useAppStore: z = W,
14
- useAppDispatch: B = X,
15
- useAppSelector: F = Y
16
- } = G ?? {}, S = /* @__PURE__ */ new Set();
17
- function J(i) {
18
- const [d, K] = I(A), [e, N] = I(null), f = z(), p = B(), H = F(q ?? (() => {
19
- })), [u, P] = I(!1), [o, m] = I(!1), L = Q(u), b = r(() => {
13
+ const { clientIdSelector: z, isSignalROnlineSelector: c } = D ?? {}, { setIsSignalROnlineAction: a } = M ?? {}, {
14
+ useAppStore: B = X,
15
+ useAppDispatch: F = Y,
16
+ useAppSelector: J = Z
17
+ } = k ?? {}, S = /* @__PURE__ */ new Set();
18
+ function K(i) {
19
+ const [d, N] = I(A), [e, P] = I(null), f = B(), p = F(), H = J(z ?? (() => {
20
+ })), [u, Q] = I(!1), [o, m] = I(!1), L = V(u), b = s(() => {
20
21
  (c == null ? void 0 : c(f.getState())) === !1 && a && p(a({ isSignalROnline: !0 })), o || m(!0);
21
- }, [p, o, f]), U = b, C = r(() => {
22
+ }, [p, o, f]), U = b, C = s(() => {
22
23
  (c == null ? void 0 : c(f.getState())) === !0 && a && p(a({ isSignalROnline: !1 })), o && m(!1);
23
- }, [p, o, f]), E = r(
24
+ }, [p, o, f]), y = s(
24
25
  async (t) => e ? e.joinGroup(t) : !1,
25
26
  [e]
26
- ), O = r(
27
+ ), E = s(
27
28
  async (t) => {
28
29
  e && e.groups.indexOf(t) >= 0 && await (e == null ? void 0 : e.leaveGroup(t));
29
30
  },
30
31
  [e]
31
- ), g = r(
32
+ ), O = s(
32
33
  (t, n, l) => e ? e == null ? void 0 : e.addSignalListener(
33
34
  t,
34
35
  n,
35
36
  l
36
37
  ) : h,
37
38
  [e]
38
- ), w = r(
39
+ ), g = s(
39
40
  (t, n) => {
40
41
  e && e.removeSignalListener(t, n);
41
42
  },
42
43
  [e]
43
- ), y = r(() => e ? e.getHubConnectionId() : null, [e]);
44
- return s(() => {
44
+ ), w = s(() => e ? e.getHubConnectionId() : null, [e]);
45
+ return r(() => {
45
46
  let t = !1;
46
47
  return import("./SignalR.mjs").then(({ default: n }) => {
47
- t || N(
48
+ t || P(
48
49
  new n({
49
50
  signalRApiUrl: d,
50
51
  hub: i,
51
- logger: M,
52
+ logger: G,
52
53
  enableLogging: j,
53
54
  serverTimeoutInMilliseconds: x,
54
- keepAliveIntervalInMilliseconds: T
55
+ keepAliveIntervalInMilliseconds: T,
56
+ initialReconnectDelayMs: q
55
57
  })
56
58
  );
57
59
  }), () => {
58
60
  t = !0;
59
61
  };
60
- }, [i, d]), s(() => {
62
+ }, [i, d]), r(() => {
61
63
  function t(n) {
62
- K(n);
64
+ N(n);
63
65
  }
64
66
  return S.add(t), () => {
65
67
  S.delete(t);
66
68
  };
67
- }, []), s(() => {
69
+ }, []), r(() => {
68
70
  L.current = u;
69
- }, [u]), s(() => {
71
+ }, [u]), r(() => {
70
72
  const t = e == null ? void 0 : e.addEventListener(
71
73
  "connected",
72
74
  b
@@ -77,7 +79,7 @@ function ee(v, k, D, G) {
77
79
  "disconnected",
78
80
  C
79
81
  );
80
- return e && !L.current && P(!0), () => {
82
+ return e && !L.current && Q(!0), () => {
81
83
  t == null || t(), n == null || n(), l == null || l();
82
84
  };
83
85
  }, [
@@ -85,14 +87,14 @@ function ee(v, k, D, G) {
85
87
  b,
86
88
  C,
87
89
  U
88
- ]), s(() => {
90
+ ]), r(() => {
89
91
  e == null || e.setClientId(H || void 0);
90
- }, [e, H]), s(() => {
92
+ }, [e, H]), r(() => {
91
93
  async function t() {
92
94
  await (e == null ? void 0 : e.connect());
93
95
  }
94
96
  u && t();
95
- }, [e, u]), s(
97
+ }, [e, u]), r(
96
98
  () => () => {
97
99
  e == null || e.leaveAllGroups().then(() => {
98
100
  e == null || e.disconnect();
@@ -101,20 +103,20 @@ function ee(v, k, D, G) {
101
103
  });
102
104
  },
103
105
  [e]
104
- ), V(
106
+ ), W(
105
107
  () => ({
106
108
  isHubConnected: o,
107
- join: E,
108
- leave: O,
109
- subscribe: g,
110
- unsubscribe: w,
111
- getHubConnectionId: y
109
+ join: y,
110
+ leave: E,
111
+ subscribe: O,
112
+ unsubscribe: g,
113
+ getHubConnectionId: w
112
114
  }),
113
- [o, E, O, g, w, y]
115
+ [o, y, E, O, g, w]
114
116
  );
115
117
  }
116
118
  return {
117
- useSignalR: J,
119
+ useSignalR: K,
118
120
  setUrl(i) {
119
121
  A = i, S.forEach((d) => {
120
122
  d(i);
@@ -123,5 +125,5 @@ function ee(v, k, D, G) {
123
125
  };
124
126
  }
125
127
  export {
126
- ee as default
128
+ te as default
127
129
  };
@@ -1,5 +1,5 @@
1
1
  import createUseSignalRHook from './createUseSignalRHook';
2
2
  import SignalR from './SignalR';
3
- import type { SignalRConfig } from './types';
3
+ import type { SignalRConfig, SignalRDelayRange } from './types';
4
4
  export { createUseSignalRHook, SignalR };
5
- export type { SignalRConfig };
5
+ export type { SignalRConfig, SignalRDelayRange };
@@ -14,5 +14,19 @@ export declare type SignalRConfig = {
14
14
  serverTimeoutInMilliseconds?: number;
15
15
  /** @default 15000 */
16
16
  keepAliveIntervalInMilliseconds?: number;
17
+ /**
18
+ * Random delay range waited before the first reconnect attempt after the
19
+ * connection closes unexpectedly. Spreads the reconnects of many clients that
20
+ * lose the connection at the same moment (e.g. a server restart) over time.
21
+ * Set both to 0 to reconnect immediately.
22
+ * @default { min: 500, max: 5000 }
23
+ */
24
+ initialReconnectDelayMs?: SignalRDelayRange;
25
+ };
26
+ export declare type SignalRDelayRange = {
27
+ /** Shortest delay in milliseconds */
28
+ min: number;
29
+ /** Longest delay in milliseconds */
30
+ max: number;
17
31
  };
18
32
  export declare type SignalRHookConfig = Omit<SignalRConfig, 'hub'>;