@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.
package/dist/index.mjs CHANGED
@@ -467,6 +467,7 @@ var EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`;
467
467
  var LIVE_SSE_QUERY_PARAM = `live_sse`;
468
468
  var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
469
469
  var PAUSE_STREAM = `pause-stream`;
470
+ var SYSTEM_WAKE = `system-wake`;
470
471
  var LOG_MODE_QUERY_PARAM = `log`;
471
472
  var SUBSET_PARAM_WHERE = `subset__where`;
472
473
  var SUBSET_PARAM_LIMIT = `subset__limit`;
@@ -1142,7 +1143,7 @@ function canonicalShapeKey(url) {
1142
1143
  cleanUrl.searchParams.sort();
1143
1144
  return cleanUrl.toString();
1144
1145
  }
1145
- 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;
1146
+ 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;
1146
1147
  var ShapeStream = class {
1147
1148
  constructor(options) {
1148
1149
  __privateAdd(this, _ShapeStream_instances);
@@ -1193,6 +1194,7 @@ var ShapeStream = class {
1193
1194
  __privateAdd(this, _sseBackoffMaxDelay, 5e3);
1194
1195
  // Maximum delay cap (ms)
1195
1196
  __privateAdd(this, _unsubscribeFromVisibilityChanges);
1197
+ __privateAdd(this, _unsubscribeFromWakeDetection);
1196
1198
  __privateAdd(this, _staleCacheBuster);
1197
1199
  // Cache buster set when stale CDN response detected, used on retry requests to bypass cache
1198
1200
  __privateAdd(this, _staleCacheRetryCount, 0);
@@ -1237,6 +1239,7 @@ var ShapeStream = class {
1237
1239
  ));
1238
1240
  __privateSet(this, _fetchClient2, createFetchWithConsumedMessages(__privateGet(this, _sseFetchClient)));
1239
1241
  __privateMethod(this, _ShapeStream_instances, subscribeToVisibilityChanges_fn).call(this);
1242
+ __privateMethod(this, _ShapeStream_instances, subscribeToWakeDetection_fn).call(this);
1240
1243
  }
1241
1244
  get shapeHandle() {
1242
1245
  return __privateGet(this, _shapeHandle);
@@ -1263,9 +1266,10 @@ var ShapeStream = class {
1263
1266
  };
1264
1267
  }
1265
1268
  unsubscribeAll() {
1266
- var _a;
1269
+ var _a, _b;
1267
1270
  __privateGet(this, _subscribers).clear();
1268
1271
  (_a = __privateGet(this, _unsubscribeFromVisibilityChanges)) == null ? void 0 : _a.call(this);
1272
+ (_b = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _b.call(this);
1269
1273
  }
1270
1274
  /** Unix time at which we last synced. Undefined when `isLoading` is true. */
1271
1275
  lastSyncedAt() {
@@ -1452,6 +1456,7 @@ _sseFallbackToLongPolling = new WeakMap();
1452
1456
  _sseBackoffBaseDelay = new WeakMap();
1453
1457
  _sseBackoffMaxDelay = new WeakMap();
1454
1458
  _unsubscribeFromVisibilityChanges = new WeakMap();
1459
+ _unsubscribeFromWakeDetection = new WeakMap();
1455
1460
  _staleCacheBuster = new WeakMap();
1456
1461
  _staleCacheRetryCount = new WeakMap();
1457
1462
  _maxStaleCacheRetries = new WeakMap();
@@ -1460,7 +1465,7 @@ replayMode_get = function() {
1460
1465
  return __privateGet(this, _lastSeenCursor) !== void 0;
1461
1466
  };
1462
1467
  start_fn = async function() {
1463
- var _a, _b, _c, _d, _e;
1468
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1464
1469
  __privateSet(this, _started, true);
1465
1470
  try {
1466
1471
  await __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
@@ -1486,17 +1491,20 @@ start_fn = async function() {
1486
1491
  }
1487
1492
  __privateSet(this, _connected, false);
1488
1493
  (_c = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _c.call(this);
1494
+ (_d = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _d.call(this);
1489
1495
  return;
1490
1496
  }
1491
1497
  if (err instanceof Error) {
1492
1498
  __privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, err);
1493
1499
  }
1494
1500
  __privateSet(this, _connected, false);
1495
- (_d = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _d.call(this);
1501
+ (_e = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _e.call(this);
1502
+ (_f = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _f.call(this);
1496
1503
  throw err;
1497
1504
  }
1498
1505
  __privateSet(this, _connected, false);
1499
- (_e = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _e.call(this);
1506
+ (_g = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _g.call(this);
1507
+ (_h = __privateGet(this, _unsubscribeFromWakeDetection)) == null ? void 0 : _h.call(this);
1500
1508
  };
1501
1509
  requestShape_fn = async function() {
1502
1510
  var _a, _b;
@@ -1521,7 +1529,9 @@ requestShape_fn = async function() {
1521
1529
  resumingFromPause
1522
1530
  });
1523
1531
  } catch (e) {
1524
- if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && requestAbortController.signal.aborted && requestAbortController.signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
1532
+ const abortReason = requestAbortController.signal.reason;
1533
+ const isRestartAbort = requestAbortController.signal.aborted && (abortReason === FORCE_DISCONNECT_AND_REFRESH || abortReason === SYSTEM_WAKE);
1534
+ if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && isRestartAbort) {
1525
1535
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
1526
1536
  }
1527
1537
  if (e instanceof FetchBackoffAbortError) {
@@ -1950,8 +1960,11 @@ sendErrorToSubscribers_fn = function(error) {
1950
1960
  errorFn == null ? void 0 : errorFn(error);
1951
1961
  });
1952
1962
  };
1963
+ hasBrowserVisibilityAPI_fn = function() {
1964
+ return typeof document === `object` && typeof document.hidden === `boolean` && typeof document.addEventListener === `function`;
1965
+ };
1953
1966
  subscribeToVisibilityChanges_fn = function() {
1954
- if (typeof document === `object` && typeof document.hidden === `boolean` && typeof document.addEventListener === `function`) {
1967
+ if (__privateMethod(this, _ShapeStream_instances, hasBrowserVisibilityAPI_fn).call(this)) {
1955
1968
  const visibilityHandler = () => {
1956
1969
  if (document.hidden) {
1957
1970
  __privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
@@ -1965,6 +1978,44 @@ subscribeToVisibilityChanges_fn = function() {
1965
1978
  });
1966
1979
  }
1967
1980
  };
1981
+ /**
1982
+ * Detects system wake from sleep using timer gap detection.
1983
+ * When the system sleeps, setInterval timers are paused. On wake,
1984
+ * the elapsed wall-clock time since the last tick will be much larger
1985
+ * than the interval period, indicating the system was asleep.
1986
+ *
1987
+ * Only active in non-browser environments (Bun, Node.js) where
1988
+ * `document.visibilitychange` is not available. In browsers,
1989
+ * `#subscribeToVisibilityChanges` handles this instead. Without wake
1990
+ * detection, in-flight HTTP requests (long-poll or SSE) may hang until
1991
+ * the OS TCP timeout.
1992
+ */
1993
+ subscribeToWakeDetection_fn = function() {
1994
+ if (__privateMethod(this, _ShapeStream_instances, hasBrowserVisibilityAPI_fn).call(this)) return;
1995
+ const INTERVAL_MS = 2e3;
1996
+ const WAKE_THRESHOLD_MS = 4e3;
1997
+ let lastTickTime = Date.now();
1998
+ const timer = setInterval(() => {
1999
+ const now = Date.now();
2000
+ const elapsed = now - lastTickTime;
2001
+ lastTickTime = now;
2002
+ if (elapsed > INTERVAL_MS + WAKE_THRESHOLD_MS) {
2003
+ if (__privateGet(this, _state) === `active` && __privateGet(this, _requestAbortController)) {
2004
+ __privateSet(this, _isRefreshing, true);
2005
+ __privateGet(this, _requestAbortController).abort(SYSTEM_WAKE);
2006
+ queueMicrotask(() => {
2007
+ __privateSet(this, _isRefreshing, false);
2008
+ });
2009
+ }
2010
+ }
2011
+ }, INTERVAL_MS);
2012
+ if (typeof timer === `object` && `unref` in timer) {
2013
+ timer.unref();
2014
+ }
2015
+ __privateSet(this, _unsubscribeFromWakeDetection, () => {
2016
+ clearInterval(timer);
2017
+ });
2018
+ };
1968
2019
  /**
1969
2020
  * Resets the state of the stream, optionally with a provided
1970
2021
  * shape handle