@korajs/sync 0.1.3 → 0.1.4

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/dist/index.cjs CHANGED
@@ -642,8 +642,10 @@ var WebSocketTransport = class {
642
642
  errorHandler = null;
643
643
  serializer;
644
644
  WebSocketImpl;
645
+ connectTimeout;
645
646
  constructor(options) {
646
647
  this.serializer = options?.serializer ?? new JsonMessageSerializer();
648
+ this.connectTimeout = options?.connectTimeout ?? 1e4;
647
649
  if (options?.WebSocketImpl) {
648
650
  this.WebSocketImpl = options.WebSocketImpl;
649
651
  } else if (typeof globalThis.WebSocket !== "undefined") {
@@ -659,12 +661,38 @@ var WebSocketTransport = class {
659
661
  });
660
662
  }
661
663
  return new Promise((resolve, reject) => {
664
+ let settled = false;
665
+ const settle = (fn) => {
666
+ if (settled) return;
667
+ settled = true;
668
+ clearTimeout(timer);
669
+ fn();
670
+ };
671
+ const timer = setTimeout(() => {
672
+ settle(() => {
673
+ const err = new import_core2.SyncError("WebSocket connection timed out", {
674
+ url,
675
+ timeout: this.connectTimeout
676
+ });
677
+ if (this.ws) {
678
+ try {
679
+ this.ws.onclose = null;
680
+ this.ws.onerror = null;
681
+ this.ws.close();
682
+ } catch {
683
+ }
684
+ this.ws = null;
685
+ }
686
+ this.errorHandler?.(err);
687
+ reject(err);
688
+ });
689
+ }, this.connectTimeout);
662
690
  try {
663
691
  const connectUrl = options?.authToken ? `${url}${url.includes("?") ? "&" : "?"}token=${encodeURIComponent(options.authToken)}` : url;
664
692
  const ws = new this.WebSocketImpl(connectUrl);
665
693
  this.ws = ws;
666
694
  ws.onopen = () => {
667
- resolve();
695
+ settle(() => resolve());
668
696
  };
669
697
  ws.onmessage = (event) => {
670
698
  try {
@@ -688,15 +716,17 @@ var WebSocketTransport = class {
688
716
  this.errorHandler?.(err);
689
717
  if (!this.isConnected()) {
690
718
  this.ws = null;
691
- reject(err);
719
+ settle(() => reject(err));
692
720
  }
693
721
  };
694
722
  } catch (err) {
695
- reject(
696
- err instanceof import_core2.SyncError ? err : new import_core2.SyncError("Failed to create WebSocket", {
697
- url,
698
- error: String(err)
699
- })
723
+ settle(
724
+ () => reject(
725
+ err instanceof import_core2.SyncError ? err : new import_core2.SyncError("Failed to create WebSocket", {
726
+ url,
727
+ error: String(err)
728
+ })
729
+ )
700
730
  );
701
731
  }
702
732
  });
@@ -1257,8 +1287,7 @@ var SyncEngine = class {
1257
1287
  };
1258
1288
  this.transport.send(handshake);
1259
1289
  } catch (err) {
1260
- this.transitionTo("error");
1261
- this.transitionTo("disconnected");
1290
+ this.ensureDisconnected();
1262
1291
  throw err;
1263
1292
  }
1264
1293
  }
@@ -1620,6 +1649,7 @@ var ReconnectionManager = class {
1620
1649
  attempt = 0;
1621
1650
  timer = null;
1622
1651
  stopped = false;
1652
+ running = false;
1623
1653
  waitResolve = null;
1624
1654
  constructor(config) {
1625
1655
  this.initialDelay = config?.initialDelay ?? 1e3;
@@ -1637,25 +1667,30 @@ var ReconnectionManager = class {
1637
1667
  */
1638
1668
  async start(onReconnect) {
1639
1669
  this.stopped = false;
1670
+ this.running = true;
1640
1671
  this.attempt = 0;
1641
- while (!this.stopped) {
1642
- if (this.maxAttempts > 0 && this.attempt >= this.maxAttempts) {
1643
- return false;
1644
- }
1645
- const delay = this.getNextDelay();
1646
- this.attempt++;
1647
- await this.wait(delay);
1648
- if (this.stopped) return false;
1649
- try {
1650
- const success = await onReconnect();
1651
- if (success) {
1652
- this.reset();
1653
- return true;
1672
+ try {
1673
+ while (!this.stopped) {
1674
+ if (this.maxAttempts > 0 && this.attempt >= this.maxAttempts) {
1675
+ return false;
1676
+ }
1677
+ const delay = this.getNextDelay();
1678
+ this.attempt++;
1679
+ await this.wait(delay);
1680
+ if (this.stopped) return false;
1681
+ try {
1682
+ const success = await onReconnect();
1683
+ if (success) {
1684
+ this.reset();
1685
+ return true;
1686
+ }
1687
+ } catch {
1654
1688
  }
1655
- } catch {
1656
1689
  }
1690
+ return false;
1691
+ } finally {
1692
+ this.running = false;
1657
1693
  }
1658
- return false;
1659
1694
  }
1660
1695
  /**
1661
1696
  * Stop any pending reconnection attempt.
@@ -1688,6 +1723,12 @@ var ReconnectionManager = class {
1688
1723
  const jitterOffset = (this.random() - 0.5) * 2 * jitterRange;
1689
1724
  return Math.max(0, Math.round(baseDelay + jitterOffset));
1690
1725
  }
1726
+ /**
1727
+ * Whether the reconnection loop is currently running.
1728
+ */
1729
+ isRunning() {
1730
+ return this.running;
1731
+ }
1691
1732
  /**
1692
1733
  * Current attempt number (for testing).
1693
1734
  */