@electric-sql/client 1.5.5 → 1.5.7
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 +65 -8
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +4 -2
- package/dist/index.browser.mjs +4 -4
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.legacy-esm.js +65 -8
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +65 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +56 -8
- package/src/fetch.ts +26 -0
- package/src/helpers.ts +15 -0
- package/src/shape-stream-state.ts +23 -0
- package/src/shape.ts +6 -2
- package/src/types.ts +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -476,6 +476,12 @@ function getOffset(message) {
|
|
|
476
476
|
const lsn = message.headers.global_last_seen_lsn;
|
|
477
477
|
return lsn ? `${lsn}_0` : void 0;
|
|
478
478
|
}
|
|
479
|
+
function bigintReplacer(_key, value) {
|
|
480
|
+
return typeof value === `bigint` ? value.toString() : value;
|
|
481
|
+
}
|
|
482
|
+
function bigintSafeStringify(value) {
|
|
483
|
+
return JSON.stringify(value, bigintReplacer);
|
|
484
|
+
}
|
|
479
485
|
function isVisibleInSnapshot(txid, snapshot) {
|
|
480
486
|
const xid = BigInt(txid);
|
|
481
487
|
const xmin = BigInt(snapshot.xmin);
|
|
@@ -646,6 +652,12 @@ function createFetchWithChunkBuffer(fetchClient, prefetchOptions = ChunkPrefetch
|
|
|
646
652
|
let prefetchQueue;
|
|
647
653
|
const prefetchClient = async (...args) => {
|
|
648
654
|
const url = args[0].toString();
|
|
655
|
+
const method = getRequestMethod(args[0], args[1]);
|
|
656
|
+
if (method !== `GET`) {
|
|
657
|
+
prefetchQueue == null ? void 0 : prefetchQueue.abort();
|
|
658
|
+
prefetchQueue = void 0;
|
|
659
|
+
return fetchClient(...args);
|
|
660
|
+
}
|
|
649
661
|
const prefetchedRequest = prefetchQueue == null ? void 0 : prefetchQueue.consume(...args);
|
|
650
662
|
if (prefetchedRequest) {
|
|
651
663
|
return prefetchedRequest;
|
|
@@ -815,6 +827,15 @@ function chainAborter(aborter, sourceSignal) {
|
|
|
815
827
|
}
|
|
816
828
|
function noop() {
|
|
817
829
|
}
|
|
830
|
+
function getRequestMethod(input, init) {
|
|
831
|
+
if (init == null ? void 0 : init.method) {
|
|
832
|
+
return init.method.toUpperCase();
|
|
833
|
+
}
|
|
834
|
+
if (typeof Request !== `undefined` && input instanceof Request) {
|
|
835
|
+
return input.method.toUpperCase();
|
|
836
|
+
}
|
|
837
|
+
return `GET`;
|
|
838
|
+
}
|
|
818
839
|
|
|
819
840
|
// src/expression-compiler.ts
|
|
820
841
|
function compileExpression(expr, columnMapper) {
|
|
@@ -1491,6 +1512,12 @@ var FetchingState = class extends ActiveState {
|
|
|
1491
1512
|
const staleResult = this.checkStaleResponse(input);
|
|
1492
1513
|
if (staleResult) return staleResult;
|
|
1493
1514
|
const shared = this.parseResponseFields(input);
|
|
1515
|
+
if (input.status === 204) {
|
|
1516
|
+
return {
|
|
1517
|
+
action: `accepted`,
|
|
1518
|
+
state: new LiveState(shared, { sseFallbackToLongPolling: true })
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1494
1521
|
return { action: `accepted`, state: new SyncingState(shared) };
|
|
1495
1522
|
}
|
|
1496
1523
|
canEnterReplayMode() {
|
|
@@ -1720,6 +1747,13 @@ var PausedState = class _PausedState extends ShapeStreamState {
|
|
|
1720
1747
|
get replayCursor() {
|
|
1721
1748
|
return this.previousState.replayCursor;
|
|
1722
1749
|
}
|
|
1750
|
+
handleResponseMetadata(input) {
|
|
1751
|
+
const transition = this.previousState.handleResponseMetadata(input);
|
|
1752
|
+
if (transition.action === `accepted`) {
|
|
1753
|
+
return { action: `accepted`, state: new _PausedState(transition.state) };
|
|
1754
|
+
}
|
|
1755
|
+
return transition;
|
|
1756
|
+
}
|
|
1723
1757
|
withHandle(handle) {
|
|
1724
1758
|
return new _PausedState(this.previousState.withHandle(handle));
|
|
1725
1759
|
}
|
|
@@ -2110,7 +2144,7 @@ var ShapeStream = class {
|
|
|
2110
2144
|
);
|
|
2111
2145
|
}, 3e4);
|
|
2112
2146
|
try {
|
|
2113
|
-
const { metadata, data } = await this.fetchSnapshot(opts);
|
|
2147
|
+
const { metadata, data, responseOffset, responseHandle } = await this.fetchSnapshot(opts);
|
|
2114
2148
|
const dataWithEndBoundary = data.concat([
|
|
2115
2149
|
{ headers: __spreadValues({ control: `snapshot-end` }, metadata) },
|
|
2116
2150
|
{ headers: __spreadValues({ control: `subset-end` }, opts) }
|
|
@@ -2120,6 +2154,25 @@ var ShapeStream = class {
|
|
|
2120
2154
|
new Set(data.map((message) => message.key))
|
|
2121
2155
|
);
|
|
2122
2156
|
__privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, dataWithEndBoundary, false);
|
|
2157
|
+
if (responseOffset !== null || responseHandle !== null) {
|
|
2158
|
+
const transition = __privateGet(this, _syncState).handleResponseMetadata({
|
|
2159
|
+
status: 200,
|
|
2160
|
+
responseHandle,
|
|
2161
|
+
responseOffset,
|
|
2162
|
+
responseCursor: null,
|
|
2163
|
+
expiredHandle: null,
|
|
2164
|
+
now: Date.now(),
|
|
2165
|
+
maxStaleCacheRetries: __privateGet(this, _maxStaleCacheRetries),
|
|
2166
|
+
createCacheBuster: () => `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
|
|
2167
|
+
});
|
|
2168
|
+
if (transition.action === `accepted`) {
|
|
2169
|
+
__privateSet(this, _syncState, transition.state);
|
|
2170
|
+
} else {
|
|
2171
|
+
console.warn(
|
|
2172
|
+
`[Electric] Snapshot response metadata was not accepted by state "${__privateGet(this, _syncState).kind}" (action: ${transition.action}). Stream offset was not advanced from snapshot.`
|
|
2173
|
+
);
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2123
2176
|
return {
|
|
2124
2177
|
metadata,
|
|
2125
2178
|
data
|
|
@@ -2138,7 +2191,7 @@ var ShapeStream = class {
|
|
|
2138
2191
|
* `subsetMethod: 'POST'` on the stream to send parameters in the request body instead.
|
|
2139
2192
|
*
|
|
2140
2193
|
* @param opts - The options for the snapshot request.
|
|
2141
|
-
* @returns The metadata and the
|
|
2194
|
+
* @returns The metadata, data, and the response's offset/handle for state advancement.
|
|
2142
2195
|
*/
|
|
2143
2196
|
async fetchSnapshot(opts) {
|
|
2144
2197
|
var _a, _b, _c;
|
|
@@ -2154,7 +2207,7 @@ var ShapeStream = class {
|
|
|
2154
2207
|
headers: __spreadProps(__spreadValues({}, result.requestHeaders), {
|
|
2155
2208
|
"Content-Type": `application/json`
|
|
2156
2209
|
}),
|
|
2157
|
-
body:
|
|
2210
|
+
body: bigintSafeStringify(__privateMethod(this, _ShapeStream_instances, buildSubsetBody_fn).call(this, opts))
|
|
2158
2211
|
};
|
|
2159
2212
|
} else {
|
|
2160
2213
|
const result = await __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
|
|
@@ -2189,7 +2242,9 @@ var ShapeStream = class {
|
|
|
2189
2242
|
rawData,
|
|
2190
2243
|
schema
|
|
2191
2244
|
);
|
|
2192
|
-
|
|
2245
|
+
const responseOffset = response.headers.get(CHUNK_LAST_OFFSET_HEADER) || null;
|
|
2246
|
+
const responseHandle = response.headers.get(SHAPE_HANDLE_HEADER);
|
|
2247
|
+
return { metadata, data, responseOffset, responseHandle };
|
|
2193
2248
|
}
|
|
2194
2249
|
};
|
|
2195
2250
|
_error = new WeakMap();
|
|
@@ -2402,7 +2457,7 @@ constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
|
|
|
2402
2457
|
if (subsetParams.params)
|
|
2403
2458
|
fetchUrl.searchParams.set(
|
|
2404
2459
|
SUBSET_PARAM_WHERE_PARAMS,
|
|
2405
|
-
|
|
2460
|
+
bigintSafeStringify(subsetParams.params)
|
|
2406
2461
|
);
|
|
2407
2462
|
if (subsetParams.limit)
|
|
2408
2463
|
setQueryParam(fetchUrl, SUBSET_PARAM_LIMIT, subsetParams.limit);
|
|
@@ -2581,7 +2636,7 @@ requestShapeLongPoll_fn = async function(opts) {
|
|
|
2581
2636
|
const messages = res || `[]`;
|
|
2582
2637
|
const batch = __privateGet(this, _messageParser).parse(messages, schema);
|
|
2583
2638
|
if (!Array.isArray(batch)) {
|
|
2584
|
-
const preview = (_a =
|
|
2639
|
+
const preview = (_a = bigintSafeStringify(batch)) == null ? void 0 : _a.slice(0, 200);
|
|
2585
2640
|
throw new FetchError(
|
|
2586
2641
|
response.status,
|
|
2587
2642
|
`Received non-array response body from shape endpoint. This may indicate a proxy or CDN is returning an unexpected response. Expected a JSON array, got ${typeof batch}: ${preview}`,
|
|
@@ -2639,7 +2694,9 @@ requestShapeSSE_fn = async function(opts) {
|
|
|
2639
2694
|
if (requestAbortController.signal.aborted) {
|
|
2640
2695
|
throw new FetchBackoffAbortError();
|
|
2641
2696
|
}
|
|
2642
|
-
|
|
2697
|
+
if (error instanceof FetchError || error instanceof StaleCacheError || error instanceof MissingHeadersError) {
|
|
2698
|
+
throw error;
|
|
2699
|
+
}
|
|
2643
2700
|
} finally {
|
|
2644
2701
|
const connectionDuration = Date.now() - __privateGet(this, _lastSseConnectionStartTime);
|
|
2645
2702
|
const wasAborted = requestAbortController.signal.aborted;
|
|
@@ -2943,7 +3000,7 @@ var Shape = class {
|
|
|
2943
3000
|
* Returns void; data will be emitted via the stream and processed by this Shape.
|
|
2944
3001
|
*/
|
|
2945
3002
|
async requestSnapshot(params) {
|
|
2946
|
-
const key =
|
|
3003
|
+
const key = bigintSafeStringify(params);
|
|
2947
3004
|
__privateGet(this, _requestedSubSnapshots).add(key);
|
|
2948
3005
|
await __privateMethod(this, _Shape_instances, awaitUpToDate_fn).call(this);
|
|
2949
3006
|
await this.stream.requestSnapshot(params);
|