hume 0.10.4-beta.2 → 0.10.4-beta.3

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.
@@ -75,15 +75,9 @@ class ChatSocket {
75
75
  (_b = (_a = this.eventHandlers).close) === null || _b === void 0 ? void 0 : _b.call(_a, event);
76
76
  };
77
77
  this.handleError = (event) => {
78
- var _a, _b, _c, _d, _e, _f;
79
- try {
80
- const message = (_a = event.message) !== null && _a !== void 0 ? _a : `core.ReconnectingWebSocket error (${JSON.stringify(event)})`;
81
- (_c = (_b = this.eventHandlers).error) === null || _c === void 0 ? void 0 : _c.call(_b, new Error(message));
82
- }
83
- catch (_g) {
84
- const message = (_d = event.message) !== null && _d !== void 0 ? _d : `core.ReconnectingWebSocket error (unable to stringify)`;
85
- (_f = (_e = this.eventHandlers).error) === null || _f === void 0 ? void 0 : _f.call(_e, new Error(message));
86
- }
78
+ var _a, _b;
79
+ // Create and dispatch a new Error object using the message from the standardized event.
80
+ (_b = (_a = this.eventHandlers).error) === null || _b === void 0 ? void 0 : _b.call(_a, new Error(event.message));
87
81
  };
88
82
  this.socket = socket;
89
83
  this.socket.addEventListener("open", this.handleOpen);
