@electric-sql/client 1.0.3 → 1.0.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.
@@ -313,6 +313,7 @@ var WHERE_QUERY_PARAM = `where`;
313
313
  var REPLICA_PARAM = `replica`;
314
314
  var WHERE_PARAMS_PARAM = `params`;
315
315
  var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
316
+ var PAUSE_STREAM = `pause-stream`;
316
317
 
317
318
  // src/fetch.ts
318
319
  var HTTP_RETRY_STATUS_CODES = [429];
@@ -581,7 +582,7 @@ function resolveHeaders(headers) {
581
582
  return Object.fromEntries(resolvedEntries);
582
583
  });
583
584
  }
584
- var _error, _fetchClient2, _messageParser, _subscribers, _started, _lastOffset, _liveCacheBuster, _lastSyncedAt, _isUpToDate, _connected, _shapeHandle, _schema, _onError, _requestAbortController, _isRefreshing, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _ShapeStream_instances, start_fn, nextTick_fn, publish_fn, sendErrorToSubscribers_fn, reset_fn;
585
+ var _error, _fetchClient2, _messageParser, _subscribers, _started, _state, _lastOffset, _liveCacheBuster, _lastSyncedAt, _isUpToDate, _connected, _shapeHandle, _schema, _onError, _requestAbortController, _isRefreshing, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _ShapeStream_instances, start_fn, requestShape_fn, pause_fn, resume_fn, nextTick_fn, publish_fn, sendErrorToSubscribers_fn, subscribeToVisibilityChanges_fn, reset_fn;
585
586
  var ShapeStream = class {
586
587
  constructor(options) {
587
588
  __privateAdd(this, _ShapeStream_instances);
@@ -590,6 +591,7 @@ var ShapeStream = class {
590
591
  __privateAdd(this, _messageParser);
591
592
  __privateAdd(this, _subscribers, /* @__PURE__ */ new Map());
592
593
  __privateAdd(this, _started, false);
594
+ __privateAdd(this, _state, `active`);
593
595
  __privateAdd(this, _lastOffset);
594
596
  __privateAdd(this, _liveCacheBuster);
595
597
  // Seconds since our Electric Epoch 😎
@@ -626,6 +628,7 @@ var ShapeStream = class {
626
628
  createFetchWithChunkBuffer(fetchWithBackoffClient)
627
629
  )
628
630
  ));
631
+ __privateMethod(this, _ShapeStream_instances, subscribeToVisibilityChanges_fn).call(this);
629
632
  }
