@sanity/client 7.22.0 → 7.23.0

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.
@@ -188,14 +188,11 @@ function sliceWithEllipsis(str, max) {
188
188
  class CorsOriginError extends Error {
189
189
  projectId;
190
190
  addOriginUrl;
191
- constructor({ projectId: projectId2 }) {
192
- super("CorsOriginError"), this.name = "CorsOriginError", this.projectId = projectId2;
193
- const url = new URL(`https://sanity.io/manage/project/${projectId2}/api`);
194
- if (typeof location < "u") {
195
- const { origin } = location;
196
- url.searchParams.set("cors", "add"), url.searchParams.set("origin", origin), this.addOriginUrl = url, this.message = `The current origin is not allowed to connect to the Live Content API. Add it here: ${url}`;
197
- } else
198
- this.message = `The current origin is not allowed to connect to the Live Content API. Change your configuration here: ${url}`;
191
+ constructor({ projectId: projectId2, credentials } = {}) {
192
+ if (super("CorsOriginError"), this.name = "CorsOriginError", this.projectId = projectId2, projectId2 && typeof location < "u") {
193
+ const url = new URL(`https://sanity.io/manage/project/${projectId2}/api`), { origin } = location;
194
+ url.searchParams.set("cors", "add"), url.searchParams.set("origin", origin), credentials && url.searchParams.set("credentials", ""), this.addOriginUrl = url, this.message = `The current origin is not allowed to connect to the Live Content API. Add it here: ${url}`;
195
+ } else projectId2 ? this.message = `The current origin is not allowed to connect to the Live Content API. Change your configuration here: https://sanity.io/manage/project/${projectId2}/api` : this.message = "The current origin is not allowed to connect to the Live Content API.";
199
196
  }
200
197
  }
201
198
  const httpError = {
@@ -984,6 +981,35 @@ function _getDocuments(client, httpRequest, ids, opts = {}) {
984
981
  })
985
982
  );
986
983
  }
