@electric-sql/client 1.4.2 → 1.5.1

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.
@@ -1177,7 +1177,7 @@ function canonicalShapeKey(url) {
1177
1177
  cleanUrl.searchParams.sort();
1178
1178
  return cleanUrl.toString();
1179
1179
  }
1180
- 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, _lastSeenCursor, _currentFetchUrl, _lastSseConnectionStartTime, _minSseConnectionDuration, _consecutiveShortSseConnections, _maxShortSseConnections, _sseFallbackToLongPolling, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _staleCacheBuster, _staleCacheRetryCount, _maxStaleCacheRetries, _ShapeStream_instances, replayMode_get, 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;
1180
+ 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, _lastSeenCursor, _currentFetchUrl, _lastSseConnectionStartTime, _minSseConnectionDuration, _consecutiveShortSseConnections, _maxShortSseConnections, _sseFallbackToLongPolling, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _staleCacheBuster, _staleCacheRetryCount, _maxStaleCacheRetries, _ShapeStream_instances, replayMode_get, 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, buildSubsetBody_fn;
1181
1181
  var ShapeStream = class {
1182
1182
  constructor(options) {
1183
1183
  __privateAdd(this, _ShapeStream_instances);
@@ -1392,25 +1392,53 @@ var ShapeStream = class {
1392
1392
  * Fetch a snapshot for subset of data.
1393
1393
  * Returns the metadata and the data, but does not inject it into the subscribed data stream.
1394
1394
  *
1395
+ * By default, uses GET to send subset parameters as query parameters. This may hit URL length
1396
+ * limits (HTTP 414) with large WHERE clauses or many parameters. Set `method: 'POST'` or use
1397
+ * `subsetMethod: 'POST'` on the stream to send parameters in the request body instead.
1398
+ *
1395
1399
  * @param opts - The options for the snapshot request.
1396
1400
  * @returns The metadata and the data for the snapshot.
1397
1401
  */
1398
1402
  async fetchSnapshot(opts) {
1399
- var _a;
1400
- const { fetchUrl, requestHeaders } = await __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
1401
- const response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
1402
- headers: requestHeaders
1403
- });
1403
+ var _a, _b, _c;
1404
+ const method = (_b = (_a = opts.method) != null ? _a : this.options.subsetMethod) != null ? _b : `GET`;
1405
+ const usePost = method === `POST`;
1406
+ let fetchUrl;
1407
+ let fetchOptions;
1408
+ if (usePost) {
1409
+ const result = await __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true);
1410
+ fetchUrl = result.fetchUrl;
1411
+ fetchOptions = {
1412
+ method: `POST`,
1413
+ headers: __spreadProps(__spreadValues({}, result.requestHeaders), {
1414
+ "Content-Type": `application/json`
1415
+ }),
1416
+ body: JSON.stringify(__privateMethod(this, _ShapeStream_instances, buildSubsetBody_fn).call(this, opts))
1417
+ };
1418
+ } else {
1419
+ const result = await __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
1420
+ fetchUrl = result.fetchUrl;
1421
+ fetchOptions = { headers: result.requestHeaders };
1422
+ }
1423
+ const usedHandle = __privateGet(this, _shapeHandle);
1424
+ let response;
1425
+ try {
1426
+ response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), fetchOptions);
1427
+ } catch (e) {
1428
+ if (e instanceof FetchError && e.status === 409) {
1429
+ if (usedHandle) {
1430
+ const shapeKey = canonicalShapeKey(fetchUrl);
1431
+ expiredShapesCache.markExpired(shapeKey, usedHandle);
1432
+ }
1433
+ __privateSet(this, _shapeHandle, e.headers[SHAPE_HANDLE_HEADER] || `${usedHandle != null ? usedHandle : `handle`}-next`);
1434
+ return this.fetchSnapshot(opts);
1435
+ }
1436
+ throw e;
1437
+ }
1404
1438
  if (!response.ok) {
1405
- throw new FetchError(
1406
- response.status,
1407
- void 0,
1408
- void 0,
1409
- Object.fromEntries([...response.headers.entries()]),
1410
- fetchUrl.toString()
1411
- );
1439
+ throw await FetchError.fromResponse(response, fetchUrl.toString());
1412
1440
  }
1413
- const schema = (_a = __privateGet(this, _schema)) != null ? _a : getSchemaFromHeaders(response.headers, {
1441
+ const schema = (_c = __privateGet(this, _schema)) != null ? _c : getSchemaFromHeaders(response.headers, {
1414
1442
  required: true,
1415
1443
  url: fetchUrl.toString()
1416
1444
  });
@@ -1419,10 +1447,7 @@ var ShapeStream = class {
1419
1447
  rawData,
1420
1448
  schema
1421
1449
  );
1422
- return {
1423
- metadata,
1424
- data
1425
- };
1450
+ return { metadata, data };
1426
1451
  }
1427
1452
  };
1428
1453
  _error = new WeakMap();
@@ -1738,8 +1763,9 @@ onInitialResponse_fn = async function(response) {
1738
1763
  );
1739
1764
  } else {
1740
1765
  console.warn(
1741
- `[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${shapeHandle}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. Ignoring the stale handle and continuing with handle "${__privateGet(this, _shapeHandle)}".`
1766
+ `[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${shapeHandle}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. Ignoring the stale response and continuing with handle "${__privateGet(this, _shapeHandle)}".`
1742
1767
  );
1768
+ return;
1743
1769
  }
1744
1770
  }
1745
1771
  const lastOffset = headers.get(CHUNK_LAST_OFFSET_HEADER);
@@ -1992,6 +2018,44 @@ reset_fn = function(handle) {
1992
2018
  __privateSet(this, _staleCacheBuster, void 0);
1993
2019
  __privateSet(this, _staleCacheRetryCount, 0);
1994
2020
  };
2021
+ buildSubsetBody_fn = function(opts) {
2022
+ var _a, _b, _c, _d;
2023
+ const body = {};
2024
+ if (opts.whereExpr) {
2025
+ body.where = compileExpression(
2026
+ opts.whereExpr,
2027
+ (_a = this.options.columnMapper) == null ? void 0 : _a.encode
2028
+ );
2029
+ body.where_expr = opts.whereExpr;
2030
+ } else if (opts.where && typeof opts.where === `string`) {
2031
+ body.where = encodeWhereClause(
2032
+ opts.where,
2033
+ (_b = this.options.columnMapper) == null ? void 0 : _b.encode
2034
+ );
2035
+ }
2036
+ if (opts.params) {
2037
+ body.params = opts.params;
2038
+ }
2039
+ if (opts.limit !== void 0) {
2040
+ body.limit = opts.limit;
2041
+ }
2042
+ if (opts.offset !== void 0) {
2043
+ body.offset = opts.offset;
2044
+ }
2045
+ if (opts.orderByExpr) {
2046
+ body.order_by = compileOrderBy(
2047
+ opts.orderByExpr,
2048
+ (_c = this.options.columnMapper) == null ? void 0 : _c.encode
2049
+ );
2050
+ body.order_by_expr = opts.orderByExpr;
2051
+ } else if (opts.orderBy && typeof opts.orderBy === `string`) {
2052
+ body.order_by = encodeWhereClause(
2053
+ opts.orderBy,
2054
+ (_d = this.options.columnMapper) == null ? void 0 : _d.encode
2055
+ );
2056
+ }
2057
+ return body;
2058
+ };
1995
2059
  ShapeStream.Replica = {
1996
2060
  FULL: `full`,
1997
2061
  DEFAULT: `default`