@sanity/client 7.21.0 → 7.22.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.
@@ -99,6 +99,7 @@ class ClientError extends Error {
99
99
  response;
100
100
  statusCode = 400;
101
101
  responseBody;
102
+ traceId;
102
103
  details;
103
104
  constructor(res, context) {
104
105
  const props = extractErrorProps(res, context);
@@ -109,6 +110,7 @@ class ServerError extends Error {
109
110
  response;
110
111
  statusCode = 500;
111
112
  responseBody;
113
+ traceId;
112
114
  details;
113
115
  constructor(res) {
114
116
  const props = extractErrorProps(res);
@@ -120,29 +122,30 @@ function extractErrorProps(res, context) {
120
122
  response: res,
121
123
  statusCode: res.statusCode,
122
124
  responseBody: stringifyBody(body, res),
125
+ traceId: extractTraceId(res),
123
126
  message: "",
124
127
  details: void 0
125
128
  };
126
129
  if (!stegaClean.isRecord(body))
127
- return props.message = httpErrorMessage(res, body), props;
130
+ return props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`, props;
128
131
  const error = body.error;
129
132
  if (typeof error == "string" && typeof body.message == "string")
130
- return props.message = `${error} - ${body.message}`, props;
133
+ return props.message = `${error} - ${body.message}${formatTraceId(props.traceId)}`, props;
131
134
  if (typeof error != "object" || error === null)
132
- return typeof error == "string" ? props.message = error : typeof body.message == "string" ? props.message = body.message : props.message = httpErrorMessage(res, body), props;
135
+ return typeof error == "string" ? props.message = `${error}${formatTraceId(props.traceId)}` : typeof body.message == "string" ? props.message = `${body.message}${formatTraceId(props.traceId)}` : props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`, props;
133
136
  if (isMutationError(error) || isActionError(error)) {
134
137
  const allItems = error.items || [], items = allItems.slice(0, MAX_ITEMS_IN_ERROR_MESSAGE).map((item) => item.error?.description).filter(Boolean);
135
138
  let itemsStr = items.length ? `:
136
139
  - ${items.join(`
137
140
  - `)}` : "";
138
141
  return allItems.length > MAX_ITEMS_IN_ERROR_MESSAGE && (itemsStr += `
139
- ...and ${allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE} more`), props.message = `${error.description}${itemsStr}`, props.details = body.error, props;
142
+ ...and ${allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE} more`), props.message = `${error.description}${formatTraceId(props.traceId)}${itemsStr}`, props.details = body.error, props;
140
143
  }
141
144
  if (isQueryParseError(error)) {
142
145
  const tag = context?.options?.query?.tag;
143
- return props.message = formatQueryParseError(error, tag), props.details = body.error, props;
146
+ return props.message = formatQueryParseError(error, tag, props.traceId), props.details = body.error, props;
144
147
  }
145
- return "description" in error && typeof error.description == "string" ? (props.message = error.description, props.details = error, props) : (props.message = httpErrorMessage(res, body), props);
148
+ return "description" in error && typeof error.description == "string" ? (props.message = `${error.description}${formatTraceId(props.traceId)}`, props.details = error, props) : (props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`, props);
146
149
  }
147
150
  function isMutationError(error) {
148
151
  return "type" in error && error.type === "mutationError" && "description" in error && typeof error.description == "string";
@@ -153,37 +156,43 @@ function isActionError(error) {
153
156
  function isQueryParseError(error) {
154
157
  return stegaClean.isRecord(error) && error.type === "queryParseError" && typeof error.query == "string" && typeof error.start == "number" && typeof error.end == "number";
155
158
  }
156
- function formatQueryParseError(error, tag) {
157
- const { query, start, end, description } = error;
159
+ function formatQueryParseError(error, tag, traceId) {
160
+ const { query, start, end, description } = error, withTraceId = traceId ? `
161
+ (traceId: ${traceId})` : "";
158
162
  if (!query || typeof start > "u")
159
- return `GROQ query parse error: ${description}`;
163
+ return `GROQ query parse error: ${description}${withTraceId}`;
160
164
  const withTag = tag ? `
161
165
 
162
166
  Tag: ${tag}` : "";
163
167
  return `GROQ query parse error:
164
- ${codeFrame(query, { start, end }, description)}${withTag}`;
168
+ ${codeFrame(query, { start, end }, description)}${withTag}${withTraceId}`;
165
169
  }
166
170
  function httpErrorMessage(res, body) {
167
171
  const details = typeof body == "string" ? ` (${sliceWithEllipsis(body, 100)})` : "", statusMessage = res.statusMessage ? ` ${res.statusMessage}` : "";
168
172
  return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}${details}`;
169
173
  }
174
+ function extractTraceId(res) {
175
+ const traceparent = res?.headers?.traceparent;
176
+ if (traceparent)
177
+ return traceparent.split("-")[1];
178
+ }
170
179
  function stringifyBody(body, res) {
171
180
  return (res.headers["content-type"] || "").toLowerCase().indexOf("application/json") !== -1 ? JSON.stringify(body, null, 2) : body;
172
181
  }
182
+ function formatTraceId(traceId) {
183
+ return traceId ? ` (traceId: ${traceId})` : "";
184
+ }
173
185
  function sliceWithEllipsis(str, max) {
174
186
  return str.length > max ? `${str.slice(0, max)}\u2026` : str;
175
187
  }
176
188
  class CorsOriginError extends Error {
177
189
  projectId;
178
190
  addOriginUrl;
179
- constructor({ projectId: projectId2 }) {
180
- super("CorsOriginError"), this.name = "CorsOriginError", this.projectId = projectId2;
181
- const url = new URL(`https://sanity.io/manage/project/${projectId2}/api`);
182
- if (typeof location < "u") {
183
- const { origin } = location;
184
- 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}`;
185
- } else
186
- 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.";
187
196
  }
188
197
  }
189
198
  const httpError = {
@@ -1502,19 +1511,14 @@ class LiveClient {
1502
1511
  "welcome",
1503
1512
  "reconnect",
1504
1513
  "goaway"
1505
- ]), checkCors = fetchObservable(url, {
1506
- method: "OPTIONS",
1507
- mode: "cors",
1508
- credentials: esOptions.withCredentials ? "include" : "omit",
1509
- headers: esOptions.headers
1510
- }).pipe(
1511
- rxjs.catchError(() => {
1512
- throw new CorsOriginError({ projectId: projectId2 });
1513
- })
1514
+ ]), checkCors = checkCorsObservable(
1515
+ new URL(this.#client.getUrl("/check/cors", !1)),
1516
+ projectId2,
1517
+ esOptions.withCredentials === !0
1514
1518
  ), observable = events.pipe(
1515
1519
  reconnectOnConnectionFailure(),
1516
1520
  rxjs.mergeMap((event) => event.type === "reconnect" ? checkCors.pipe(rxjs.mergeMap(() => rxjs.of(event))) : rxjs.of(event)),
1517
- rxjs.catchError((err) => checkCors.pipe(
1521
+ rxjs.catchError((err) => err instanceof CorsOriginError ? rxjs.throwError(() => err) : checkCors.pipe(
1518
1522
  rxjs.mergeMap(() => {
1519
1523
  throw err;
1520
1524
  })
@@ -1535,17 +1539,27 @@ class LiveClient {
1535
1539
  return eventsCache.set(key, observable), observable;
1536
1540
  }
1537
1541
  }
1538
- function fetchObservable(url, init) {
1542
+ function checkCorsObservable(url, projectId2, requireCredentials) {
1539
1543
  return new rxjs.Observable((observer) => {
1540
- const controller = new AbortController(), signal = controller.signal;
1541
- return fetch(url, { ...init, signal: controller.signal }).then(
1542
- (response) => {
1543
- observer.next(response), observer.complete();
1544
- },
1545
- (err) => {
1546
- signal.aborted || observer.error(err);
1544
+ const controller = new AbortController(), { signal } = controller;
1545
+ return fetch(url, { method: "GET", mode: "cors", credentials: "omit", signal }).then((response) => {
1546
+ if (!(signal.aborted || !response.ok))
1547
+ return response.json();
1548
+ }).then((body) => {
1549
+ if (!signal.aborted) {
1550
+ if (requireCredentials && body?.result?.withCredentials === !1) {
1551
+ observer.error(new CorsOriginError({ projectId: projectId2, credentials: !0 }));
1552
+ return;
1553
+ }
1554
+ if (body?.result?.allowed === !1) {
1555
+ observer.error(new CorsOriginError({ projectId: projectId2, credentials: requireCredentials }));
1556
+ return;
1557
+ }
1558
+ observer.next(), observer.complete();
1547
1559
  }
1548
- ), () => controller.abort();
1560
+ }).catch(() => {
1561
+ signal.aborted || observer.closed || (observer.next(), observer.complete());
1562
+ }), () => controller.abort();
1549
1563
  });
1550
1564
  }
1551
1565
  const eventsCache = /* @__PURE__ */ new Map();