arifa-client 1.0.13 → 1.1.13

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.
@@ -4,11 +4,12 @@ class ArifaClient {
4
4
  this.isConnected = false;
5
5
  this.reconnectAttempts = 0;
6
6
  this.reconnectTimer = null;
7
+ this.reconnectScheduled = false;
7
8
  this.internetOnline = true;
8
9
  this.internetTimer = null;
9
10
  this.recipient = null;
10
- this.listeners = [];
11
- this.connectionListeners = [];
11
+ this.listeners = new Set();
12
+ this.connectionListeners = new Set();
12
13
  this.HEALTH_URL = "https://notifications.arifa.dev/health";
13
14
  this.MAX_BACKOFF = 60000;
14
15
  this.apiKey = apiKey;
@@ -36,7 +37,7 @@ class ArifaClient {
36
37
  const controller = new AbortController();
37
38
  const timeout = setTimeout(() => controller.abort(), 3000);
38
39
  await fetch(this.HEALTH_URL, {
39
- method: "GET",
40
+ method: "HEAD",
40
41
  cache: "no-store",
41
42
  signal: controller.signal,
42
43
  });
@@ -76,15 +77,18 @@ class ArifaClient {
76
77
  }
77
78
  return {
78
79
  listen: (callback) => {
79
- this.listeners.push(callback);
80
+ this.listeners.add(callback);
80
81
  },
81
- unsubscribe: () => {
82
- this.listeners = [];
82
+ unsubscribe: (callback) => {
83
+ if (callback)
84
+ this.listeners.delete(callback);
85
+ else
86
+ this.listeners.clear();
83
87
  },
84
88
  };
85
89
  }
86
90
  onConnectionChange(callback) {
87
- this.connectionListeners.push(callback);
91
+ this.connectionListeners.add(callback);
88
92
  }
89
93
  emitConnection(state) {
90
94
  this.connectionListeners.forEach((cb) => cb(state));
@@ -95,24 +99,31 @@ class ArifaClient {
95
99
  return;
96
100
  if (!this.internetOnline)
97
101
  return;
98
- if (this.ws && this.ws.readyState === WebSocket.OPEN)
102
+ if (this.ws &&
103
+ (this.ws.readyState === WebSocket.OPEN ||
104
+ this.ws.readyState === WebSocket.CONNECTING)) {
99
105
  return;
106
+ }
100
107
  this.ws = new WebSocket(`${this.wsUrl}/connect?api_key=${this.apiKey}&recipient=${this.recipient}&client=${this.client}`);
101
108
  this.ws.onopen = () => {
102
109
  this.isConnected = true;
103
110
  this.reconnectAttempts = 0;
111
+ this.reconnectScheduled = false;
112
+ if (this.reconnectTimer) {
113
+ clearTimeout(this.reconnectTimer);
114
+ this.reconnectTimer = null;
115
+ }
104
116
  this.emitConnection("connected");
105
117
  };
106
118
  this.ws.onmessage = (event) => {
107
119
  const parsed = this.safeParse(event.data);
108
- if (!parsed)
109
- return;
110
120
  // IMMEDIATE ACK
111
121
  this.ws.send(JSON.stringify({
112
122
  kind: "ack",
113
123
  event_id: parsed.ack.event_id,
114
124
  }));
115
- this.listeners.forEach((fn) => fn(parsed.event));
125
+ if (parsed.event)
126
+ this.listeners.forEach((fn) => fn(parsed.event));
116
127
  };
117
128
  this.ws.onclose = () => {
118
129
  this.isConnected = false;
@@ -125,13 +136,15 @@ class ArifaClient {
125
136
  };
126
137
  }
127
138
  scheduleReconnect() {
128
- if (!this.internetOnline)
139
+ if (!this.internetOnline || this.reconnectScheduled)
129
140
  return;
141
+ this.reconnectScheduled = true;
130
142
  const base = Math.min(this.MAX_BACKOFF, 1000 * 2 ** this.reconnectAttempts);
131
143
  const jitter = Math.random() * 1000;
132
144
  const timeout = base + jitter;
133
145
  this.reconnectAttempts++;
134
146
  this.reconnectTimer = window.setTimeout(() => {
147
+ this.reconnectScheduled = false;
135
148
  this.connect();
136
149
  }, timeout);
137
150
  }
@@ -7,11 +7,12 @@ var ArifaClient = (function () {
7
7
  this.isConnected = false;
8
8
  this.reconnectAttempts = 0;
9
9
  this.reconnectTimer = null;
10
+ this.reconnectScheduled = false;
10
11
  this.internetOnline = true;
11
12
  this.internetTimer = null;
12
13
  this.recipient = null;
13
- this.listeners = [];
14
- this.connectionListeners = [];
14
+ this.listeners = new Set();
15
+ this.connectionListeners = new Set();
15
16
  this.HEALTH_URL = "https://notifications.arifa.dev/health";
16
17
  this.MAX_BACKOFF = 60000;
17
18
  this.apiKey = apiKey;
@@ -39,7 +40,7 @@ var ArifaClient = (function () {
39
40
  const controller = new AbortController();
40
41
  const timeout = setTimeout(() => controller.abort(), 3000);
41
42
  await fetch(this.HEALTH_URL, {
42
- method: "GET",
43
+ method: "HEAD",
43
44
  cache: "no-store",
44
45
  signal: controller.signal,
45
46
  });
@@ -79,15 +80,18 @@ var ArifaClient = (function () {
79
80
  }
80
81
  return {
81
82
  listen: (callback) => {
82
- this.listeners.push(callback);
83
+ this.listeners.add(callback);
83
84
  },
84
- unsubscribe: () => {
85
- this.listeners = [];
85
+ unsubscribe: (callback) => {
86
+ if (callback)
87
+ this.listeners.delete(callback);
88
+ else
89
+ this.listeners.clear();
86
90
  },
87
91
  };
88
92
  }
89
93
  onConnectionChange(callback) {
90
- this.connectionListeners.push(callback);
94
+ this.connectionListeners.add(callback);
91
95
  }
92
96
  emitConnection(state) {
93
97
  this.connectionListeners.forEach((cb) => cb(state));
@@ -98,24 +102,31 @@ var ArifaClient = (function () {
98
102
  return;
99
103
  if (!this.internetOnline)
100
104
  return;
101
- if (this.ws && this.ws.readyState === WebSocket.OPEN)
105
+ if (this.ws &&
106
+ (this.ws.readyState === WebSocket.OPEN ||
107
+ this.ws.readyState === WebSocket.CONNECTING)) {
102
108
  return;
109
+ }
103
110
  this.ws = new WebSocket(`${this.wsUrl}/connect?api_key=${this.apiKey}&recipient=${this.recipient}&client=${this.client}`);
104
111
  this.ws.onopen = () => {
105
112
  this.isConnected = true;
106
113
  this.reconnectAttempts = 0;
114
+ this.reconnectScheduled = false;
115
+ if (this.reconnectTimer) {
116
+ clearTimeout(this.reconnectTimer);
117
+ this.reconnectTimer = null;
118
+ }
107
119
  this.emitConnection("connected");
108
120
  };
109
121
  this.ws.onmessage = (event) => {
110
122
  const parsed = this.safeParse(event.data);
111
- if (!parsed)
112
- return;
113
123
  // IMMEDIATE ACK
114
124
  this.ws.send(JSON.stringify({
115
125
  kind: "ack",
116
126
  event_id: parsed.ack.event_id,
117
127
  }));
118
- this.listeners.forEach((fn) => fn(parsed.event));
128
+ if (parsed.event)
129
+ this.listeners.forEach((fn) => fn(parsed.event));
119
130
  };
120
131
  this.ws.onclose = () => {
121
132
  this.isConnected = false;
@@ -128,13 +139,15 @@ var ArifaClient = (function () {
128
139
  };
129
140
  }
130
141
  scheduleReconnect() {
131
- if (!this.internetOnline)
142
+ if (!this.internetOnline || this.reconnectScheduled)
132
143
  return;
144
+ this.reconnectScheduled = true;
133
145
  const base = Math.min(this.MAX_BACKOFF, 1000 * 2 ** this.reconnectAttempts);
134
146
  const jitter = Math.random() * 1000;
135
147
  const timeout = base + jitter;
136
148
  this.reconnectAttempts++;
137
149
  this.reconnectTimer = window.setTimeout(() => {
150
+ this.reconnectScheduled = false;
138
151
  this.connect();
139
152
  }, timeout);
140
153
  }
@@ -26,6 +26,7 @@ export declare class ArifaClient {
26
26
  private isConnected;
27
27
  private reconnectAttempts;
28
28
  private reconnectTimer;
29
+ private reconnectScheduled;
29
30
  private internetOnline;
30
31
  private internetTimer;
31
32
  private recipient;
@@ -39,7 +40,7 @@ export declare class ArifaClient {
39
40
  private startInternetMonitor;
40
41
  subscribe(recipient: string): {
41
42
  listen: (callback: (event: ArifaEvent) => void) => void;
42
- unsubscribe: () => void;
43
+ unsubscribe: (callback?: (event: ArifaEvent) => void) => void;
43
44
  };
44
45
  onConnectionChange(callback: ConnectionCallback): void;
45
46
  private emitConnection;
@@ -1 +1 @@
1
- {"version":3,"file":"ArifaClient.d.ts","sourceRoot":"","sources":["../../src/ArifaClient.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,GAAG,CAAC;AACtB,KAAK,eAAe,GAAG,WAAW,GAAG,cAAc,CAAC;AAEpD,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAE3D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAAuB;IAE7C,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,SAAS,CAAuB;IAExC,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,mBAAmB,CAA4B;IAEvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4C;IACvE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;gBAE1B,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,kBAAkB;IAStE,OAAO,CAAC,SAAS;YAaH,aAAa;IAkB3B,OAAO,CAAC,oBAAoB;IA2B5B,SAAS,CAAC,SAAS,EAAE,MAAM;2BAOJ,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;;;IASlD,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB;IAI/C,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,OAAO;IAyCf,OAAO,CAAC,iBAAiB;IAiBnB,MAAM,CAAC,EACX,SAAS,EACT,OAAO,EACP,MAAM,EACN,MAAM,GACP,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IA0B1C,UAAU;IAUV,SAAS;CAGV"}
1
+ {"version":3,"file":"ArifaClient.d.ts","sourceRoot":"","sources":["../../src/ArifaClient.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,GAAG,CAAC;AACtB,KAAK,eAAe,GAAG,WAAW,GAAG,cAAc,CAAC;AAEpD,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,cAAc;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAE3D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,kBAAkB,CAAS;IAEnC,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,SAAS,CAAuB;IAExC,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,mBAAmB,CAAsC;IAEjE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4C;IACvE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;gBAE1B,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,kBAAkB;IAStE,OAAO,CAAC,SAAS;YAaH,aAAa;IAkB3B,OAAO,CAAC,oBAAoB;IA2B5B,SAAS,CAAC,SAAS,EAAE,MAAM;2BAOJ,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;iCAGrB,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;;IAOxD,kBAAkB,CAAC,QAAQ,EAAE,kBAAkB;IAI/C,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,OAAO;IAsDf,OAAO,CAAC,iBAAiB;IAmBnB,MAAM,CAAC,EACX,SAAS,EACT,OAAO,EACP,MAAM,EACN,MAAM,GACP,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IA0B1C,UAAU;IAUV,SAAS;CAGV"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arifa-client",
3
- "version": "1.0.13",
3
+ "version": "1.1.13",
4
4
  "description": "JavaScript/TypeScript client SDK for Arifa Realtime Notification Service",
5
5
  "main": "dist/arifa-client.iife.js",
6
6
  "module": "dist/arifa-client.esm.js",