@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.
@@ -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`;
@@ -891,8 +891,202 @@ function compileOrderBy(clauses, columnMapper) {
891
891
  }).join(`, `);
892
892
  }
893
893
 
894
- // src/client.ts
895
- var import_fetch_event_source = require("@microsoft/fetch-event-source");
894
+ // ../../node_modules/.pnpm/@microsoft+fetch-event-source@2.0.1_patch_hash=46f4e76dd960e002a542732bb4323817a24fce1673cb71e2f458fe09776fa188/node_modules/@microsoft/fetch-event-source/lib/esm/parse.js
895
+ async function getBytes(stream, onChunk) {
896
+ const reader = stream.getReader();
897
+ let result;
898
+ while (!(result = await reader.read()).done) {
899
+ onChunk(result.value);
900
+ }
901
+ }
902
+ function getLines(onLine) {
903
+ let buffer;
904
+ let position;
905
+ let fieldLength;
906
+ let discardTrailingNewline = false;
907
+ return function onChunk(arr) {
908
+ if (buffer === void 0) {
909
+ buffer = arr;
910
+ position = 0;
911
+ fieldLength = -1;
912
+ } else {
913
+ buffer = concat(buffer, arr);
914
+ }
915
+ const bufLength = buffer.length;
916
+ let lineStart = 0;
917
+ while (position < bufLength) {
918
+ if (discardTrailingNewline) {
919
+ if (buffer[position] === 10) {
920
+ lineStart = ++position;
921
+ }
922
+ discardTrailingNewline = false;
923
+ }
924
+ let lineEnd = -1;
925
+ for (; position < bufLength && lineEnd === -1; ++position) {
926
+ switch (buffer[position]) {
927
+ case 58:
928
+ if (fieldLength === -1) {
929
+ fieldLength = position - lineStart;
930
+ }
931
+ break;
932
+ case 13:
933
+ discardTrailingNewline = true;
934
+ case 10:
935
+ lineEnd = position;
936
+ break;
937
+ }
938
+ }
939
+ if (lineEnd === -1) {
940
+ break;
941
+ }
942
+ onLine(buffer.subarray(lineStart, lineEnd), fieldLength);
943
+ lineStart = position;
944
+ fieldLength = -1;
945
+ }
946
+ if (lineStart === bufLength) {
947
+ buffer = void 0;
948
+ } else if (lineStart !== 0) {
949
+ buffer = buffer.subarray(lineStart);
950
+ position -= lineStart;
951
+ }
952
+ };
953
+ }
954
+ function getMessages(onId, onRetry, onMessage) {
955
+ let message = newMessage();
956
+ const decoder = new TextDecoder();
957
+ return function onLine(line, fieldLength) {
958
+ if (line.length === 0) {
959
+ onMessage === null || onMessage === void 0 ? void 0 : onMessage(message);
960
+ message = newMessage();
961
+ } else if (fieldLength > 0) {
962
+ const field = decoder.decode(line.subarray(0, fieldLength));
963
+ const valueOffset = fieldLength + (line[fieldLength + 1] === 32 ? 2 : 1);
964
+ const value = decoder.decode(line.subarray(valueOffset));
965
+ switch (field) {
966
+ case "data":
967
+ message.data = message.data ? message.data + "\n" + value : value;
968
+ break;
969
+ case "event":
970
+ message.event = value;
971
+ break;
972
+ case "id":
973
+ onId(message.id = value);
974
+ break;
975
+ case "retry":
976
+ const retry = parseInt(value, 10);
977
+ if (!isNaN(retry)) {
978
+ onRetry(message.retry = retry);
979
+ }
980
+ break;
981
+ }
982
+ }
983
+ };
984
+ }
985
+ function concat(a, b) {
986
+ const res = new Uint8Array(a.length + b.length);
987
+ res.set(a);
988
+ res.set(b, a.length);
989
+ return res;
990
+ }
991
+ function newMessage() {
992
+ return {
993
+ data: "",
994
+ event: "",
995
+ id: "",
996
+ retry: void 0
997
+ };
998
+ }
999
+
1000
+ // ../../node_modules/.pnpm/@microsoft+fetch-event-source@2.0.1_patch_hash=46f4e76dd960e002a542732bb4323817a24fce1673cb71e2f458fe09776fa188/node_modules/@microsoft/fetch-event-source/lib/esm/fetch.js
1001
+ var __rest = function(s, e) {
1002
+ var t = {};
1003
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
1004
+ t[p] = s[p];
1005
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
1006
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
1007
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
1008
+ t[p[i]] = s[p[i]];
1009
+ }
1010
+ return t;
1011
+ };
1012
+ var EventStreamContentType = "text/event-stream";
1013
+ var DefaultRetryInterval = 1e3;
1014
+ var LastEventId = "last-event-id";
1015
+ function fetchEventSource(input, _a) {
1016
+ 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"]);
1017
+ return new Promise((resolve, reject) => {
1018
+ const headers = Object.assign({}, inputHeaders);
1019
+ if (!headers.accept) {
1020
+ headers.accept = EventStreamContentType;
1021
+ }
1022
+ let curRequestController;
1023
+ function onVisibilityChange() {
1024
+ curRequestController.abort();
1025
+ if (typeof document !== "undefined" && !document.hidden) {
1026
+ create();
1027
+ }
1028
+ }
1029
+ if (typeof document !== "undefined" && !openWhenHidden) {
1030
+ document.addEventListener("visibilitychange", onVisibilityChange);
1031
+ }
1032
+ let retryInterval = DefaultRetryInterval;
1033
+ let retryTimer = 0;
1034
+ function dispose() {
1035
+ if (typeof document !== "undefined") {
1036
+ document.removeEventListener("visibilitychange", onVisibilityChange);
1037
+ }
1038
+ clearTimeout(retryTimer);
1039
+ curRequestController.abort();
1040
+ }
1041
+ inputSignal === null || inputSignal === void 0 ? void 0 : inputSignal.addEventListener("abort", () => {
1042
+ dispose();
1043
+ });
1044
+ const fetch2 = inputFetch !== null && inputFetch !== void 0 ? inputFetch : window.fetch;
1045
+ const onopen = inputOnOpen !== null && inputOnOpen !== void 0 ? inputOnOpen : defaultOnOpen;
1046
+ async function create() {
1047
+ var _a2;
1048
+ curRequestController = new AbortController();
1049
+ const sig = inputSignal.aborted ? inputSignal : curRequestController.signal;
1050
+ try {
1051
+ const response = await fetch2(input, Object.assign(Object.assign({}, rest), { headers, signal: sig }));
1052
+ await onopen(response);
1053
+ await getBytes(response.body, getLines(getMessages((id) => {
1054
+ if (id) {
1055
+ headers[LastEventId] = id;
1056
+ } else {
1057
+ delete headers[LastEventId];
1058
+ }
1059
+ }, (retry) => {
1060
+ retryInterval = retry;
1061
+ }, onmessage)));
1062
+ onclose === null || onclose === void 0 ? void 0 : onclose();
1063
+ dispose();
1064
+ resolve();
1065
+ } catch (err) {
1066
+ if (sig.aborted) {
1067
+ dispose();
1068
+ reject(err);
1069
+ } else if (!curRequestController.signal.aborted) {
1070
+ try {
1071
+ const interval = (_a2 = onerror === null || onerror === void 0 ? void 0 : onerror(err)) !== null && _a2 !== void 0 ? _a2 : retryInterval;
1072
+ clearTimeout(retryTimer);
1073
+ retryTimer = setTimeout(create, interval);
1074
+ } catch (innerErr) {
1075
+ dispose();
1076
+ reject(innerErr);
1077
+ }
1078
+ }
1079
+ }
1080
+ }
1081
+ create();
1082
+ });
1083
+ }
1084
+ function defaultOnOpen(response) {
1085
+ const contentType = response.headers.get("content-type");
1086
+ if (!(contentType === null || contentType === void 0 ? void 0 : contentType.startsWith(EventStreamContentType))) {
1087
+ throw new Error(`Expected content-type to be ${EventStreamContentType}, Actual: ${contentType}`);
1088
+ }
1089
+ }
896
1090
 
897
1091
  // src/expired-shapes-cache.ts
898
1092
  var ExpiredShapesCache = class {
@@ -2127,7 +2321,8 @@ requestShape_fn = async function() {
2127
2321
  }
2128
2322
  const newShapeHandle = e.headers[SHAPE_HANDLE_HEADER] || `${__privateGet(this, _syncState).handle}-next`;
2129
2323
  __privateMethod(this, _ShapeStream_instances, reset_fn).call(this, newShapeHandle);
2130
- await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, Array.isArray(e.json) ? e.json : [e.json]);
2324
+ const messages409 = Array.isArray(e.json) ? e.json : e.json != null ? [e.json] : [];
2325
+ await __privateMethod(this, _ShapeStream_instances, publish_fn).call(this, messages409);
2131
2326
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
2132
2327
  } else {
2133
2328
  throw e;
@@ -2310,6 +2505,12 @@ onInitialResponse_fn = async function(response) {
2310
2505
  return true;
2311
2506
  };
2312
2507
  onMessages_fn = async function(batch, isSseMessage = false) {
2508
+ if (!Array.isArray(batch)) {
2509
+ console.warn(
2510
+ `[Electric] #onMessages called with non-array argument (${typeof batch}). This is a client bug \u2014 please report it.`
2511
+ );
2512
+ return;
2513
+ }
2313
2514
  if (batch.length === 0) return;
