@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/cjs/index.cjs
CHANGED
|
@@ -256,15 +256,37 @@ var MessageParser = class {
|
|
|
256
256
|
parse(messages, schema) {
|
|
257
257
|
return JSON.parse(messages, (key, value) => {
|
|
258
258
|
if ((key === `value` || key === `old_value`) && typeof value === `object` && value !== null) {
|
|
259
|
-
|
|
260
|
-
Object.keys(row).forEach((key2) => {
|
|
261
|
-
row[key2] = this.parseRow(key2, row[key2], schema);
|
|
262
|
-
});
|
|
263
|
-
if (this.transformer) value = this.transformer(value);
|
|
259
|
+
return this.transformMessageValue(value, schema);
|
|
264
260
|
}
|
|
265
261
|
return value;
|
|
266
262
|
});
|
|
267
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Parse an array of ChangeMessages from a snapshot response.
|
|
266
|
+
* Applies type parsing and transformations to the value and old_value properties.
|
|
267
|
+
*/
|
|
268
|
+
parseSnapshotData(messages, schema) {
|
|
269
|
+
return messages.map((message) => {
|
|
270
|
+
const msg = message;
|
|
271
|
+
if (msg.value && typeof msg.value === `object` && msg.value !== null) {
|
|
272
|
+
msg.value = this.transformMessageValue(msg.value, schema);
|
|
273
|
+
}
|
|
274
|
+
if (msg.old_value && typeof msg.old_value === `object` && msg.old_value !== null) {
|
|
275
|
+
msg.old_value = this.transformMessageValue(msg.old_value, schema);
|
|
276
|
+
}
|
|
277
|
+
return msg;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Transform a message value or old_value object by parsing its columns.
|
|
282
|
+
*/
|
|
283
|
+
transformMessageValue(value, schema) {
|
|
284
|
+
const row = value;
|
|
285
|
+
Object.keys(row).forEach((key) => {
|
|
286
|
+
row[key] = this.parseRow(key, row[key], schema);
|
|
287
|
+
});
|
|
288
|
+
return this.transformer ? this.transformer(row) : row;
|
|
289
|
+
}
|
|
268
290
|
// Parses the message values using the provided parser based on the schema information
|
|
269
291
|
parseRow(key, value, schema) {
|
|
270
292
|
var _b;
|
|
@@ -810,9 +832,8 @@ function canonicalShapeKey(url) {
|
|
|
810
832
|
cleanUrl.searchParams.sort();
|
|
811
833
|
return cleanUrl.toString();
|
|
812
834
|
}
|
|
813
|
-
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
|
|
835
|
+
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;
|
|
814
836
|
var ShapeStream = class {
|
|
815
|
-
// Maximum delay cap (ms)
|
|
816
837
|
constructor(options) {
|
|
817
838
|
__privateAdd(this, _ShapeStream_instances);
|
|
818
839
|
__privateAdd(this, _error, null);
|
|
@@ -856,6 +877,8 @@ var ShapeStream = class {
|
|
|
856
877
|
__privateAdd(this, _sseBackoffBaseDelay, 100);
|
|
857
878
|
// Base delay for exponential backoff (ms)
|
|
858
879
|
__privateAdd(this, _sseBackoffMaxDelay, 5e3);
|
|
880
|
+
// Maximum delay cap (ms)
|
|
881
|
+
__privateAdd(this, _unsubscribeFromVisibilityChanges);
|
|
859
882
|
var _a, _b, _c, _d;
|
|
860
883
|
this.options = __spreadValues({ subscribe: true }, options);
|
|
861
884
|
validateOptions(this.options);
|
|
@@ -911,7 +934,9 @@ var ShapeStream = class {
|
|
|
911
934
|
};
|
|
912
935
|
}
|
|
913
936
|
unsubscribeAll() {
|
|
937
|
+
var _a;
|
|
914
938
|
__privateGet(this, _subscribers).clear();
|
|
939
|
+
(_a = __privateGet(this, _unsubscribeFromVisibilityChanges)) == null ? void 0 : _a.call(this);
|
|
915
940
|
}
|
|
916
941
|
/** Unix time at which we last synced. Undefined when `isLoading` is true. */
|
|
917
942
|
lastSyncedAt() {
|
|
@@ -954,7 +979,7 @@ var ShapeStream = class {
|
|
|
954
979
|
});
|
|
955
980
|
}
|
|
956
981
|
/**
|
|
957
|
-
* Request a snapshot for subset of data.
|
|
982
|
+
* Request a snapshot for subset of data and inject it into the subscribed data stream.
|
|
958
983
|
*
|
|
959
984
|
* Only available when mode is `changes_only`.
|
|
960
985
|
* Returns the insertion point & the data, but more importantly injects the data
|
|
@@ -981,8 +1006,7 @@ var ShapeStream = class {
|
|
|
981
1006
|
if (__privateGet(this, _activeSnapshotRequests) === 1) {
|
|
982
1007
|
__privateMethod(this, _ShapeStream_instances, pause_fn).call(this);
|
|
983
1008
|
}
|
|
984
|
-
const {
|
|
985
|
-
const { metadata, data } = yield __privateMethod(this, _ShapeStream_instances, fetchSnapshot_fn).call(this, fetchUrl, requestHeaders);
|
|
1009
|
+
const { metadata, data } = yield this.fetchSnapshot(opts);
|
|
986
1010
|
const dataWithEndBoundary = data.concat([
|
|
987
1011
|
{ headers: __spreadValues({ control: `snapshot-end` }, metadata) }
|
|
988
1012
|
]);
|
|
@@ -1003,6 +1027,44 @@ var ShapeStream = class {
|
|
|
1003
1027
|
}
|
|
1004
1028
|
});
|
|
1005
1029
|
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Fetch a snapshot for subset of data.
|
|
1032
|
+
* Returns the metadata and the data, but does not inject it into the subscribed data stream.
|
|
1033
|
+
*
|
|
1034
|
+
* @param opts - The options for the snapshot request.
|
|
1035
|
+
* @returns The metadata and the data for the snapshot.
|
|
1036
|
+
*/
|
|
1037
|
+
fetchSnapshot(opts) {
|
|
1038
|
+
return __async(this, null, function* () {
|
|
1039
|
+
var _a;
|
|
1040
|
+
const { fetchUrl, requestHeaders } = yield __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
|
|
1041
|
+
const response = yield __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
|
|
1042
|
+
headers: requestHeaders
|
|
1043
|
+
});
|
|
1044
|
+
if (!response.ok) {
|
|
1045
|
+
throw new FetchError(
|
|
1046
|
+
response.status,
|
|
1047
|
+
void 0,
|
|
1048
|
+
void 0,
|
|
1049
|
+
Object.fromEntries([...response.headers.entries()]),
|
|
1050
|
+
fetchUrl.toString()
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
const schema = (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(response.headers, {
|
|
1054
|
+
required: true,
|
|
1055
|
+
url: fetchUrl.toString()
|
|
1056
|
+
});
|
|
1057
|
+
const { metadata, data: rawData } = yield response.json();
|
|
1058
|
+
const data = __privateGet(this, _messageParser).parseSnapshotData(
|
|
1059
|
+
rawData,
|
|
1060
|
+
schema
|
|
1061
|
+
);
|
|
1062
|
+
return {
|
|
1063
|
+
metadata,
|
|
1064
|
+
data
|
|
1065
|
+
};
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1006
1068
|
};
|
|
1007
1069
|
_error = new WeakMap();
|
|
1008
1070
|
_fetchClient2 = new WeakMap();
|
|
@@ -1038,6 +1100,7 @@ _maxShortSseConnections = new WeakMap();
|
|
|
1038
1100
|
_sseFallbackToLongPolling = new WeakMap();
|
|
1039
1101
|
_sseBackoffBaseDelay = new WeakMap();
|
|
1040
1102
|
_sseBackoffMaxDelay = new WeakMap();
|
|
1103
|
+
_unsubscribeFromVisibilityChanges = new WeakMap();
|
|
1041
1104
|
_ShapeStream_instances = new WeakSet();
|
|
1042
1105
|
start_fn = function() {
|
|
1043
1106
|
return __async(this, null, function* () {
|
|
@@ -1107,7 +1170,8 @@ requestShape_fn = function() {
|
|
|
1107
1170
|
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
1108
1171
|
}
|
|
1109
1172
|
if (e instanceof FetchBackoffAbortError) {
|
|
1110
|
-
|
|
1173
|
+
const currentState = __privateGet(this, _state);
|
|
1174
|
+
if (requestAbortController.signal.aborted && requestAbortController.signal.reason === PAUSE_STREAM && currentState === `pause-requested`) {
|
|
1111
1175
|
__privateSet(this, _state, `paused`);
|
|
1112
1176
|
}
|
|
1113
1177
|
return;
|
|
@@ -1175,7 +1239,8 @@ constructUrl_fn = function(url, resumingFromPause, subsetParams) {
|
|
|
1175
1239
|
}
|
|
1176
1240
|
fetchUrl.searchParams.set(OFFSET_QUERY_PARAM, __privateGet(this, _lastOffset));
|
|
1177
1241
|
fetchUrl.searchParams.set(LOG_MODE_QUERY_PARAM, __privateGet(this, _mode));
|
|
1178
|
-
|
|
1242
|
+
const isSnapshotRequest = subsetParams !== void 0;
|
|
1243
|
+
if (__privateGet(this, _isUpToDate) && !isSnapshotRequest) {
|
|
1179
1244
|
if (!__privateGet(this, _isRefreshing) && !resumingFromPause) {
|
|
1180
1245
|
fetchUrl.searchParams.set(LIVE_QUERY_PARAM, `true`);
|
|
1181
1246
|
}
|
|
@@ -1232,11 +1297,7 @@ onInitialResponse_fn = function(response) {
|
|
|
1232
1297
|
if (liveCacheBuster) {
|
|
1233
1298
|
__privateSet(this, _liveCacheBuster, liveCacheBuster);
|
|
1234
1299
|
}
|
|
1235
|
-
|
|
1236
|
-
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
1237
|
-
return schemaHeader ? JSON.parse(schemaHeader) : {};
|
|
1238
|
-
};
|
|
1239
|
-
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchema());
|
|
1300
|
+
__privateSet(this, _schema, (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(headers));
|
|
1240
1301
|
if (status === 204) {
|
|
1241
1302
|
__privateSet(this, _lastSyncedAt, Date.now());
|
|
1242
1303
|
}
|
|
@@ -1368,7 +1429,10 @@ pause_fn = function() {
|
|
|
1368
1429
|
}
|
|
1369
1430
|
};
|
|
1370
1431
|
resume_fn = function() {
|
|
1371
|
-
if (__privateGet(this, _started) && __privateGet(this, _state) === `paused`) {
|
|
1432
|
+
if (__privateGet(this, _started) && (__privateGet(this, _state) === `paused` || __privateGet(this, _state) === `pause-requested`)) {
|
|
1433
|
+
if (__privateGet(this, _state) === `pause-requested`) {
|
|
1434
|
+
__privateSet(this, _state, `active`);
|
|
1435
|
+
}
|
|
1372
1436
|
__privateMethod(this, _ShapeStream_instances, start_fn).call(this);
|
|
1373
1437
|
}
|
|
1374
1438
|
};
|
|
@@ -1440,6 +1504,9 @@ subscribeToVisibilityChanges_fn = function() {
|
|
|
1440
1504
|
}
|
|
1441
1505
|
};
|
|
1442
1506
|
document.addEventListener(`visibilitychange`, visibilityHandler);
|
|
1507
|
+
__privateSet(this, _unsubscribeFromVisibilityChanges, () => {
|
|
1508
|
+
document.removeEventListener(`visibilitychange`, visibilityHandler);
|
|
1509
|
+
});
|
|
1443
1510
|
}
|
|
1444
1511
|
};
|
|
1445
1512
|
/**
|
|
@@ -1458,33 +1525,20 @@ reset_fn = function(handle) {
|
|
|
1458
1525
|
__privateSet(this, _consecutiveShortSseConnections, 0);
|
|
1459
1526
|
__privateSet(this, _sseFallbackToLongPolling, false);
|
|
1460
1527
|
};
|
|
1461
|
-
fetchSnapshot_fn = function(url, headers) {
|
|
1462
|
-
return __async(this, null, function* () {
|
|
1463
|
-
const response = yield __privateGet(this, _fetchClient2).call(this, url.toString(), { headers });
|
|
1464
|
-
if (!response.ok) {
|
|
1465
|
-
throw new FetchError(
|
|
1466
|
-
response.status,
|
|
1467
|
-
void 0,
|
|
1468
|
-
void 0,
|
|
1469
|
-
Object.fromEntries([...response.headers.entries()]),
|
|
1470
|
-
url.toString()
|
|
1471
|
-
);
|
|
1472
|
-
}
|
|
1473
|
-
const { metadata, data } = yield response.json();
|
|
1474
|
-
const batch = __privateGet(this, _messageParser).parse(
|
|
1475
|
-
JSON.stringify(data),
|
|
1476
|
-
__privateGet(this, _schema)
|
|
1477
|
-
);
|
|
1478
|
-
return {
|
|
1479
|
-
metadata,
|
|
1480
|
-
data: batch
|
|
1481
|
-
};
|
|
1482
|
-
});
|
|
1483
|
-
};
|
|
1484
1528
|
ShapeStream.Replica = {
|
|
1485
1529
|
FULL: `full`,
|
|
1486
1530
|
DEFAULT: `default`
|
|
1487
1531
|
};
|
|
1532
|
+
function getSchemaFromHeaders(headers, options) {
|
|
1533
|
+
const schemaHeader = headers.get(SHAPE_SCHEMA_HEADER);
|
|
1534
|
+
if (!schemaHeader) {
|
|
1535
|
+
if ((options == null ? void 0 : options.required) && (options == null ? void 0 : options.url)) {
|
|
1536
|
+
throw new MissingHeadersError(options.url, [SHAPE_SCHEMA_HEADER]);
|
|
1537
|
+
}
|
|
1538
|
+
return {};
|
|
1539
|
+
}
|
|
1540
|
+
return JSON.parse(schemaHeader);
|
|
1541
|
+
}
|
|
1488
1542
|
function validateParams(params) {
|
|
1489
1543
|
if (!params) return;
|
|
1490
1544
|
const reservedParams = Object.keys(params).filter(
|