@@ -121,6 +121,15 @@ export declare class ReconnectingWebSocket {
121
121
  private _getNextDelay;
122
122
  private _wait;
123
123
  private _getNextUrl;
124
+ /**
125
+ * Handles the final "tear down" process when connection attempts must permanently stop
126
+ * (e.g., max retries reached, fatal configuration error).
127
+ * Releases locks, disables reconnection, dispatches final error and close events.
128
+ *
129
+ * @param error - The specific Error instance indicating the reason for termination.
130
+ * @param closeReason - The reason string to use for the final CloseEvent.
131
+ */
132
+ private _shutdown;
124
133
  private _connect;
125
134
  private _handleTimeout;
126
135
  private _disconnect;
@@ -128,7 +137,28 @@ export declare class ReconnectingWebSocket {
128
137
  private _callEventListener;
129
138
  private _handleOpen;
130
139
  private _handleMessage;
140
+ /**
141
+ * Adapts a raw error or event input into a standardized `Events.ErrorEvent`.
142
+ * This utility is called by `_handleError` to ensure it operates on a
143
+ * consistent error structure.
144
+ * @param rawErrorOrEventInput - The raw error data (e.g., Error instance, DOM Event, Events.ErrorEvent).
145
+ * @returns A standardized `Events.ErrorEvent` containing an underlying `Error` instance.
146
+ */
147
+ private _adaptError;
148
+ /**
149
+ * Core handler for all errors. It first standardizes the error input using `_adaptError`,
150
+ * then manages disconnection, dispatches the standardized error event, and initiates reconnection.
151
+ * @param rawErrorOrEventInput - The error data from any internal source.
152
+ */
131
153
  private _handleError;
154
+ /**
155
+ * Handles WebSocket close events, either native or synthesized internally.
156
+ *
157
+ * Adapts the event if necessary, manages state, dispatches standardized close events,
158
+ * and initiates reconnection if appropriate.
159
+ *
160
+ * @param eventInfo - Either an internal Events.CloseEvent or a native DOM CloseEvent.
161
+ */
132
162
  private _handleClose;
133
163
  private _removeListeners;
134
164
  private _addListeners;
@@ -38,6 +38,7 @@ exports.ReconnectingWebSocket = void 0;
38
38
  const runtime_1 = require("../runtime");
39
39
  const Events = __importStar(require("./events"));
40
40
  const ws_1 = require("ws");
41
+ const ABNORMAL_CLOSURE_CODE = 1006;
41
42
  const getGlobalWebSocket = () => {
42
43
  if (typeof WebSocket !== "undefined") {
43
44
  // @ts-ignore
@@ -115,33 +116,70 @@ class ReconnectingWebSocket {
115
116
  }
116
117
  this._listeners.message.forEach((listener) => this._callEventListener(event, listener));
117
118
  };
118
- this._handleError = (event) => {
119
- this._debug("error event", event.message);
120
- this._disconnect(undefined, event.message === "TIMEOUT" ? "timeout" : undefined);
121
- if (this.onerror) {
122
- this.onerror(event);
123
- }
119
+ /**
120
+ * Core handler for all errors. It first standardizes the error input using `_adaptError`,
121
+ * then manages disconnection, dispatches the standardized error event, and initiates reconnection.
122
+ * @param rawErrorOrEventInput - The error data from any internal source.
123
+ */
124
+ this._handleError = (rawErrorOrEventInput) => {
125
+ this._debug("Raw error/event received by _handleError, passing to _adaptError:", rawErrorOrEventInput);
126
+ const adaptedError = this._adaptError(rawErrorOrEventInput);
127
+ const { error, message } = adaptedError;
128
+ // Close with abnormal closure code so _handleClose will reconnect if there's a socket
129
+ this._disconnect(ABNORMAL_CLOSURE_CODE, message);
130
+ this._debug("Processed error. Dispatching Event:", message, error);
131
+ if (this.onerror)
132
+ this.onerror(adaptedError);
124
133
  this._debug("exec error listeners");
125
- this._listeners.error.forEach((listener) => this._callEventListener(event, listener));
126
- this._connect();
134
+ this._listeners.error.forEach((listener) => this._callEventListener(adaptedError, listener));
135
+ // If we never even got a ws instance, _disconnect returned early so we need to explicitly retry here
136
+ if (!this._ws && this._shouldReconnect) {
137
+ this._debug("Error before socket created; scheduling initial reconnect.");
138
+ this._connect();
139
+ }
127
140
  };
141
+ /**
142
+ * Handles WebSocket close events, either native or synthesized internally.
143
+ *
144
+ * Adapts the event if necessary, manages state, dispatches standardized close events,
145
+ * and initiates reconnection if appropriate.
146
+ *
147
+ * @param eventInfo - Either an internal Events.CloseEvent or a native DOM CloseEvent.
148
+ */
128
149
  this._handleClose = (event) => {
129
- this._debug("close event");
150
+ this._debug("Raw close event received by _handleClose:", event);
151
+ // Adapt event if event is an instance of the (browser) native CloseEvent
152
+ const isNativeCloseEvent = typeof CloseEvent !== "undefined" && event instanceof CloseEvent;
153
+ const adaptedEvent = isNativeCloseEvent
154
+ ? new Events.CloseEvent(event.code, event.reason, this)
155
+ : event;
156
+ // Clean up state
130
157
  this._clearTimeouts();
131
- if (event.code === 1000) {
158
+ this._ws = undefined;
159
+ this._connectLock = false;
160
+ // Determine reconnection intent
161
+ if (this._closeCalled) {
132
162
  this._shouldReconnect = false;
163
+ this._debug("Reconnection stopped: RWS.close() was called.");
133
164
  }
134
- if (this._shouldReconnect) {
135
- this._connect();
136
- }
137
- if (this.onclose) {
138
- this.onclose(event);
165
+ else if (adaptedEvent.code === 1000) {
166
+ this._shouldReconnect = false;
167
+ this._debug("Reconnection stopped: Received close code 1000 (intentional server close).");
139
168
  }
140
- this._listeners.close.forEach((listener) => this._callEventListener(event, listener));
169
+ // Dispatch event to listeners
170
+ if (this.onclose)
171
+ this.onclose(adaptedEvent);
172
+ this._listeners.close.forEach((listener) => this._callEventListener(adaptedEvent, listener));
173
+ // Conditionally attempt reconnection
174
+ if (this._shouldReconnect)
175
+ this._connect();
141
176
  };
142
177
  this._url = url;
143
178
  this._protocols = protocols;
144
179
  this._options = options;
180
+ if (!isWebSocket(this._options.WebSocket)) {
181
+ throw Error("No valid WebSocket class provided");
182
+ }
145
183
  if (this._options.startClosed) {
146
184
  this._shouldReconnect = false;
147
185
  }
@@ -267,8 +305,8 @@ class ReconnectingWebSocket {
267
305
  this._connect();
268
306
  }
269
307
  else {
308
+ // If the socket is already connected then disconnect. The socket will conditionally reconnected in _handleClose
270
309
  this._disconnect(code, reason);
271
- this._connect();
272
310
  }
273
311
  }
274
312
  /**
@@ -356,35 +394,73 @@ class ReconnectingWebSocket {
356
394
  }
357
395
  throw Error("Invalid URL");
358
396
  }
397
+ /**
398
+ * Handles the final "tear down" process when connection attempts must permanently stop
399
+ * (e.g., max retries reached, fatal configuration error).
400
+ * Releases locks, disables reconnection, dispatches final error and close events.
401
+ *
402
+ * @param error - The specific Error instance indicating the reason for termination.
403
+ * @param closeReason - The reason string to use for the final CloseEvent.
404
+ */
405
+ _shutdown(error, closeReason) {
406
+ this._debug("Terminating connection attempts. Reason:", error.message);
407
+ // Ensure state prevents further attempts
408
+ this._connectLock = false;
409
+ this._shouldReconnect = false;
410
+ // Dispatch error event
411
+ const errorEvent = this._adaptError(error);
412
+ if (this.onerror)
413
+ this.onerror(errorEvent);
414
+ this._listeners.error.forEach((listener) => this._callEventListener(errorEvent, listener));
415
+ // Dispatch close event
416
+ const closeEvent = new Events.CloseEvent(1000, closeReason, this);
417
+ if (this.onclose)
418
+ this.onclose(closeEvent);
419
+ this._listeners.close.forEach((listener) => this._callEventListener(closeEvent, listener));
420
+ }
359
421
  _connect() {
360
- if (this._connectLock || !this._shouldReconnect) {
422
+ // Check locks and intent
423
+ if (this._connectLock) {
424
+ this._debug("Connection attempt already in progress.");
425
+ return;
426
+ }
427
+ if (!this._shouldReconnect) {
428
+ this._debug("Reconnection disabled, skipping connect attempt.");
361
429
  return;
362
430
  }
431
+ // Set lock for this attempt
363
432
  this._connectLock = true;
364
433
  const { maxRetries = DEFAULT.maxRetries, connectionTimeout = DEFAULT.connectionTimeout, WebSocket = getGlobalWebSocket(), } = this._options;
434
+ // Max retries check
365
435
  if (this._retryCount >= maxRetries) {
366
- this._debug("max retries reached", this._retryCount, ">=", maxRetries);
436
+ this._shutdown(new Error(`Max retries (${maxRetries}) reached. Giving up.`), "Max retries reached");
367
437
  return;
368
438
  }
439
+ // Prepare connection attempt
369
440
  this._retryCount++;
370
441
  this._debug("connect", this._retryCount);
371
442
  this._removeListeners();
372
- if (!isWebSocket(WebSocket)) {
373
- throw Error("No valid WebSocket class provided");
374
- }
443
+ // Connection attempt
375
444
  this._wait()
376
445
  .then(() => this._getNextUrl(this._url))
377
446
  .then((url) => {
378
- // close could be called before creating the ws
447
+ // Close could be called before creating the ws
379
448
  if (this._closeCalled) {
449
+ this._connectLock = false;
450
+ this._debug("Connection cancelled: ReconnectingWebSocket.close() called during setup.");
380
451
  return;
381
452
  }
382
453
  this._debug("connect", { url, protocols: this._protocols });
383
454
  this._ws = this._protocols ? new WebSocket(url, this._protocols) : new WebSocket(url);
384
455
  this._ws.binaryType = this._binaryType;
385
- this._connectLock = false;
386
456
  this._addListeners();
457
+ this._connectLock = false;
387
458
  this._connectTimeout = setTimeout(() => this._handleTimeout(), connectionTimeout);
459
+ })
460
+ .catch((error) => {
461
+ this._debug("Connection setup failed:", error);
462
+ this._connectLock = false;
463
+ this._handleError(error);
388
464
  });
389
465
  }
390
466
  _handleTimeout() {
@@ -419,6 +495,32 @@ class ReconnectingWebSocket {
419
495
  listener(event);
420
496
  }
421
497
  }
498
+ /**
499
+ * Adapts a raw error or event input into a standardized `Events.ErrorEvent`.
500
+ * This utility is called by `_handleError` to ensure it operates on a
501
+ * consistent error structure.
502
+ * @param rawErrorOrEventInput - The raw error data (e.g., Error instance, DOM Event, Events.ErrorEvent).
503
+ * @returns A standardized `Events.ErrorEvent` containing an underlying `Error` instance.
504
+ */
505
+ _adaptError(rawErrorOrEventInput) {
506
+ this._debug("Adapting raw error/event via _adaptError:", rawErrorOrEventInput);
507
+ let underlyingError;
508
+ if (rawErrorOrEventInput instanceof Events.ErrorEvent && rawErrorOrEventInput.error instanceof Error) {
509
+ return rawErrorOrEventInput;
510
+ }
511
+ if (rawErrorOrEventInput instanceof Error) {
512
+ underlyingError = rawErrorOrEventInput;
513
+ }
514
+ else if (typeof Event !== "undefined" &&
515
+ rawErrorOrEventInput instanceof Event &&
516
+ rawErrorOrEventInput.type === "error") {
517
+ underlyingError = new Error("WebSocket low-level error occurred (see browser/runtime console for native event details).");
518
+ }
519
+ else {
520
+ underlyingError = new Error(`Unknown WebSocket error. Raw data: ${String(rawErrorOrEventInput !== null && rawErrorOrEventInput !== void 0 ? rawErrorOrEventInput : "undefined")}`);
521
+ }
522
+ return new Events.ErrorEvent(underlyingError, this);
523
+ }
422
524
  _removeListeners() {
423
525
  if (!this._ws) {
424
526
  return;
@@ -438,7 +540,6 @@ class ReconnectingWebSocket {
438
540
  this._ws.addEventListener("open", this._handleOpen);
439
541
  this._ws.addEventListener("close", this._handleClose);
440
542
  this._ws.addEventListener("message", this._handleMessage);
441
- // @ts-ignore
442
543
  this._ws.addEventListener("error", this._handleError);
443
544
  }
444
545
  _clearTimeouts() {
@@ -75,15 +75,9 @@ class ChatSocket {
75
75
  (_b = (_a = this.eventHandlers).close) === null || _b === void 0 ? void 0 : _b.call(_a, event);
76
76
  };
77
77
  this.handleError = (event) => {
78
- var _a, _b, _c, _d, _e, _f;
79
- try {
80
- const message = (_a = event.message) !== null && _a !== void 0 ? _a : `core.ReconnectingWebSocket error (${JSON.stringify(event)})`;
81
- (_c = (_b = this.eventHandlers).error) === null || _c === void 0 ? void 0 : _c.call(_b, new Error(message));
82
- }
83
- catch (_g) {
84
- const message = (_d = event.message) !== null && _d !== void 0 ? _d : `core.ReconnectingWebSocket error (unable to stringify)`;
85
- (_f = (_e = this.eventHandlers).error) === null || _f === void 0 ? void 0 : _f.call(_e, new Error(message));
86
- }
78
+ var _a, _b;
79
+ // Create and dispatch a new Error object using the message from the standardized event.
80
+ (_b = (_a = this.eventHandlers).error) === null || _b === void 0 ? void 0 : _b.call(_a, new Error(event.message));
87
81
  };
88
82
  this.socket = socket;
89
83
  this.socket.addEventListener("open", this.handleOpen);
@@ -121,6 +121,15 @@ export declare class ReconnectingWebSocket {
121
121
  private _getNextDelay;
122
122
  private _wait;
123
123
  private _getNextUrl;
124
+ /**
125
+ * Handles the final "tear down" process when connection attempts must permanently stop
126
+ * (e.g., max retries reached, fatal configuration error).
127
+ * Releases locks, disables reconnection, dispatches final error and close events.
128
+ *
129
+ * @param error - The specific Error instance indicating the reason for termination.
130
+ * @param closeReason - The reason string to use for the final CloseEvent.
131
+ */
132
+ private _shutdown;
124
133
  private _connect;
125
134
  private _handleTimeout;
126
135
  private _disconnect;
@@ -128,7 +137,28 @@ export declare class ReconnectingWebSocket {
128
137
  private _callEventListener;
129
138
  private _handleOpen;
130
139
  private _handleMessage;
140
+ /**
141
+ * Adapts a raw error or event input into a standardized `Events.ErrorEvent`.
142
+ * This utility is called by `_handleError` to ensure it operates on a
143
+ * consistent error structure.
144
+ * @param rawErrorOrEventInput - The raw error data (e.g., Error instance, DOM Event, Events.ErrorEvent).
145
+ * @returns A standardized `Events.ErrorEvent` containing an underlying `Error` instance.
146
+ */
147
+ private _adaptError;
148
+ /**
149
+ * Core handler for all errors. It first standardizes the error input using `_adaptError`,
150
+ * then manages disconnection, dispatches the standardized error event, and initiates reconnection.
151
+ * @param rawErrorOrEventInput - The error data from any internal source.
152
+ */
131
153
  private _handleError;
154
+ /**
155
+ * Handles WebSocket close events, either native or synthesized internally.
156
+ *
157
+ * Adapts the event if necessary, manages state, dispatches standardized close events,
158
+ * and initiates reconnection if appropriate.
159
+ *
160
+ * @param eventInfo - Either an internal Events.CloseEvent or a native DOM CloseEvent.
161
+ */
132
162
  private _handleClose;
133
163
  private _removeListeners;
134
164
  private _addListeners;
@@ -38,6 +38,7 @@ exports.ReconnectingWebSocket = void 0;
38
38
  const runtime_1 = require("../runtime");
39
39
  const Events = __importStar(require("./events"));
40
40
  const ws_1 = require("ws");
41
+ const ABNORMAL_CLOSURE_CODE = 1006;
41
42
  const getGlobalWebSocket = () => {
42
43
  if (typeof WebSocket !== "undefined") {
43
44
  // @ts-ignore
@@ -115,33 +116,70 @@ class ReconnectingWebSocket {
115
116
  }
116
117
  this._listeners.message.forEach((listener) => this._callEventListener(event, listener));
117
118
  };
118
- this._handleError = (event) => {
119
- this._debug("error event", event.message);
120
- this._disconnect(undefined, event.message === "TIMEOUT" ? "timeout" : undefined);
121
- if (this.onerror) {
122
- this.onerror(event);
123
- }
119
+ /**
120
+ * Core handler for all errors. It first standardizes the error input using `_adaptError`,
121
+ * then manages disconnection, dispatches the standardized error event, and initiates reconnection.
122
+ * @param rawErrorOrEventInput - The error data from any internal source.
123
+ */
124
+ this._handleError = (rawErrorOrEventInput) => {
125
+ this._debug("Raw error/event received by _handleError, passing to _adaptError:", rawErrorOrEventInput);
126
+ const adaptedError = this._adaptError(rawErrorOrEventInput);
127
+ const { error, message } = adaptedError;
128
+ // Close with abnormal closure code so _handleClose will reconnect if there's a socket
129
+ this._disconnect(ABNORMAL_CLOSURE_CODE, message);
130
+ this._debug("Processed error. Dispatching Event:", message, error);
131
+ if (this.onerror)
132
+ this.onerror(adaptedError);
124
133
  this._debug("exec error listeners");
125
- this._listeners.error.forEach((listener) => this._callEventListener(event, listener));
126
- this._connect();
134
+ this._listeners.error.forEach((listener) => this._callEventListener(adaptedError, listener));
135
+ // If we never even got a ws instance, _disconnect returned early so we need to explicitly retry here
136
+ if (!this._ws && this._shouldReconnect) {
137
+ this._debug("Error before socket created; scheduling initial reconnect.");
138
+ this._connect();
139
+ }
127
140
  };
141
+ /**
142
+ * Handles WebSocket close events, either native or synthesized internally.
143
+ *
144
+ * Adapts the event if necessary, manages state, dispatches standardized close events,
145
+ * and initiates reconnection if appropriate.
146
+ *
147
+ * @param eventInfo - Either an internal Events.CloseEvent or a native DOM CloseEvent.
148
+ */
128
149
  this._handleClose = (event) => {
129
- this._debug("close event");
150
+ this._debug("Raw close event received by _handleClose:", event);
151
+ // Adapt event if event is an instance of the (browser) native CloseEvent
152
+ const isNativeCloseEvent = typeof CloseEvent !== "undefined" && event instanceof CloseEvent;
153
+ const adaptedEvent = isNativeCloseEvent
154
+ ? new Events.CloseEvent(event.code, event.reason, this)
155
+ : event;
156
+ // Clean up state
130
157
  this._clearTimeouts();
131
- if (event.code === 1000) {
158
+ this._ws = undefined;
159
+ this._connectLock = false;
160
+ // Determine reconnection intent
161
+ if (this._closeCalled) {
132
162
  this._shouldReconnect = false;
163
+ this._debug("Reconnection stopped: RWS.close() was called.");
133
164
  }
134
- if (this._shouldReconnect) {
135
- this._connect();
136
- }
137
- if (this.onclose) {
138
- this.onclose(event);
165
+ else if (adaptedEvent.code === 1000) {
166
+ this._shouldReconnect = false;
167
+ this._debug("Reconnection stopped: Received close code 1000 (intentional server close).");
139
168
  }
140
- this._listeners.close.forEach((listener) => this._callEventListener(event, listener));
169
+ // Dispatch event to listeners
170
+ if (this.onclose)
171
+ this.onclose(adaptedEvent);
172
+ this._listeners.close.forEach((listener) => this._callEventListener(adaptedEvent, listener));
173
+ // Conditionally attempt reconnection
174
+ if (this._shouldReconnect)
175
+ this._connect();
141
176
  };
142
177
  this._url = url;
143
178
  this._protocols = protocols;
144
179
  this._options = options;
180
+ if (!isWebSocket(this._options.WebSocket)) {
181
+ throw Error("No valid WebSocket class provided");
182
+ }
145
183
  if (this._options.startClosed) {
146
184
  this._shouldReconnect = false;
147
185
  }
@@ -267,8 +305,8 @@ class ReconnectingWebSocket {
267
305
  this._connect();
268
306
  }
269
307
  else {
308
+ // If the socket is already connected then disconnect. The socket will conditionally reconnected in _handleClose
270
309
  this._disconnect(code, reason);
271
- this._connect();
272
310
  }
273
311
  }
274
312
  /**
@@ -356,35 +394,73 @@ class ReconnectingWebSocket {
356
394
  }
357
395
  throw Error("Invalid URL");
358
396
  }
397
+ /**
398
+ * Handles the final "tear down" process when connection attempts must permanently stop
399
+ * (e.g., max retries reached, fatal configuration error).
400
+ * Releases locks, disables reconnection, dispatches final error and close events.
401
+ *
402
+ * @param error - The specific Error instance indicating the reason for termination.
403
+ * @param closeReason - The reason string to use for the final CloseEvent.
404
+ */
405
+ _shutdown(error, closeReason) {
406
+ this._debug("Terminating connection attempts. Reason:", error.message);
407
+ // Ensure state prevents further attempts
408
+ this._connectLock = false;
409
+ this._shouldReconnect = false;
410
+ // Dispatch error event
411
+ const errorEvent = this._adaptError(error);
412
+ if (this.onerror)
413
+ this.onerror(errorEvent);
414
+ this._listeners.error.forEach((listener) => this._callEventListener(errorEvent, listener));
415
+ // Dispatch close event
416
+ const closeEvent = new Events.CloseEvent(1000, closeReason, this);
417
+ if (this.onclose)
418
+ this.onclose(closeEvent);
419
+ this._listeners.close.forEach((listener) => this._callEventListener(closeEvent, listener));
420
+ }
359
421
  _connect() {
360
- if (this._connectLock || !this._shouldReconnect) {
422
+ // Check locks and intent
423
+ if (this._connectLock) {
424
+ this._debug("Connection attempt already in progress.");
425
+ return;
426
+ }
427
+ if (!this._shouldReconnect) {
428
+ this._debug("Reconnection disabled, skipping connect attempt.");
361
429
  return;
362
430
  }
431
+ // Set lock for this attempt
363
432
  this._connectLock = true;
364
433
  const { maxRetries = DEFAULT.maxRetries, connectionTimeout = DEFAULT.connectionTimeout, WebSocket = getGlobalWebSocket(), } = this._options;
434
+ // Max retries check
365
435
  if (this._retryCount >= maxRetries) {
366
- this._debug("max retries reached", this._retryCount, ">=", maxRetries);
436
+ this._shutdown(new Error(`Max retries (${maxRetries}) reached. Giving up.`), "Max retries reached");
367
437
  return;
368
438
  }
439
+ // Prepare connection attempt
369
440
  this._retryCount++;
370
441
  this._debug("connect", this._retryCount);
371
442
  this._removeListeners();
372
- if (!isWebSocket(WebSocket)) {
373
- throw Error("No valid WebSocket class provided");
374
- }
443
+ // Connection attempt
375
444
  this._wait()
376
445
  .then(() => this._getNextUrl(this._url))
377
446
  .then((url) => {
378
- // close could be called before creating the ws
447
+ // Close could be called before creating the ws
379
448
  if (this._closeCalled) {
449
+ this._connectLock = false;
450
+ this._debug("Connection cancelled: ReconnectingWebSocket.close() called during setup.");
380
451
  return;
381
452
  }
382
453
  this._debug("connect", { url, protocols: this._protocols });
383
454
  this._ws = this._protocols ? new WebSocket(url, this._protocols) : new WebSocket(url);
384
455
  this._ws.binaryType = this._binaryType;
385
- this._connectLock = false;
386
456
  this._addListeners();
457
+ this._connectLock = false;
387
458
  this._connectTimeout = setTimeout(() => this._handleTimeout(), connectionTimeout);
459
+ })
460
+ .catch((error) => {
461
+ this._debug("Connection setup failed:", error);
462
+ this._connectLock = false;
463
+ this._handleError(error);
388
464
  });
389
465
  }
390
466
  _handleTimeout() {
@@ -419,6 +495,32 @@ class ReconnectingWebSocket {
419
495
  listener(event);
420
496
  }
421
497
  }
498
+ /**
499
+ * Adapts a raw error or event input into a standardized `Events.ErrorEvent`.
500
+ * This utility is called by `_handleError` to ensure it operates on a
501
+ * consistent error structure.
502
+ * @param rawErrorOrEventInput - The raw error data (e.g., Error instance, DOM Event, Events.ErrorEvent).
503
+ * @returns A standardized `Events.ErrorEvent` containing an underlying `Error` instance.
504
+ */
505
+ _adaptError(rawErrorOrEventInput) {
506
+ this._debug("Adapting raw error/event via _adaptError:", rawErrorOrEventInput);
507
+ let underlyingError;
508
+ if (rawErrorOrEventInput instanceof Events.ErrorEvent && rawErrorOrEventInput.error instanceof Error) {
509
+ return rawErrorOrEventInput;
510
+ }
511
+ if (rawErrorOrEventInput instanceof Error) {
512
+ underlyingError = rawErrorOrEventInput;
513
+ }
514
+ else if (typeof Event !== "undefined" &&
515
+ rawErrorOrEventInput instanceof Event &&
516
+ rawErrorOrEventInput.type === "error") {
517
+ underlyingError = new Error("WebSocket low-level error occurred (see browser/runtime console for native event details).");
518
+ }
519
+ else {
520
+ underlyingError = new Error(`Unknown WebSocket error. Raw data: ${String(rawErrorOrEventInput !== null && rawErrorOrEventInput !== void 0 ? rawErrorOrEventInput : "undefined")}`);
521
+ }
522
+ return new Events.ErrorEvent(underlyingError, this);
523
+ }
422
524
  _removeListeners() {
423
525
  if (!this._ws) {
424
526
  return;
@@ -438,7 +540,6 @@ class ReconnectingWebSocket {
438
540
  this._ws.addEventListener("open", this._handleOpen);
439
541
  this._ws.addEventListener("close", this._handleClose);
440
542
  this._ws.addEventListener("message", this._handleMessage);
441
- // @ts-ignore
442
543
  this._ws.addEventListener("error", this._handleError);
443
544
  }
444
545
  _clearTimeouts() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hume",
3
- "version": "0.10.4-beta.2",
3
+ "version": "0.10.4-beta.3",
4
4
  "private": false,
5
5
  "repository": "https://github.com/HumeAI/hume-typescript-sdk",
6
6
  "main": "./index.js",