630
633
  get shapeHandle() {
631
634
  return __privateGet(this, _shapeHandle);
@@ -671,6 +674,9 @@ var ShapeStream = class {
671
674
  hasStarted() {
672
675
  return __privateGet(this, _started);
673
676
  }
677
+ isPaused() {
678
+ return __privateGet(this, _state) === `paused`;
679
+ }
674
680
  /**
675
681
  * Refreshes the shape stream.
676
682
  * This preemptively aborts any ongoing long poll and reconnects without
@@ -694,6 +700,7 @@ _fetchClient2 = new WeakMap();
694
700
  _messageParser = new WeakMap();
695
701
  _subscribers = new WeakMap();
696
702
  _started = new WeakMap();
703
+ _state = new WeakMap();
697
704
  _lastOffset = new WeakMap();
698
705
  _liveCacheBuster = new WeakMap();
699
706
  _lastSyncedAt = new WeakMap();
@@ -710,131 +717,10 @@ _tickPromiseRejecter = new WeakMap();
710
717
  _ShapeStream_instances = new WeakSet();
711
718
  start_fn = function() {
712
719
  return __async(this, null, function* () {
713
- var _a, _b, _c, _d, _e;
714
- if (__privateGet(this, _started)) throw new Error(`Cannot start stream twice`);
720
+ var _a;
715
721
  __privateSet(this, _started, true);
716
722
  try {
717
- while (!((_a = this.options.signal) == null ? void 0 : _a.aborted) && !__privateGet(this, _isUpToDate) || this.options.subscribe) {
718
- const { url, signal } = this.options;
719
- const [requestHeaders, params] = yield Promise.all([
720
- resolveHeaders(this.options.headers),
721
- this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
722
- ]);
723
- if (params) {
724
- validateParams(params);
725
- }
726
- const fetchUrl = new URL(url);
727
- if (params) {
728
- if (params.table)
729
- setQueryParam(fetchUrl, TABLE_QUERY_PARAM, params.table);
730
- if (params.where)
731
- setQueryParam(fetchUrl, WHERE_QUERY_PARAM, params.where);
732
- if (params.columns)
733
- setQueryParam(fetchUrl, COLUMNS_QUERY_PARAM, params.columns);
734
- if (params.replica)
735
- setQueryParam(fetchUrl, REPLICA_PARAM, params.replica);
736
- if (params.params)
737
- setQueryParam(fetchUrl, WHERE_PARAMS_PARAM, params.params);
738
- const customParams = __spreadValues({}, params);
739
- delete customParams.table;
740
- delete customParams.where;
741
- delete customParams.columns;
742
- delete customParams.replica;
743
- delete customParams.params;
744
- for (const [key, value] of Object.entries(customParams)) {
745
- setQueryParam(fetchUrl, key, value);
746
- }
747
- }
748
- fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
749
- if (__privateGet(this, _isUpToDate)) {
750
- if (!__privateGet(this, _isRefreshing)) {
751
- fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
752
- }
753
- fetchUrl.searchParams.set(
754
- LIVE_CACHE_BUSTER_QUERY_PARAM,
755
- __privateGet(this, _liveCacheBuster)
756
- );
757
- }
758
- if (__privateGet(this, _shapeHandle)) {
759
- fetchUrl.searchParams.set(
760
- SHAPE_HANDLE_QUERY_PARAM,
761
- __privateGet(this, _shapeHandle)
762
- );
763
- }
764
- fetchUrl.searchParams.sort();
765
- __privateSet(this, _requestAbortController, new AbortController());
766
- let abortListener;
767
- if (signal) {
768
- abortListener = () => {
769
- var _a2;
770
- (_a2 = __privateGet(this, _requestAbortController)) == null ? void 0 : _a2.abort(signal.reason);
771
- };
772
- signal.addEventListener(`abort`, abortListener, { once: true });
773
- if (signal.aborted) {
774
- (_b = __privateGet(this, _requestAbortController)) == null ? void 0 : _b.abort(signal.reason);
775
- }
776
- }
777
- let response;
778
- try {
779
- response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
780
- signal: __privateGet(this, _requestAbortController).signal,
781
- headers: requestHeaders
782
- });
783
- __privateSet(this, _connected, true);
784
- } catch (e) {
785
- if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && __privateGet(this, _requestAbortController).signal.aborted && __privateGet(this, _requestAbortController).signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
786
- continue;
787
- }
788
- if (e instanceof FetchBackoffAbortError) break;
789
- if (!(e instanceof FetchError)) throw e;
790
- if (e.status == 409) {
791
- const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER];
792
- __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
793
- yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
794
- continue;
795
- } else {
796
- __privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
797
- throw e;
798
- }
799
- } finally {
800
- if (abortListener && signal) {
801
- signal.removeEventListener(`abort`, abortListener);
802
- }
803
- __privateSet(this, _requestAbortController, void 0);
804
- }
805
- const { headers, status } = response;
806
- const shapeHandle = headers.get(SHAPE_HANDLE_HEADER);
807
- if (shapeHandle) {
808
- __privateSet(this, _shapeHandle, shapeHandle);
809
- }
810
- const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER);
811
- if (lastOffset) {
812
- __privateSet(this, _lastOffset, lastOffset);
813
- }
814
- const liveCacheBuster = headers.get(LIVE_CACHE_BUSTER_HEADER);
815
- if (liveCacheBuster) {
816
- __privateSet(this, _liveCacheBuster, liveCacheBuster);
817
- }
818
- const getSchema = () => {
819
- const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
820
- return schemaHeader ? JSON.parse(schemaHeader) : {};
821
- };
822
- __privateSet(this, _schema, (_c = __privateGet(this, _schema)) != null ? _c : getSchema());
823
- if (status === 204) {
824
- __privateSet(this, _lastSyncedAt, Date.now());
825
- }
826
- const messages = (yield response.text()) || `[]`;
827
- const batch = __privateGet(this, _messageParser).parse(messages, __privateGet(this, _schema));
828
- if (batch.length > 0) {
829
- const lastMessage = batch[batch.length - 1];
830
- if (isUpToDateMessage(lastMessage)) {
831
- __privateSet(this, _lastSyncedAt, Date.now());
832
- __privateSet(this, _isUpToDate, true);
833
- }
834
- yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, batch);
835
- }
836
- (_d = __privateGet(this, _tickPromiseResolver)) == null ? void 0 : _d.call(this);
837
- }
723
+ yield __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
838
724
  } catch (err) {
839
725
  __privateSet(this, _error, err);
840
726
  if (__privateGet(this, _onError)) {
@@ -855,10 +741,155 @@ start_fn = function() {
855
741
  throw err;
856
742
  } finally {
857
743
  __privateSet(this, _connected, false);
858
- (_e = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _e.call(this);
744
+ (_a = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _a.call(this);
859
745
  }
860
746
  });
861
747
  };
748
+ requestShape_fn = function() {
749
+ return __async(this, null, function* () {
750
+ var _a, _b, _c, _d;
751
+ if (__privateGet(this, _state) === `pause-requested`) {
752
+ __privateSet(this, _state, `paused`);
753
+ return;
754
+ }
755
+ if (!this.options.subscribe && (((_a = this.options.signal) == null ? void 0 : _a.aborted) || __privateGet(this, _isUpToDate))) {
756
+ return;
757
+ }
758
+ const resumingFromPause = __privateGet(this, _state) === `paused`;
759
+ __privateSet(this, _state, `active`);
760
+ const { url, signal } = this.options;
761
+ const [requestHeaders, params] = yield Promise.all([
762
+ resolveHeaders(this.options.headers),
763
+ this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
764
+ ]);
765
+ if (params) {
766
+ validateParams(params);
767
+ }
768
+ const fetchUrl = new URL(url);
769
+ if (params) {
770
+ if (params.table) setQueryParam(fetchUrl, TABLE_QUERY_PARAM, params.table);
771
+ if (params.where) setQueryParam(fetchUrl, WHERE_QUERY_PARAM, params.where);
772
+ if (params.columns)
773
+ setQueryParam(fetchUrl, COLUMNS_QUERY_PARAM, params.columns);
774
+ if (params.replica) setQueryParam(fetchUrl, REPLICA_PARAM, params.replica);
775
+ if (params.params)
776
+ setQueryParam(fetchUrl, WHERE_PARAMS_PARAM, params.params);
777
+ const customParams = __spreadValues({}, params);
778
+ delete customParams.table;
779
+ delete customParams.where;
780
+ delete customParams.columns;
781
+ delete customParams.replica;
782
+ delete customParams.params;
783
+ for (const [key, value] of Object.entries(customParams)) {
784
+ setQueryParam(fetchUrl, key, value);
785
+ }
786
+ }
787
+ fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
788
+ if (__privateGet(this, _isUpToDate)) {
789
+ if (!__privateGet(this, _isRefreshing) && !resumingFromPause) {
790
+ fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
791
+ }
792
+ fetchUrl.searchParams.set(
793
+ LIVE_CACHE_BUSTER_QUERY_PARAM,
794
+ __privateGet(this, _liveCacheBuster)
795
+ );
796
+ }
797
+ if (__privateGet(this, _shapeHandle)) {
798
+ fetchUrl.searchParams.set(SHAPE_HANDLE_QUERY_PARAM, __privateGet(this, _shapeHandle));
799
+ }
800
+ fetchUrl.searchParams.sort();
801
+ __privateSet(this, _requestAbortController, new AbortController());
802
+ let abortListener;
803
+ if (signal) {
804
+ abortListener = () => {
805
+ var _a2;
806
+ (_a2 = __privateGet(this, _requestAbortController)) == null ? void 0 : _a2.abort(signal.reason);
807
+ };
808
+ signal.addEventListener(`abort`, abortListener, { once: true });
809
+ if (signal.aborted) {
810
+ (_b = __privateGet(this, _requestAbortController)) == null ? void 0 : _b.abort(signal.reason);
811
+ }
812
+ }
813
+ let response;
814
+ try {
815
+ response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
816
+ signal: __privateGet(this, _requestAbortController).signal,
817
+ headers: requestHeaders
818
+ });
819
+ __privateSet(this, _connected, true);
820
+ } catch (e) {
821
+ if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && __privateGet(this, _requestAbortController).signal.aborted && __privateGet(this, _requestAbortController).signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
822
+ return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
823
+ }
824
+ if (e instanceof FetchBackoffAbortError) {
825
+ if (__privateGet(this, _requestAbortController).signal.aborted && __privateGet(this, _requestAbortController).signal.reason === PAUSE_STREAM) {
826
+ __privateSet(this, _state, `paused`);
827
+ }
828
+ return;
829
+ }
830
+ if (!(e instanceof FetchError)) throw e;
831
+ if (e.status == 409) {
832
+ const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER];
833
+ __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
834
+ yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
835
+ return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
836
+ } else {
837
+ __privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
838
+ throw e;
839
+ }
840
+ } finally {
841
+ if (abortListener && signal) {
842
+ signal.removeEventListener(`abort`, abortListener);
843
+ }
844
+ __privateSet(this, _requestAbortController, void 0);
845
+ }
846
+ const { headers, status } = response;
847
+ const shapeHandle = headers.get(SHAPE_HANDLE_HEADER);
848
+ if (shapeHandle) {
849
+ __privateSet(this, _shapeHandle, shapeHandle);
850
+ }
851
+ const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER);
852
+ if (lastOffset) {
853
+ __privateSet(this, _lastOffset, lastOffset);
854
+ }
855
+ const liveCacheBuster = headers.get(LIVE_CACHE_BUSTER_HEADER);
856
+ if (liveCacheBuster) {
857
+ __privateSet(this, _liveCacheBuster, liveCacheBuster);
858
+ }
859
+ const getSchema = () => {
860
+ const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
861
+ return schemaHeader ? JSON.parse(schemaHeader) : {};
862
+ };
863
+ __privateSet(this, _schema, (_c = __privateGet(this, _schema)) != null ? _c : getSchema());
864
+ if (status === 204) {
865
+ __privateSet(this, _lastSyncedAt, Date.now());
866
+ }
867
+ const messages = (yield response.text()) || `[]`;
868
+ const batch = __privateGet(this, _messageParser).parse(messages, __privateGet(this, _schema));
869
+ if (batch.length > 0) {
870
+ const lastMessage = batch[batch.length - 1];
871
+ if (isUpToDateMessage(lastMessage)) {
872
+ __privateSet(this, _lastSyncedAt, Date.now());
873
+ __privateSet(this, _isUpToDate, true);
874
+ }
875
+ yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, batch);
876
+ }
877
+ (_d = __privateGet(this, _tickPromiseResolver)) == null ? void 0 : _d.call(this);
878
+ return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
879
+ });
880
+ };
881
+ pause_fn = function() {
882
+ var _a;
883
+ if (__privateGet(this, _started) && __privateGet(this, _state) === `active`) {
884
+ __privateSet(this, _state, `pause-requested`);
885
+ (_a = __privateGet(this, _requestAbortController)) == null ? void 0 : _a.abort(PAUSE_STREAM);
886
+ }
887
+ };
888
+ resume_fn = function() {
889
+ if (__privateGet(this, _started) && __privateGet(this, _state) === `paused`) {
890
+ __privateMethod(this, _ShapeStream_instances, start_fn).call(this);
891
+ }
892
+ };
862
893
  nextTick_fn = function() {
863
894
  return __async(this, null, function* () {
864
895
  if (__privateGet(this, _tickPromise)) {
@@ -896,6 +927,18 @@ sendErrorToSubscribers_fn = function(error) {
896
927
  errorFn == null ? void 0 : errorFn(error);
897
928
  });
898
929
  };
930
+ subscribeToVisibilityChanges_fn = function() {
931
+ if (typeof document === `object` && typeof document.hidden === `boolean` && typeof document.addEventListener === `function`) {
932
+ const visibilityHandler = () => {
933
+ if (document.hidden) {
934
+ __privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
935
+ } else {
936
+ __privateMethod(this, _ShapeStream_instances, resume_fn).call(this);
937
+ }
938
+ };
939
+ document.addEventListener(`visibilitychange`, visibilityHandler);
940
+ }
941
+ };
899
942
  /**
900
943
  * Resets the state of the stream, optionally with a provided
901
944
  * shape handle