@neta-art/cohub 2.14.0 → 2.14.1
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.
|
@@ -2411,7 +2411,9 @@ type WebsocketClientOptions = {
|
|
|
2411
2411
|
pingIntervalMs?: number;
|
|
2412
2412
|
pongTimeoutMs?: number;
|
|
2413
2413
|
debug?: boolean;
|
|
2414
|
-
getAccessToken?: (
|
|
2414
|
+
getAccessToken?: (options?: {
|
|
2415
|
+
forceRefresh?: boolean;
|
|
2416
|
+
}) => Promise<string | null> | string | null;
|
|
2415
2417
|
WebSocketImpl?: WebSocketConstructor;
|
|
2416
2418
|
};
|
|
2417
2419
|
type WebsocketClientState = "idle" | "connecting" | "reconnecting" | "open" | "closed";
|
|
@@ -2496,6 +2498,9 @@ declare class WebsocketClient {
|
|
|
2496
2498
|
private reconnectTimer;
|
|
2497
2499
|
private reconnectTimerResolver;
|
|
2498
2500
|
private reconnectAttempt;
|
|
2501
|
+
private authReconnectAttempted;
|
|
2502
|
+
private forceRefreshOnNextAuth;
|
|
2503
|
+
private retryAuthClose;
|
|
2499
2504
|
private manuallyClosed;
|
|
2500
2505
|
private connectPromise;
|
|
2501
2506
|
private authWaiter;
|
package/dist/chunks/websocket.js
CHANGED
|
@@ -66,12 +66,13 @@ const normalizeOptions = (options = {}) => ({
|
|
|
66
66
|
debug: options.debug === true
|
|
67
67
|
});
|
|
68
68
|
const formatCloseMessage = (code, reason) => `WebSocket closed: ${code ?? 0} ${reason || ""}`.trim();
|
|
69
|
+
const AUTH_CLOSE_CODE = 4003;
|
|
70
|
+
const AUTH_CLOSE_REASON = "authentication failed";
|
|
69
71
|
const isRetryableCloseCode = (code) => {
|
|
70
72
|
if (code === 1e3) return false;
|
|
71
|
-
if (code ===
|
|
73
|
+
if (code === AUTH_CLOSE_CODE) return false;
|
|
72
74
|
return true;
|
|
73
75
|
};
|
|
74
|
-
const AUTH_CLOSE_REASON = "authentication failed";
|
|
75
76
|
const PATCH_STREAM_BUFFER_MAX_PENDING = 128;
|
|
76
77
|
const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
77
78
|
const isRealtimeCompactFrame = (value) => {
|
|
@@ -144,6 +145,9 @@ var WebsocketClient = class {
|
|
|
144
145
|
reconnectTimer = null;
|
|
145
146
|
reconnectTimerResolver = null;
|
|
146
147
|
reconnectAttempt = 0;
|
|
148
|
+
authReconnectAttempted = false;
|
|
149
|
+
forceRefreshOnNextAuth = false;
|
|
150
|
+
retryAuthClose = false;
|
|
147
151
|
manuallyClosed = false;
|
|
148
152
|
connectPromise = null;
|
|
149
153
|
authWaiter = null;
|
|
@@ -223,12 +227,18 @@ var WebsocketClient = class {
|
|
|
223
227
|
resolveOnce();
|
|
224
228
|
} catch (error) {
|
|
225
229
|
const authError = error instanceof Error ? error : /* @__PURE__ */ new Error("authentication failed");
|
|
230
|
+
const recoverable = Boolean(this.getAccessToken && this.autoReconnect && !this.manuallyClosed && !this.authReconnectAttempted);
|
|
231
|
+
this.retryAuthClose = recoverable;
|
|
232
|
+
if (recoverable) {
|
|
233
|
+
this.authReconnectAttempted = true;
|
|
234
|
+
this.forceRefreshOnNextAuth = true;
|
|
235
|
+
}
|
|
226
236
|
this.emit("error", {
|
|
227
237
|
error: authError,
|
|
228
|
-
recoverable
|
|
238
|
+
recoverable
|
|
229
239
|
});
|
|
230
240
|
rejectOnce(authError);
|
|
231
|
-
ws.close(
|
|
241
|
+
ws.close(AUTH_CLOSE_CODE, AUTH_CLOSE_REASON);
|
|
232
242
|
}
|
|
233
243
|
};
|
|
234
244
|
ws.onmessage = (event) => {
|
|
@@ -249,7 +259,9 @@ var WebsocketClient = class {
|
|
|
249
259
|
this.patchStreamBuffers.clear();
|
|
250
260
|
const closeError = new Error(formatCloseMessage(event.code, event.reason));
|
|
251
261
|
this.rejectAuthWaiter(closeError);
|
|
252
|
-
const
|
|
262
|
+
const retryAuthClose = event.code === AUTH_CLOSE_CODE && this.retryAuthClose;
|
|
263
|
+
this.retryAuthClose = false;
|
|
264
|
+
const willReconnect = !this.manuallyClosed && this.autoReconnect && (retryAuthClose || isRetryableCloseCode(event.code));
|
|
253
265
|
this.log("closed", {
|
|
254
266
|
code: event.code,
|
|
255
267
|
reason: event.reason,
|
|
@@ -276,6 +288,9 @@ var WebsocketClient = class {
|
|
|
276
288
|
this.ws?.close(code, reason);
|
|
277
289
|
this.ws = null;
|
|
278
290
|
this.connectPromise = null;
|
|
291
|
+
this.authReconnectAttempted = false;
|
|
292
|
+
this.forceRefreshOnNextAuth = false;
|
|
293
|
+
this.retryAuthClose = false;
|
|
279
294
|
this.compactStreamContexts.clear();
|
|
280
295
|
this.patchStreamBuffers.clear();
|
|
281
296
|
for (const state of this.roomSubscriptions.values()) {
|
|
@@ -399,7 +414,9 @@ var WebsocketClient = class {
|
|
|
399
414
|
ws.send(JSON.stringify(event));
|
|
400
415
|
}
|
|
401
416
|
async authenticate() {
|
|
402
|
-
const
|
|
417
|
+
const forceRefresh = this.forceRefreshOnNextAuth;
|
|
418
|
+
this.forceRefreshOnNextAuth = false;
|
|
419
|
+
const token = this.getAccessToken ? await this.getAccessToken(forceRefresh ? { forceRefresh: true } : void 0) : null;
|
|
403
420
|
if (!token) throw new WebsocketAuthError("missing access token");
|
|
404
421
|
const waiter = this.createAuthWaiter();
|
|
405
422
|
this.send({
|
|
@@ -411,6 +428,7 @@ var WebsocketClient = class {
|
|
|
411
428
|
});
|
|
412
429
|
await waiter.promise;
|
|
413
430
|
await this.restoreRoomSubscriptions();
|
|
431
|
+
this.authReconnectAttempted = false;
|
|
414
432
|
}
|
|
415
433
|
flushRoomSubscriptions() {
|
|
416
434
|
if (this.ws?.readyState !== WebSocket.OPEN) return;
|
|
@@ -808,7 +826,7 @@ var WebsocketClient = class {
|
|
|
808
826
|
await this.connect().catch((error) => {
|
|
809
827
|
this.emit("error", {
|
|
810
828
|
error,
|
|
811
|
-
recoverable:
|
|
829
|
+
recoverable: this.state === "reconnecting"
|
|
812
830
|
});
|
|
813
831
|
});
|
|
814
832
|
}
|