@electric-sql/client 1.5.1 → 1.5.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.
@@ -504,6 +504,7 @@ var EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`;
504
504
  var LIVE_SSE_QUERY_PARAM = `live_sse`;
505
505
  var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
506
506
  var PAUSE_STREAM = `pause-stream`;
507
+ var SYSTEM_WAKE = `system-wake`;
507
508
  var LOG_MODE_QUERY_PARAM = `log`;
508
509
  var SUBSET_PARAM_WHERE = `subset__where`;
509
510
  var SUBSET_PARAM_LIMIT = `subset__limit`;
@@ -1177,7 +1178,7 @@ function canonicalShapeKey(url) {
1177
1178
  cleanUrl.searchParams.sort();
1178
1179
  return cleanUrl.toString();
1179
1180
  }
1180
- var _error, _fetchClient2, _sseFetchClient, _messageParser, _subscribers, _started, _state, _lastOffset, _liveCacheBuster, _lastSyncedAt, _isUpToDate, _isMidStream, _connected, _shapeHandle, _mode, _schema, _onError, _requestAbortController, _isRefreshing, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _messageChain, _snapshotTracker, _activeSnapshotRequests, _midStreamPromise, _midStreamPromiseResolver, _lastSeenCursor, _currentFetchUrl, _lastSseConnectionStartTime, _minSseConnectionDuration, _consecutiveShortSseConnections, _maxShortSseConnections, _sseFallbackToLongPolling, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _staleCacheBuster, _staleCacheRetryCount, _maxStaleCacheRetries, _ShapeStream_instances, replayMode_get, start_fn, requestShape_fn, constructUrl_fn, createAbortListener_fn, onInitialResponse_fn, onMessages_fn, fetchShape_fn, requestShapeLongPoll_fn, requestShapeSSE_fn, pause_fn, resume_fn, nextTick_fn, waitForStreamEnd_fn, publish_fn, sendErrorToSubscribers_fn, subscribeToVisibilityChanges_fn, reset_fn, buildSubsetBody_fn;
1181
+ var _error, _fetchClient2, _sseFetchClient, _messageParser, _subscribers, _started, _state, _lastOffset, _liveCacheBuster, _lastSyncedAt, _isUpToDate, _isMidStream, _connected, _shapeHandle, _mode, _schema, _onError, _requestAbortController, _isRefreshing, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _messageChain, _snapshotTracker, _activeSnapshotRequests, _midStreamPromise, _midStreamPromiseResolver, _lastSeenCursor, _currentFetchUrl, _lastSseConnectionStartTime, _minSseConnectionDuration, _consecutiveShortSseConnections, _maxShortSseConnections, _sseFallbackToLongPolling, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _unsubscribeFromWakeDetection, _staleCacheBuster, _staleCacheRetryCount, _maxStaleCacheRetries, _ShapeStream_instances, replayMode_get, start_fn, requestShape_fn, constructUrl_fn, createAbortListener_fn, onInitialResponse_fn, onMessages_fn, fetchShape_fn, requestShapeLongPoll_fn, requestShapeSSE_fn, pause_fn, resume_fn, nextTick_fn, waitForStreamEnd_fn, publish_fn, sendErrorToSubscribers_fn, hasBrowserVisibilityAPI_fn, subscribeToVisibilityChanges_fn, subscribeToWakeDetection_fn, reset_fn, buildSubsetBody_fn;
1181
1182
  var ShapeStream = class {
1182
1183
  constructor(options) {
1183
1184
  __privateAdd(this, _ShapeStream_instances);
@@ -1228,6 +1229,7 @@ var ShapeStream = class {
1228
1229
  __privateAdd(this, _sseBackoffMaxDelay, 5e3);
1229
1230
  // Maximum delay cap (ms)
1230
1231
  __privateAdd(this, _unsubscribeFromVisibilityChanges);
1232
+ __privateAdd(this, _unsubscribeFromWakeDetection);
1231
1233
  __privateAdd(this, _staleCacheBuster);
1232
1234
  // Cache buster set when stale CDN response detected, used on retry requests to bypass cache
1233
1235
  __privateAdd(this, _staleCacheRetryCount, 0);
@@ -1272,6 +1274,7 @@ var ShapeStream = class {
1272
1274
  ));
1273
1275
  __privateSet(this, _fetchClient2, createFetchWithConsumedMessages(__privateGet(this, _sseFetchClient)));
1274
1276
  __privateMethod(this, _ShapeStream_instances, subscribeToVisibilityChanges_fn).call(this);
1277
+ __privateMethod(this, _ShapeStream_instances, subscribeToWakeDetection_fn).call(this);
1275
1278
  }
1276
1279
  get shapeHandle() {
1277
1280
  return __privateGet(this, _shapeHandle);
@@ -1298,9 +1301,10 @@ var ShapeStream = class {
1298
1301
  };
1299
1302
  }
1300
1303
  unsubscribeAll() {
1301
- var _a;
1304
+ var _a, _b;
1302
1305
  __privateGet(this, _subscribers).clear();
1303
1306
  (_a = __privateGet(this, _unsubscribeFromVisibilityChanges)) == null ? void 0 : _a.call(this);
1307
+ (_b = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _b.call(this);
1304
1308
  }
1305
1309
  /** Unix time at which we last synced. Undefined when `isLoading` is true. */
1306
1310
  lastSyncedAt() {
@@ -1487,6 +1491,7 @@ _sseFallbackToLongPolling = new WeakMap();
1487
1491
  _sseBackoffBaseDelay = new WeakMap();
1488
1492
  _sseBackoffMaxDelay = new WeakMap();
1489
1493
  _unsubscribeFromVisibilityChanges = new WeakMap();
1494
+ _unsubscribeFromWakeDetection = new WeakMap();
1490
1495
  _staleCacheBuster = new WeakMap();
1491
1496
  _staleCacheRetryCount = new WeakMap();
1492
1497
  _maxStaleCacheRetries = new WeakMap();
@@ -1495,7 +1500,7 @@ replayMode_get = function() {
1495
1500
  return __privateGet(this, _lastSeenCursor) !== void 0;
1496
1501
  };
1497
1502
  start_fn = async function() {
1498
- var _a, _b, _c, _d, _e;
1503
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1499
1504
  __privateSet(this, _started, true);
1500
1505
  try {
1501
1506
  await __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
@@ -1521,17 +1526,20 @@ start_fn = async function() {
1521
1526
  }
1522
1527
  __privateSet(this, _connected, false);
1523
1528
  (_c = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _c.call(this);
1529
+ (_d = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _d.call(this);
1524
1530
  return;
1525
1531
  }
1526
1532
  if (err instanceof Error) {
1527
1533
  __privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, err);
1528
1534
  }
1529
1535
  __privateSet(this, _connected, false);
1530
- (_d = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _d.call(this);
1536
+ (_e = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _e.call(this);
1537
+ (_f = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _f.call(this);
1531
1538
  throw err;
1532
1539
  }
1533
1540
  __privateSet(this, _connected, false);
1534
- (_e = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _e.call(this);
1541
+ (_g = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _g.call(this);
1542
+ (_h = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _h.call(this);
1535
1543
  };
1536
1544
  requestShape_fn = async function() {
1537
1545
  var _a, _b;
@@ -1556,7 +1564,9 @@ requestShape_fn = async function() {
1556
1564
  resumingFromPause
1557
1565
  });
1558
1566
  } catch (e) {
1559
- if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && requestAbortController.signal.aborted && requestAbortController.signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
1567
+ const abortReason = requestAbortController.signal.reason;
1568
+ const isRestartAbort = requestAbortController.signal.aborted && (abortReason === FORCE_DISCONNECT_AND_REFRESH || abortReason === SYSTEM_WAKE);
1569
+ if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && isRestartAbort) {
1560
1570
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
1561
1571
  }
1562
1572
  if (e instanceof FetchBackoffAbortError) {
@@ -1985,8 +1995,11 @@ sendErrorToSubscribers_fn = function(error) {
1985
1995
  errorFn == null ? void 0 : errorFn(error);
1986
1996
  });
1987
1997
  };
1998
+ hasBrowserVisibilityAPI_fn = function() {
1999
+ return typeof document === `object` && typeof document.hidden === `boolean` && typeof document.addEventListener === `function`;
2000
+ };
1988
2001
  subscribeToVisibilityChanges_fn = function() {
1989
- if (typeof document === `object` && typeof document.hidden === `boolean` && typeof document.addEventListener === `function`) {
2002
+ if (__privateMethod(this, _ShapeStream_instances, hasBrowserVisibilityAPI_fn).call(this)) {
1990
2003
  const visibilityHandler = () => {
1991
2004
  if (document.hidden) {
1992
2005
  __privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
@@ -2000,6 +2013,44 @@ subscribeToVisibilityChanges_fn = function() {
2000
2013
  });
2001
2014
  }
2002
2015
  };
2016
+ /**
2017
+ * Detects system wake from sleep using timer gap detection.
2018
+ * When the system sleeps, setInterval timers are paused. On wake,
2019
+ * the elapsed wall-clock time since the last tick will be much larger
2020
+ * than the interval period, indicating the system was asleep.
2021
+ *
2022
+ * Only active in non-browser environments (Bun, Node.js) where
2023
+ * `document.visibilitychange` is not available. In browsers,
2024
+ * `#subscribeToVisibilityChanges` handles this instead. Without wake
2025
+ * detection, in-flight HTTP requests (long-poll or SSE) may hang until
2026
+ * the OS TCP timeout.
2027
+ */
2028
+ subscribeToWakeDetection_fn = function() {
2029
+ if (__privateMethod(this, _ShapeStream_instances, hasBrowserVisibilityAPI_fn).call(this)) return;
2030
+ const INTERVAL_MS = 2e3;
2031
+ const WAKE_THRESHOLD_MS = 4e3;
2032
+ let lastTickTime = Date.now();
2033
+ const timer = setInterval(() => {
2034
+ const now = Date.now();
2035
+ const elapsed = now - lastTickTime;
2036
+ lastTickTime = now;
2037
+ if (elapsed > INTERVAL_MS + WAKE_THRESHOLD_MS) {
2038
+ if (__privateGet(this, _state) === `active` && __privateGet(this, _requestAbortController)) {
2039
+ __privateSet(this, _isRefreshing, true);
2040
+ __privateGet(this, _requestAbortController).abort(SYSTEM_WAKE);
2041
+ queueMicrotask(() => {
2042
+ __privateSet(this, _isRefreshing, false);
2043
+ });
2044
+ }
2045
+ }
2046
+ }, INTERVAL_MS);
2047
+ if (typeof timer === `object` && `unref` in timer) {
2048
+ timer.unref();
2049
+ }
2050
+ __privateSet(this, _unsubscribeFromWakeDetection, () => {
2051
+ clearInterval(timer);
2052
+ });
2053
+ };
2003
2054
  /**
2004
2055
  * Resets the state of the stream, optionally with a provided
2005
2056
  * shape handle