@electric-sql/client 1.5.4 → 1.5.6

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.
@@ -463,10 +463,10 @@ function snakeCamelMapper(schema) {
463
463
 
464
464
  // src/helpers.ts
465
465
  function isChangeMessage(message) {
466
- return `key` in message;
466
+ return message != null && `key` in message;
467
467
  }
468
468
  function isControlMessage(message) {
469
- return !isChangeMessage(message);
469
+ return message != null && !isChangeMessage(message);
470
470
  }
471
471
  function isUpToDateMessage(message) {
472
472
  return isControlMessage(message) && message.headers.control === `up-to-date`;
@@ -646,6 +646,12 @@ function createFetchWithChunkBuffer(fetchClient, prefetchOptions = ChunkPrefetch
646
646
  let prefetchQueue;
647
647
  const prefetchClient = async (...args) => {
648
648
  const url = args[0].toString();
649
+ const method = getRequestMethod(args[0], args[1]);
650
+ if (method !== `GET`) {
651
+ prefetchQueue == null ? void 0 : prefetchQueue.abort();
652
+ prefetchQueue = void 0;
653
+ return fetchClient(...args);
654
+ }
649
655
  const prefetchedRequest = prefetchQueue == null ? void 0 : prefetchQueue.consume(...args);
650
656
  if (prefetchedRequest) {
651
657
  return prefetchedRequest;
@@ -815,6 +821,15 @@ function chainAborter(aborter, sourceSignal) {
815
821
  }
816
822
  function noop() {
817
823
  }
824
+ function getRequestMethod(input, init) {
825
+ if (init == null ? void 0 : init.method) {
826
+ return init.method.toUpperCase();
827
+ }
828
+ if (typeof Request !== `undefined` && input instanceof Request) {
829
+ return input.method.toUpperCase();
830
+ }
831
+ return `GET`;
832
+ }
818
833
 
819
834
  // src/expression-compiler.ts
820
835
  function compileExpression(expr, columnMapper) {
@@ -1491,6 +1506,12 @@ var FetchingState = class extends ActiveState {
1491
1506
  const staleResult = this.checkStaleResponse(input);
1492
1507
  if (staleResult) return staleResult;
1493
1508
  const shared = this.parseResponseFields(input);
1509
+ if (input.status === 204) {
1510
+ return {
1511
+ action: `accepted`,
1512
+ state: new LiveState(shared, { sseFallbackToLongPolling: true })
1513
+ };
1514
+ }
1494
1515
  return { action: `accepted`, state: new SyncingState(shared) };
1495
1516
  }
1496
1517
  canEnterReplayMode() {
@@ -2321,7 +2342,8 @@ requestShape_fn = async function() {
2321
2342
  }
2322
2343
  const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER] || `${__privateGet(this, _syncState).handle}-next`;
2323
2344
  __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
2324
- await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, Array.isArray(e.json) ? e.json : [e.json]);
2345
+ const messages409 = Array.isArray(e.json) ? e.json : e.json != null ? [e.json] : [];
2346
+ await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, messages409);
2325
2347
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
2326
2348
  } else {
2327
2349
  throw e;
@@ -2504,6 +2526,12 @@ onInitialResponse_fn = async function(response) {
2504
2526
  return true;
2505
2527
  };
2506
2528
  onMessages_fn = async function(batch, isSseMessage = false) {
2529
+ if (!Array.isArray(batch)) {
2530
+ console.warn(
2531
+ `[Electric] #onMessages called with non-array argument (${typeof batch}). This is a client bug \u2014 please report it.`
2532
+ );
2533
+ return;
2534
+ }
2507
2535
  if (batch.length === 0) return;
2508
2536
  const lastMessage = batch[batch.length - 1];
2509
2537
  const hasUpToDateMessage = isUpToDateMessage(lastMessage);
@@ -2560,6 +2588,7 @@ fetchShape_fn = async function(opts) {
2560
2588
  return __privateMethod(this, _ShapeStream_instances, requestShapeLongPoll_fn).call(this, opts);
2561
2589
  };
2562
2590
  requestShapeLongPoll_fn = async function(opts) {
2591
+ var _a;
2563
2592
  const { fetchUrl, requestAbortController, headers } = opts;
2564
2593
  const response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
2565
2594
  signal: requestAbortController.signal,
@@ -2572,6 +2601,16 @@ requestShapeLongPoll_fn = async function(opts) {
2572
2601
  const res = await response.text();
2573
2602
  const messages = res || `[]`;
2574
2603
  const batch = __privateGet(this, _messageParser).parse(messages, schema);
2604
+ if (!Array.isArray(batch)) {
2605
+ const preview = (_a = JSON.stringify(batch)) == null ? void 0 : _a.slice(0, 200);
2606
+ throw new FetchError(
2607
+ response.status,
2608
+ `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}`,
2609
+ void 0,
2610
+ Object.fromEntries(response.headers.entries()),
2611
+ fetchUrl.toString()
2612
+ );
2613
+ }
2575
2614
  await __privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, batch);
2576
2615
  };
2577
2616
  requestShapeSSE_fn = async function(opts) {
@@ -2621,7 +2660,9 @@ requestShapeSSE_fn = async function(opts) {
2621
2660
  if (requestAbortController.signal.aborted) {
2622
2661
  throw new FetchBackoffAbortError();
2623
2662
  }
2624
- throw error;
2663
+ if (error instanceof FetchError || error instanceof StaleCacheError || error instanceof MissingHeadersError) {
2664
+ throw error;
2665
+ }
2625
2666
  } finally {
2626
2667
  const connectionDuration = Date.now() - __privateGet(this, _lastSseConnectionStartTime);
2627
2668
  const wasAborted = requestAbortController.signal.aborted;