@sanity/client 7.22.1 → 7.23.1

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.
@@ -419,6 +419,17 @@ const initConfig = (config, prevConfig) => {
419
419
  };
420
420
  class ConnectionFailedError extends Error {
421
421
  name = "ConnectionFailedError";
422
+ /**
423
+ * HTTP status code of the rejected connection attempt, if known.
424
+ * Only set when the EventSource implementation exposes it — the polyfill used in
425
+ * Node.js and when custom headers (eg authorization) are required does, while
426
+ * native EventSource implementations (browser and Node.js) do not.
427
+ */
428
+ status;
429
+ constructor(message, options = {}) {
430
+ const { status, ...errorOptions } = options;
431
+ super(message, errorOptions), this.status = status;
432
+ }
422
433
  }
423
434
  class DisconnectError extends Error {
424
435
  name = "DisconnectError";
@@ -462,6 +473,11 @@ function connectWithESInstance(es, events) {
462
473
  );
463
474
  return;
464
475
  }
476
+ const rawStatus = evt.status, status = typeof rawStatus == "number" ? rawStatus : void 0;
477
+ if (status !== void 0) {
478
+ observer.error(new ConnectionFailedError("EventSource connection failed", { status }));
479
+ return;
480
+ }
465
481
  es.readyState === es.CLOSED ? observer.error(new ConnectionFailedError("EventSource connection failed")) : emitReconnect && observer.next({ type: "reconnect" });
466
482
  }
467
483
  function onOpen() {
@@ -981,6 +997,35 @@ function _getDocuments(client, httpRequest, ids, opts = {}) {
981
997
  })
982
998
  );
983
999
  }
1000
+ const DOCUMENTS_EXISTS_BATCH_SIZE = 100;
1001
+ function _documentsExists(client, httpRequest, ids, opts = {}) {
1002
+ if (ids.length === 0)
1003
+ return rxjs.of(/* @__PURE__ */ new Set());
1004
+ const batches = [];
1005
+ for (let i = 0; i < ids.length; i += DOCUMENTS_EXISTS_BATCH_SIZE)
1006
+ batches.push(ids.slice(i, i + DOCUMENTS_EXISTS_BATCH_SIZE));
1007
+ const fetchBatch = (batchIds) => _requestObservable(client, httpRequest, {
1008
+ uri: _getDataUrl(client, "doc", batchIds.map(encodeURIComponent).join(",")),
1009
+ tag: opts.tag,
1010
+ signal: opts.signal,
1011
+ query: { excludeContent: !0 }
1012
+ }).pipe(
1013
+ operators.filter(isResponse),
1014
+ operators.map((event) => {
1015
+ const missing = /* @__PURE__ */ new Set();
1016
+ for (const omitted of event.body.omitted || [])
1017
+ omitted.reason === "existence" && missing.add(omitted.id);
1018
+ return new Set(batchIds.filter((id) => !missing.has(id)));
1019
+ })
1020
+ );
1021
+ return rxjs.from(batches).pipe(
1022
+ operators.concatMap(fetchBatch),
1023
+ operators.reduce((acc, set) => {
1024
+ for (const id of set) acc.add(id);
1025
+ return acc;
1026
+ }, /* @__PURE__ */ new Set())
1027
+ );
1028
+ }
984
1029
  function _getReleaseDocuments(client, httpRequest, releaseId, opts = {}) {
985
1030
  return _dataRequest(
986
1031
  client,
@@ -1117,7 +1162,7 @@ const hasDataConfig = (client) => {
1117
1162
  return config.dataset !== void 0 && config.projectId !== void 0 || config.resource !== void 0;
1118
1163
  }, isQuery = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "query")), isMutate = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "mutate")), isDoc = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "doc", "")), isListener = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "listen")), isHistory = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "history", "")), isData = (client, uri) => uri.startsWith("/data/") || isQuery(client, uri) || isMutate(client, uri) || isDoc(client, uri) || isListener(client, uri) || isHistory(client, uri);