2314
2515
  const lastMessage = batch[batch.length - 1];
2315
2516
  const hasUpToDateMessage = isUpToDateMessage(lastMessage);
@@ -2366,6 +2567,7 @@ fetchShape_fn = async function(opts) {
2366
2567
  return __privateMethod(this, _ShapeStream_instances, requestShapeLongPoll_fn).call(this, opts);
2367
2568
  };
2368
2569
  requestShapeLongPoll_fn = async function(opts) {
2570
+ var _a;
2369
2571
  const { fetchUrl, requestAbortController, headers } = opts;
2370
2572
  const response = await __privateGet(this, _fetchClient2).call(this, fetchUrl.toString(), {
2371
2573
  signal: requestAbortController.signal,
@@ -2378,6 +2580,16 @@ requestShapeLongPoll_fn = async function(opts) {
2378
2580
  const res = await response.text();
2379
2581
  const messages = res || `[]`;
2380
2582
  const batch = __privateGet(this, _messageParser).parse(messages, schema);
2583
+ if (!Array.isArray(batch)) {
2584
+ const preview = (_a = JSON.stringify(batch)) == null ? void 0 : _a.slice(0, 200);
2585
+ throw new FetchError(
2586
+ response.status,
2587
+ `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}`,
2588
+ void 0,
2589
+ Object.fromEntries(response.headers.entries()),
2590
+ fetchUrl.toString()
2591
+ );
2592
+ }
2381
2593
  await __privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, batch);
2382
2594
  };
2383
2595
  requestShapeSSE_fn = async function(opts) {
@@ -2390,7 +2602,7 @@ requestShapeSSE_fn = async function(opts) {
2390
2602
  let ignoredStaleResponse = false;
2391
2603
  try {
2392
2604
  let buffer = [];
2393
- await (0, import_fetch_event_source.fetchEventSource)(fetchUrl.toString(), {
2605
+ await fetchEventSource(fetchUrl.toString(), {
2394
2606
  headers: sseHeaders,
2395
2607
  fetch: fetch2,
2396
2608
  onopen: async (response) => {