@electric-sql/client 1.1.4 → 1.1.5
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 +81 -38
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +17 -8
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +17 -8
- package/dist/index.legacy-esm.js +79 -36
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +81 -38
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +71 -32
- package/src/parser.ts +45 -7
package/dist/index.d.ts
CHANGED
|
@@ -368,16 +368,14 @@ interface ShapeStreamInterface<T extends Row<unknown> = Row> {
|
|
|
368
368
|
error?: unknown;
|
|
369
369
|
mode: LogMode;
|
|
370
370
|
forceDisconnectAndRefresh(): Promise<void>;
|
|
371
|
-
requestSnapshot(params: {
|
|
372
|
-
where?: string;
|
|
373
|
-
params?: Record<string, string>;
|
|
374
|
-
limit: number;
|
|
375
|
-
offset?: number;
|
|
376
|
-
orderBy: string;
|
|
377
|
-
}): Promise<{
|
|
371
|
+
requestSnapshot(params: SubsetParams): Promise<{
|
|
378
372
|
metadata: SnapshotMetadata;
|
|
379
373
|
data: Array<Message<T>>;
|
|
380
374
|
}>;
|
|
375
|
+
fetchSnapshot(opts: SubsetParams): Promise<{
|
|
376
|
+
metadata: SnapshotMetadata;
|
|
377
|
+
data: Array<ChangeMessage<T>>;
|
|
378
|
+
}>;
|
|
381
379
|
}
|
|
382
380
|
/**
|
|
383
381
|
* Reads updates to a shape from Electric using HTTP requests and long polling or
|
|
@@ -451,7 +449,7 @@ declare class ShapeStream<T extends Row<unknown> = Row> implements ShapeStreamIn
|
|
|
451
449
|
*/
|
|
452
450
|
forceDisconnectAndRefresh(): Promise<void>;
|
|
453
451
|
/**
|
|
454
|
-
* Request a snapshot for subset of data.
|
|
452
|
+
* Request a snapshot for subset of data and inject it into the subscribed data stream.
|
|
455
453
|
*
|
|
456
454
|
* Only available when mode is `changes_only`.
|
|
457
455
|
* Returns the insertion point & the data, but more importantly injects the data
|
|
@@ -468,6 +466,17 @@ declare class ShapeStream<T extends Row<unknown> = Row> implements ShapeStreamIn
|
|
|
468
466
|
metadata: SnapshotMetadata;
|
|
469
467
|
data: Array<ChangeMessage<T>>;
|
|
470
468
|
}>;
|
|
469
|
+
/**
|
|
470
|
+
* Fetch a snapshot for subset of data.
|
|
471
|
+
* Returns the metadata and the data, but does not inject it into the subscribed data stream.
|
|
472
|
+
*
|
|
473
|
+
* @param opts - The options for the snapshot request.
|
|
474
|
+
* @returns The metadata and the data for the snapshot.
|
|
475
|
+
*/
|
|
476
|
+
fetchSnapshot(opts: SubsetParams): Promise<{
|
|
477
|
+
metadata: SnapshotMetadata;
|
|
478
|
+
data: Array<ChangeMessage<T>>;
|
|
479
|
+
}>;
|
|
471
480
|
}
|
|
472
481
|
|
|
473
482
|
type ShapeData<T extends Row<unknown> = Row> = Map<string, T>;
|
package/dist/index.legacy-esm.js
CHANGED
|
@@ -203,15 +203,37 @@ var MessageParser = class {
|
|
|
203
203
|
parse(messages, schema) {
|
|
204
204
|
return JSON.parse(messages, (key, value) => {
|
|
205
205
|
if ((key === `value` || key === `old_value`) && typeof value === `object` && value !== null) {
|
|
206
|
-
|
|
207
|
-
Object.keys(row).forEach((key2) => {
|
|
208
|
-
row[key2] = this.parseRow(key2, row[key2], schema);
|
|
209
|
-
});
|
|
210
|
-
if (this.transformer) value = this.transformer(value);
|
|
206
|
+
return this.transformMessageValue(value, schema);
|
|
211
207
|
}
|
|
212
208
|
return value;
|
|
213
209
|
});
|
|
214
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Parse an array of ChangeMessages from a snapshot response.
|
|
213
|
+
* Applies type parsing and transformations to the value and old_value properties.
|
|
214
|
+
*/
|
|
215
|
+
parseSnapshotData(messages, schema) {
|
|
216
|
+
return messages.map((message) => {
|
|
217
|
+
const msg = message;
|
|
218
|
+
if (msg.value && typeof msg.value === `object` && msg.value !== null) {
|
|
219
|
+
msg.value = this.transformMessageValue(msg.value, schema);
|
|
220
|
+
}
|
|
221
|
+
if (msg.old_value && typeof msg.old_value === `object` && msg.old_value !== null) {
|
|
222
|
+
msg.old_value = this.transformMessageValue(msg.old_value, schema);
|
|
223
|
+
}
|
|
224
|
+
return msg;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Transform a message value or old_value object by parsing its columns.
|
|
229
|
+
*/
|
|
230
|
+
transformMessageValue(value, schema) {
|
|
231
|
+
const row = value;
|
|
232
|
+
Object.keys(row).forEach((key) => {
|
|
233
|
+
row[key] = this.parseRow(key, row[key], schema);
|
|
234
|
+
});
|
|
235
|
+
return this.transformer ? this.transformer(row) : row;
|
|
236
|
+
}
|
|
215
237
|
// Parses the message values using the provided parser based on the schema information
|
|
216
238
|
parseRow(key, value, schema) {
|
|
217
239
|
var _b;
|
|
@@ -751,7 +773,7 @@ function canonicalShapeKey(url) {
|
|
|
751
773
|
cleanUrl.searchParams.sort();
|
|
752
774
|
return cleanUrl.toString();
|
|
753
775
|
}
|
|
754
|
-
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, _lastSseConnectionStartTime, _minSseConnectionDuration, _consecutiveShortSseConnections, _maxShortSseConnections, _sseFallbackToLongPolling, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _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
|
|
776
|
+
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, _lastSseConnectionStartTime, _minSseConnectionDuration, _consecutiveShortSseConnections, _maxShortSseConnections, _sseFallbackToLongPolling, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _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;
|
|
755
777
|
var ShapeStream = class {
|
|
756
778
|
constructor(options) {
|
|
757
779
|
__privateAdd(this, _ShapeStream_instances);
|
|
@@ -896,7 +918,7 @@ var ShapeStream = class {
|
|
|
896
918
|
__privateSet(this, _isRefreshing, false);
|
|
897
919
|
}
|
|
898
920
|
/**
|
|
899
|
-
* Request a snapshot for subset of data.
|
|
921
|
+
* Request a snapshot for subset of data and inject it into the subscribed data stream.
|
|
900
922
|
*
|
|
901
923
|
* Only available when mode is `changes_only`.
|
|
902
924
|
* Returns the insertion point & the data, but more importantly injects the data
|
|
@@ -922,8 +944,7 @@ var ShapeStream = class {
|
|
|
922
944
|
if (__privateGet(this, _activeSnapshotRequests) === 1) {
|
|
923
945
|
__privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
|
|
924
946
|
}
|
|
925
|
-
const {
|
|
926
|
-
const { metadata, data } = await __privateMethod(this, _ShapeStream_instances, fetchSnapshot_fn).call(this, fetchUrl, requestHeaders);
|
|
947
|
+
const { metadata, data } = await this.fetchSnapshot(opts);
|
|
927
948
|
const dataWithEndBoundary = data.concat([
|
|
928
949
|
{ headers: __spreadValues({ control: `snapshot-end` }, metadata) }
|
|
929
950
|
]);
|
|
@@ -943,6 +964,42 @@ var ShapeStream = class {
|
|
|
943
964
|
}
|
|
944
965
|
}
|
|
945
966
|
}
|
|
967
|
+
/**
|
|
968
|
+
* Fetch a snapshot for subset of data.
|
|
969
|
+
* Returns the metadata and the data, but does not inject it into the subscribed data stream.
|
|
970
|
+
*
|
|
971
|
+
* @param opts - The options for the snapshot request.
|
|
972
|
+
* @returns The metadata and the data for the snapshot.
|
|
973
|
+
*/
|
|
974
|
+
async fetchSnapshot(opts) {
|
|
975
|
+
var _a;
|
|
976
|
+
const { fetchUrl, requestHeaders } = await __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
|
|
977
|
+
const response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
|
|
978
|
+
headers: requestHeaders
|
|
979
|
+
});
|
|
980
|
+
if (!response.ok) {
|
|
981
|
+
throw new FetchError(
|
|
982
|
+
response.status,
|
|
983
|
+
void 0,
|
|
984
|
+
void 0,
|
|
985
|
+
Object.fromEntries([...response.headers.entries()]),
|
|
986
|
+
fetchUrl.toString()
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
const schema = (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(response.headers, {
|
|
990
|
+
required: true,
|
|
991
|
+
url: fetchUrl.toString()
|
|
992
|
+
});
|
|
993
|
+
const { metadata, data: rawData } = await response.json();
|
|
994
|
+
const data = __privateGet(this, _messageParser).parseSnapshotData(
|
|
995
|
+
rawData,
|
|
996
|
+
schema
|
|
997
|
+
);
|
|
998
|
+
return {
|
|
999
|
+
metadata,
|
|
1000
|
+
data
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
946
1003
|
};
|
|
947
1004
|
_error = new WeakMap();
|
|
948
1005
|
_fetchClient2 = new WeakMap();
|
|
@@ -1112,7 +1169,8 @@ constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
|
|
|
1112
1169
|
}
|
|
1113
1170
|
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
|
|
1114
1171
|
fetchUrl.searchParams.set(LOG_MODE_QUERY_PARAM, __privateGet(this, _mode));
|
|
1115
|
-
|
|
1172
|
+
const isSnapshotRequest = subsetParams !== void 0;
|
|
1173
|
+
if (__privateGet(this, _isUpToDate) && !isSnapshotRequest) {
|
|
1116
1174
|
if (!__privateGet(this, _isRefreshing) && !resumingFromPause) {
|
|
1117
1175
|
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
|
|
1118
1176
|
}
|
|
@@ -1165,11 +1223,7 @@ onInitialResponse_fn = async function(response) {
|
|
|
1165
1223
|
if (liveCacheBuster) {
|
|
1166
1224
|
__privateSet(this, _liveCacheBuster, liveCacheBuster);
|
|
1167
1225
|
}
|
|
1168
|
-
|
|
1169
|
-
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
1170
|
-
return schemaHeader ? JSON.parse(schemaHeader) : {};
|
|
1171
|
-
};
|
|
1172
|
-
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchema());
|
|
1226
|
+
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(headers));
|
|
1173
1227
|
if (status === 204) {
|
|
1174
1228
|
__privateSet(this, _lastSyncedAt, Date.now());
|
|
1175
1229
|
}
|
|
@@ -1382,31 +1436,20 @@ reset_fn = function(handle) {
|
|
|
1382
1436
|
__privateSet(this, _consecutiveShortSseConnections, 0);
|
|
1383
1437
|
__privateSet(this, _sseFallbackToLongPolling, false);
|
|
1384
1438
|
};
|
|
1385
|
-
fetchSnapshot_fn = async function(url, headers) {
|
|
1386
|
-
const response = await __privateGet(this, _fetchClient2).call(this, url.toString(), { headers });
|
|
1387
|
-
if (!response.ok) {
|
|
1388
|
-
throw new FetchError(
|
|
1389
|
-
response.status,
|
|
1390
|
-
void 0,
|
|
1391
|
-
void 0,
|
|
1392
|
-
Object.fromEntries([...response.headers.entries()]),
|
|
1393
|
-
url.toString()
|
|
1394
|
-
);
|
|
1395
|
-
}
|
|
1396
|
-
const { metadata, data } = await response.json();
|
|
1397
|
-
const batch = __privateGet(this, _messageParser).parse(
|
|
1398
|
-
JSON.stringify(data),
|
|
1399
|
-
__privateGet(this, _schema)
|
|
1400
|
-
);
|
|
1401
|
-
return {
|
|
1402
|
-
metadata,
|
|
1403
|
-
data: batch
|
|
1404
|
-
};
|
|
1405
|
-
};
|
|
1406
1439
|
ShapeStream.Replica = {
|
|
1407
1440
|
FULL: `full`,
|
|
1408
1441
|
DEFAULT: `default`
|
|
1409
1442
|
};
|
|
1443
|
+
function getSchemaFromHeaders(headers, options) {
|
|
1444
|
+
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
1445
|
+
if (!schemaHeader) {
|
|
1446
|
+
if ((options == null ? void 0 : options.required) && (options == null ? void 0 : options.url)) {
|
|
1447
|
+
throw new MissingHeadersError(options.url, [SHAPE_SCHEMA_HEADER]);
|
|
1448
|
+
}
|
|
1449
|
+
return {};
|
|
1450
|
+
}
|
|
1451
|
+
return JSON.parse(schemaHeader);
|
|
1452
|
+
}
|
|
1410
1453
|
function validateParams(params) {
|
|
1411
1454
|
if (!params) return;
|
|
1412
1455
|
const reservedParams = Object.keys(params).filter(
|