1119
1164
  function _requestObservable(client, httpRequest, options) {
1120
- const uri = options.url || options.uri, config = client.config(), canUseCdn = typeof options.canUseCdn > "u" ? ["GET", "HEAD"].indexOf(options.method || "GET") >= 0 && isData(client, uri) : options.canUseCdn;
1165
+ const callSiteStack = new Error(), uri = options.url || options.uri, config = client.config(), canUseCdn = typeof options.canUseCdn > "u" ? ["GET", "HEAD"].indexOf(options.method || "GET") >= 0 && isData(client, uri) : options.canUseCdn;
1121
1166
  let useCdn = (options.useCdn ?? config.useCdn) && canUseCdn;
1122
1167
  const tag = options.tag && config.requestTagPrefix ? [config.requestTagPrefix, options.tag].join(".") : options.tag || config.requestTagPrefix;
1123
1168
  if (tag && options.tag !== null && (options.query = { tag: requestTag(tag), ...options.query }), ["GET", "HEAD", "POST"].indexOf(options.method || "GET") >= 0 && isQuery(client, uri)) {
@@ -1133,7 +1178,8 @@ function _requestObservable(client, httpRequest, options) {
1133
1178
  const reqOptions = requestOptions(
1134
1179
  config,
1135
1180
  Object.assign({}, options, {
1136
- url: _getUrl(client, uri, useCdn)
1181
+ url: _getUrl(client, uri, useCdn),
1182
+ callSiteStack
1137
1183
  })
1138
1184
  ), request = new rxjs.Observable(
1139
1185
  (subscriber) => httpRequest(reqOptions, config.requester).subscribe(subscriber)
@@ -1403,11 +1449,11 @@ var defaults = (obj, defaults2) => Object.keys(defaults2).concat(Object.keys(obj
1403
1449
  const pick = (obj, props) => props.reduce((selection, prop) => (typeof obj[prop] > "u" || (selection[prop] = obj[prop]), selection), {}), eventSourcePolyfill = rxjs.defer(() => import("@sanity/eventsource")).pipe(
1404
1450
  operators.map(({ default: EventSource2 }) => EventSource2),
1405
1451
  rxjs.shareReplay(1)
1406
- );
1452
+ ), RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 429]);
1407
1453
  function reconnectOnConnectionFailure() {
1408
1454
  return function(source) {
1409
1455
  return source.pipe(
1410
- rxjs.catchError((err, caught) => err instanceof ConnectionFailedError ? rxjs.concat(rxjs.of({ type: "reconnect" }), rxjs.timer(1e3).pipe(rxjs.mergeMap(() => caught))) : rxjs.throwError(() => err))
1456
+ rxjs.catchError((err, caught) => err instanceof ConnectionFailedError && (typeof err.status != "number" || err.status < 400 || err.status >= 500 || RETRYABLE_STATUSES.has(err.status)) ? rxjs.concat(rxjs.of({ type: "reconnect" }), rxjs.timer(1e3).pipe(rxjs.mergeMap(() => caught))) : rxjs.throwError(() => err))
1411
1457
  );
1412
1458
  };
1413
1459
  }
@@ -2487,6 +2533,16 @@ class ObservableSanityClient {
2487
2533
  getDocuments(ids, options) {
2488
2534
  return _getDocuments(this, this.#httpRequest, ids, options);
2489
2535
  }
2536
+ /**
2537
+ * Convenient and bandwidth efficient method of checking wether a set of document IDs exists.
2538
+ * Returns a set of the IDs that exist.
2539
+ *
2540
+ * @param ids - Document IDs to check
2541
+ * @param options - Request options
2542
+ */
2543
+ documentsExists(ids, options) {
2544
+ return _documentsExists(this, this.#httpRequest, ids, options);
2545
+ }
2490
2546
  create(document, options) {
2491
2547
  return _create(this, this.#httpRequest, document, "create", options);
2492
2548
  }
@@ -2764,6 +2820,16 @@ class SanityClient {
2764
2820
  getDocuments(ids, options) {
2765
2821
  return rxjs.lastValueFrom(_getDocuments(this, this.#httpRequest, ids, options));
2766
2822
  }
2823
+ /**
2824
+ * Convenient and bandwidth efficient method of checking wether a set of document IDs exists.
2825
+ * Returns a set of the IDs that exist.
2826
+ *
2827
+ * @param ids - Document IDs to check
2828
+ * @param options - Request options
2829
+ */
2830
+ documentsExists(ids, options) {
2831
+ return rxjs.lastValueFrom(_documentsExists(this, this.#httpRequest, ids, options));
2832
+ }
2767
2833
  create(document, options) {
2768
2834
  return rxjs.lastValueFrom(
2769
2835
  _create(this, this.#httpRequest, document, "create", options)