@electric-sql/client 1.5.3 → 1.5.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.
@@ -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`;
@@ -854,10 +854,202 @@ function compileOrderBy(clauses, columnMapper) {
854
854
  }).join(`, `);
855
855
  }
856
856
 
857
- // src/client.ts
858
- import {
859
- fetchEventSource
860
- } from "@microsoft/fetch-event-source";
857
+ // ../../node_modules/.pnpm/@microsoft+fetch-event-source@2.0.1_patch_hash=46f4e76dd960e002a542732bb4323817a24fce1673cb71e2f458fe09776fa188/node_modules/@microsoft/fetch-event-source/lib/esm/parse.js
858
+ async function getBytes(stream, onChunk) {
859
+ const reader = stream.getReader();
860
+ let result;
861
+ while (!(result = await reader.read()).done) {
862
+ onChunk(result.value);
863
+ }
864
+ }
865
+ function getLines(onLine) {
866
+ let buffer;
867
+ let position;
868
+ let fieldLength;
869
+ let discardTrailingNewline = false;
870
+ return function onChunk(arr) {
871
+ if (buffer === void 0) {
872
+ buffer = arr;
873
+ position = 0;
874
+ fieldLength = -1;
875
+ } else {
876
+ buffer = concat(buffer, arr);
877
+ }
878
+ const bufLength = buffer.length;
879
+ let lineStart = 0;
880
+ while (position < bufLength) {
881
+ if (discardTrailingNewline) {
882
+ if (buffer[position] === 10) {
883
+ lineStart = ++position;
884
+ }
885
+ discardTrailingNewline = false;
886
+ }
887
+ let lineEnd = -1;
888
+ for (; position < bufLength && lineEnd === -1; ++position) {
889
+ switch (buffer[position]) {
890
+ case 58:
891
+ if (fieldLength === -1) {
892
+ fieldLength = position - lineStart;
893
+ }
894
+ break;
895
+ case 13:
896
+ discardTrailingNewline = true;
897
+ case 10:
898
+ lineEnd = position;
899
+ break;
900
+ }
901
+ }
902
+ if (lineEnd === -1) {
903
+ break;
904
+ }
905
+ onLine(buffer.subarray(lineStart, lineEnd), fieldLength);
906
+ lineStart = position;
907
+ fieldLength = -1;
908
+ }
909
+ if (lineStart === bufLength) {
910
+ buffer = void 0;
911
+ } else if (lineStart !== 0) {
912
+ buffer = buffer.subarray(lineStart);
913
+ position -= lineStart;
914
+ }
915
+ };
916
+ }
917
+ function getMessages(onId, onRetry, onMessage) {
918
+ let message = newMessage();
919
+ const decoder = new TextDecoder();
920
+ return function onLine(line, fieldLength) {
921
+ if (line.length === 0) {
922
+ onMessage === null || onMessage === void 0 ? void 0 : onMessage(message);
923
+ message = newMessage();
924
+ } else if (fieldLength > 0) {
925
+ const field = decoder.decode(line.subarray(0, fieldLength));
926
+ const valueOffset = fieldLength + (line[fieldLength + 1] === 32 ? 2 : 1);
927
+ const value = decoder.decode(line.subarray(valueOffset));
928
+ switch (field) {
929
+ case "data":
930
+ message.data = message.data ? message.data + "\n" + value : value;
931
+ break;
932
+ case "event":
933
+ message.event = value;
934
+ break;
935
+ case "id":
936
+ onId(message.id = value);
937
+ break;
938
+ case "retry":
939
+ const retry = parseInt(value, 10);
940
+ if (!isNaN(retry)) {
941
+ onRetry(message.retry = retry);
942
+ }
943
+ break;
944
+ }
945
+ }
946
+ };
947
+ }
948
+ function concat(a, b) {
949
+ const res = new Uint8Array(a.length + b.length);
950
+ res.set(a);
951
+ res.set(b, a.length);
952
+ return res;
953
+ }
954
+ function newMessage() {
955
+ return {
956
+ data: "",
957
+ event: "",
958
+ id: "",
959
+ retry: void 0
960
+ };
961
+ }
962
+
963
+ // ../../node_modules/.pnpm/@microsoft+fetch-event-source@2.0.1_patch_hash=46f4e76dd960e002a542732bb4323817a24fce1673cb71e2f458fe09776fa188/node_modules/@microsoft/fetch-event-source/lib/esm/fetch.js
964
+ var __rest = function(s, e) {
965
+ var t = {};
966
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
967
+ t[p] = s[p];
968
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
969
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
970
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
971
+ t[p[i]] = s[p[i]];
972
+ }
973
+ return t;
974
+ };
975
+ var EventStreamContentType = "text/event-stream";
976
+ var DefaultRetryInterval = 1e3;
977
+ var LastEventId = "last-event-id";
978
+ function fetchEventSource(input, _a) {
979
+ var { signal: inputSignal, headers: inputHeaders, onopen: inputOnOpen, onmessage, onclose, onerror, openWhenHidden, fetch: inputFetch } = _a, rest = __rest(_a, ["signal", "headers", "onopen", "onmessage", "onclose", "onerror", "openWhenHidden", "fetch"]);
980
+ return new Promise((resolve, reject) => {
981
+ const headers = Object.assign({}, inputHeaders);
982
+ if (!headers.accept) {
983
+ headers.accept = EventStreamContentType;
984
+ }
985
+ let curRequestController;
986
+ function onVisibilityChange() {
987
+ curRequestController.abort();
988
+ if (typeof document !== "undefined" && !document.hidden) {
989
+ create();
990
+ }
991
+ }
992
+ if (typeof document !== "undefined" && !openWhenHidden) {
993
+ document.addEventListener("visibilitychange", onVisibilityChange);
994
+ }
995
+ let retryInterval = DefaultRetryInterval;
996
+ let retryTimer = 0;
997
+ function dispose() {
998
+ if (typeof document !== "undefined") {
999
+ document.removeEventListener("visibilitychange", onVisibilityChange);
1000
+ }
1001
+ clearTimeout(retryTimer);
1002
+ curRequestController.abort();
1003
+ }
1004
+ inputSignal === null || inputSignal === void 0 ? void 0 : inputSignal.addEventListener("abort", () => {
1005
+ dispose();
1006
+ });
1007
+ const fetch2 = inputFetch !== null && inputFetch !== void 0 ? inputFetch : window.fetch;
1008
+ const onopen = inputOnOpen !== null && inputOnOpen !== void 0 ? inputOnOpen : defaultOnOpen;
1009
+ async function create() {
1010
+ var _a2;
1011
+ curRequestController = new AbortController();
1012
+ const sig = inputSignal.aborted ? inputSignal : curRequestController.signal;
1013
+ try {
1014
+ const response = await fetch2(input, Object.assign(Object.assign({}, rest), { headers, signal: sig }));
1015
+ await onopen(response);
1016
+ await getBytes(response.body, getLines(getMessages((id) => {
1017
+ if (id) {
1018
+ headers[LastEventId] = id;
1019
+ } else {
1020
+ delete headers[LastEventId];
1021
+ }
1022
+ }, (retry) => {
1023
+ retryInterval = retry;
1024
+ }, onmessage)));
1025
+ onclose === null || onclose === void 0 ? void 0 : onclose();
1026
+ dispose();
1027
+ resolve();
1028
+ } catch (err) {
1029
+ if (sig.aborted) {
1030
+ dispose();
1031
+ reject(err);
1032
+ } else if (!curRequestController.signal.aborted) {
1033
+ try {
1034
+ const interval = (_a2 = onerror === null || onerror === void 0 ? void 0 : onerror(err)) !== null && _a2 !== void 0 ? _a2 : retryInterval;
1035
+ clearTimeout(retryTimer);
1036
+ retryTimer = setTimeout(create, interval);
1037
+ } catch (innerErr) {
1038
+ dispose();
1039
+ reject(innerErr);
1040
+ }
1041
+ }
1042
+ }
1043
+ }
1044
+ create();
1045
+ });
1046
+ }
1047
+ function defaultOnOpen(response) {
1048
+ const contentType = response.headers.get("content-type");
1049
+ if (!(contentType === null || contentType === void 0 ? void 0 : contentType.startsWith(EventStreamContentType))) {
1050
+ throw new Error(`Expected content-type to be ${EventStreamContentType}, Actual: ${contentType}`);
1051
+ }
1052
+ }
861
1053
 
862
1054
  // src/expired-shapes-cache.ts
863
1055
  var ExpiredShapesCache = class {
@@ -2092,7 +2284,8 @@ requestShape_fn = async function() {
2092
2284
  }
2093
2285
  const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER] || `${__privateGet(this, _syncState).handle}-next`;
2094
2286
  __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
2095
- await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, Array.isArray(e.json) ? e.json : [e.json]);
2287
+ const messages409 = Array.isArray(e.json) ? e.json : e.json != null ? [e.json] : [];
2288
+ await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, messages409);
2096
2289
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
2097
2290
  } else {
2098
2291
  throw e;
@@ -2275,6 +2468,12 @@ onInitialResponse_fn = async function(response) {
2275
2468
  return true;
2276
2469
  };
2277
2470
  onMessages_fn = async function(batch, isSseMessage = false) {
2471
+ if (!Array.isArray(batch)) {
2472
+ console.warn(
2473
+ `[Electric] #onMessages called with non-array argument (${typeof batch}). This is a client bug \u2014 please report it.`
2474
+ );
2475
+ return;
2476
+ }
2278
2477
  if (batch.length === 0) return;
