@hardlydifficult/websocket 1.0.0 → 1.0.2

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 ADDED
@@ -0,0 +1,316 @@
1
+ # @hardlydifficult/websocket
2
+
3
+ A resilient WebSocket client for Node.js with automatic reconnection, heartbeat-based dead connection detection, and graceful request draining.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hardlydifficult/websocket
9
+ ```
10
+
11
+ Requires Node.js 18+.
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { ReconnectingWebSocket } from "@hardlydifficult/websocket";
17
+
18
+ interface Message {
19
+ type: string;
20
+ data: unknown;
21
+ }
22
+
23
+ const client = new ReconnectingWebSocket<Message>({
24
+ url: "ws://localhost:8080",
25
+ });
26
+
27
+ client.on("open", () => {
28
+ console.log("Connected");
29
+ client.send({ type: "hello", data: "world" });
30
+ });
31
+
32
+ client.on("message", (msg) => {
33
+ console.log("Received:", msg);
34
+ });
35
+
36
+ client.on("error", (err) => {
37
+ console.error("Error:", err);
38
+ });
39
+
40
+ client.connect();
41
+ ```
42
+
43
+ ## ReconnectingWebSocket
44
+
45
+ A generic WebSocket client that automatically reconnects on disconnection, sends protocol-level pings for heartbeats, and parses JSON messages.
46
+
47
+ ### Constructor
48
+
49
+ ```typescript
50
+ const client = new ReconnectingWebSocket<T>(options: WebSocketOptions);
51
+ ```
52
+
53
+ | Option | Type | Default | Description |
54
+ |--------|------|---------|-------------|
55
+ | `url` | `string` | — | WebSocket server URL (required) |
56
+ | `backoff.initialDelayMs` | `number` | `1000` | Initial reconnection delay in milliseconds |
57
+ | `backoff.maxDelayMs` | `number` | `30000` | Maximum reconnection delay in milliseconds |
58
+ | `backoff.multiplier` | `number` | `2` | Multiplier applied per reconnection attempt |
59
+ | `heartbeat.intervalMs` | `number` | `30000` | Interval between pings in milliseconds |
60
+ | `heartbeat.timeoutMs` | `number` | `10000` | Time to wait for pong before terminating |
61
+
62
+ ### Methods
63
+
64
+ #### `connect(): void`
65
+
66
+ Connect to the WebSocket server. Idempotent — calling multiple times has no additional effect. If a reconnect timer is pending, cancels it and connects immediately, resetting the attempt counter.
67
+
68
+ ```typescript
69
+ client.connect();
70
+ ```
71
+
72
+ #### `disconnect(): void`
73
+
74
+ Disconnect from the server and stop all reconnection attempts. Closes the socket with code 1000.
75
+
76
+ ```typescript
77
+ client.disconnect();
78
+ ```
79
+
80
+ #### `send(message: T): void`
81
+
82
+ Send a message as JSON. No-op if not currently connected.
83
+
84
+ ```typescript
85
+ client.send({ type: "ping" });
86
+ ```
87
+
88
+ #### `stopReconnecting(): void`
89
+
90
+ Prevent reconnection without closing the current connection. Useful for graceful shutdown: deliver in-flight results but do not reconnect if the socket drops.
91
+
92
+ ```typescript
93
+ client.stopReconnecting();
94
+ ```
95
+
96
+ #### `on<K extends keyof WebSocketEvents<T>>(event: K, listener: WebSocketEvents<T>[K]): () => void`
97
+
98
+ Subscribe to a WebSocket lifecycle event. Multiple listeners per event are supported. Returns an unsubscribe function.
99
+
100
+ ```typescript
101
+ const unsubscribe = client.on("message", (msg) => {
102
+ console.log(msg);
103
+ });
104
+
105
+ unsubscribe(); // Stop listening
106
+ ```
107
+
108
+ ### Events
109
+
110
+ #### `open`
111
+
112
+ Fired when the connection is established.
113
+
114
+ ```typescript
115
+ client.on("open", () => {
116
+ console.log("Connected");
117
+ });
118
+ ```
119
+
120
+ #### `close`
121
+
122
+ Fired when the connection is closed.
123
+
124
+ ```typescript
125
+ client.on("close", (code: number, reason: string) => {
126
+ console.log(`Closed with code ${code}: ${reason}`);
127
+ });
128
+ ```
129
+
130
+ #### `error`
131
+
132
+ Fired on connection or parse errors.
133
+
134
+ ```typescript
135
+ client.on("error", (error: Error) => {
136
+ console.error("Error:", error.message);
137
+ });
138
+ ```
139
+
140
+ #### `message`
141
+
142
+ Fired when a message is received and parsed.
143
+
144
+ ```typescript
145
+ client.on("message", (data: T) => {
146
+ console.log("Received:", data);
147
+ });
148
+ ```
149
+
150
+ ### Properties
151
+
152
+ #### `connected: boolean`
153
+
154
+ Whether the socket is currently open.
155
+
156
+ ```typescript
157
+ if (client.connected) {
158
+ client.send({ type: "ping" });
159
+ }
160
+ ```
161
+
162
+ ### Exponential Backoff
163
+
164
+ The client uses exponential backoff for reconnection delays. The delay for attempt `n` is calculated as:
165
+
166
+ ```
167
+ delay = min(initialDelayMs × multiplier^n, maxDelayMs)
168
+ ```
169
+
170
+ For example, with default settings (initial: 1000ms, max: 30000ms, multiplier: 2):
171
+ - Attempt 0: 1000ms
172
+ - Attempt 1: 2000ms
173
+ - Attempt 2: 4000ms
174
+ - Attempt 3: 8000ms
175
+ - Attempt 4+: 30000ms (capped)
176
+
177
+ You can access this calculation directly:
178
+
179
+ ```typescript
180
+ import { getBackoffDelay } from "@hardlydifficult/websocket";
181
+
182
+ const delay = getBackoffDelay(2, {
183
+ initialDelayMs: 1000,
184
+ maxDelayMs: 30000,
185
+ multiplier: 2,
186
+ });
187
+ // delay = 4000
188
+ ```
189
+
190
+ ## RequestTracker
191
+
192
+ Tracks active requests and manages draining state. Centralizes the pattern of rejecting new work during shutdown and notifying listeners when the last request completes.
193
+
194
+ ### Constructor
195
+
196
+ ```typescript
197
+ const tracker = new RequestTracker();
198
+ ```
199
+
200
+ ### Methods
201
+
202
+ #### `tryAccept(): boolean`
203
+
204
+ Try to accept a new request. Returns `false` if draining — caller should send a rejection response.
205
+
206
+ ```typescript
207
+ if (tracker.tryAccept()) {
208
+ // Process request
209
+ tracker.complete();
210
+ } else {
211
+ // Send rejection (service is shutting down)
212
+ }
213
+ ```
214
+
215
+ #### `complete(): void`
216
+
217
+ Mark a request as complete. Decrements the active count and emits `drained` when the last request finishes during a drain.
218
+
219
+ ```typescript
220
+ tracker.complete();
221
+ ```
222
+
223
+ #### `startDraining(reason: string): void`
224
+
225
+ Enter draining mode — no new requests will be accepted. Idempotent: subsequent calls are ignored. Emits `draining` immediately and `drained` when active reaches zero.
226
+
227
+ ```typescript
228
+ tracker.startDraining("server shutting down");
229
+ ```
230
+
231
+ #### `on<K extends keyof RequestTrackerEvents>(event: K, listener: RequestTrackerEvents[K]): () => void`
232
+
233
+ Subscribe to a RequestTracker event. Returns an unsubscribe function.
234
+
235
+ ```typescript
236
+ const unsubscribe = tracker.on("drained", () => {
237
+ console.log("All requests completed");
238
+ });
239
+ ```
240
+
241
+ ### Events
242
+
243
+ #### `draining`
244
+
245
+ Fired when draining mode is entered.
246
+
247
+ ```typescript
248
+ tracker.on("draining", (reason: string) => {
249
+ console.log(`Draining: ${reason}`);
250
+ });
251
+ ```
252
+
253
+ #### `drained`
254
+
255
+ Fired when all active requests complete during drain.
256
+
257
+ ```typescript
258
+ tracker.on("drained", () => {
259
+ console.log("Ready to shut down");
260
+ });
261
+ ```
262
+
263
+ ### Properties
264
+
265
+ #### `draining: boolean`
266
+
267
+ Whether the tracker is in draining mode.
268
+
269
+ ```typescript
270
+ if (tracker.draining) {
271
+ console.log("Not accepting new requests");
272
+ }
273
+ ```
274
+
275
+ #### `active: number`
276
+
277
+ Number of currently active requests.
278
+
279
+ ```typescript
280
+ console.log(`${tracker.active} requests in flight`);
281
+ ```
282
+
283
+ ### Example: Graceful Shutdown
284
+
285
+ ```typescript
286
+ import { ReconnectingWebSocket, RequestTracker } from "@hardlydifficult/websocket";
287
+
288
+ const client = new ReconnectingWebSocket({ url: "ws://localhost:8080" });
289
+ const tracker = new RequestTracker();
290
+
291
+ client.on("message", (msg) => {
292
+ if (!tracker.tryAccept()) {
293
+ // Reject new requests during shutdown
294
+ return;
295
+ }
296
+
297
+ // Process message
298
+ processMessage(msg);
299
+ tracker.complete();
300
+ });
301
+
302
+ // Initiate graceful shutdown
303
+ async function shutdown() {
304
+ client.stopReconnecting();
305
+ tracker.startDraining("server shutting down");
306
+
307
+ // Wait for all in-flight requests to complete
308
+ await new Promise<void>((resolve) => {
309
+ tracker.on("drained", () => {
310
+ resolve();
311
+ });
312
+ });
313
+
314
+ client.disconnect();
315
+ }
316
+ ```
@@ -11,6 +11,10 @@ export declare function getBackoffDelay(attempt: number, options: Required<Backo
11
11
  * A generic WebSocket client that automatically reconnects on disconnection,
12
12
  * sends protocol-level pings for heartbeats, and parses JSON messages.
13
13
  *
14
+ * Supports optional bearer-token auth via the `auth` option. The token is
15
+ * fetched on every connect (including reconnects), so reconnects automatically
16
+ * pick up fresh tokens.
17
+ *
14
18
  * @typeParam T - The shape of messages exchanged over the socket (JSON-serializable)
15
19
  */
16
20
  export declare class ReconnectingWebSocket<T> {
@@ -18,6 +22,9 @@ export declare class ReconnectingWebSocket<T> {
18
22
  private readonly url;
19
23
  private readonly backoff;
20
24
  private readonly heartbeat;
25
+ private readonly auth;
26
+ private readonly protocols;
27
+ private readonly extraHeaders;
21
28
  private reconnectAttempt;
22
29
  private shouldReconnect;
23
30
  private heartbeatInterval;
@@ -36,13 +43,22 @@ export declare class ReconnectingWebSocket<T> {
36
43
  * Idempotent — no-op if already connected.
37
44
  * If a reconnect timer is pending, cancels it and connects immediately,
38
45
  * resetting the attempt counter.
46
+ *
47
+ * When `auth` is configured, fetches a bearer token before connecting.
39
48
  */
40
49
  connect(): void;
50
+ private connectInternal;
41
51
  /**
42
52
  * Disconnect from the server and stop all reconnection attempts.
43
53
  * Closes the socket with code 1000.
44
54
  */
45
55
  disconnect(): void;
56
+ /**
57
+ * Force close and reconnect. Useful for token refresh: close the current
58
+ * connection and reconnect with a fresh token (fetched via `auth.getToken`).
59
+ * Resets the backoff counter.
60
+ */
61
+ reconnect(): void;
46
62
  /**
47
63
  * Send a message as JSON. No-op if not currently connected.
48
64
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ReconnectingWebSocket.d.ts","sourceRoot":"","sources":["../src/ReconnectingWebSocket.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAEd,eAAe,EACf,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAapB;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAChC,MAAM,CAGR;AAED;;;;;GAKG;AACH,qBAAa,qBAAqB,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,gBAAgB,CAA8C;IAEtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAG3B;gBAEQ,OAAO,EAAE,gBAAgB;IAMrC;;;;OAIG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,CAAC,CAAC,EACnC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAC9B,MAAM,IAAI;IAYb;;;;;OAKG;IACH,OAAO,IAAI,IAAI;IAmCf;;;OAGG;IACH,UAAU,IAAI,IAAI;IAelB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI;IAMtB;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAIxB,2CAA2C;IAC3C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,OAAO;IAUf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAOd,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,IAAI;CAab"}
1
+ {"version":3,"file":"ReconnectingWebSocket.d.ts","sourceRoot":"","sources":["../src/ReconnectingWebSocket.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,cAAc,EAEd,eAAe,EACf,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAapB;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAChC,MAAM,CAGR;AAED;;;;;;;;;GASG;AACH,qBAAa,qBAAqB,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqC;IAClE,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,gBAAgB,CAA8C;IAEtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAG3B;gBAEQ,OAAO,EAAE,gBAAgB;IASrC;;;;OAIG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,CAAC,CAAC,EACnC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAC9B,MAAM,IAAI;IAYb;;;;;;;OAOG;IACH,OAAO,IAAI,IAAI;YAID,eAAe;IAwD7B;;;OAGG;IACH,UAAU,IAAI,IAAI;IAelB;;;;OAIG;IACH,SAAS,IAAI,IAAI;IAoBjB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI;IAMtB;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAIxB,2CAA2C;IAC3C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,OAAO;IAUf,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAOd,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,IAAI;CAab"}
@@ -30,6 +30,10 @@ function getBackoffDelay(attempt, options) {
30
30
  * A generic WebSocket client that automatically reconnects on disconnection,
31
31
  * sends protocol-level pings for heartbeats, and parses JSON messages.
32
32
  *
33
+ * Supports optional bearer-token auth via the `auth` option. The token is
34
+ * fetched on every connect (including reconnects), so reconnects automatically
35
+ * pick up fresh tokens.
36
+ *
33
37
  * @typeParam T - The shape of messages exchanged over the socket (JSON-serializable)
34
38
  */
35
39
  class ReconnectingWebSocket {
@@ -37,6 +41,9 @@ class ReconnectingWebSocket {
37
41
  url;
38
42
  backoff;
39
43
  heartbeat;
44
+ auth;
45
+ protocols;
46
+ extraHeaders;
40
47
  reconnectAttempt = 0;
41
48
  shouldReconnect = true;
42
49
  heartbeatInterval = null;
@@ -47,6 +54,9 @@ class ReconnectingWebSocket {
47
54
  this.url = options.url;
48
55
  this.backoff = { ...BACKOFF_DEFAULTS, ...options.backoff };
49
56
  this.heartbeat = { ...HEARTBEAT_DEFAULTS, ...options.heartbeat };
57
+ this.auth = options.auth;
58
+ this.protocols = options.protocols;
59
+ this.extraHeaders = options.headers;
50
60
  }
51
61
  /**
52
62
  * Subscribe to a WebSocket lifecycle event.
@@ -69,8 +79,13 @@ class ReconnectingWebSocket {
69
79
  * Idempotent — no-op if already connected.
70
80
  * If a reconnect timer is pending, cancels it and connects immediately,
71
81
  * resetting the attempt counter.
82
+ *
83
+ * When `auth` is configured, fetches a bearer token before connecting.
72
84
  */
73
85
  connect() {
86
+ void this.connectInternal();
87
+ }
88
+ async connectInternal() {
74
89
  if (this.ws) {
75
90
  return;
76
91
  }
@@ -80,7 +95,22 @@ class ReconnectingWebSocket {
80
95
  this.reconnectAttempt = 0;
81
96
  }
82
97
  this.shouldReconnect = true;
83
- this.ws = new ws_1.default(this.url);
98
+ const headers = { ...this.extraHeaders };
99
+ if (this.auth) {
100
+ try {
101
+ const token = await this.auth.getToken();
102
+ if (token !== "") {
103
+ headers.Authorization = `Bearer ${token}`;
104
+ }
105
+ }
106
+ catch (err) {
107
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
108
+ this.scheduleReconnect();
109
+ return;
110
+ }
111
+ }
112
+ const hasHeaders = Object.keys(headers).length > 0;
113
+ this.ws = new ws_1.default(this.url, this.protocols, hasHeaders ? { headers } : undefined);
84
114
  this.ws.on("open", () => {
85
115
  this.onOpen();
86
116
  });
@@ -113,6 +143,26 @@ class ReconnectingWebSocket {
113
143
  this.ws = null;
114
144
  }
115
145
  }
146
+ /**
147
+ * Force close and reconnect. Useful for token refresh: close the current
148
+ * connection and reconnect with a fresh token (fetched via `auth.getToken`).
149
+ * Resets the backoff counter.
150
+ */
151
+ reconnect() {
152
+ this.stopHeartbeat();
153
+ if (this.reconnectTimeout) {
154
+ clearTimeout(this.reconnectTimeout);
155
+ this.reconnectTimeout = null;
156
+ }
157
+ this.reconnectAttempt = 0;
158
+ if (this.ws) {
159
+ this.ws.removeAllListeners();
160
+ this.ws.close(4000, "Token refresh");
161
+ this.ws = null;
162
+ }
163
+ this.shouldReconnect = true;
164
+ void this.connectInternal();
165
+ }
116
166
  /**
117
167
  * Send a message as JSON. No-op if not currently connected.
118
168
  */
@@ -203,7 +253,7 @@ class ReconnectingWebSocket {
203
253
  this.reconnectAttempt++;
204
254
  this.reconnectTimeout = null;
205
255
  this.ws = null;
206
- this.connect();
256
+ void this.connectInternal();
207
257
  }, delay);
208
258
  }
209
259
  emit(event, ...args) {
@@ -1 +1 @@
1
- {"version":3,"file":"ReconnectingWebSocket.js","sourceRoot":"","sources":["../src/ReconnectingWebSocket.ts"],"names":[],"mappings":";;;;;;AA2BA,0CAMC;AAjCD,4CAA2B;AAS3B,MAAM,gBAAgB,GAA6B;IACjD,cAAc,EAAE,IAAI;IACpB,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,CAAC;CACd,CAAC;AAEF,MAAM,kBAAkB,GAA+B;IACrD,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,KAAK;CACjB,CAAC;AAEF;;;;;;GAMG;AACH,SAAgB,eAAe,CAC7B,OAAe,EACf,OAAiC;IAEjC,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAa,qBAAqB;IACxB,EAAE,GAAqB,IAAI,CAAC;IACnB,GAAG,CAAS;IACZ,OAAO,CAA2B;IAClC,SAAS,CAA6B;IAC/C,gBAAgB,GAAG,CAAC,CAAC;IACrB,eAAe,GAAG,IAAI,CAAC;IACvB,iBAAiB,GAA0C,IAAI,CAAC;IAChE,gBAAgB,GAAyC,IAAI,CAAC;IAC9D,gBAAgB,GAAyC,IAAI,CAAC;IAErD,cAAc,GAAG,IAAI,GAAG,EAGtC,CAAC;IAEJ,YAAY,OAAyB;QACnC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3D,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACH,EAAE,CACA,KAAQ,EACR,QAA+B;QAE/B,IAAI,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtC,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,GAAG,EAAE;YACV,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,EAAE,GAAG,IAAI,YAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAuB,EAAE,EAAE;YAChD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAY,EAAE,MAAc,EAAE,EAAE;YACnD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YACnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;YAC5C,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,OAAU;QACb,IAAI,IAAI,CAAC,EAAE,EAAE,UAAU,KAAK,YAAS,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,gBAAgB;QACd,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED,2CAA2C;IAC3C,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,EAAE,EAAE,UAAU,KAAK,YAAS,CAAC,IAAI,CAAC;IAChD,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAEO,OAAO,CAAC,IAAY,EAAE,MAAc;QAC1C,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACf,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAEjC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,KAAY;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;IAEO,MAAM;QACZ,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,IAAuB;QACvC,IAAI,CAAC;YACH,IAAI,GAAW,CAAC;YAChB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;iBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC3C,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,EAAE,EAAE,UAAU,KAAK,YAAS,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;gBACtC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC;YACvB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;YACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACtC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,iBAAiB;QACvB,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACnE,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAMO,IAAI,CAAC,KAA+B,EAAE,GAAG,IAAe;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO;QACT,CAAC;QACD,KAAK,MAAM,QAAQ,IAAI,GAAG,EAAE,CAAC;YAC1B,QAAsC,CAAC,GAAG,IAAI,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;CACF;AA1ND,sDA0NC"}
1
+ {"version":3,"file":"ReconnectingWebSocket.js","sourceRoot":"","sources":["../src/ReconnectingWebSocket.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { ReconnectingWebSocket } from "./ReconnectingWebSocket.js";
2
2
  export { RequestTracker } from "./RequestTracker.js";
3
- export type { BackoffOptions, HeartbeatOptions, WebSocketOptions, } from "./types.js";
3
+ export { calculateTokenRefreshTime } from "./tokenRefresh.js";
4
+ export type { AuthOptions, BackoffOptions, HeartbeatOptions, WebSocketOptions, } from "./types.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EACV,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RequestTracker = exports.ReconnectingWebSocket = void 0;
3
+ exports.calculateTokenRefreshTime = exports.RequestTracker = exports.ReconnectingWebSocket = void 0;
4
4
  var ReconnectingWebSocket_js_1 = require("./ReconnectingWebSocket.js");
5
5
  Object.defineProperty(exports, "ReconnectingWebSocket", { enumerable: true, get: function () { return ReconnectingWebSocket_js_1.ReconnectingWebSocket; } });
6
6
  var RequestTracker_js_1 = require("./RequestTracker.js");
7
7
  Object.defineProperty(exports, "RequestTracker", { enumerable: true, get: function () { return RequestTracker_js_1.RequestTracker; } });
8
+ var tokenRefresh_js_1 = require("./tokenRefresh.js");
9
+ Object.defineProperty(exports, "calculateTokenRefreshTime", { enumerable: true, get: function () { return tokenRefresh_js_1.calculateTokenRefreshTime; } });
8
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAC9B,yDAAqD;AAA5C,mHAAA,cAAc,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAC9B,yDAAqD;AAA5C,mHAAA,cAAc,OAAA;AACvB,qDAA8D;AAArD,4HAAA,yBAAyB,OAAA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Calculate when to schedule proactive token refresh. Uses the later of:
3
+ *
4
+ * - 50% of token lifetime (protects short-lived tokens)
5
+ * - 2 minutes before expiry (ensures adequate buffer for longer tokens)
6
+ *
7
+ * Examples:
8
+ *
9
+ * - 60-second token: refresh at 30s (50% rule wins)
10
+ * - 5-minute token: refresh at 3min (2-min buffer wins)
11
+ * - 1-hour token: refresh at 58min (2-min buffer wins)
12
+ *
13
+ * @param issuedAt - Timestamp when token was issued (ms since epoch)
14
+ * @param expiresAt - Timestamp when token expires (ms since epoch)
15
+ * @returns Timestamp when refresh should be scheduled (ms since epoch)
16
+ */
17
+ export declare function calculateTokenRefreshTime(issuedAt: number, expiresAt: number): number;
18
+ //# sourceMappingURL=tokenRefresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenRefresh.d.ts","sourceRoot":"","sources":["../src/tokenRefresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,CAQR"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateTokenRefreshTime = calculateTokenRefreshTime;
4
+ /**
5
+ * Calculate when to schedule proactive token refresh. Uses the later of:
6
+ *
7
+ * - 50% of token lifetime (protects short-lived tokens)
8
+ * - 2 minutes before expiry (ensures adequate buffer for longer tokens)
9
+ *
10
+ * Examples:
11
+ *
12
+ * - 60-second token: refresh at 30s (50% rule wins)
13
+ * - 5-minute token: refresh at 3min (2-min buffer wins)
14
+ * - 1-hour token: refresh at 58min (2-min buffer wins)
15
+ *
16
+ * @param issuedAt - Timestamp when token was issued (ms since epoch)
17
+ * @param expiresAt - Timestamp when token expires (ms since epoch)
18
+ * @returns Timestamp when refresh should be scheduled (ms since epoch)
19
+ */
20
+ function calculateTokenRefreshTime(issuedAt, expiresAt) {
21
+ const lifetimeMs = expiresAt - issuedAt;
22
+ const twoMinutesMs = 2 * 60 * 1000;
23
+ const halfLifetime = issuedAt + Math.floor(lifetimeMs / 2);
24
+ const twoMinutesBefore = expiresAt - twoMinutesMs;
25
+ return Math.max(halfLifetime, twoMinutesBefore);
26
+ }
27
+ //# sourceMappingURL=tokenRefresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenRefresh.js","sourceRoot":"","sources":["../src/tokenRefresh.ts"],"names":[],"mappings":";;AAgBA,8DAWC;AA3BD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,yBAAyB,CACvC,QAAgB,EAChB,SAAiB;IAEjB,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAEnC,MAAM,YAAY,GAAG,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAC3D,MAAM,gBAAgB,GAAG,SAAS,GAAG,YAAY,CAAC;IAElD,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;AAClD,CAAC"}
package/dist/types.d.ts CHANGED
@@ -18,6 +18,14 @@ export interface HeartbeatOptions {
18
18
  /** Time to wait for pong before terminating. Default: 10000 */
19
19
  timeoutMs?: number;
20
20
  }
21
+ /**
22
+ * Auth configuration. Token is fetched on each connection (initial and reconnects),
23
+ * so reconnects automatically pick up a fresh token.
24
+ */
25
+ export interface AuthOptions {
26
+ /** Returns a bearer token. Called on every connect and reconnect. */
27
+ getToken: () => Promise<string> | string;
28
+ }
21
29
  /**
22
30
  * Configuration options for ReconnectingWebSocket.
23
31
  */
@@ -28,6 +36,12 @@ export interface WebSocketOptions {
28
36
  backoff?: BackoffOptions;
29
37
  /** Heartbeat configuration */
30
38
  heartbeat?: HeartbeatOptions;
39
+ /** Auth configuration. Token is added as an Authorization header on each connect. */
40
+ auth?: AuthOptions;
41
+ /** WebSocket subprotocols. */
42
+ protocols?: string[];
43
+ /** Additional headers for the WebSocket handshake. */
44
+ headers?: Record<string, string>;
31
45
  }
32
46
  /**
33
47
  * Event callbacks for ReconnectingWebSocket.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,0CAA0C;IAC1C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,0CAA0C;IAC1C,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,kDAAkD;IAClD,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,2DAA2D;IAC3D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,qFAAqF;IACrF,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,0CAA0C;IAC1C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,0CAA0C;IAC1C,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,kDAAkD;IAClD,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,2DAA2D;IAC3D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardlydifficult/websocket",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [