@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.
package/dist/index.mjs CHANGED
@@ -426,10 +426,10 @@ function snakeCamelMapper(schema) {
426
426
 
427
427
  // src/helpers.ts
428
428
  function isChangeMessage(message) {
429
- return `key` in message;
429
+ return message != null && `key` in message;
430
430
  }
431
431
  function isControlMessage(message) {
432
- return !isChangeMessage(message);
432
+ return message != null && !isChangeMessage(message);
433
433
  }
434
434
  function isUpToDateMessage(message) {
435
435
  return isControlMessage(message) && message.headers.control === `up-to-date`;
@@ -609,6 +609,12 @@ function createFetchWithChunkBuffer(fetchClient, prefetchOptions = ChunkPrefetch
609
609
  let prefetchQueue;
610
610
  const prefetchClient = async (...args) => {
611
611
  const url = args[0].toString();
612
+ const method = getRequestMethod(args[0], args[1]);
613
+ if (method !== `GET`) {
614
+ prefetchQueue == null ? void 0 : prefetchQueue.abort();
615
+ prefetchQueue = void 0;
616
+ return fetchClient(...args);
617
+ }
612
618
  const prefetchedRequest = prefetchQueue == null ? void 0 : prefetchQueue.consume(...args);
613
619
  if (prefetchedRequest) {
614
620
  return prefetchedRequest;
@@ -778,6 +784,15 @@ function chainAborter(aborter, sourceSignal) {
778
784
  }
779
785
  function noop() {
780
786
  }
787
+ function getRequestMethod(input, init) {
788
+ if (init == null ? void 0 : init.method) {
789
+ return init.method.toUpperCase();
790
+ }
791
+ if (typeof Request !== `undefined` && input instanceof Request) {
792
+ return input.method.toUpperCase();
793
+ }
794
+ return `GET`;
795
+ }
781
796
 
782
797
  // src/expression-compiler.ts
783
798
  function compileExpression(expr, columnMapper) {
@@ -1454,6 +1469,12 @@ var FetchingState = class extends ActiveState {
1454
1469
  const staleResult = this.checkStaleResponse(input);
1455
1470
  if (staleResult) return staleResult;
1456
1471
  const shared = this.parseResponseFields(input);
1472
+ if (input.status === 204) {
1473
+ return {
1474
+ action: `accepted`,
1475
+ state: new LiveState(shared, { sseFallbackToLongPolling: true })
1476
+ };
1477
+ }
1457
1478
  return { action: `accepted`, state: new SyncingState(shared) };
1458
1479
  }
1459
1480
  canEnterReplayMode() {
@@ -2284,7 +2305,8 @@ requestShape_fn = async function() {
2284
2305
  }
2285
2306
  const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER] || `${__privateGet(this, _syncState).handle}-next`;
2286
2307
  __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
2287
- await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, Array.isArray(e.json) ? e.json : [e.json]);
2308
+ const messages409 = Array.isArray(e.json) ? e.json : e.json != null ? [e.json] : [];
2309
+ await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, messages409);
2288
2310
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
2289
2311
  } else {
2290
2312
  throw e;
@@ -2467,6 +2489,12 @@ onInitialResponse_fn = async function(response) {
2467
2489
  return true;
2468
2490
  };
2469
2491
  onMessages_fn = async function(batch, isSseMessage = false) {
2492
+ if (!Array.isArray(batch)) {
2493
+ console.warn(
2494
+ `[Electric] #onMessages called with non-array argument (${typeof batch}). This is a client bug \u2014 please report it.`
2495
+ );
2496
+ return;
2497
+ }
2470
2498
  if (batch.length === 0) return;
2471
2499
  const lastMessage = batch[batch.length - 1];
2472
2500
  const hasUpToDateMessage = isUpToDateMessage(lastMessage);
@@ -2523,6 +2551,7 @@ fetchShape_fn = async function(opts) {
2523
2551
  return __privateMethod(this, _ShapeStream_instances, requestShapeLongPoll_fn).call(this, opts);
2524
2552
  };
2525
2553
  requestShapeLongPoll_fn = async function(opts) {
2554
+ var _a;
2526
2555
  const { fetchUrl, requestAbortController, headers } = opts;
2527
2556
  const response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
2528
2557
  signal: requestAbortController.signal,
@@ -2535,6 +2564,16 @@ requestShapeLongPoll_fn = async function(opts) {
2535
2564
  const res = await response.text();
2536
2565
  const messages = res || `[]`;
2537
2566
  const batch = __privateGet(this, _messageParser).parse(messages, schema);
2567
+ if (!Array.isArray(batch)) {
2568
+ const preview = (_a = JSON.stringify(batch)) == null ? void 0 : _a.slice(0, 200);
2569
+ throw new FetchError(
2570
+ response.status,
2571
+ `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}`,
2572
+ void 0,
2573
+ Object.fromEntries(response.headers.entries()),
2574
+ fetchUrl.toString()
2575
+ );
2576
+ }
2538
2577
  await __privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, batch);
2539
2578
  };
2540
2579
  requestShapeSSE_fn = async function(opts) {
@@ -2584,7 +2623,9 @@ requestShapeSSE_fn = async function(opts) {
2584
2623
  if (requestAbortController.signal.aborted) {
2585
2624
  throw new FetchBackoffAbortError();
2586
2625
  }
2587
- throw error;
2626
+ if (error instanceof FetchError || error instanceof StaleCacheError || error instanceof MissingHeadersError) {
2627
+ throw error;
2628
+ }
2588
2629
  } finally {
2589
2630
  const connectionDuration = Date.now() - __privateGet(this, _lastSseConnectionStartTime);
2590
2631
  const wasAborted = requestAbortController.signal.aborted;