@electric-sql/client 1.1.3 → 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 +95 -41
- 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 +93 -39
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +95 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +96 -34
- package/src/parser.ts +45 -7
package/dist/index.mjs
CHANGED
|
@@ -225,15 +225,37 @@ var MessageParser = class {
|
|
|
225
225
|
parse(messages, schema) {
|
|
226
226
|
return JSON.parse(messages, (key, value) => {
|
|
227
227
|
if ((key === `value` || key === `old_value`) && typeof value === `object` && value !== null) {
|
|
228
|
-
|
|
229
|
-
Object.keys(row).forEach((key2) => {
|
|
230
|
-
row[key2] = this.parseRow(key2, row[key2], schema);
|
|
231
|
-
});
|
|
232
|
-
if (this.transformer) value = this.transformer(value);
|
|
228
|
+
return this.transformMessageValue(value, schema);
|
|
233
229
|
}
|
|
234
230
|
return value;
|
|
235
231
|
});
|
|
236
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Parse an array of ChangeMessages from a snapshot response.
|
|
235
|
+
* Applies type parsing and transformations to the value and old_value properties.
|
|
236
|
+
*/
|
|
237
|
+
parseSnapshotData(messages, schema) {
|
|
238
|
+
return messages.map((message) => {
|
|
239
|
+
const msg = message;
|
|
240
|
+
if (msg.value && typeof msg.value === `object` && msg.value !== null) {
|
|
241
|
+
msg.value = this.transformMessageValue(msg.value, schema);
|
|
242
|
+
}
|
|
243
|
+
if (msg.old_value && typeof msg.old_value === `object` && msg.old_value !== null) {
|
|
244
|
+
msg.old_value = this.transformMessageValue(msg.old_value, schema);
|
|
245
|
+
}
|
|
246
|
+
return msg;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Transform a message value or old_value object by parsing its columns.
|
|
251
|
+
*/
|
|
252
|
+
transformMessageValue(value, schema) {
|
|
253
|
+
const row = value;
|
|
254
|
+
Object.keys(row).forEach((key) => {
|
|
255
|
+
row[key] = this.parseRow(key, row[key], schema);
|
|
256
|
+
});
|
|
257
|
+
return this.transformer ? this.transformer(row) : row;
|
|
258
|
+
}
|
|
237
259
|
// Parses the message values using the provided parser based on the schema information
|
|
238
260
|
parseRow(key, value, schema) {
|
|
239
261
|
var _b;
|
|
@@ -781,9 +803,8 @@ function canonicalShapeKey(url) {
|
|
|
781
803
|
cleanUrl.searchParams.sort();
|
|
782
804
|
return cleanUrl.toString();
|
|
783
805
|
}
|
|
784
|
-
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, _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
|
|
806
|
+
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;
|
|
785
807
|
var ShapeStream = class {
|
|
786
|
-
// Maximum delay cap (ms)
|
|
787
808
|
constructor(options) {
|
|
788
809
|
__privateAdd(this, _ShapeStream_instances);
|
|
789
810
|
__privateAdd(this, _error, null);
|
|
@@ -827,6 +848,8 @@ var ShapeStream = class {
|
|
|
827
848
|
__privateAdd(this, _sseBackoffBaseDelay, 100);
|
|
828
849
|
// Base delay for exponential backoff (ms)
|
|
829
850
|
__privateAdd(this, _sseBackoffMaxDelay, 5e3);
|
|
851
|
+
// Maximum delay cap (ms)
|
|
852
|
+
__privateAdd(this, _unsubscribeFromVisibilityChanges);
|
|
830
853
|
var _a, _b, _c, _d;
|
|
831
854
|
this.options = __spreadValues({ subscribe: true }, options);
|
|
832
855
|
validateOptions(this.options);
|
|
@@ -882,7 +905,9 @@ var ShapeStream = class {
|
|
|
882
905
|
};
|
|
883
906
|
}
|
|
884
907
|
unsubscribeAll() {
|
|
908
|
+
var _a;
|
|
885
909
|
__privateGet(this, _subscribers).clear();
|
|
910
|
+
(_a = __privateGet(this, _unsubscribeFromVisibilityChanges)) == null ? void 0 : _a.call(this);
|
|
886
911
|
}
|
|
887
912
|
/** Unix time at which we last synced. Undefined when `isLoading` is true. */
|
|
888
913
|
lastSyncedAt() {
|
|
@@ -925,7 +950,7 @@ var ShapeStream = class {
|
|
|
925
950
|
});
|
|
926
951
|
}
|
|
927
952
|
/**
|
|
928
|
-
* Request a snapshot for subset of data.
|
|
953
|
+
* Request a snapshot for subset of data and inject it into the subscribed data stream.
|
|
929
954
|
*
|
|
930
955
|
* Only available when mode is `changes_only`.
|
|
931
956
|
* Returns the insertion point & the data, but more importantly injects the data
|
|
@@ -952,8 +977,7 @@ var ShapeStream = class {
|
|
|
952
977
|
if (__privateGet(this, _activeSnapshotRequests) === 1) {
|
|
953
978
|
__privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
|
|
954
979
|
}
|
|
955
|
-
const {
|
|
956
|
-
const { metadata, data } = yield __privateMethod(this, _ShapeStream_instances, fetchSnapshot_fn).call(this, fetchUrl, requestHeaders);
|
|
980
|
+
const { metadata, data } = yield this.fetchSnapshot(opts);
|
|
957
981
|
const dataWithEndBoundary = data.concat([
|
|
958
982
|
{ headers: __spreadValues({ control: `snapshot-end` }, metadata) }
|
|
959
983
|
]);
|
|
@@ -974,6 +998,44 @@ var ShapeStream = class {
|
|
|
974
998
|
}
|
|
975
999
|
});
|
|
976
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Fetch a snapshot for subset of data.
|
|
1003
|
+
* Returns the metadata and the data, but does not inject it into the subscribed data stream.
|
|
1004
|
+
*
|
|
1005
|
+
* @param opts - The options for the snapshot request.
|
|
1006
|
+
* @returns The metadata and the data for the snapshot.
|
|
1007
|
+
*/
|
|
1008
|
+
fetchSnapshot(opts) {
|
|
1009
|
+
return __async(this, null, function* () {
|
|
1010
|
+
var _a;
|
|
1011
|
+
const { fetchUrl, requestHeaders } = yield __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
|
|
1012
|
+
const response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
|
|
1013
|
+
headers: requestHeaders
|
|
1014
|
+
});
|
|
1015
|
+
if (!response.ok) {
|
|
1016
|
+
throw new FetchError(
|
|
1017
|
+
response.status,
|
|
1018
|
+
void 0,
|
|
1019
|
+
void 0,
|
|
1020
|
+
Object.fromEntries([...response.headers.entries()]),
|
|
1021
|
+
fetchUrl.toString()
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
const schema = (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(response.headers, {
|
|
1025
|
+
required: true,
|
|
1026
|
+
url: fetchUrl.toString()
|
|
1027
|
+
});
|
|
1028
|
+
const { metadata, data: rawData } = yield response.json();
|
|
1029
|
+
const data = __privateGet(this, _messageParser).parseSnapshotData(
|
|
1030
|
+
rawData,
|
|
1031
|
+
schema
|
|
1032
|
+
);
|
|
1033
|
+
return {
|
|
1034
|
+
metadata,
|
|
1035
|
+
data
|
|
1036
|
+
};
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
977
1039
|
};
|
|
978
1040
|
_error = new WeakMap();
|
|
979
1041
|
_fetchClient2 = new WeakMap();
|
|
@@ -1009,6 +1071,7 @@ _maxShortSseConnections = new WeakMap();
|
|
|
1009
1071
|
_sseFallbackToLongPolling = new WeakMap();
|
|
1010
1072
|
_sseBackoffBaseDelay = new WeakMap();
|
|
1011
1073
|
_sseBackoffMaxDelay = new WeakMap();
|
|
1074
|
+
_unsubscribeFromVisibilityChanges = new WeakMap();
|
|
1012
1075
|
_ShapeStream_instances = new WeakSet();
|
|
1013
1076
|
start_fn = function() {
|
|
1014
1077
|
return __async(this, null, function* () {
|
|
@@ -1078,7 +1141,8 @@ requestShape_fn = function() {
|
|
|
1078
1141
|
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
1079
1142
|
}
|
|
1080
1143
|
if (e instanceof FetchBackoffAbortError) {
|
|
1081
|
-
|
|
1144
|
+
const currentState = __privateGet(this, _state);
|
|
1145
|
+
if (requestAbortController.signal.aborted && requestAbortController.signal.reason === PAUSE_STREAM && currentState === `pause-requested`) {
|
|
1082
1146
|
__privateSet(this, _state, `paused`);
|
|
1083
1147
|
}
|
|
1084
1148
|
return;
|
|
@@ -1146,7 +1210,8 @@ constructUrl_fn = function(url, resumingFromPause, subsetParams) {
|
|
|
1146
1210
|
}
|
|
1147
1211
|
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
|
|
1148
1212
|
fetchUrl.searchParams.set(LOG_MODE_QUERY_PARAM, __privateGet(this, _mode));
|
|
1149
|
-
|
|
1213
|
+
const isSnapshotRequest = subsetParams !== void 0;
|
|
1214
|
+
if (__privateGet(this, _isUpToDate) && !isSnapshotRequest) {
|
|
1150
1215
|
if (!__privateGet(this, _isRefreshing) && !resumingFromPause) {
|
|
1151
1216
|
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
|
|
1152
1217
|
}
|
|
@@ -1203,11 +1268,7 @@ onInitialResponse_fn = function(response) {
|
|
|
1203
1268
|
if (liveCacheBuster) {
|
|
1204
1269
|
__privateSet(this, _liveCacheBuster, liveCacheBuster);
|
|
1205
1270
|
}
|
|
1206
|
-
|
|
1207
|
-
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
1208
|
-
return schemaHeader ? JSON.parse(schemaHeader) : {};
|
|
1209
|
-
};
|
|
1210
|
-
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchema());
|
|
1271
|
+
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(headers));
|
|
1211
1272
|
if (status === 204) {
|
|
1212
1273
|
__privateSet(this, _lastSyncedAt, Date.now());
|
|
1213
1274
|
}
|
|
@@ -1339,7 +1400,10 @@ pause_fn = function() {
|
|
|
1339
1400
|
}
|
|
1340
1401
|
};
|
|
1341
1402
|
resume_fn = function() {
|
|
1342
|
-
if (__privateGet(this, _started) && __privateGet(this, _state) === `paused`) {
|
|
1403
|
+
if (__privateGet(this, _started) && (__privateGet(this, _state) === `paused` || __privateGet(this, _state) === `pause-requested`)) {
|
|
1404
|
+
if (__privateGet(this, _state) === `pause-requested`) {
|
|
1405
|
+
__privateSet(this, _state, `active`);
|
|
1406
|
+
}
|
|
1343
1407
|
__privateMethod(this, _ShapeStream_instances, start_fn).call(this);
|
|
1344
1408
|
}
|
|
1345
1409
|
};
|
|
@@ -1411,6 +1475,9 @@ subscribeToVisibilityChanges_fn = function() {
|
|
|
1411
1475
|
}
|
|
1412
1476
|
};
|
|
1413
1477
|
document.addEventListener(`visibilitychange`, visibilityHandler);
|
|
1478
|
+
__privateSet(this, _unsubscribeFromVisibilityChanges, () => {
|
|
1479
|
+
document.removeEventListener(`visibilitychange`, visibilityHandler);
|
|
1480
|
+
});
|
|
1414
1481
|
}
|
|
1415
1482
|
};
|
|
1416
1483
|
/**
|
|
@@ -1429,33 +1496,20 @@ reset_fn = function(handle) {
|
|
|
1429
1496
|
__privateSet(this, _consecutiveShortSseConnections, 0);
|
|
1430
1497
|
__privateSet(this, _sseFallbackToLongPolling, false);
|
|
1431
1498
|
};
|
|
1432
|
-
fetchSnapshot_fn = function(url, headers) {
|
|
1433
|
-
return __async(this, null, function* () {
|
|
1434
|
-
const response = yield __privateGet(this, _fetchClient2).call(this, url.toString(), { headers });
|
|
1435
|
-
if (!response.ok) {
|
|
1436
|
-
throw new FetchError(
|
|
1437
|
-
response.status,
|
|
1438
|
-
void 0,
|
|
1439
|
-
void 0,
|
|
1440
|
-
Object.fromEntries([...response.headers.entries()]),
|
|
1441
|
-
url.toString()
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1444
|
-
const { metadata, data } = yield response.json();
|
|
1445
|
-
const batch = __privateGet(this, _messageParser).parse(
|
|
1446
|
-
JSON.stringify(data),
|
|
1447
|
-
__privateGet(this, _schema)
|
|
1448
|
-
);
|
|
1449
|
-
return {
|
|
1450
|
-
metadata,
|
|
1451
|
-
data: batch
|
|
1452
|
-
};
|
|
1453
|
-
});
|
|
1454
|
-
};
|
|
1455
1499
|
ShapeStream.Replica = {
|
|
1456
1500
|
FULL: `full`,
|
|
1457
1501
|
DEFAULT: `default`
|
|
1458
1502
|
};
|
|
1503
|
+
function getSchemaFromHeaders(headers, options) {
|
|
1504
|
+
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
1505
|
+
if (!schemaHeader) {
|
|
1506
|
+
if ((options == null ? void 0 : options.required) && (options == null ? void 0 : options.url)) {
|
|
1507
|
+
throw new MissingHeadersError(options.url, [SHAPE_SCHEMA_HEADER]);
|
|
1508
|
+
}
|
|
1509
|
+
return {};
|
|
1510
|
+
}
|
|
1511
|
+
return JSON.parse(schemaHeader);
|
|
1512
|
+
}
|
|
1459
1513
|
function validateParams(params) {
|
|
1460
1514
|
if (!params) return;
|
|
1461
1515
|
const reservedParams = Object.keys(params).filter(
|