@electric-sql/client 1.1.3 → 1.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/src/client.ts CHANGED
@@ -489,6 +489,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
489
489
  #sseFallbackToLongPolling = false
490
490
  #sseBackoffBaseDelay = 100 // Base delay for exponential backoff (ms)
491
491
  #sseBackoffMaxDelay = 5000 // Maximum delay cap (ms)
492
+ #unsubscribeFromVisibilityChanges?: () => void
492
493
 
493
494
  constructor(options: ShapeStreamOptions<GetExtensions<T>>) {
494
495
  this.options = { subscribe: true, ...options }
@@ -656,9 +657,17 @@ export class ShapeStream<T extends Row<unknown> = Row>
656
657
  }
657
658
 
658
659
  if (e instanceof FetchBackoffAbortError) {
660
+ // Check current state - it may have changed due to concurrent pause/resume calls
661
+ // from the visibility change handler during the async fetch operation.
662
+ // TypeScript's flow analysis doesn't account for concurrent state changes.
663
+ const currentState = this.#state as
664
+ | `active`
665
+ | `pause-requested`
666
+ | `paused`
659
667
  if (
660
668
  requestAbortController.signal.aborted &&
661
- requestAbortController.signal.reason === PAUSE_STREAM
669
+ requestAbortController.signal.reason === PAUSE_STREAM &&
670
+ currentState === `pause-requested`
662
671
  ) {
663
672
  this.#state = `paused`
664
673
  }
@@ -1045,7 +1054,15 @@ export class ShapeStream<T extends Row<unknown> = Row>
1045
1054
  }
1046
1055
 
1047
1056
  #resume() {
1048
- if (this.#started && this.#state === `paused`) {
1057
+ if (
1058
+ this.#started &&
1059
+ (this.#state === `paused` || this.#state === `pause-requested`)
1060
+ ) {
1061
+ // If we're resuming from pause-requested state, we need to set state back to active
1062
+ // to prevent the pause from completing
1063
+ if (this.#state === `pause-requested`) {
1064
+ this.#state = `active`
1065
+ }
1049
1066
  this.#start()
1050
1067
  }
1051
1068
  }
@@ -1066,6 +1083,7 @@ export class ShapeStream<T extends Row<unknown> = Row>
1066
1083
 
1067
1084
  unsubscribeAll(): void {
1068
1085
  this.#subscribers.clear()
1086
+ this.#unsubscribeFromVisibilityChanges?.()
1069
1087
  }
1070
1088
 
1071
1089
  /** Unix time at which we last synced. Undefined when `isLoading` is true. */
@@ -1192,6 +1210,11 @@ export class ShapeStream<T extends Row<unknown> = Row>
1192
1210
  }
1193
1211
 
1194
1212
  document.addEventListener(`visibilitychange`, visibilityHandler)
1213
+
1214
+ // Store cleanup function to remove the event listener
1215
+ this.#unsubscribeFromVisibilityChanges = () => {
1216
+ document.removeEventListener(`visibilitychange`, visibilityHandler)
1217
+ }
1195
1218
  }
1196
1219
  }
1197
1220