@electric-sql/client 1.0.4 → 1.0.6
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 +176 -61
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +29 -9
- package/dist/index.browser.mjs +3 -3
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +29 -9
- package/dist/index.legacy-esm.js +164 -61
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +178 -61
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -3
- package/src/client.ts +256 -90
- package/src/constants.ts +1 -0
- package/src/fetch.ts +4 -1
- package/src/helpers.ts +14 -1
- package/src/parser.ts +3 -3
- package/src/types.ts +5 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -296,6 +296,13 @@ function isControlMessage(message) {
|
|
|
296
296
|
function isUpToDateMessage(message) {
|
|
297
297
|
return isControlMessage(message) && message.headers.control === `up-to-date`;
|
|
298
298
|
}
|
|
299
|
+
function getOffset(message) {
|
|
300
|
+
const lsn = message.headers.global_last_seen_lsn;
|
|
301
|
+
if (!lsn) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
return `${lsn}_0`;
|
|
305
|
+
}
|
|
299
306
|
|
|
300
307
|
// src/constants.ts
|
|
301
308
|
var LIVE_CACHE_BUSTER_HEADER = `electric-cursor`;
|
|
@@ -312,6 +319,7 @@ var TABLE_QUERY_PARAM = `table`;
|
|
|
312
319
|
var WHERE_QUERY_PARAM = `where`;
|
|
313
320
|
var REPLICA_PARAM = `replica`;
|
|
314
321
|
var WHERE_PARAMS_PARAM = `params`;
|
|
322
|
+
var EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`;
|
|
315
323
|
var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
|
|
316
324
|
var PAUSE_STREAM = `pause-stream`;
|
|
317
325
|
|
|
@@ -340,7 +348,8 @@ function createFetchWithBackoff(fetchClient, backoffOptions = BackoffDefaults) {
|
|
|
340
348
|
try {
|
|
341
349
|
const result = yield fetchClient(...args);
|
|
342
350
|
if (result.ok) return result;
|
|
343
|
-
|
|
351
|
+
const err = yield FetchError.fromResponse(result, url.toString());
|
|
352
|
+
throw err;
|
|
344
353
|
} catch (e) {
|
|
345
354
|
onFailedAttempt == null ? void 0 : onFailedAttempt();
|
|
346
355
|
if ((_a = options == null ? void 0 : options.signal) == null ? void 0 : _a.aborted) {
|
|
@@ -538,6 +547,7 @@ function noop() {
|
|
|
538
547
|
}
|
|
539
548
|
|
|
540
549
|
// src/client.ts
|
|
550
|
+
var import_fetch_event_source = require("@microsoft/fetch-event-source");
|
|
541
551
|
var RESERVED_PARAMS = /* @__PURE__ */ new Set([
|
|
542
552
|
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
543
553
|
SHAPE_HANDLE_QUERY_PARAM,
|
|
@@ -582,12 +592,14 @@ function resolveHeaders(headers) {
|
|
|
582
592
|
return Object.fromEntries(resolvedEntries);
|
|
583
593
|
});
|
|
584
594
|
}
|
|
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;
|
|
595
|
+
var _error, _fetchClient2, _sseFetchClient, _messageParser, _subscribers, _started, _state, _lastOffset, _liveCacheBuster, _lastSyncedAt, _isUpToDate, _connected, _shapeHandle, _schema, _onError, _requestAbortController, _isRefreshing, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _messageChain, _ShapeStream_instances, start_fn, requestShape_fn, constructUrl_fn, createAbortListener_fn, onInitialResponse_fn, onMessages_fn, fetchShape_fn, requestShapeLongPoll_fn, requestShapeSSE_fn, pause_fn, resume_fn, nextTick_fn, publish_fn, sendErrorToSubscribers_fn, subscribeToVisibilityChanges_fn, reset_fn;
|
|
586
596
|
var ShapeStream = class {
|
|
597
|
+
// promise chain for incoming messages
|
|
587
598
|
constructor(options) {
|
|
588
599
|
__privateAdd(this, _ShapeStream_instances);
|
|
589
600
|
__privateAdd(this, _error, null);
|
|
590
601
|
__privateAdd(this, _fetchClient2);
|
|
602
|
+
__privateAdd(this, _sseFetchClient);
|
|
591
603
|
__privateAdd(this, _messageParser);
|
|
592
604
|
__privateAdd(this, _subscribers, /* @__PURE__ */ new Map());
|
|
593
605
|
__privateAdd(this, _started, false);
|
|
@@ -607,6 +619,7 @@ var ShapeStream = class {
|
|
|
607
619
|
__privateAdd(this, _tickPromise);
|
|
608
620
|
__privateAdd(this, _tickPromiseResolver);
|
|
609
621
|
__privateAdd(this, _tickPromiseRejecter);
|
|
622
|
+
__privateAdd(this, _messageChain, Promise.resolve([]));
|
|
610
623
|
var _a, _b, _c;
|
|
611
624
|
this.options = __spreadValues({ subscribe: true }, options);
|
|
612
625
|
validateOptions(this.options);
|
|
@@ -616,18 +629,21 @@ var ShapeStream = class {
|
|
|
616
629
|
__privateSet(this, _messageParser, new MessageParser(options.parser));
|
|
617
630
|
__privateSet(this, _onError, this.options.onError);
|
|
618
631
|
const baseFetchClient = (_b = options.fetchClient) != null ? _b : (...args) => fetch(...args);
|
|
619
|
-
const
|
|
632
|
+
const backOffOpts = __spreadProps(__spreadValues({}, (_c = options.backoffOptions) != null ? _c : BackoffDefaults), {
|
|
620
633
|
onFailedAttempt: () => {
|
|
621
634
|
var _a2, _b2;
|
|
622
635
|
__privateSet(this, _connected, false);
|
|
623
636
|
(_b2 = (_a2 = options.backoffOptions) == null ? void 0 : _a2.onFailedAttempt) == null ? void 0 : _b2.call(_a2);
|
|
624
637
|
}
|
|
625
|
-
})
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
638
|
+
});
|
|
639
|
+
const fetchWithBackoffClient = createFetchWithBackoff(
|
|
640
|
+
baseFetchClient,
|
|
641
|
+
backOffOpts
|
|
642
|
+
);
|
|
643
|
+
__privateSet(this, _sseFetchClient, createFetchWithResponseHeadersCheck(
|
|
644
|
+
createFetchWithChunkBuffer(fetchWithBackoffClient)
|
|
630
645
|
));
|
|
646
|
+
__privateSet(this, _fetchClient2, createFetchWithConsumedMessages(__privateGet(this, _sseFetchClient)));
|
|
631
647
|
__privateMethod(this, _ShapeStream_instances, subscribeToVisibilityChanges_fn).call(this);
|
|
632
648
|
}
|
|
633
649
|
get shapeHandle() {
|
|
@@ -697,6 +713,7 @@ var ShapeStream = class {
|
|
|
697
713
|
};
|
|
698
714
|
_error = new WeakMap();
|
|
699
715
|
_fetchClient2 = new WeakMap();
|
|
716
|
+
_sseFetchClient = new WeakMap();
|
|
700
717
|
_messageParser = new WeakMap();
|
|
701
718
|
_subscribers = new WeakMap();
|
|
702
719
|
_started = new WeakMap();
|
|
@@ -714,6 +731,7 @@ _isRefreshing = new WeakMap();
|
|
|
714
731
|
_tickPromise = new WeakMap();
|
|
715
732
|
_tickPromiseResolver = new WeakMap();
|
|
716
733
|
_tickPromiseRejecter = new WeakMap();
|
|
734
|
+
_messageChain = new WeakMap();
|
|
717
735
|
_ShapeStream_instances = new WeakSet();
|
|
718
736
|
start_fn = function() {
|
|
719
737
|
return __async(this, null, function* () {
|
|
@@ -747,7 +765,7 @@ start_fn = function() {
|
|
|
747
765
|
};
|
|
748
766
|
requestShape_fn = function() {
|
|
749
767
|
return __async(this, null, function* () {
|
|
750
|
-
var _a, _b
|
|
768
|
+
var _a, _b;
|
|
751
769
|
if (__privateGet(this, _state) === `pause-requested`) {
|
|
752
770
|
__privateSet(this, _state, `paused`);
|
|
753
771
|
return;
|
|
@@ -758,6 +776,48 @@ requestShape_fn = function() {
|
|
|
758
776
|
const resumingFromPause = __privateGet(this, _state) === `paused`;
|
|
759
777
|
__privateSet(this, _state, `active`);
|
|
760
778
|
const { url, signal } = this.options;
|
|
779
|
+
const { fetchUrl, requestHeaders } = yield __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, url, resumingFromPause);
|
|
780
|
+
const abortListener = yield __privateMethod(this, _ShapeStream_instances, createAbortListener_fn).call(this, signal);
|
|
781
|
+
const requestAbortController = __privateGet(this, _requestAbortController);
|
|
782
|
+
try {
|
|
783
|
+
yield __privateMethod(this, _ShapeStream_instances, fetchShape_fn).call(this, {
|
|
784
|
+
fetchUrl,
|
|
785
|
+
requestAbortController,
|
|
786
|
+
headers: requestHeaders,
|
|
787
|
+
resumingFromPause
|
|
788
|
+
});
|
|
789
|
+
} catch (e) {
|
|
790
|
+
if ((e instanceof FetchError || e instanceof FetchBackoffAbortError) && requestAbortController.signal.aborted && requestAbortController.signal.reason === FORCE_DISCONNECT_AND_REFRESH) {
|
|
791
|
+
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
792
|
+
}
|
|
793
|
+
if (e instanceof FetchBackoffAbortError) {
|
|
794
|
+
if (requestAbortController.signal.aborted && requestAbortController.signal.reason === PAUSE_STREAM) {
|
|
795
|
+
__privateSet(this, _state, `paused`);
|
|
796
|
+
}
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
if (!(e instanceof FetchError)) throw e;
|
|
800
|
+
if (e.status == 409) {
|
|
801
|
+
const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER];
|
|
802
|
+
__privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
|
|
803
|
+
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, e.json);
|
|
804
|
+
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
805
|
+
} else {
|
|
806
|
+
__privateMethod(this, _ShapeStream_instances, sendErrorToSubscribers_fn).call(this, e);
|
|
807
|
+
throw e;
|
|
808
|
+
}
|
|
809
|
+
} finally {
|
|
810
|
+
if (abortListener && signal) {
|
|
811
|
+
signal.removeEventListener(`abort`, abortListener);
|
|
812
|
+
}
|
|
813
|
+
__privateSet(this, _requestAbortController, void 0);
|
|
814
|
+
}
|
|
815
|
+
(_b = __privateGet(this, _tickPromiseResolver)) == null ? void 0 : _b.call(this);
|
|
816
|
+
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
817
|
+
});
|
|
818
|
+
};
|
|
819
|
+
constructUrl_fn = function(url, resumingFromPause) {
|
|
820
|
+
return __async(this, null, function* () {
|
|
761
821
|
const [requestHeaders, params] = yield Promise.all([
|
|
762
822
|
resolveHeaders(this.options.headers),
|
|
763
823
|
this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
|
|
@@ -798,51 +858,32 @@ requestShape_fn = function() {
|
|
|
798
858
|
fetchUrl.searchParams.set(SHAPE_HANDLE_QUERY_PARAM, __privateGet(this, _shapeHandle));
|
|
799
859
|
}
|
|
800
860
|
fetchUrl.searchParams.sort();
|
|
861
|
+
return {
|
|
862
|
+
fetchUrl,
|
|
863
|
+
requestHeaders
|
|
864
|
+
};
|
|
865
|
+
});
|
|
866
|
+
};
|
|
867
|
+
createAbortListener_fn = function(signal) {
|
|
868
|
+
return __async(this, null, function* () {
|
|
869
|
+
var _a;
|
|
801
870
|
__privateSet(this, _requestAbortController, new AbortController());
|
|
802
|
-
let abortListener;
|
|
803
871
|
if (signal) {
|
|
804
|
-
abortListener = () => {
|
|
872
|
+
const abortListener = () => {
|
|
805
873
|
var _a2;
|
|
806
874
|
(_a2 = __privateGet(this, _requestAbortController)) == null ? void 0 : _a2.abort(signal.reason);
|
|
807
875
|
};
|
|
808
876
|
signal.addEventListener(`abort`, abortListener, { once: true });
|
|
809
877
|
if (signal.aborted) {
|
|
810
|
-
(
|
|
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;
|
|
878
|
+
(_a = __privateGet(this, _requestAbortController)) == null ? void 0 : _a.abort(signal.reason);
|
|
839
879
|
}
|
|
840
|
-
|
|
841
|
-
if (abortListener && signal) {
|
|
842
|
-
signal.removeEventListener(`abort`, abortListener);
|
|
843
|
-
}
|
|
844
|
-
__privateSet(this, _requestAbortController, void 0);
|
|
880
|
+
return abortListener;
|
|
845
881
|
}
|
|
882
|
+
});
|
|
883
|
+
};
|
|
884
|
+
onInitialResponse_fn = function(response) {
|
|
885
|
+
return __async(this, null, function* () {
|
|
886
|
+
var _a;
|
|
846
887
|
const { headers, status } = response;
|
|
847
888
|
const shapeHandle = headers.get(SHAPE_HANDLE_HEADER);
|
|
848
889
|
if (shapeHandle) {
|
|
@@ -860,22 +901,93 @@ requestShape_fn = function() {
|
|
|
860
901
|
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
861
902
|
return schemaHeader ? JSON.parse(schemaHeader) : {};
|
|
862
903
|
};
|
|
863
|
-
__privateSet(this, _schema, (
|
|
904
|
+
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchema());
|
|
864
905
|
if (status === 204) {
|
|
865
906
|
__privateSet(this, _lastSyncedAt, Date.now());
|
|
866
907
|
}
|
|
867
|
-
|
|
868
|
-
|
|
908
|
+
});
|
|
909
|
+
};
|
|
910
|
+
onMessages_fn = function(batch, isSseMessage = false) {
|
|
911
|
+
return __async(this, null, function* () {
|
|
869
912
|
if (batch.length > 0) {
|
|
870
913
|
const lastMessage = batch[batch.length - 1];
|
|
871
914
|
if (isUpToDateMessage(lastMessage)) {
|
|
915
|
+
if (isSseMessage) {
|
|
916
|
+
const offset = getOffset(lastMessage);
|
|
917
|
+
if (offset) {
|
|
918
|
+
__privateSet(this, _lastOffset, offset);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
872
921
|
__privateSet(this, _lastSyncedAt, Date.now());
|
|
873
922
|
__privateSet(this, _isUpToDate, true);
|
|
874
923
|
}
|
|
875
924
|
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, batch);
|
|
876
925
|
}
|
|
877
|
-
|
|
878
|
-
|
|
926
|
+
});
|
|
927
|
+
};
|
|
928
|
+
fetchShape_fn = function(opts) {
|
|
929
|
+
return __async(this, null, function* () {
|
|
930
|
+
if (__privateGet(this, _isUpToDate) && this.options.experimentalLiveSse && !__privateGet(this, _isRefreshing) && !opts.resumingFromPause) {
|
|
931
|
+
opts.fetchUrl.searchParams.set(EXPERIMENTAL_LIVE_SSE_QUERY_PARAM, `true`);
|
|
932
|
+
return __privateMethod(this, _ShapeStream_instances, requestShapeSSE_fn).call(this, opts);
|
|
933
|
+
}
|
|
934
|
+
return __privateMethod(this, _ShapeStream_instances, requestShapeLongPoll_fn).call(this, opts);
|
|
935
|
+
});
|
|
936
|
+
};
|
|
937
|
+
requestShapeLongPoll_fn = function(opts) {
|
|
938
|
+
return __async(this, null, function* () {
|
|
939
|
+
const { fetchUrl, requestAbortController, headers } = opts;
|
|
940
|
+
const response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
|
|
941
|
+
signal: requestAbortController.signal,
|
|
942
|
+
headers
|
|
943
|
+
});
|
|
944
|
+
__privateSet(this, _connected, true);
|
|
945
|
+
yield __privateMethod(this, _ShapeStream_instances, onInitialResponse_fn).call(this, response);
|
|
946
|
+
const schema = __privateGet(this, _schema);
|
|
947
|
+
const res = yield response.text();
|
|
948
|
+
const messages = res || `[]`;
|
|
949
|
+
const batch = __privateGet(this, _messageParser).parse(messages, schema);
|
|
950
|
+
yield __privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, batch);
|
|
951
|
+
});
|
|
952
|
+
};
|
|
953
|
+
requestShapeSSE_fn = function(opts) {
|
|
954
|
+
return __async(this, null, function* () {
|
|
955
|
+
const { fetchUrl, requestAbortController, headers } = opts;
|
|
956
|
+
const fetch2 = __privateGet(this, _sseFetchClient);
|
|
957
|
+
try {
|
|
958
|
+
let buffer = [];
|
|
959
|
+
yield (0, import_fetch_event_source.fetchEventSource)(fetchUrl.toString(), {
|
|
960
|
+
headers,
|
|
961
|
+
fetch: fetch2,
|
|
962
|
+
onopen: (response) => __async(this, null, function* () {
|
|
963
|
+
__privateSet(this, _connected, true);
|
|
964
|
+
yield __privateMethod(this, _ShapeStream_instances, onInitialResponse_fn).call(this, response);
|
|
965
|
+
}),
|
|
966
|
+
onmessage: (event) => {
|
|
967
|
+
if (event.data) {
|
|
968
|
+
const schema = __privateGet(this, _schema);
|
|
969
|
+
const message = __privateGet(this, _messageParser).parse(
|
|
970
|
+
event.data,
|
|
971
|
+
schema
|
|
972
|
+
);
|
|
973
|
+
buffer.push(message);
|
|
974
|
+
if (isUpToDateMessage(message)) {
|
|
975
|
+
__privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, buffer, true);
|
|
976
|
+
buffer = [];
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
},
|
|
980
|
+
onerror: (error) => {
|
|
981
|
+
throw error;
|
|
982
|
+
},
|
|
983
|
+
signal: requestAbortController.signal
|
|
984
|
+
});
|
|
985
|
+
} catch (error) {
|
|
986
|
+
if (requestAbortController.signal.aborted) {
|
|
987
|
+
throw new FetchBackoffAbortError();
|
|
988
|
+
}
|
|
989
|
+
throw error;
|
|
990
|
+
}
|
|
879
991
|
});
|
|
880
992
|
};
|
|
881
993
|
pause_fn = function() {
|
|
@@ -909,17 +1021,20 @@ nextTick_fn = function() {
|
|
|
909
1021
|
};
|
|
910
1022
|
publish_fn = function(messages) {
|
|
911
1023
|
return __async(this, null, function* () {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1024
|
+
__privateSet(this, _messageChain, __privateGet(this, _messageChain).then(
|
|
1025
|
+
() => Promise.all(
|
|
1026
|
+
Array.from(__privateGet(this, _subscribers).values()).map((_0) => __async(this, [_0], function* ([callback, __]) {
|
|
1027
|
+
try {
|
|
1028
|
+
yield callback(messages);
|
|
1029
|
+
} catch (err) {
|
|
1030
|
+
queueMicrotask(() => {
|
|
1031
|
+
throw err;
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}))
|
|
1035
|
+
)
|
|
1036
|
+
));
|
|
1037
|
+
return __privateGet(this, _messageChain);
|
|
923
1038
|
});
|
|
924
1039
|
};
|
|
925
1040
|
sendErrorToSubscribers_fn = function(error) {
|