@electric-sql/client 1.0.10 → 1.0.12
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 +338 -24
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +90 -5
- package/dist/index.browser.mjs +3 -3
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +90 -5
- package/dist/index.legacy-esm.js +325 -24
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +337 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +203 -6
- package/src/constants.ts +12 -0
- package/src/fetch.ts +19 -1
- package/src/helpers.ts +34 -1
- package/src/index.ts +5 -1
- package/src/shape.ts +104 -14
- package/src/snapshot-tracker.ts +88 -0
- package/src/types.ts +40 -6
package/dist/cjs/index.cjs
CHANGED
|
@@ -53,6 +53,14 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
53
53
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
54
54
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
55
55
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
56
|
+
var __privateWrapper = (obj, member, setter, getter) => ({
|
|
57
|
+
set _(value) {
|
|
58
|
+
__privateSet(obj, member, value, setter);
|
|
59
|
+
},
|
|
60
|
+
get _() {
|
|
61
|
+
return __privateGet(obj, member, getter);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
56
64
|
var __async = (__this, __arguments, generator) => {
|
|
57
65
|
return new Promise((resolve, reject) => {
|
|
58
66
|
var fulfilled = (value) => {
|
|
@@ -84,6 +92,7 @@ __export(src_exports, {
|
|
|
84
92
|
ShapeStream: () => ShapeStream,
|
|
85
93
|
isChangeMessage: () => isChangeMessage,
|
|
86
94
|
isControlMessage: () => isControlMessage,
|
|
95
|
+
isVisibleInSnapshot: () => isVisibleInSnapshot,
|
|
87
96
|
resolveValue: () => resolveValue
|
|
88
97
|
});
|
|
89
98
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -308,6 +317,13 @@ function getOffset(message) {
|
|
|
308
317
|
}
|
|
309
318
|
return `${lsn}_0`;
|
|
310
319
|
}
|
|
320
|
+
function isVisibleInSnapshot(txid, snapshot) {
|
|
321
|
+
const xid = BigInt(txid);
|
|
322
|
+
const xmin = BigInt(snapshot.xmin);
|
|
323
|
+
const xmax = BigInt(snapshot.xmax);
|
|
324
|
+
const xip = snapshot.xip_list.map(BigInt);
|
|
325
|
+
return xid < xmin || xid < xmax && !xip.includes(xid);
|
|
326
|
+
}
|
|
311
327
|
|
|
312
328
|
// src/constants.ts
|
|
313
329
|
var LIVE_CACHE_BUSTER_HEADER = `electric-cursor`;
|
|
@@ -328,12 +344,24 @@ var WHERE_PARAMS_PARAM = `params`;
|
|
|
328
344
|
var EXPERIMENTAL_LIVE_SSE_QUERY_PARAM = `experimental_live_sse`;
|
|
329
345
|
var FORCE_DISCONNECT_AND_REFRESH = `force-disconnect-and-refresh`;
|
|
330
346
|
var PAUSE_STREAM = `pause-stream`;
|
|
347
|
+
var LOG_MODE_QUERY_PARAM = `log`;
|
|
348
|
+
var SUBSET_PARAM_WHERE = `subset__where`;
|
|
349
|
+
var SUBSET_PARAM_LIMIT = `subset__limit`;
|
|
350
|
+
var SUBSET_PARAM_OFFSET = `subset__offset`;
|
|
351
|
+
var SUBSET_PARAM_ORDER_BY = `subset__order_by`;
|
|
352
|
+
var SUBSET_PARAM_WHERE_PARAMS = `subset__params`;
|
|
331
353
|
var ELECTRIC_PROTOCOL_QUERY_PARAMS = [
|
|
332
354
|
LIVE_QUERY_PARAM,
|
|
333
355
|
SHAPE_HANDLE_QUERY_PARAM,
|
|
334
356
|
OFFSET_QUERY_PARAM,
|
|
335
357
|
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
336
|
-
EXPIRED_HANDLE_QUERY_PARAM
|
|
358
|
+
EXPIRED_HANDLE_QUERY_PARAM,
|
|
359
|
+
LOG_MODE_QUERY_PARAM,
|
|
360
|
+
SUBSET_PARAM_WHERE,
|
|
361
|
+
SUBSET_PARAM_LIMIT,
|
|
362
|
+
SUBSET_PARAM_OFFSET,
|
|
363
|
+
SUBSET_PARAM_ORDER_BY,
|
|
364
|
+
SUBSET_PARAM_WHERE_PARAMS
|
|
337
365
|
];
|
|
338
366
|
|
|
339
367
|
// src/fetch.ts
|
|
@@ -444,10 +472,20 @@ function createFetchWithResponseHeadersCheck(fetchClient) {
|
|
|
444
472
|
const headers = response.headers;
|
|
445
473
|
const missingHeaders = [];
|
|
446
474
|
const addMissingHeaders = (requiredHeaders) => missingHeaders.push(...requiredHeaders.filter((h) => !headers.has(h)));
|
|
447
|
-
addMissingHeaders(requiredElectricResponseHeaders);
|
|
448
475
|
const input = args[0];
|
|
449
476
|
const urlString = input.toString();
|
|
450
477
|
const url = new URL(urlString);
|
|
478
|
+
const isSnapshotRequest = [
|
|
479
|
+
SUBSET_PARAM_WHERE,
|
|
480
|
+
SUBSET_PARAM_WHERE_PARAMS,
|
|
481
|
+
SUBSET_PARAM_LIMIT,
|
|
482
|
+
SUBSET_PARAM_OFFSET,
|
|
483
|
+
SUBSET_PARAM_ORDER_BY
|
|
484
|
+
].some((p) => url.searchParams.has(p));
|
|
485
|
+
if (isSnapshotRequest) {
|
|
486
|
+
return response;
|
|
487
|
+
}
|
|
488
|
+
addMissingHeaders(requiredElectricResponseHeaders);
|
|
451
489
|
if (url.searchParams.get(LIVE_QUERY_PARAM) === `true`) {
|
|
452
490
|
addMissingHeaders(requiredLiveResponseHeaders);
|
|
453
491
|
}
|
|
@@ -615,6 +653,68 @@ var ExpiredShapesCache = class {
|
|
|
615
653
|
};
|
|
616
654
|
var expiredShapesCache = new ExpiredShapesCache();
|
|
617
655
|
|
|
656
|
+
// src/snapshot-tracker.ts
|
|
657
|
+
var SnapshotTracker = class {
|
|
658
|
+
constructor() {
|
|
659
|
+
this.activeSnapshots = /* @__PURE__ */ new Map();
|
|
660
|
+
this.xmaxSnapshots = /* @__PURE__ */ new Map();
|
|
661
|
+
this.snapshotsByDatabaseLsn = /* @__PURE__ */ new Map();
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Add a new snapshot for tracking
|
|
665
|
+
*/
|
|
666
|
+
addSnapshot(metadata, keys) {
|
|
667
|
+
var _a, _b, _c, _d;
|
|
668
|
+
this.activeSnapshots.set(metadata.snapshot_mark, {
|
|
669
|
+
xmin: BigInt(metadata.xmin),
|
|
670
|
+
xmax: BigInt(metadata.xmax),
|
|
671
|
+
xip_list: metadata.xip_list.map(BigInt),
|
|
672
|
+
keys
|
|
673
|
+
});
|
|
674
|
+
const xmaxSet = (_b = (_a = this.xmaxSnapshots.get(BigInt(metadata.xmax))) == null ? void 0 : _a.add(metadata.snapshot_mark)) != null ? _b : /* @__PURE__ */ new Set([metadata.snapshot_mark]);
|
|
675
|
+
this.xmaxSnapshots.set(BigInt(metadata.xmax), xmaxSet);
|
|
676
|
+
const databaseLsnSet = (_d = (_c = this.snapshotsByDatabaseLsn.get(BigInt(metadata.database_lsn))) == null ? void 0 : _c.add(metadata.snapshot_mark)) != null ? _d : /* @__PURE__ */ new Set([metadata.snapshot_mark]);
|
|
677
|
+
this.snapshotsByDatabaseLsn.set(
|
|
678
|
+
BigInt(metadata.database_lsn),
|
|
679
|
+
databaseLsnSet
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Remove a snapshot from tracking
|
|
684
|
+
*/
|
|
685
|
+
removeSnapshot(snapshotMark) {
|
|
686
|
+
this.activeSnapshots.delete(snapshotMark);
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Check if a change message should be filtered because its already in an active snapshot
|
|
690
|
+
* Returns true if the message should be filtered out (not processed)
|
|
691
|
+
*/
|
|
692
|
+
shouldRejectMessage(message) {
|
|
693
|
+
const txids = message.headers.txids || [];
|
|
694
|
+
if (txids.length === 0) return false;
|
|
695
|
+
const xid = Math.max(...txids);
|
|
696
|
+
for (const [xmax, snapshots] of this.xmaxSnapshots.entries()) {
|
|
697
|
+
if (xid >= xmax) {
|
|
698
|
+
for (const snapshot of snapshots) {
|
|
699
|
+
this.removeSnapshot(snapshot);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return [...this.activeSnapshots.values()].some(
|
|
704
|
+
(x) => x.keys.has(message.key) && isVisibleInSnapshot(xid, x)
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
lastSeenUpdate(newDatabaseLsn) {
|
|
708
|
+
for (const [dbLsn, snapshots] of this.snapshotsByDatabaseLsn.entries()) {
|
|
709
|
+
if (dbLsn <= newDatabaseLsn) {
|
|
710
|
+
for (const snapshot of snapshots) {
|
|
711
|
+
this.removeSnapshot(snapshot);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
|
|
618
718
|
// src/client.ts
|
|
619
719
|
var RESERVED_PARAMS = /* @__PURE__ */ new Set([
|
|
620
720
|
LIVE_CACHE_BUSTER_QUERY_PARAM,
|
|
@@ -670,9 +770,8 @@ function canonicalShapeKey(url) {
|
|
|
670
770
|
cleanUrl.searchParams.sort();
|
|
671
771
|
return cleanUrl.toString();
|
|
672
772
|
}
|
|
673
|
-
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;
|
|
773
|
+
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, _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, waitForStreamEnd_fn, publish_fn, sendErrorToSubscribers_fn, subscribeToVisibilityChanges_fn, reset_fn, fetchSnapshot_fn;
|
|
674
774
|
var ShapeStream = class {
|
|
675
|
-
// promise chain for incoming messages
|
|
676
775
|
constructor(options) {
|
|
677
776
|
__privateAdd(this, _ShapeStream_instances);
|
|
678
777
|
__privateAdd(this, _error, null);
|
|
@@ -688,8 +787,10 @@ var ShapeStream = class {
|
|
|
688
787
|
__privateAdd(this, _lastSyncedAt);
|
|
689
788
|
// unix time
|
|
690
789
|
__privateAdd(this, _isUpToDate, false);
|
|
790
|
+
__privateAdd(this, _isMidStream, true);
|
|
691
791
|
__privateAdd(this, _connected, false);
|
|
692
792
|
__privateAdd(this, _shapeHandle);
|
|
793
|
+
__privateAdd(this, _mode);
|
|
693
794
|
__privateAdd(this, _schema);
|
|
694
795
|
__privateAdd(this, _onError);
|
|
695
796
|
__privateAdd(this, _requestAbortController);
|
|
@@ -698,7 +799,13 @@ var ShapeStream = class {
|
|
|
698
799
|
__privateAdd(this, _tickPromiseResolver);
|
|
699
800
|
__privateAdd(this, _tickPromiseRejecter);
|
|
700
801
|
__privateAdd(this, _messageChain, Promise.resolve([]));
|
|
701
|
-
|
|
802
|
+
// promise chain for incoming messages
|
|
803
|
+
__privateAdd(this, _snapshotTracker, new SnapshotTracker());
|
|
804
|
+
__privateAdd(this, _activeSnapshotRequests, 0);
|
|
805
|
+
// counter for concurrent snapshot requests
|
|
806
|
+
__privateAdd(this, _midStreamPromise);
|
|
807
|
+
__privateAdd(this, _midStreamPromiseResolver);
|
|
808
|
+
var _a, _b, _c, _d;
|
|
702
809
|
this.options = __spreadValues({ subscribe: true }, options);
|
|
703
810
|
validateOptions(this.options);
|
|
704
811
|
__privateSet(this, _lastOffset, (_a = this.options.offset) != null ? _a : `-1`);
|
|
@@ -709,8 +816,9 @@ var ShapeStream = class {
|
|
|
709
816
|
options.transformer
|
|
710
817
|
));
|
|
711
818
|
__privateSet(this, _onError, this.options.onError);
|
|
712
|
-
|
|
713
|
-
const
|
|
819
|
+
__privateSet(this, _mode, (_b = this.options.log) != null ? _b : `full`);
|
|
820
|
+
const baseFetchClient = (_c = options.fetchClient) != null ? _c : (...args) => fetch(...args);
|
|
821
|
+
const backOffOpts = __spreadProps(__spreadValues({}, (_d = options.backoffOptions) != null ? _d : BackoffDefaults), {
|
|
714
822
|
onFailedAttempt: () => {
|
|
715
823
|
var _a2, _b2;
|
|
716
824
|
__privateSet(this, _connected, false);
|
|
@@ -739,6 +847,9 @@ var ShapeStream = class {
|
|
|
739
847
|
get lastOffset() {
|
|
740
848
|
return __privateGet(this, _lastOffset);
|
|
741
849
|
}
|
|
850
|
+
get mode() {
|
|
851
|
+
return __privateGet(this, _mode);
|
|
852
|
+
}
|
|
742
853
|
subscribe(callback, onError = () => {
|
|
743
854
|
}) {
|
|
744
855
|
const subscriptionId = Math.random();
|
|
@@ -791,6 +902,56 @@ var ShapeStream = class {
|
|
|
791
902
|
__privateSet(this, _isRefreshing, false);
|
|
792
903
|
});
|
|
793
904
|
}
|
|
905
|
+
/**
|
|
906
|
+
* Request a snapshot for subset of data.
|
|
907
|
+
*
|
|
908
|
+
* Only available when mode is `changes_only`.
|
|
909
|
+
* Returns the insertion point & the data, but more importantly injects the data
|
|
910
|
+
* into the subscribed data stream. Returned value is unlikely to be useful for the caller,
|
|
911
|
+
* unless the caller has complicated additional logic.
|
|
912
|
+
*
|
|
913
|
+
* Data will be injected in a way that's also tracking further incoming changes, and it'll
|
|
914
|
+
* skip the ones that are already in the snapshot.
|
|
915
|
+
*
|
|
916
|
+
* @param opts - The options for the snapshot request.
|
|
917
|
+
* @returns The metadata and the data for the snapshot.
|
|
918
|
+
*/
|
|
919
|
+
requestSnapshot(opts) {
|
|
920
|
+
return __async(this, null, function* () {
|
|
921
|
+
if (__privateGet(this, _mode) === `full`) {
|
|
922
|
+
throw new Error(
|
|
923
|
+
`Snapshot requests are not supported in ${__privateGet(this, _mode)} mode, as the consumer is guaranteed to observe all data`
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
if (!__privateGet(this, _started)) yield __privateMethod(this, _ShapeStream_instances, start_fn).call(this);
|
|
927
|
+
yield __privateMethod(this, _ShapeStream_instances, waitForStreamEnd_fn).call(this);
|
|
928
|
+
__privateWrapper(this, _activeSnapshotRequests)._++;
|
|
929
|
+
try {
|
|
930
|
+
if (__privateGet(this, _activeSnapshotRequests) === 1) {
|
|
931
|
+
__privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
|
|
932
|
+
}
|
|
933
|
+
const { fetchUrl, requestHeaders } = yield __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
|
|
934
|
+
const { metadata, data } = yield __privateMethod(this, _ShapeStream_instances, fetchSnapshot_fn).call(this, fetchUrl, requestHeaders);
|
|
935
|
+
const dataWithEndBoundary = data.concat([
|
|
936
|
+
{ headers: __spreadValues({ control: `snapshot-end` }, metadata) }
|
|
937
|
+
]);
|
|
938
|
+
__privateGet(this, _snapshotTracker).addSnapshot(
|
|
939
|
+
metadata,
|
|
940
|
+
new Set(data.map((message) => message.key))
|
|
941
|
+
);
|
|
942
|
+
__privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, dataWithEndBoundary, false);
|
|
943
|
+
return {
|
|
944
|
+
metadata,
|
|
945
|
+
data
|
|
946
|
+
};
|
|
947
|
+
} finally {
|
|
948
|
+
__privateWrapper(this, _activeSnapshotRequests)._--;
|
|
949
|
+
if (__privateGet(this, _activeSnapshotRequests) === 0) {
|
|
950
|
+
__privateMethod(this, _ShapeStream_instances, resume_fn).call(this);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
});
|
|
954
|
+
}
|
|
794
955
|
};
|
|
795
956
|
_error = new WeakMap();
|
|
796
957
|
_fetchClient2 = new WeakMap();
|
|
@@ -803,8 +964,10 @@ _lastOffset = new WeakMap();
|
|
|
803
964
|
_liveCacheBuster = new WeakMap();
|
|
804
965
|
_lastSyncedAt = new WeakMap();
|
|
805
966
|
_isUpToDate = new WeakMap();
|
|
967
|
+
_isMidStream = new WeakMap();
|
|
806
968
|
_connected = new WeakMap();
|
|
807
969
|
_shapeHandle = new WeakMap();
|
|
970
|
+
_mode = new WeakMap();
|
|
808
971
|
_schema = new WeakMap();
|
|
809
972
|
_onError = new WeakMap();
|
|
810
973
|
_requestAbortController = new WeakMap();
|
|
@@ -813,6 +976,10 @@ _tickPromise = new WeakMap();
|
|
|
813
976
|
_tickPromiseResolver = new WeakMap();
|
|
814
977
|
_tickPromiseRejecter = new WeakMap();
|
|
815
978
|
_messageChain = new WeakMap();
|
|
979
|
+
_snapshotTracker = new WeakMap();
|
|
980
|
+
_activeSnapshotRequests = new WeakMap();
|
|
981
|
+
_midStreamPromise = new WeakMap();
|
|
982
|
+
_midStreamPromiseResolver = new WeakMap();
|
|
816
983
|
_ShapeStream_instances = new WeakSet();
|
|
817
984
|
start_fn = function() {
|
|
818
985
|
return __async(this, null, function* () {
|
|
@@ -901,15 +1068,13 @@ requestShape_fn = function() {
|
|
|
901
1068
|
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
902
1069
|
});
|
|
903
1070
|
};
|
|
904
|
-
constructUrl_fn = function(url, resumingFromPause) {
|
|
1071
|
+
constructUrl_fn = function(url, resumingFromPause, subsetParams) {
|
|
905
1072
|
return __async(this, null, function* () {
|
|
906
1073
|
const [requestHeaders, params] = yield Promise.all([
|
|
907
1074
|
resolveHeaders(this.options.headers),
|
|
908
1075
|
this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
|
|
909
1076
|
]);
|
|
910
|
-
if (params)
|
|
911
|
-
validateParams(params);
|
|
912
|
-
}
|
|
1077
|
+
if (params) validateParams(params);
|
|
913
1078
|
const fetchUrl = new URL(url);
|
|
914
1079
|
if (params) {
|
|
915
1080
|
if (params.table) setQueryParam(fetchUrl, TABLE_QUERY_PARAM, params.table);
|
|
@@ -929,7 +1094,20 @@ constructUrl_fn = function(url, resumingFromPause) {
|
|
|
929
1094
|
setQueryParam(fetchUrl, key, value);
|
|
930
1095
|
}
|
|
931
1096
|
}
|
|
1097
|
+
if (subsetParams) {
|
|
1098
|
+
if (subsetParams.where)
|
|
1099
|
+
setQueryParam(fetchUrl, SUBSET_PARAM_WHERE, subsetParams.where);
|
|
1100
|
+
if (subsetParams.params)
|
|
1101
|
+
setQueryParam(fetchUrl, SUBSET_PARAM_WHERE_PARAMS, subsetParams.params);
|
|
1102
|
+
if (subsetParams.limit)
|
|
1103
|
+
setQueryParam(fetchUrl, SUBSET_PARAM_LIMIT, subsetParams.limit);
|
|
1104
|
+
if (subsetParams.offset)
|
|
1105
|
+
setQueryParam(fetchUrl, SUBSET_PARAM_OFFSET, subsetParams.offset);
|
|
1106
|
+
if (subsetParams.orderBy)
|
|
1107
|
+
setQueryParam(fetchUrl, SUBSET_PARAM_ORDER_BY, subsetParams.orderBy);
|
|
1108
|
+
}
|
|
932
1109
|
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
|
|
1110
|
+
fetchUrl.searchParams.set(LOG_MODE_QUERY_PARAM, __privateGet(this, _mode));
|
|
933
1111
|
if (__privateGet(this, _isUpToDate)) {
|
|
934
1112
|
if (!__privateGet(this, _isRefreshing) && !resumingFromPause) {
|
|
935
1113
|
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
|
|
@@ -999,7 +1177,9 @@ onInitialResponse_fn = function(response) {
|
|
|
999
1177
|
};
|
|
1000
1178
|
onMessages_fn = function(batch, isSseMessage = false) {
|
|
1001
1179
|
return __async(this, null, function* () {
|
|
1180
|
+
var _a;
|
|
1002
1181
|
if (batch.length > 0) {
|
|
1182
|
+
__privateSet(this, _isMidStream, true);
|
|
1003
1183
|
const lastMessage = batch[batch.length - 1];
|
|
1004
1184
|
if (isUpToDateMessage(lastMessage)) {
|
|
1005
1185
|
if (isSseMessage) {
|
|
@@ -1010,8 +1190,16 @@ onMessages_fn = function(batch, isSseMessage = false) {
|
|
|
1010
1190
|
}
|
|
1011
1191
|
__privateSet(this, _lastSyncedAt, Date.now());
|
|
1012
1192
|
__privateSet(this, _isUpToDate, true);
|
|
1193
|
+
__privateSet(this, _isMidStream, false);
|
|
1194
|
+
(_a = __privateGet(this, _midStreamPromiseResolver)) == null ? void 0 : _a.call(this);
|
|
1013
1195
|
}
|
|
1014
|
-
|
|
1196
|
+
const messagesToProcess = batch.filter((message) => {
|
|
1197
|
+
if (isChangeMessage(message)) {
|
|
1198
|
+
return !__privateGet(this, _snapshotTracker).shouldRejectMessage(message);
|
|
1199
|
+
}
|
|
1200
|
+
return true;
|
|
1201
|
+
});
|
|
1202
|
+
yield __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, messagesToProcess);
|
|
1015
1203
|
}
|
|
1016
1204
|
});
|
|
1017
1205
|
};
|
|
@@ -1109,6 +1297,24 @@ nextTick_fn = function() {
|
|
|
1109
1297
|
return __privateGet(this, _tickPromise);
|
|
1110
1298
|
});
|
|
1111
1299
|
};
|
|
1300
|
+
waitForStreamEnd_fn = function() {
|
|
1301
|
+
return __async(this, null, function* () {
|
|
1302
|
+
if (!__privateGet(this, _isMidStream)) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
if (__privateGet(this, _midStreamPromise)) {
|
|
1306
|
+
return __privateGet(this, _midStreamPromise);
|
|
1307
|
+
}
|
|
1308
|
+
__privateSet(this, _midStreamPromise, new Promise((resolve) => {
|
|
1309
|
+
__privateSet(this, _midStreamPromiseResolver, resolve);
|
|
1310
|
+
}));
|
|
1311
|
+
__privateGet(this, _midStreamPromise).finally(() => {
|
|
1312
|
+
__privateSet(this, _midStreamPromise, void 0);
|
|
1313
|
+
__privateSet(this, _midStreamPromiseResolver, void 0);
|
|
1314
|
+
});
|
|
1315
|
+
return __privateGet(this, _midStreamPromise);
|
|
1316
|
+
});
|
|
1317
|
+
};
|
|
1112
1318
|
publish_fn = function(messages) {
|
|
1113
1319
|
return __async(this, null, function* () {
|
|
1114
1320
|
__privateSet(this, _messageChain, __privateGet(this, _messageChain).then(
|
|
@@ -1153,8 +1359,33 @@ reset_fn = function(handle) {
|
|
|
1153
1359
|
__privateSet(this, _liveCacheBuster, ``);
|
|
1154
1360
|
__privateSet(this, _shapeHandle, handle);
|
|
1155
1361
|
__privateSet(this, _isUpToDate, false);
|
|
1362
|
+
__privateSet(this, _isMidStream, true);
|
|
1156
1363
|
__privateSet(this, _connected, false);
|
|
1157
1364
|
__privateSet(this, _schema, void 0);
|
|
1365
|
+
__privateSet(this, _activeSnapshotRequests, 0);
|
|
1366
|
+
};
|
|
1367
|
+
fetchSnapshot_fn = function(url, headers) {
|
|
1368
|
+
return __async(this, null, function* () {
|
|
1369
|
+
const response = yield __privateGet(this, _fetchClient2).call(this, url.toString(), { headers });
|
|
1370
|
+
if (!response.ok) {
|
|
1371
|
+
throw new FetchError(
|
|
1372
|
+
response.status,
|
|
1373
|
+
void 0,
|
|
1374
|
+
void 0,
|
|
1375
|
+
Object.fromEntries([...response.headers.entries()]),
|
|
1376
|
+
url.toString()
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
const { metadata, data } = yield response.json();
|
|
1380
|
+
const batch = __privateGet(this, _messageParser).parse(
|
|
1381
|
+
JSON.stringify(data),
|
|
1382
|
+
__privateGet(this, _schema)
|
|
1383
|
+
);
|
|
1384
|
+
return {
|
|
1385
|
+
metadata,
|
|
1386
|
+
data: batch
|
|
1387
|
+
};
|
|
1388
|
+
});
|
|
1158
1389
|
};
|
|
1159
1390
|
ShapeStream.Replica = {
|
|
1160
1391
|
FULL: `full`,
|
|
@@ -1176,7 +1407,7 @@ function validateOptions(options) {
|
|
|
1176
1407
|
if (options.signal && !(options.signal instanceof AbortSignal)) {
|
|
1177
1408
|
throw new InvalidSignalError();
|
|
1178
1409
|
}
|
|
1179
|
-
if (options.offset !== void 0 && options.offset !== `-1` && !options.handle) {
|
|
1410
|
+
if (options.offset !== void 0 && options.offset !== `-1` && options.offset !== `now` && !options.handle) {
|
|
1180
1411
|
throw new MissingShapeHandleError();
|
|
1181
1412
|
}
|
|
1182
1413
|
validateParams(options.params);
|
|
@@ -1205,12 +1436,15 @@ function convertWhereParamsToObj(allPgParams) {
|
|
|
1205
1436
|
}
|
|
1206
1437
|
|
|
1207
1438
|
// src/shape.ts
|
|
1208
|
-
var _data, _subscribers2, _status, _error2, _Shape_instances, process_fn, updateShapeStatus_fn, handleError_fn, notify_fn;
|
|
1439
|
+
var _data, _subscribers2, _insertedKeys, _requestedSubSnapshots, _reexecuteSnapshotsPending, _status, _error2, _Shape_instances, process_fn, reexecuteSnapshots_fn, awaitUpToDate_fn, updateShapeStatus_fn, handleError_fn, notify_fn;
|
|
1209
1440
|
var Shape = class {
|
|
1210
1441
|
constructor(stream) {
|
|
1211
1442
|
__privateAdd(this, _Shape_instances);
|
|
1212
1443
|
__privateAdd(this, _data, /* @__PURE__ */ new Map());
|
|
1213
1444
|
__privateAdd(this, _subscribers2, /* @__PURE__ */ new Map());
|
|
1445
|
+
__privateAdd(this, _insertedKeys, /* @__PURE__ */ new Set());
|
|
1446
|
+
__privateAdd(this, _requestedSubSnapshots, /* @__PURE__ */ new Set());
|
|
1447
|
+
__privateAdd(this, _reexecuteSnapshotsPending, false);
|
|
1214
1448
|
__privateAdd(this, _status, `syncing`);
|
|
1215
1449
|
__privateAdd(this, _error2, false);
|
|
1216
1450
|
this.stream = stream;
|
|
@@ -1269,6 +1503,22 @@ var Shape = class {
|
|
|
1269
1503
|
isConnected() {
|
|
1270
1504
|
return this.stream.isConnected();
|
|
1271
1505
|
}
|
|
1506
|
+
/** Current log mode of the underlying stream */
|
|
1507
|
+
get mode() {
|
|
1508
|
+
return this.stream.mode;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Request a snapshot for subset of data. Only available when mode is changes_only.
|
|
1512
|
+
* Returns void; data will be emitted via the stream and processed by this Shape.
|
|
1513
|
+
*/
|
|
1514
|
+
requestSnapshot(params) {
|
|
1515
|
+
return __async(this, null, function* () {
|
|
1516
|
+
const key = JSON.stringify(params);
|
|
1517
|
+
__privateGet(this, _requestedSubSnapshots).add(key);
|
|
1518
|
+
yield __privateMethod(this, _Shape_instances, awaitUpToDate_fn).call(this);
|
|
1519
|
+
yield this.stream.requestSnapshot(params);
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1272
1522
|
subscribe(callback) {
|
|
1273
1523
|
const subscriptionId = Math.random();
|
|
1274
1524
|
__privateGet(this, _subscribers2).set(subscriptionId, callback);
|
|
@@ -1285,6 +1535,9 @@ var Shape = class {
|
|
|
1285
1535
|
};
|
|
1286
1536
|
_data = new WeakMap();
|
|
1287
1537
|
_subscribers2 = new WeakMap();
|
|
1538
|
+
_insertedKeys = new WeakMap();
|
|
1539
|
+
_requestedSubSnapshots = new WeakMap();
|
|
1540
|
+
_reexecuteSnapshotsPending = new WeakMap();
|
|
1288
1541
|
_status = new WeakMap();
|
|
1289
1542
|
_error2 = new WeakMap();
|
|
1290
1543
|
_Shape_instances = new WeakSet();
|
|
@@ -1293,33 +1546,93 @@ process_fn = function(messages) {
|
|
|
1293
1546
|
messages.forEach((message) => {
|
|
1294
1547
|
if (isChangeMessage(message)) {
|
|
1295
1548
|
shouldNotify = __privateMethod(this, _Shape_instances, updateShapeStatus_fn).call(this, `syncing`);
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1549
|
+
if (this.mode === `full`) {
|
|
1550
|
+
switch (message.headers.operation) {
|
|
1551
|
+
case `insert`:
|
|
1552
|
+
__privateGet(this, _data).set(message.key, message.value);
|
|
1553
|
+
break;
|
|
1554
|
+
case `update`:
|
|
1555
|
+
__privateGet(this, _data).set(message.key, __spreadValues(__spreadValues({}, __privateGet(this, _data).get(message.key)), message.value));
|
|
1556
|
+
break;
|
|
1557
|
+
case `delete`:
|
|
1558
|
+
__privateGet(this, _data).delete(message.key);
|
|
1559
|
+
break;
|
|
1560
|
+
}
|
|
1561
|
+
} else {
|
|
1562
|
+
switch (message.headers.operation) {
|
|
1563
|
+
case `insert`:
|
|
1564
|
+
__privateGet(this, _insertedKeys).add(message.key);
|
|
1565
|
+
__privateGet(this, _data).set(message.key, message.value);
|
|
1566
|
+
break;
|
|
1567
|
+
case `update`:
|
|
1568
|
+
if (__privateGet(this, _insertedKeys).has(message.key)) {
|
|
1569
|
+
__privateGet(this, _data).set(message.key, __spreadValues(__spreadValues({}, __privateGet(this, _data).get(message.key)), message.value));
|
|
1570
|
+
}
|
|
1571
|
+
break;
|
|
1572
|
+
case `delete`:
|
|
1573
|
+
if (__privateGet(this, _insertedKeys).has(message.key)) {
|
|
1574
|
+
__privateGet(this, _data).delete(message.key);
|
|
1575
|
+
__privateGet(this, _insertedKeys).delete(message.key);
|
|
1576
|
+
}
|
|
1577
|
+
break;
|
|
1578
|
+
}
|
|
1306
1579
|
}
|
|
1307
1580
|
}
|
|
1308
1581
|
if (isControlMessage(message)) {
|
|
1309
1582
|
switch (message.headers.control) {
|
|
1310
1583
|
case `up-to-date`:
|
|
1311
1584
|
shouldNotify = __privateMethod(this, _Shape_instances, updateShapeStatus_fn).call(this, `up-to-date`);
|
|
1585
|
+
if (__privateGet(this, _reexecuteSnapshotsPending)) {
|
|
1586
|
+
__privateSet(this, _reexecuteSnapshotsPending, false);
|
|
1587
|
+
void __privateMethod(this, _Shape_instances, reexecuteSnapshots_fn).call(this);
|
|
1588
|
+
}
|
|
1312
1589
|
break;
|
|
1313
1590
|
case `must-refetch`:
|
|
1314
1591
|
__privateGet(this, _data).clear();
|
|
1592
|
+
__privateGet(this, _insertedKeys).clear();
|
|
1315
1593
|
__privateSet(this, _error2, false);
|
|
1316
1594
|
shouldNotify = __privateMethod(this, _Shape_instances, updateShapeStatus_fn).call(this, `syncing`);
|
|
1595
|
+
__privateSet(this, _reexecuteSnapshotsPending, true);
|
|
1317
1596
|
break;
|
|
1318
1597
|
}
|
|
1319
1598
|
}
|
|
1320
1599
|
});
|
|
1321
1600
|
if (shouldNotify) __privateMethod(this, _Shape_instances, notify_fn).call(this);
|
|
1322
1601
|
};
|
|
1602
|
+
reexecuteSnapshots_fn = function() {
|
|
1603
|
+
return __async(this, null, function* () {
|
|
1604
|
+
yield __privateMethod(this, _Shape_instances, awaitUpToDate_fn).call(this);
|
|
1605
|
+
yield Promise.all(
|
|
1606
|
+
Array.from(__privateGet(this, _requestedSubSnapshots)).map((jsonParams) => __async(this, null, function* () {
|
|
1607
|
+
try {
|
|
1608
|
+
const snapshot = JSON.parse(jsonParams);
|
|
1609
|
+
yield this.stream.requestSnapshot(snapshot);
|
|
1610
|
+
} catch (_) {
|
|
1611
|
+
}
|
|
1612
|
+
}))
|
|
1613
|
+
);
|
|
1614
|
+
});
|
|
1615
|
+
};
|
|
1616
|
+
awaitUpToDate_fn = function() {
|
|
1617
|
+
return __async(this, null, function* () {
|
|
1618
|
+
if (this.stream.isUpToDate) return;
|
|
1619
|
+
yield new Promise((resolve) => {
|
|
1620
|
+
const check = () => {
|
|
1621
|
+
if (this.stream.isUpToDate) {
|
|
1622
|
+
clearInterval(interval);
|
|
1623
|
+
unsub();
|
|
1624
|
+
resolve();
|
|
1625
|
+
}
|
|
1626
|
+
};
|
|
1627
|
+
const interval = setInterval(check, 10);
|
|
1628
|
+
const unsub = this.stream.subscribe(
|
|
1629
|
+
() => check(),
|
|
1630
|
+
() => check()
|
|
1631
|
+
);
|
|
1632
|
+
check();
|
|
1633
|
+
});
|
|
1634
|
+
});
|
|
1635
|
+
};
|
|
1323
1636
|
updateShapeStatus_fn = function(status) {
|
|
1324
1637
|
const stateChanged = __privateGet(this, _status) !== status;
|
|
1325
1638
|
__privateSet(this, _status, status);
|
|
@@ -1345,6 +1658,7 @@ notify_fn = function() {
|
|
|
1345
1658
|
ShapeStream,
|
|
1346
1659
|
isChangeMessage,
|
|
1347
1660
|
isControlMessage,
|
|
1661
|
+
isVisibleInSnapshot,
|
|
1348
1662
|
resolveValue
|
|
1349
1663
|
});
|
|
1350
1664
|
//# sourceMappingURL=index.cjs.map
|