2279
2478
  const lastMessage = batch[batch.length - 1];
2280
2479
  const hasUpToDateMessage = isUpToDateMessage(lastMessage);
@@ -2331,6 +2530,7 @@ fetchShape_fn = async function(opts) {
2331
2530
  return __privateMethod(this, _ShapeStream_instances, requestShapeLongPoll_fn).call(this, opts);
2332
2531
  };
2333
2532
  requestShapeLongPoll_fn = async function(opts) {
2533
+ var _a;
2334
2534
  const { fetchUrl, requestAbortController, headers } = opts;
2335
2535
  const response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
2336
2536
  signal: requestAbortController.signal,
@@ -2343,6 +2543,16 @@ requestShapeLongPoll_fn = async function(opts) {
2343
2543
  const res = await response.text();
2344
2544
  const messages = res || `[]`;
2345
2545
  const batch = __privateGet(this, _messageParser).parse(messages, schema);
2546
+ if (!Array.isArray(batch)) {
2547
+ const preview = (_a = JSON.stringify(batch)) == null ? void 0 : _a.slice(0, 200);
2548
+ throw new FetchError(
2549
+ response.status,
2550
+ `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}`,
2551
+ void 0,
2552
+ Object.fromEntries(response.headers.entries()),
2553
+ fetchUrl.toString()
2554
+ );
2555
+ }
2346
2556
  await __privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, batch);
2347
2557
  };
2348
2558
  requestShapeSSE_fn = async function(opts) {