@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.
- package/dist/cjs/index.cjs +168 -125
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/index.browser.mjs +5 -5
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.legacy-esm.js +166 -125
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +168 -125
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +238 -180
- package/src/constants.ts +1 -0
package/dist/index.mjs
CHANGED
|
@@ -284,6 +284,7 @@ var WHERE_QUERY_PARAM = `where`;
|
|
|
284
284
|
var REPLICA_PARAM = `replica`;
|
|
285
285
|
var WHERE_PARAMS_PARAM = `params`;
|
|
286
286
|
var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
|
|
287
|
+
var PAUSE_STREAM = `pause-stream`;
|
|
287
288
|
|
|
288
289
|
// src/fetch.ts
|
|
289
290
|
var HTTP_RETRY_STATUS_CODES = [429];
|
|
@@ -552,7 +553,7 @@ function resolveHeaders(headers) {
|
|
|
552
553
|
return Object.fromEntries(resolvedEntries);
|
|
553
554
|
});
|
|
554
555
|
}
|
|
555
|
-
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;
|
|
556
|
+
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;
|
|
556
557
|
var ShapeStream = class {
|
|
557
558
|
constructor(options) {
|
|
558
559
|
__privateAdd(this, _ShapeStream_instances);
|
|
@@ -561,6 +562,7 @@ var ShapeStream = class {
|
|
|
561
562
|
__privateAdd(this, _messageParser);
|
|
562
563
|
__privateAdd(this, _subscribers, /* @__PURE__ */ new Map());
|
|
563
564
|
__privateAdd(this, _started, false);
|
|
565
|
+
__privateAdd(this, _state, `active`);
|
|
564
566
|
__privateAdd(this, _lastOffset);
|
|
565
567
|
__privateAdd(this, _liveCacheBuster);
|
|
566
568
|
// Seconds since our Electric Epoch 😎
|
|
@@ -597,6 +599,7 @@ var ShapeStream = class {
|
|
|
597
599
|
createFetchWithChunkBuffer(fetchWithBackoffClient)
|
|
598
600
|
)
|
|
599
601
|
));
|
|
602
|
+
__privateMethod(this, _ShapeStream_instances, subscribeToVisibilityChanges_fn).call(this);
|
|
600
603
|
}
|
|
601
604
|
get shapeHandle() {
|
|
602
605
|
return __privateGet(this, _shapeHandle);
|
|
@@ -642,6 +645,9 @@ var ShapeStream = class {
|
|
|
642
645
|
hasStarted() {
|
|
643
646
|
return __privateGet(this, _started);
|
|
644
647
|
}
|
|
648
|
+
isPaused() {
|
|
649
|
+
return __privateGet(this, _state) === `paused`;
|
|
650
|
+
}
|
|
645
651
|
/**
|
|
646
652
|
* Refreshes the shape stream.
|
|
647
653
|
* This preemptively aborts any ongoing long poll and reconnects without
|
|
@@ -665,6 +671,7 @@ _fetchClient2 = new WeakMap();
|
|
|
665
671
|
_messageParser = new WeakMap();
|
|
666
672
|
_subscribers = new WeakMap();
|
|
667
673
|
_started = new WeakMap();
|
|
674
|
+
_state = new WeakMap();
|
|
668
675
|
_lastOffset = new WeakMap();
|
|
669
676
|
_liveCacheBuster = new WeakMap();
|
|
670
677
|
_lastSyncedAt = new WeakMap();
|
|
@@ -681,131 +688,10 @@ _tickPromiseRejecter = new WeakMap();
|
|
|
681
688
|
_ShapeStream_instances = new WeakSet();
|
|
682
689
|
start_fn = function() {
|
|
683
690
|
return __async(this, null, function* () {
|
|
684
|
-
var _a
|
|
685
|
-
if (__privateGet(this, _started)) throw new Error(`Cannot start stream twice`);
|
|
691
|
+
var _a;
|
|
686
692
|
__privateSet(this, _started, true);
|
|
687
693
|
try {
|
|
688
|
-
|
|
689
|
-
const { url, signal } = this.options;
|
|
690
|
-
const [requestHeaders, params] = yield Promise.all([
|
|
691
|
-
resolveHeaders(this.options.headers),
|
|
692
|
-
this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
|
|
693
|
-
]);
|
|
694
|
-
if (params) {
|
|
695
|
-
validateParams(params);
|
|
696
|
-
}
|
|
697
|
-
const fetchUrl = new URL(url);
|
|
698
|
-
if (params) {
|
|
699
|
-
if (params.table)
|
|
700
|
-
setQueryParam(fetchUrl, TABLE_QUERY_PARAM, params.table);
|
|
701
|
-
if (params.where)
|
|
702
|
-
setQueryParam(fetchUrl, WHERE_QUERY_PARAM, params.where);
|
|
703
|
-
if (params.columns)
|
|
704
|
-
setQueryParam(fetchUrl, COLUMNS_QUERY_PARAM, params.columns);
|
|
705
|
-
if (params.replica)
|
|
706
|
-
setQueryParam(fetchUrl, REPLICA_PARAM, params.replica);
|
|
707
|
-
if (params.params)
|
|
708
|
-
setQueryParam(fetchUrl, WHERE_PARAMS_PARAM, params.params);
|
|
709
|
-
const customParams = __spreadValues({}, params);
|
|
710
|
-
delete customParams.table;
|
|
711
|
-
delete customParams.where;
|
|
712
|
-
delete customParams.columns;
|
|
713
|
-
delete customParams.replica;
|
|
714
|
-
delete customParams.params;
|
|
715
|
-
for (const [key, value] of Object.entries(customParams)) {
|
|
716
|
-
setQueryParam(fetchUrl, key, value);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
|
|
720
|
-
if (__privateGet(this, _isUpToDate)) {
|
|
721
|
-
if (!__privateGet(this, _isRefreshing)) {
|
|
722
|
-
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
|
|
723
|
-
}
|
|
724
|
-
fetchUrl.searchParams.set(
|
|
725
|
-
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
726
|
-
__privateGet(this, _liveCacheBuster)
|
|
727
|
-
);
|
|
728
|
-
}
|
|
729
|
-
if (__privateGet(this, _shapeHandle)) {
|
|
730
|
-
fetchUrl.searchParams.set(
|
|
731
|
-
SHAPE_HANDLE_QUERY_PARAM,
|
|
732
|
-
__privateGet(this, _shapeHandle)
|
|
733
|
-
);
|
|
734
|
-
}
|
|
735
|
-
fetchUrl.searchParams.sort();
|
|
736
|
-
__privateSet(this, _requestAbortController, new AbortController());
|
|
737
|
-
let abortListener;
|
|
738
|
-
if (signal) {
|
|
739
|
-
abortListener = () => {
|
|
740
|
-
var _a2;
|
|
741
|
-
(_a2 = __privateGet(this, _requestAbortController)) == null ? void 0 : _a2.abort(signal.reason);
|
|
742
|
-
};
|
|
743
|
-
signal.addEventListener(`abort`, abortListener, { once: true });
|
|
744
|
-
if (signal.aborted) {
|
|
745
|
-
(_b = __privateGet(this, _requestAbortController)) == null ? void 0 : _b.abort(signal.reason);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
let response;
|
|
749
|
-
try {
|
|
750
|
-
response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
|
|
751
|
-
signal: __privateGet(this, _requestAbortController).signal,
|
|
752
|
-
headers: requestHeaders
|
|
753
|
-
});
|
|
754
|
-
__privateSet(this, _connected, true);
|
|
755
|
-
} catch (e) {
|
|
756
|
-
if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && __privateGet(this, _requestAbortController).signal.aborted && __privateGet(this, _requestAbortController).signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
|
|
757
|
-
continue;
|
|
758
|
-
}
|
|
759
|
-
if (e instanceof FetchBackoffAbortError) break;
|
|
760
|
-
if (!(e instanceof FetchError)) throw e;
|
|
761
|
-
if (e.status == 409) {
|
|
762
|
-
const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER];
|
|
763
|
-
__privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
|
|
764
|
-
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
|
|
765
|
-
continue;
|
|
766
|
-
} else {
|
|
767
|
-
__privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
|
|
768
|
-
throw e;
|
|
769
|
-
}
|
|
770
|
-
} finally {
|
|
771
|
-
if (abortListener && signal) {
|
|
772
|
-
signal.removeEventListener(`abort`, abortListener);
|
|
773
|
-
}
|
|
774
|
-
__privateSet(this, _requestAbortController, void 0);
|
|
775
|
-
}
|
|
776
|
-
const { headers, status } = response;
|
|
777
|
-
const shapeHandle = headers.get(SHAPE_HANDLE_HEADER);
|
|
778
|
-
if (shapeHandle) {
|
|
779
|
-
__privateSet(this, _shapeHandle, shapeHandle);
|
|
780
|
-
}
|
|
781
|
-
const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER);
|
|
782
|
-
if (lastOffset) {
|
|
783
|
-
__privateSet(this, _lastOffset, lastOffset);
|
|
784
|
-
}
|
|
785
|
-
const liveCacheBuster = headers.get(LIVE_CACHE_BUSTER_HEADER);
|
|
786
|
-
if (liveCacheBuster) {
|
|
787
|
-
__privateSet(this, _liveCacheBuster, liveCacheBuster);
|
|
788
|
-
}
|
|
789
|
-
const getSchema = () => {
|
|
790
|
-
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
791
|
-
return schemaHeader ? JSON.parse(schemaHeader) : {};
|
|
792
|
-
};
|
|
793
|
-
__privateSet(this, _schema, (_c = __privateGet(this, _schema)) != null ? _c : getSchema());
|
|
794
|
-
if (status === 204) {
|
|
795
|
-
__privateSet(this, _lastSyncedAt, Date.now());
|
|
796
|
-
}
|
|
797
|
-
const messages = (yield response.text()) || `[]`;
|
|
798
|
-
const batch = __privateGet(this, _messageParser).parse(messages, __privateGet(this, _schema));
|
|
799
|
-
if (batch.length > 0) {
|
|
800
|
-
const lastMessage = batch[batch.length - 1];
|
|
801
|
-
if (isUpToDateMessage(lastMessage)) {
|
|
802
|
-
__privateSet(this, _lastSyncedAt, Date.now());
|
|
803
|
-
__privateSet(this, _isUpToDate, true);
|
|
804
|
-
}
|
|
805
|
-
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, batch);
|
|
806
|
-
}
|
|
807
|
-
(_d = __privateGet(this, _tickPromiseResolver)) == null ? void 0 : _d.call(this);
|
|
808
|
-
}
|
|
694
|
+
yield __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
809
695
|
} catch (err) {
|
|
810
696
|
__privateSet(this, _error, err);
|
|
811
697
|
if (__privateGet(this, _onError)) {
|
|
@@ -826,10 +712,155 @@ start_fn = function() {
|
|
|
826
712
|
throw err;
|
|
827
713
|
} finally {
|
|
828
714
|
__privateSet(this, _connected, false);
|
|
829
|
-
(
|
|
715
|
+
(_a = __privateGet(this, _tickPromiseRejecter)) == null ? void 0 : _a.call(this);
|
|
830
716
|
}
|
|
831
717
|
});
|
|
832
718
|
};
|
|
719
|
+
requestShape_fn = function() {
|
|
720
|
+
return __async(this, null, function* () {
|
|
721
|
+
var _a, _b, _c, _d;
|
|
722
|
+
if (__privateGet(this, _state) === `pause-requested`) {
|
|
723
|
+
__privateSet(this, _state, `paused`);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
if (!this.options.subscribe && (((_a = this.options.signal) == null ? void 0 : _a.aborted) || __privateGet(this, _isUpToDate))) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
const resumingFromPause = __privateGet(this, _state) === `paused`;
|
|
730
|
+
__privateSet(this, _state, `active`);
|
|
731
|
+
const { url, signal } = this.options;
|
|
732
|
+
const [requestHeaders, params] = yield Promise.all([
|
|
733
|
+
resolveHeaders(this.options.headers),
|
|
734
|
+
this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
|
|
735
|
+
]);
|
|
736
|
+
if (params) {
|
|
737
|
+
validateParams(params);
|
|
738
|
+
}
|
|
739
|
+
const fetchUrl = new URL(url);
|
|
740
|
+
if (params) {
|
|
741
|
+
if (params.table) setQueryParam(fetchUrl, TABLE_QUERY_PARAM, params.table);
|
|
742
|
+
if (params.where) setQueryParam(fetchUrl, WHERE_QUERY_PARAM, params.where);
|
|
743
|
+
if (params.columns)
|
|
744
|
+
setQueryParam(fetchUrl, COLUMNS_QUERY_PARAM, params.columns);
|
|
745
|
+
if (params.replica) setQueryParam(fetchUrl, REPLICA_PARAM, params.replica);
|
|
746
|
+
if (params.params)
|
|
747
|
+
setQueryParam(fetchUrl, WHERE_PARAMS_PARAM, params.params);
|
|
748
|
+
const customParams = __spreadValues({}, params);
|
|
749
|
+
delete customParams.table;
|
|
750
|
+
delete customParams.where;
|
|
751
|
+
delete customParams.columns;
|
|
752
|
+
delete customParams.replica;
|
|
753
|
+
delete customParams.params;
|
|
754
|
+
for (const [key, value] of Object.entries(customParams)) {
|
|
755
|
+
setQueryParam(fetchUrl, key, value);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
|
|
759
|
+
if (__privateGet(this, _isUpToDate)) {
|
|
760
|
+
if (!__privateGet(this, _isRefreshing) && !resumingFromPause) {
|
|
761
|
+
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
|
|
762
|
+
}
|
|
763
|
+
fetchUrl.searchParams.set(
|
|
764
|
+
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
765
|
+
__privateGet(this, _liveCacheBuster)
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
if (__privateGet(this, _shapeHandle)) {
|
|
769
|
+
fetchUrl.searchParams.set(SHAPE_HANDLE_QUERY_PARAM, __privateGet(this, _shapeHandle));
|
|
770
|
+
}
|
|
771
|
+
fetchUrl.searchParams.sort();
|
|
772
|
+
__privateSet(this, _requestAbortController, new AbortController());
|
|
773
|
+
let abortListener;
|
|
774
|
+
if (signal) {
|
|
775
|
+
abortListener = () => {
|
|
776
|
+
var _a2;
|
|
777
|
+
(_a2 = __privateGet(this, _requestAbortController)) == null ? void 0 : _a2.abort(signal.reason);
|
|
778
|
+
};
|
|
779
|
+
signal.addEventListener(`abort`, abortListener, { once: true });
|
|
780
|
+
if (signal.aborted) {
|
|
781
|
+
(_b = __privateGet(this, _requestAbortController)) == null ? void 0 : _b.abort(signal.reason);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
let response;
|
|
785
|
+
try {
|
|
786
|
+
response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
|
|
787
|
+
signal: __privateGet(this, _requestAbortController).signal,
|
|
788
|
+
headers: requestHeaders
|
|
789
|
+
});
|
|
790
|
+
__privateSet(this, _connected, true);
|
|
791
|
+
} catch (e) {
|
|
792
|
+
if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && __privateGet(this, _requestAbortController).signal.aborted && __privateGet(this, _requestAbortController).signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
|
|
793
|
+
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
794
|
+
}
|
|
795
|
+
if (e instanceof FetchBackoffAbortError) {
|
|
796
|
+
if (__privateGet(this, _requestAbortController).signal.aborted && __privateGet(this, _requestAbortController).signal.reason === PAUSE_STREAM) {
|
|
797
|
+
__privateSet(this, _state, `paused`);
|
|
798
|
+
}
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
if (!(e instanceof FetchError)) throw e;
|
|
802
|
+
if (e.status == 409) {
|
|
803
|
+
const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER];
|
|
804
|
+
__privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
|
|
805
|
+
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
|
|
806
|
+
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
807
|
+
} else {
|
|
808
|
+
__privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
|
|
809
|
+
throw e;
|
|
810
|
+
}
|
|
811
|
+
} finally {
|
|
812
|
+
if (abortListener && signal) {
|
|
813
|
+
signal.removeEventListener(`abort`, abortListener);
|
|
814
|
+
}
|
|
815
|
+
__privateSet(this, _requestAbortController, void 0);
|
|
816
|
+
}
|
|
817
|
+
const { headers, status } = response;
|
|
818
|
+
const shapeHandle = headers.get(SHAPE_HANDLE_HEADER);
|
|
819
|
+
if (shapeHandle) {
|
|
820
|
+
__privateSet(this, _shapeHandle, shapeHandle);
|
|
821
|
+
}
|
|
822
|
+
const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER);
|
|
823
|
+
if (lastOffset) {
|
|
824
|
+
__privateSet(this, _lastOffset, lastOffset);
|
|
825
|
+
}
|
|
826
|
+
const liveCacheBuster = headers.get(LIVE_CACHE_BUSTER_HEADER);
|
|
827
|
+
if (liveCacheBuster) {
|
|
828
|
+
__privateSet(this, _liveCacheBuster, liveCacheBuster);
|
|
829
|
+
}
|
|
830
|
+
const getSchema = () => {
|
|
831
|
+
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
832
|
+
return schemaHeader ? JSON.parse(schemaHeader) : {};
|
|
833
|
+
};
|
|
834
|
+
__privateSet(this, _schema, (_c = __privateGet(this, _schema)) != null ? _c : getSchema());
|
|
835
|
+
if (status === 204) {
|
|
836
|
+
__privateSet(this, _lastSyncedAt, Date.now());
|
|
837
|
+
}
|
|
838
|
+
const messages = (yield response.text()) || `[]`;
|
|
839
|
+
const batch = __privateGet(this, _messageParser).parse(messages, __privateGet(this, _schema));
|
|
840
|
+
if (batch.length > 0) {
|
|
841
|
+
const lastMessage = batch[batch.length - 1];
|
|
842
|
+
if (isUpToDateMessage(lastMessage)) {
|
|
843
|
+
__privateSet(this, _lastSyncedAt, Date.now());
|
|
844
|
+
__privateSet(this, _isUpToDate, true);
|
|
845
|
+
}
|
|
846
|
+
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, batch);
|
|
847
|
+
}
|
|
848
|
+
(_d = __privateGet(this, _tickPromiseResolver)) == null ? void 0 : _d.call(this);
|
|
849
|
+
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
850
|
+
});
|
|
851
|
+
};
|
|
852
|
+
pause_fn = function() {
|
|
853
|
+
var _a;
|
|
854
|
+
if (__privateGet(this, _started) && __privateGet(this, _state) === `active`) {
|
|
855
|
+
__privateSet(this, _state, `pause-requested`);
|
|
856
|
+
(_a = __privateGet(this, _requestAbortController)) == null ? void 0 : _a.abort(PAUSE_STREAM);
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
resume_fn = function() {
|
|
860
|
+
if (__privateGet(this, _started) && __privateGet(this, _state) === `paused`) {
|
|
861
|
+
__privateMethod(this, _ShapeStream_instances, start_fn).call(this);
|
|
862
|
+
}
|
|
863
|
+
};
|
|
833
864
|
nextTick_fn = function() {
|
|
834
865
|
return __async(this, null, function* () {
|
|
835
866
|
if (__privateGet(this, _tickPromise)) {
|
|
@@ -867,6 +898,18 @@ sendErrorToSubscribers_fn = function(error) {
|
|
|
867
898
|
errorFn == null ? void 0 : errorFn(error);
|
|
868
899
|
});
|
|
869
900
|
};
|
|
901
|
+
subscribeToVisibilityChanges_fn = function() {
|
|
902
|
+
if (typeof document === `object` && typeof document.hidden === `boolean` && typeof document.addEventListener === `function`) {
|
|
903
|
+
const visibilityHandler = () => {
|
|
904
|
+
if (document.hidden) {
|
|
905
|
+
__privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
|
|
906
|
+
} else {
|
|
907
|
+
__privateMethod(this, _ShapeStream_instances, resume_fn).call(this);
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
document.addEventListener(`visibilitychange`, visibilityHandler);
|
|
911
|
+
}
|
|
912
|
+
};
|
|
870
913
|
/**
|
|
871
914
|
* Resets the state of the stream, optionally with a provided
|
|
872
915
|
* shape handle
|