@sanity/client 6.24.3 → 6.24.4

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.
@@ -1,7 +1,7 @@
1
1
  import { getIt } from "get-it";
2
2
  import { adapter, environment } from "get-it";
3
3
  import { retry, jsonRequest, jsonResponse, progress, observable } from "get-it/middleware";
4
- import { Observable, from, lastValueFrom } from "rxjs";
4
+ import { Observable, defer, isObservable, of, mergeMap, from, lastValueFrom, shareReplay, catchError, concat, timer, throwError, EMPTY } from "rxjs";
5
5
  import { stegaClean } from "./_chunks-es/stegaClean.js";
6
6
  import { combineLatestWith, map, filter } from "rxjs/operators";
7
7
  class ClientError extends Error {
@@ -252,6 +252,112 @@ const initConfig = (config, prevConfig) => {
252
252
  const hostParts = newConfig.apiHost.split("://", 2), protocol = hostParts[0], host = hostParts[1], cdnHost = newConfig.isDefaultApi ? defaultCdnHost : host;
253
253
  return newConfig.useProjectHostname ? (newConfig.url = `${protocol}://${newConfig.projectId}.${host}/v${newConfig.apiVersion}`, newConfig.cdnUrl = `${protocol}://${newConfig.projectId}.${cdnHost}/v${newConfig.apiVersion}`) : (newConfig.url = `${newConfig.apiHost}/v${newConfig.apiVersion}`, newConfig.cdnUrl = newConfig.url), newConfig;
254
254
  };
255
+ class ConnectionFailedError extends Error {
256
+ name = "ConnectionFailedError";
257
+ }
258
+ class DisconnectError extends Error {
259
+ name = "DisconnectError";
260
+ reason;
261
+ constructor(message, reason, options = {}) {
262
+ super(message, options), this.reason = reason;
263
+ }
264
+ }
265
+ class ChannelError extends Error {
266
+ name = "ChannelError";
267
+ data;
268
+ constructor(message, data) {
269
+ super(message), this.data = data;
270
+ }
271
+ }
272
+ class MessageError extends Error {
273
+ name = "MessageError";
274
+ data;
275
+ constructor(message, data, options = {}) {
276
+ super(message, options), this.data = data;
277
+ }
278
+ }
279
+ class MessageParseError extends Error {
280
+ name = "MessageParseError";
281
+ }
282
+ const REQUIRED_EVENTS = ["channelError", "disconnect"];
283
+ function connectEventSource(initEventSource, events) {
284
+ return defer(() => {
285
+ const es = initEventSource();
286
+ return isObservable(es) ? es : of(es);
287
+ }).pipe(mergeMap((es) => connectWithESInstance(es, events)));
288
+ }
289
+ function connectWithESInstance(es, events) {
290
+ return new Observable((observer) => {
291
+ const emitOpen = events.includes("open"), emitReconnect = events.includes("reconnect");
292
+ function onError(evt) {
293
+ if ("data" in evt) {
294
+ const [parseError, event] = parseEvent(evt);
295
+ observer.error(
296
+ parseError ? new MessageParseError("Unable to parse EventSource error message", { cause: event }) : new MessageError((event?.data).message, event)
297
+ );
298
+ return;
299
+ }
300
+ es.readyState === es.CLOSED ? observer.error(new ConnectionFailedError("EventSource connection failed")) : emitReconnect && observer.next({ type: "reconnect" });
301
+ }
302
+ function onOpen() {
303
+ observer.next({ type: "open" });
304
+ }
305
+ function onMessage(message) {
306
+ const [parseError, event] = parseEvent(message);
307
+ if (parseError) {
308
+ observer.error(
309
+ new MessageParseError("Unable to parse EventSource message", { cause: parseError })
310
+ );
311
+ return;
312
+ }
313
+ if (message.type === "channelError") {
314
+ observer.error(new ChannelError(extractErrorMessage(event?.data), event.data));
315
+ return;
316
+ }
317
+ if (message.type === "disconnect") {
318
+ observer.error(
319
+ new DisconnectError(
320
+ `Server disconnected client: ${event.data?.reason || "unknown error"}`
321
+ )
322
+ );
323
+ return;
324
+ }
325
+ observer.next({
326
+ type: message.type,
327
+ id: message.lastEventId,
328
+ ...event.data ? { data: event.data } : {}
329
+ });
330
+ }
331
+ es.addEventListener("error", onError), emitOpen && es.addEventListener("open", onOpen);
332
+ const cleanedEvents = [.../* @__PURE__ */ new Set([...REQUIRED_EVENTS, ...events])].filter((type) => type !== "error" && type !== "open" && type !== "reconnect");
333
+ return cleanedEvents.forEach((type) => es.addEventListener(type, onMessage)), () => {
334
+ es.removeEventListener("error", onError), emitOpen && es.removeEventListener("open", onOpen), cleanedEvents.forEach((type) => es.removeEventListener(type, onMessage)), es.close();
335
+ };
336
+ });
337
+ }
338
+ function parseEvent(message) {
339
+ try {
340
+ const data = typeof message.data == "string" && JSON.parse(message.data);
341
+ return [
342
+ null,
343
+ {
344
+ type: message.type,
345
+ id: message.lastEventId,
346
+ ...isEmptyObject(data) ? {} : { data }
347
+ }
348
+ ];
349
+ } catch (err) {
350
+ return [err, null];
351
+ }
352
+ }
353
+ function extractErrorMessage(err) {
354
+ return err.error ? err.error.description ? err.error.description : typeof err.error == "string" ? err.error : JSON.stringify(err.error, null, 2) : err.message || "Unknown listener error";
355
+ }
356
+ function isEmptyObject(data) {
357
+ for (const _ in data)
358
+ return !1;
359
+ return !0;
360
+ }
255
361
  function getSelection(sel) {
256
362
  if (typeof sel == "string")
257
363
  return { id: sel };
@@ -536,8 +642,8 @@ class Transaction extends BaseTransaction {
536
642
  );
537
643
  }
538
644
  patch(patchOrDocumentId, patchOps) {
539
- const isBuilder = typeof patchOps == "function";
540
- if (typeof patchOrDocumentId != "string" && patchOrDocumentId instanceof Patch)
645
+ const isBuilder = typeof patchOps == "function", isPatch = typeof patchOrDocumentId != "string" && patchOrDocumentId instanceof Patch, isMutationSelection = typeof patchOrDocumentId == "object" && ("query" in patchOrDocumentId || "id" in patchOrDocumentId);
646
+ if (isPatch)
541
647
  return this._add({ patch: patchOrDocumentId.serialize() });
542
648
  if (isBuilder) {
543
649
  const patch = patchOps(new Patch(patchOrDocumentId, {}, this.#client));
@@ -545,6 +651,10 @@ class Transaction extends BaseTransaction {
545
651
  throw new Error("function passed to `patch()` must return the patch");
546
652
  return this._add({ patch: patch.serialize() });
547
653
  }
654
+ if (isMutationSelection) {
655
+ const patch = new Patch(patchOrDocumentId, patchOps || {}, this.#client);
656
+ return this._add({ patch: patch.serialize() });
657
+ }
548
658
  return this._add({ patch: { id: patchOrDocumentId, ...patchOps } });
549
659
  }
550
660
  }
@@ -868,7 +978,18 @@ function optionsFromFile(opts, file) {
868
978
  );
869
979
  }
870
980
  var defaults = (obj, defaults2) => Object.keys(defaults2).concat(Object.keys(obj)).reduce((target, prop) => (target[prop] = typeof obj[prop] > "u" ? defaults2[prop] : obj[prop], target), {});
871
- const pick = (obj, props) => props.reduce((selection, prop) => (typeof obj[prop] > "u" || (selection[prop] = obj[prop]), selection), {}), MAX_URL_LENGTH = 14800, possibleOptions = [
981
+ const pick = (obj, props) => props.reduce((selection, prop) => (typeof obj[prop] > "u" || (selection[prop] = obj[prop]), selection), {}), eventSourcePolyfill = defer(() => import("@sanity/eventsource")).pipe(
982
+ map(({ default: EventSource2 }) => EventSource2),
983
+ shareReplay(1)
984
+ );
985
+ function reconnectOnConnectionFailure() {
986
+ return function(source) {
987
+ return source.pipe(
988
+ catchError((err, caught) => err instanceof ConnectionFailedError ? concat(of({ type: "reconnect" }), timer(1e3).pipe(mergeMap(() => caught))) : throwError(() => err))
989
+ );
990
+ };
991
+ }
992
+ const MAX_URL_LENGTH = 14800, possibleOptions = [
872
993
  "includePreviousRevision",
873
994
  "includeResult",
874
995
  "includeMutations",
@@ -881,68 +1002,23 @@ const pick = (obj, props) => props.reduce((selection, prop) => (typeof obj[prop]
881
1002
  function _listen(query, params, opts = {}) {
882
1003
  const { url, token, withCredentials, requestTagPrefix } = this.config(), tag = opts.tag && requestTagPrefix ? [requestTagPrefix, opts.tag].join(".") : opts.tag, options = { ...defaults(opts, defaultOptions), tag }, listenOpts = pick(options, possibleOptions), qs = encodeQueryString({ query, params, options: { tag, ...listenOpts } }), uri = `${url}${_getDataUrl(this, "listen", qs)}`;
883
1004
  if (uri.length > MAX_URL_LENGTH)
884
- return new Observable((observer) => observer.error(new Error("Query too large for listener")));
885
- const listenFor = options.events ? options.events : ["mutation"], shouldEmitReconnect = listenFor.indexOf("reconnect") !== -1, esOptions = {};
1005
+ return throwError(() => new Error("Query too large for listener"));
1006
+ const listenFor = options.events ? options.events : ["mutation"], esOptions = {};
886
1007
  return (token || withCredentials) && (esOptions.withCredentials = !0), token && (esOptions.headers = {
887
1008
  Authorization: `Bearer ${token}`
888
- }), new Observable((observer) => {
889
- let es, reconnectTimer, stopped = !1, unsubscribed = !1;
890
- open();
891
- function onError() {
892
- stopped || (emitReconnect(), !stopped && es.readyState === es.CLOSED && (unsubscribe(), clearTimeout(reconnectTimer), reconnectTimer = setTimeout(open, 100)));
893
- }
894
- function onChannelError(err) {
895
- observer.error(cooerceError(err));
896
- }
897
- function onMessage(evt) {
898
- const event = parseEvent$1(evt);
899
- return event instanceof Error ? observer.error(event) : observer.next(event);
900
- }
901
- function onDisconnect() {
902
- stopped = !0, unsubscribe(), observer.complete();
903
- }
904
- function unsubscribe() {
905
- es && (es.removeEventListener("error", onError), es.removeEventListener("channelError", onChannelError), es.removeEventListener("disconnect", onDisconnect), listenFor.forEach((type) => es.removeEventListener(type, onMessage)), es.close());
906
- }
907
- function emitReconnect() {
908
- shouldEmitReconnect && observer.next({ type: "reconnect" });
909
- }
910
- async function getEventSource() {
911
- const { default: EventSource2 } = await import("@sanity/eventsource");
912
- if (unsubscribed)
913
- return;
914
- const evs = new EventSource2(uri, esOptions);
915
- return evs.addEventListener("error", onError), evs.addEventListener("channelError", onChannelError), evs.addEventListener("disconnect", onDisconnect), listenFor.forEach((type) => evs.addEventListener(type, onMessage)), evs;
916
- }
917
- function open() {
918
- getEventSource().then((eventSource) => {
919
- eventSource && (es = eventSource, unsubscribed && unsubscribe());
920
- }).catch((reason) => {
921
- observer.error(reason), stop();
922
- });
923
- }
924
- function stop() {
925
- stopped = !0, unsubscribe(), unsubscribed = !0;
926
- }
927
- return stop;
928
- });
929
- }
930
- function parseEvent$1(event) {
931
- try {
932
- const data = event.data && JSON.parse(event.data) || {};
933
- return Object.assign({ type: event.type }, data);
934
- } catch (err) {
935
- return err;
936
- }
937
- }
938
- function cooerceError(err) {
939
- if (err instanceof Error)
940
- return err;
941
- const evt = parseEvent$1(err);
942
- return evt instanceof Error ? evt : new Error(extractErrorMessage(evt));
943
- }
944
- function extractErrorMessage(err) {
945
- return err.error ? err.error.description ? err.error.description : typeof err.error == "string" ? err.error : JSON.stringify(err.error, null, 2) : err.message || "Unknown listener error";
1009
+ }), connectEventSource(() => (
1010
+ // use polyfill if there is no global EventSource or if we need to set headers
1011
+ (typeof EventSource > "u" || esOptions.headers ? eventSourcePolyfill : of(EventSource)).pipe(map((EventSource2) => new EventSource2(uri, esOptions)))
1012
+ ), listenFor).pipe(
1013
+ reconnectOnConnectionFailure(),
1014
+ filter((event) => listenFor.includes(event.type)),
1015
+ map(
1016
+ (event) => ({
1017
+ type: event.type,
1018
+ ..."data" in event ? event.data : {}
1019
+ })
1020
+ )
1021
+ );
946
1022
  }
947
1023
  const requiredApiVersion = "2021-03-26";
948
1024
  class LiveClient {
@@ -978,75 +1054,53 @@ class LiveClient {
978
1054
  );
979
1055
  const path = _getDataUrl(this.#client, "live/events"), url = new URL(this.#client.getUrl(path, !1)), tag = _tag && requestTagPrefix ? [requestTagPrefix, _tag].join(".") : _tag;
980
1056
  tag && url.searchParams.set("tag", tag), includeDrafts && url.searchParams.set("includeDrafts", "true");
981
- const listenFor = ["restart", "message", "welcome", "reconnect"], esOptions = {};
982
- return includeDrafts && token && (esOptions.headers = {
1057
+ const esOptions = {};
1058
+ includeDrafts && token && (esOptions.headers = {
983
1059
  Authorization: `Bearer ${token}`
984
- }), includeDrafts && withCredentials && (esOptions.withCredentials = !0), new Observable((observer) => {
985
- let es, reconnectTimer, stopped = !1, unsubscribed = !1;
986
- open();
987
- function onError(evt) {
988
- if (!stopped) {
989
- if ("data" in evt) {
990
- const event = parseEvent(evt);
991
- observer.error(new Error(event.message, { cause: event }));
992
- }
993
- es.readyState === es.CLOSED && (unsubscribe(), clearTimeout(reconnectTimer), reconnectTimer = setTimeout(open, 100));
994
- }
995
- }
996
- function onMessage(evt) {
997
- const event = parseEvent(evt);
998
- return event instanceof Error ? observer.error(event) : observer.next(event);
999
- }
1000
- function unsubscribe() {
1001
- if (es) {
1002
- es.removeEventListener("error", onError);
1003
- for (const type of listenFor)
1004
- es.removeEventListener(type, onMessage);
1005
- es.close();
1006
- }
1007
- }
1008
- async function getEventSource() {
1009
- const EventSourceImplementation = typeof EventSource > "u" || esOptions.headers || esOptions.withCredentials ? (await import("@sanity/eventsource")).default : EventSource;
1010
- if (unsubscribed)
1011
- return;
1012
- try {
1013
- if (await fetch(url, {
1014
- method: "OPTIONS",
1015
- mode: "cors",
1016
- credentials: esOptions.withCredentials ? "include" : "omit",
1017
- headers: esOptions.headers
1018
- }), unsubscribed)
1019
- return;
1020
- } catch {
1021
- throw new CorsOriginError({ projectId: projectId2 });
1060
+ }), includeDrafts && withCredentials && (esOptions.withCredentials = !0);
1061
+ const events = connectEventSource(() => (
1062
+ // use polyfill if there is no global EventSource or if we need to set headers
1063
+ (typeof EventSource > "u" || esOptions.headers ? eventSourcePolyfill : of(EventSource)).pipe(map((EventSource2) => new EventSource2(url.href, esOptions)))
1064
+ ), [
1065
+ "message",
1066
+ "restart",
1067
+ "welcome",
1068
+ "reconnect"
1069
+ ]).pipe(
1070
+ reconnectOnConnectionFailure(),
1071
+ map((event) => {
1072
+ if (event.type === "message") {
1073
+ const { data, ...rest } = event;
1074
+ return { ...rest, tags: data.tags };
1022
1075
  }
1023
- const evs = new EventSourceImplementation(url.toString(), esOptions);
1024
- evs.addEventListener("error", onError);
1025
- for (const type of listenFor)
1026
- evs.addEventListener(type, onMessage);
1027
- return evs;
1028
- }
1029
- function open() {
1030
- getEventSource().then((eventSource) => {
1031
- eventSource && (es = eventSource, unsubscribed && unsubscribe());
1032
- }).catch((reason) => {
1033
- observer.error(reason), stop();
1034
- });
1035
- }
1036
- function stop() {
1037
- stopped = !0, unsubscribe(), unsubscribed = !0;
1038
- }
1039
- return stop;
1040
- });
1076
+ return event;
1077
+ })
1078
+ ), checkCors = fetchObservable(url, {
1079
+ method: "OPTIONS",
1080
+ mode: "cors",
1081
+ credentials: esOptions.withCredentials ? "include" : "omit",
1082
+ headers: esOptions.headers
1083
+ }).pipe(
1084
+ mergeMap(() => EMPTY),
1085
+ catchError(() => {
1086
+ throw new CorsOriginError({ projectId: projectId2 });
1087
+ })
1088
+ );
1089
+ return concat(checkCors, events);
1041
1090
  }
1042
1091
  }
1043
- function parseEvent(event) {
1044
- try {
1045
- const data = event.data && JSON.parse(event.data) || {};
1046
- return { type: event.type, id: event.lastEventId, ...data };
1047
- } catch (err) {
1048
- return err;
1049
- }
1092
+ function fetchObservable(url, init) {
1093
+ return new Observable((observer) => {
1094
+ const controller = new AbortController(), signal = controller.signal;
1095
+ return fetch(url, { ...init, signal: controller.signal }).then(
1096
+ (response) => {
1097
+ observer.next(response), observer.complete();
1098
+ },
1099
+ (err) => {
1100
+ signal.aborted || observer.error(err);
1101
+ }
1102
+ ), () => controller.abort();
1103
+ });
1050
1104
  }
1051
1105
  class ObservableDatasetsClient {
1052
1106
  #client;
@@ -1569,8 +1623,13 @@ const exp = defineCreateClientExports(envMiddleware, SanityClient), requester =
1569
1623
  export {
1570
1624
  BasePatch,
1571
1625
  BaseTransaction,
1626
+ ChannelError,
1572
1627
  ClientError,
1628
+ ConnectionFailedError,
1573
1629
  CorsOriginError,
1630
+ DisconnectError,
1631
+ MessageError,
1632
+ MessageParseError,
1574
1633
  ObservablePatch,
1575
1634
  ObservableSanityClient,
1576
1635
  ObservableTransaction,
@@ -1578,6 +1637,7 @@ export {
1578
1637
  SanityClient,
1579
1638
  ServerError,
1580
1639
  Transaction,
1640
+ connectEventSource,
1581
1641
  createClient,
1582
1642
  deprecatedCreateClient as default,
1583
1643
  requester,