984
+ const DOCUMENTS_EXISTS_BATCH_SIZE = 100;
985
+ function _documentsExists(client, httpRequest, ids, opts = {}) {
986
+ if (ids.length === 0)
987
+ return rxjs.of(/* @__PURE__ */ new Set());
988
+ const batches = [];
989
+ for (let i = 0; i < ids.length; i += DOCUMENTS_EXISTS_BATCH_SIZE)
990
+ batches.push(ids.slice(i, i + DOCUMENTS_EXISTS_BATCH_SIZE));
991
+ const fetchBatch = (batchIds) => _requestObservable(client, httpRequest, {
992
+ uri: _getDataUrl(client, "doc", batchIds.map(encodeURIComponent).join(",")),
993
+ tag: opts.tag,
994
+ signal: opts.signal,
995
+ query: { excludeContent: !0 }
996
+ }).pipe(
997
+ operators.filter(isResponse),
998
+ operators.map((event) => {
999
+ const missing = /* @__PURE__ */ new Set();
1000
+ for (const omitted of event.body.omitted || [])
1001
+ omitted.reason === "existence" && missing.add(omitted.id);
1002
+ return new Set(batchIds.filter((id) => !missing.has(id)));
1003
+ })
1004
+ );
1005
+ return rxjs.from(batches).pipe(
1006
+ operators.concatMap(fetchBatch),
1007
+ operators.reduce((acc, set) => {
1008
+ for (const id of set) acc.add(id);
1009
+ return acc;
1010
+ }, /* @__PURE__ */ new Set())
1011
+ );
1012
+ }
987
1013
  function _getReleaseDocuments(client, httpRequest, releaseId, opts = {}) {
988
1014
  return _dataRequest(
989
1015
  client,
@@ -1120,7 +1146,7 @@ const hasDataConfig = (client) => {
1120
1146
  return config.dataset !== void 0 && config.projectId !== void 0 || config.resource !== void 0;
1121
1147
  }, 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);
1122
1148
  function _requestObservable(client, httpRequest, options) {
1123
- 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;
1149
+ 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;
1124
1150
  let useCdn = (options.useCdn ?? config.useCdn) && canUseCdn;
1125
1151
  const tag = options.tag && config.requestTagPrefix ? [config.requestTagPrefix, options.tag].join(".") : options.tag || config.requestTagPrefix;
1126
1152
  if (tag && options.tag !== null && (options.query = { tag: requestTag(tag), ...options.query }), ["GET", "HEAD", "POST"].indexOf(options.method || "GET") >= 0 && isQuery(client, uri)) {
@@ -1136,7 +1162,8 @@ function _requestObservable(client, httpRequest, options) {
1136
1162
  const reqOptions = requestOptions(
1137
1163
  config,
1138
1164
  Object.assign({}, options, {
1139
- url: _getUrl(client, uri, useCdn)
1165
+ url: _getUrl(client, uri, useCdn),
1166
+ callSiteStack
1140
1167
  })
1141
1168
  ), request = new rxjs.Observable(
1142
1169
  (subscriber) => httpRequest(reqOptions, config.requester).subscribe(subscriber)
@@ -1514,19 +1541,14 @@ class LiveClient {
1514
1541
  "welcome",
1515
1542
  "reconnect",
1516
1543
  "goaway"
1517
- ]), checkCors = fetchObservable(url, {
1518
- method: "OPTIONS",
1519
- mode: "cors",
1520
- credentials: esOptions.withCredentials ? "include" : "omit",
1521
- headers: esOptions.headers
1522
- }).pipe(
1523
- rxjs.catchError(() => {
1524
- throw new CorsOriginError({ projectId: projectId2 });
1525
- })
1544
+ ]), checkCors = checkCorsObservable(
1545
+ new URL(this.#client.getUrl("/check/cors", !1)),
1546
+ projectId2,
1547
+ esOptions.withCredentials === !0
1526
1548
  ), observable = events.pipe(
1527
1549
  reconnectOnConnectionFailure(),
1528
1550
  rxjs.mergeMap((event) => event.type === "reconnect" ? checkCors.pipe(rxjs.mergeMap(() => rxjs.of(event))) : rxjs.of(event)),
1529
- rxjs.catchError((err) => checkCors.pipe(
1551
+ rxjs.catchError((err) => err instanceof CorsOriginError ? rxjs.throwError(() => err) : checkCors.pipe(
1530
1552
  rxjs.mergeMap(() => {
1531
1553
  throw err;
1532
1554
  })
@@ -1547,17 +1569,27 @@ class LiveClient {
1547
1569
  return eventsCache.set(key, observable), observable;
1548
1570
  }
1549
1571
  }
1550
- function fetchObservable(url, init) {
1572
+ function checkCorsObservable(url, projectId2, requireCredentials) {
1551
1573
  return new rxjs.Observable((observer) => {
1552
- const controller = new AbortController(), signal = controller.signal;
1553
- return fetch(url, { ...init, signal: controller.signal }).then(
1554
- (response) => {
1555
- observer.next(response), observer.complete();
1556
- },
1557
- (err) => {
1558
- signal.aborted || observer.error(err);
1574
+ const controller = new AbortController(), { signal } = controller;
1575
+ return fetch(url, { method: "GET", mode: "cors", credentials: "omit", signal }).then((response) => {
1576
+ if (!(signal.aborted || !response.ok))
1577
+ return response.json();
1578
+ }).then((body) => {
1579
+ if (!signal.aborted) {
1580
+ if (requireCredentials && body?.result?.withCredentials === !1) {
1581
+ observer.error(new CorsOriginError({ projectId: projectId2, credentials: !0 }));
1582
+ return;
1583
+ }
1584
+ if (body?.result?.allowed === !1) {
1585
+ observer.error(new CorsOriginError({ projectId: projectId2, credentials: requireCredentials }));
1586
+ return;
1587
+ }
1588
+ observer.next(), observer.complete();
1559
1589
  }
1560
- ), () => controller.abort();
1590
+ }).catch(() => {
1591
+ signal.aborted || observer.closed || (observer.next(), observer.complete());
1592
+ }), () => controller.abort();
1561
1593
  });
1562
1594
  }
1563
1595
  const eventsCache = /* @__PURE__ */ new Map();
@@ -2485,6 +2517,16 @@ class ObservableSanityClient {
2485
2517
  getDocuments(ids, options) {
2486
2518
  return _getDocuments(this, this.#httpRequest, ids, options);
2487
2519
  }
2520
+ /**
2521
+ * Convenient and bandwidth efficient method of checking wether a set of document IDs exists.
2522
+ * Returns a set of the IDs that exist.
2523
+ *
2524
+ * @param ids - Document IDs to check
2525
+ * @param options - Request options
2526
+ */
2527
+ documentsExists(ids, options) {
2528
+ return _documentsExists(this, this.#httpRequest, ids, options);
2529
+ }
2488
2530
  create(document, options) {
2489
2531
  return _create(this, this.#httpRequest, document, "create", options);
2490
2532
  }
@@ -2762,6 +2804,16 @@ class SanityClient {
2762
2804
  getDocuments(ids, options) {
2763
2805
  return rxjs.lastValueFrom(_getDocuments(this, this.#httpRequest, ids, options));
2764
2806
  }
2807
+ /**
2808
+ * Convenient and bandwidth efficient method of checking wether a set of document IDs exists.
2809
+ * Returns a set of the IDs that exist.
2810
+ *
2811
+ * @param ids - Document IDs to check
2812
+ * @param options - Request options
2813
+ */
2814
+ documentsExists(ids, options) {
2815
+ return rxjs.lastValueFrom(_documentsExists(this, this.#httpRequest, ids, options));
2816
+ }
2765
2817
  create(document, options) {
2766
2818
  return rxjs.lastValueFrom(
2767
2819
  _create(this, this.#httpRequest, document, "create", options)