@sanity/client 7.21.0 → 7.22.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.
@@ -855,6 +855,7 @@ export declare class ClientError extends Error {
855
855
  response: ErrorProps['response']
856
856
  statusCode: ErrorProps['statusCode']
857
857
  responseBody: ErrorProps['responseBody']
858
+ traceId: ErrorProps['traceId']
858
859
  details: ErrorProps['details']
859
860
  constructor(res: Any, context?: HttpContext)
860
861
  }
@@ -1515,6 +1516,7 @@ export declare interface ErrorProps {
1515
1516
  response: Any
1516
1517
  statusCode: number
1517
1518
  responseBody: Any
1519
+ traceId?: string
1518
1520
  details: Any
1519
1521
  }
1520
1522
 
@@ -1714,7 +1716,11 @@ export declare type FitMode = 'preserve' | 'stretch' | 'crop' | 'smartcrop' | 'p
1714
1716
  * @returns A formatted error message string.
1715
1717
  * @public
1716
1718
  */
1717
- export declare function formatQueryParseError(error: QueryParseError, tag?: string | null): string
1719
+ export declare function formatQueryParseError(
1720
+ error: QueryParseError,
1721
+ tag?: string | null,
1722
+ traceId?: string,
1723
+ ): string
1718
1724
 
1719
1725
  /** @beta */
1720
1726
  declare type GenerateAsyncInstruction<T extends Record<string, Any> = Record<string, Any>> = (
@@ -6061,6 +6067,7 @@ export declare class ServerError extends Error {
6061
6067
  response: ErrorProps['response']
6062
6068
  statusCode: ErrorProps['statusCode']
6063
6069
  responseBody: ErrorProps['responseBody']
6070
+ traceId: ErrorProps['traceId']
6064
6071
  details: ErrorProps['details']
6065
6072
  constructor(res: Any)
6066
6073
  }
@@ -855,6 +855,7 @@ export declare class ClientError extends Error {
855
855
  response: ErrorProps['response']
856
856
  statusCode: ErrorProps['statusCode']
857
857
  responseBody: ErrorProps['responseBody']
858
+ traceId: ErrorProps['traceId']
858
859
  details: ErrorProps['details']
859
860
  constructor(res: Any, context?: HttpContext)
860
861
  }
@@ -1515,6 +1516,7 @@ export declare interface ErrorProps {
1515
1516
  response: Any
1516
1517
  statusCode: number
1517
1518
  responseBody: Any
1519
+ traceId?: string
1518
1520
  details: Any
1519
1521
  }
1520
1522
 
@@ -1714,7 +1716,11 @@ export declare type FitMode = 'preserve' | 'stretch' | 'crop' | 'smartcrop' | 'p
1714
1716
  * @returns A formatted error message string.
1715
1717
  * @public
1716
1718
  */
1717
- export declare function formatQueryParseError(error: QueryParseError, tag?: string | null): string
1719
+ export declare function formatQueryParseError(
1720
+ error: QueryParseError,
1721
+ tag?: string | null,
1722
+ traceId?: string,
1723
+ ): string
1718
1724
 
1719
1725
  /** @beta */
1720
1726
  declare type GenerateAsyncInstruction<T extends Record<string, Any> = Record<string, Any>> = (
@@ -6061,6 +6067,7 @@ export declare class ServerError extends Error {
6061
6067
  response: ErrorProps['response']
6062
6068
  statusCode: ErrorProps['statusCode']
6063
6069
  responseBody: ErrorProps['responseBody']
6070
+ traceId: ErrorProps['traceId']
6064
6071
  details: ErrorProps['details']
6065
6072
  constructor(res: Any)
6066
6073
  }
package/dist/stega.d.cts CHANGED
@@ -855,6 +855,7 @@ export declare class ClientError extends Error {
855
855
  response: ErrorProps['response']
856
856
  statusCode: ErrorProps['statusCode']
857
857
  responseBody: ErrorProps['responseBody']
858
+ traceId: ErrorProps['traceId']
858
859
  details: ErrorProps['details']
859
860
  constructor(res: Any, context?: HttpContext)
860
861
  }
@@ -1515,6 +1516,7 @@ export declare interface ErrorProps {
1515
1516
  response: Any
1516
1517
  statusCode: number
1517
1518
  responseBody: Any
1519
+ traceId?: string
1518
1520
  details: Any
1519
1521
  }
1520
1522
 
@@ -1714,7 +1716,11 @@ export declare type FitMode = 'preserve' | 'stretch' | 'crop' | 'smartcrop' | 'p
1714
1716
  * @returns A formatted error message string.
1715
1717
  * @public
1716
1718
  */
1717
- export declare function formatQueryParseError(error: QueryParseError, tag?: string | null): string
1719
+ export declare function formatQueryParseError(
1720
+ error: QueryParseError,
1721
+ tag?: string | null,
1722
+ traceId?: string,
1723
+ ): string
1718
1724
 
1719
1725
  /** @beta */
1720
1726
  declare type GenerateAsyncInstruction<T extends Record<string, Any> = Record<string, Any>> = (
@@ -6061,6 +6067,7 @@ export declare class ServerError extends Error {
6061
6067
  response: ErrorProps['response']
6062
6068
  statusCode: ErrorProps['statusCode']
6063
6069
  responseBody: ErrorProps['responseBody']
6070
+ traceId: ErrorProps['traceId']
6064
6071
  details: ErrorProps['details']
6065
6072
  constructor(res: Any)
6066
6073
  }
package/dist/stega.d.ts CHANGED
@@ -855,6 +855,7 @@ export declare class ClientError extends Error {
855
855
  response: ErrorProps['response']
856
856
  statusCode: ErrorProps['statusCode']
857
857
  responseBody: ErrorProps['responseBody']
858
+ traceId: ErrorProps['traceId']
858
859
  details: ErrorProps['details']
859
860
  constructor(res: Any, context?: HttpContext)
860
861
  }
@@ -1515,6 +1516,7 @@ export declare interface ErrorProps {
1515
1516
  response: Any
1516
1517
  statusCode: number
1517
1518
  responseBody: Any
1519
+ traceId?: string
1518
1520
  details: Any
1519
1521
  }
1520
1522
 
@@ -1714,7 +1716,11 @@ export declare type FitMode = 'preserve' | 'stretch' | 'crop' | 'smartcrop' | 'p
1714
1716
  * @returns A formatted error message string.
1715
1717
  * @public
1716
1718
  */
1717
- export declare function formatQueryParseError(error: QueryParseError, tag?: string | null): string
1719
+ export declare function formatQueryParseError(
1720
+ error: QueryParseError,
1721
+ tag?: string | null,
1722
+ traceId?: string,
1723
+ ): string
1718
1724
 
1719
1725
  /** @beta */
1720
1726
  declare type GenerateAsyncInstruction<T extends Record<string, Any> = Record<string, Any>> = (
@@ -6061,6 +6067,7 @@ export declare class ServerError extends Error {
6061
6067
  response: ErrorProps['response']
6062
6068
  statusCode: ErrorProps['statusCode']
6063
6069
  responseBody: ErrorProps['responseBody']
6070
+ traceId: ErrorProps['traceId']
6064
6071
  details: ErrorProps['details']
6065
6072
  constructor(res: Any)
6066
6073
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/client",
3
- "version": "7.21.0",
3
+ "version": "7.22.0",
4
4
  "description": "Client for retrieving, creating and patching data from Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -64,6 +64,7 @@ export class ClientError extends Error {
64
64
  response: ErrorProps['response']
65
65
  statusCode: ErrorProps['statusCode'] = 400
66
66
  responseBody: ErrorProps['responseBody']
67
+ traceId: ErrorProps['traceId']
67
68
  details: ErrorProps['details']
68
69
 
69
70
  constructor(res: Any, context?: HttpContext) {
@@ -78,6 +79,7 @@ export class ServerError extends Error {
78
79
  response: ErrorProps['response']
79
80
  statusCode: ErrorProps['statusCode'] = 500
80
81
  responseBody: ErrorProps['responseBody']
82
+ traceId: ErrorProps['traceId']
81
83
  details: ErrorProps['details']
82
84
 
83
85
  constructor(res: Any) {
@@ -93,13 +95,14 @@ function extractErrorProps(res: Any, context?: HttpContext): ErrorProps {
93
95
  response: res,
94
96
  statusCode: res.statusCode,
95
97
  responseBody: stringifyBody(body, res),
98
+ traceId: extractTraceId(res),
96
99
  message: '',
97
100
  details: undefined as Any,
98
101
  }
99
102
 
100
103
  // Fall back early if we didn't get a JSON object returned as expected
101
104
  if (!isRecord(body)) {
102
- props.message = httpErrorMessage(res, body)
105
+ props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`
103
106
  return props
104
107
  }
105
108
 
@@ -107,18 +110,18 @@ function extractErrorProps(res: Any, context?: HttpContext): ErrorProps {
107
110
 
108
111
  // API/Boom style errors ({statusCode, error, message})
109
112
  if (typeof error === 'string' && typeof body.message === 'string') {
110
- props.message = `${error} - ${body.message}`
113
+ props.message = `${error} - ${body.message}${formatTraceId(props.traceId)}`
111
114
  return props
112
115
  }
113
116
 
114
117
  // Content Lake errors with a `error` prop being an object
115
118
  if (typeof error !== 'object' || error === null) {
116
119
  if (typeof error === 'string') {
117
- props.message = error
120
+ props.message = `${error}${formatTraceId(props.traceId)}`
118
121
  } else if (typeof body.message === 'string') {
119
- props.message = body.message
122
+ props.message = `${body.message}${formatTraceId(props.traceId)}`
120
123
  } else {
121
- props.message = httpErrorMessage(res, body)
124
+ props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`
122
125
  }
123
126
  return props
124
127
  }
@@ -134,7 +137,7 @@ function extractErrorProps(res: Any, context?: HttpContext): ErrorProps {
134
137
  if (allItems.length > MAX_ITEMS_IN_ERROR_MESSAGE) {
135
138
  itemsStr += `\n...and ${allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE} more`
136
139
  }
137
- props.message = `${error.description}${itemsStr}`
140
+ props.message = `${error.description}${formatTraceId(props.traceId)}${itemsStr}`
138
141
  props.details = body.error
139
142
  return props
140
143
  }
@@ -142,20 +145,20 @@ function extractErrorProps(res: Any, context?: HttpContext): ErrorProps {
142
145
  // Query parse errors
143
146
  if (isQueryParseError(error)) {
144
147
  const tag = context?.options?.query?.tag
145
- props.message = formatQueryParseError(error, tag)
148
+ props.message = formatQueryParseError(error, tag, props.traceId)
146
149
  props.details = body.error
147
150
  return props
148
151
  }
149
152
 
150
153
  if ('description' in error && typeof error.description === 'string') {
151
154
  // Query/database errors ({error: {description, other, arb, props}})
152
- props.message = error.description
155
+ props.message = `${error.description}${formatTraceId(props.traceId)}`
153
156
  props.details = error
154
157
  return props
155
158
  }
156
159
 
157
160
  // Other, more arbitrary errors
158
- props.message = httpErrorMessage(res, body)
161
+ props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`
159
162
  return props
160
163
  }
161
164
 
@@ -196,17 +199,22 @@ export function isQueryParseError(error: object): error is QueryParseError {
196
199
  * @returns A formatted error message string.
197
200
  * @public
198
201
  */
199
- export function formatQueryParseError(error: QueryParseError, tag?: string | null) {
202
+ export function formatQueryParseError(
203
+ error: QueryParseError,
204
+ tag?: string | null,
205
+ traceId?: string,
206
+ ) {
200
207
  const {query, start, end, description} = error
208
+ const withTraceId = traceId ? `\n(traceId: ${traceId})` : ''
201
209
 
202
210
  if (!query || typeof start === 'undefined') {
203
- return `GROQ query parse error: ${description}`
211
+ return `GROQ query parse error: ${description}${withTraceId}`
204
212
  }
205
213
 
206
214
  const withTag = tag ? `\n\nTag: ${tag}` : ''
207
215
  const framed = codeFrame(query, {start, end}, description)
208
216
 
209
- return `GROQ query parse error:\n${framed}${withTag}`
217
+ return `GROQ query parse error:\n${framed}${withTag}${withTraceId}`
210
218
  }
211
219
 
212
220
  function httpErrorMessage(res: Any, body: unknown) {
@@ -215,12 +223,33 @@ function httpErrorMessage(res: Any, body: unknown) {
215
223
  return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}${details}`
216
224
  }
217
225
 
226
+ /**
227
+ * Extract the traceId from the traceparent header on the response.
228
+ *
229
+ * The traceparent is on the format [version]-[traceId]-[parentId]-[traceFlags], but
230
+ * when debugging end-user issues it's the traceId we need to be able to get hold of
231
+ * the relevant traces.
232
+ *
233
+ * @see https://www.w3.org/TR/trace-context/
234
+ * @returns The traceId for HTTP response
235
+ */
236
+ function extractTraceId(res: Any): string | undefined {
237
+ const traceparent = res?.headers?.['traceparent']
238
+ if (!traceparent) return
239
+
240
+ return traceparent.split('-')[1]
241
+ }
242
+
218
243
  function stringifyBody(body: Any, res: Any) {
219
244
  const contentType = (res.headers['content-type'] || '').toLowerCase()
220
245
  const isJson = contentType.indexOf('application/json') !== -1
221
246
  return isJson ? JSON.stringify(body, null, 2) : body
222
247
  }
223
248
 
249
+ function formatTraceId(traceId: string | undefined): string {
250
+ return traceId ? ` (traceId: ${traceId})` : ''
251
+ }
252
+
224
253
  function sliceWithEllipsis(str: string, max: number) {
225
254
  return str.length > max ? `${str.slice(0, max)}…` : str
226
255
  }
package/src/types.ts CHANGED
@@ -433,6 +433,7 @@ export interface ErrorProps {
433
433
  response: Any
434
434
  statusCode: number
435
435
  responseBody: Any
436
+ traceId?: string
436
437
  details: Any
437
438
  }
438
439
 
@@ -2059,6 +2059,7 @@
2059
2059
  response;
2060
2060
  statusCode = 400;
2061
2061
  responseBody;
2062
+ traceId;
2062
2063
  details;
2063
2064
  constructor(res, context) {
2064
2065
  const props = extractErrorProps(res, context);
@@ -2069,6 +2070,7 @@
2069
2070
  response;
2070
2071
  statusCode = 500;
2071
2072
  responseBody;
2073
+ traceId;
2072
2074
  details;
2073
2075
  constructor(res) {
2074
2076
  const props = extractErrorProps(res);
@@ -2080,29 +2082,30 @@
2080
2082
  response: res,
2081
2083
  statusCode: res.statusCode,
2082
2084
  responseBody: stringifyBody(body, res),
2085
+ traceId: extractTraceId(res),
2083
2086
  message: "",
2084
2087
  details: void 0
2085
2088
  };
2086
2089
  if (!isRecord(body))
2087
- return props.message = httpErrorMessage(res, body), props;
2090
+ return props.message = `${httpErrorMessage(res, body)}${formatTraceId(props.traceId)}`, props;
2088
2091
  const error = body.error;
2089
2092
  if (typeof error == "string" && typeof body.message == "string")
2090
- return props.message = `${error} - ${body.message}`, props;
2093
+ return props.message = `${error} - ${body.message}${formatTraceId(props.traceId)}`, props;
2091
2094
  if (typeof error != "object" || error === null)
2092
- return typeof error == "string" ? props.message = error : typeof body.message == "string" ? props.message = body.message : props.message = httpErrorMessage(res, body), props;
2095
+ 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;
2093
2096
  if (isMutationError(error) || isActionError(error)) {
2094
2097
  const allItems = error.items || [], items = allItems.slice(0, MAX_ITEMS_IN_ERROR_MESSAGE).map((item) => item.error?.description).filter(Boolean);
2095
2098
  let itemsStr = items.length ? `:
2096
2099
  - ${items.join(`
2097
2100
  - `)}` : "";
2098
2101
  return allItems.length > MAX_ITEMS_IN_ERROR_MESSAGE && (itemsStr += `
2099
- ...and ${allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE} more`), props.message = `${error.description}${itemsStr}`, props.details = body.error, props;
2102
+ ...and ${allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE} more`), props.message = `${error.description}${formatTraceId(props.traceId)}${itemsStr}`, props.details = body.error, props;
2100
2103
  }
2101
2104
  if (isQueryParseError(error)) {
2102
2105
  const tag = context?.options?.query?.tag;
2103
- return props.message = formatQueryParseError(error, tag), props.details = body.error, props;
2106
+ return props.message = formatQueryParseError(error, tag, props.traceId), props.details = body.error, props;
2104
2107
  }
2105
- return "description" in error && typeof error.description == "string" ? (props.message = error.description, props.details = error, props) : (props.message = httpErrorMessage(res, body), props);
2108
+ 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);
2106
2109
  }
2107
2110
  function isMutationError(error) {
2108
2111
  return "type" in error && error.type === "mutationError" && "description" in error && typeof error.description == "string";
@@ -2113,23 +2116,32 @@
2113
2116
  function isQueryParseError(error) {
2114
2117
  return isRecord(error) && error.type === "queryParseError" && typeof error.query == "string" && typeof error.start == "number" && typeof error.end == "number";
2115
2118
  }
2116
- function formatQueryParseError(error, tag) {
2117
- const { query, start, end, description } = error;
2119
+ function formatQueryParseError(error, tag, traceId) {
2120
+ const { query, start, end, description } = error, withTraceId = traceId ? `
2121
+ (traceId: ${traceId})` : "";
2118
2122
  if (!query || typeof start > "u")
2119
- return `GROQ query parse error: ${description}`;
2123
+ return `GROQ query parse error: ${description}${withTraceId}`;
2120
2124
  const withTag = tag ? `
2121
2125
 
2122
2126
  Tag: ${tag}` : "";
2123
2127
  return `GROQ query parse error:
2124
- ${codeFrame(query, { start, end }, description)}${withTag}`;
2128
+ ${codeFrame(query, { start, end }, description)}${withTag}${withTraceId}`;
2125
2129
  }
2126
2130
  function httpErrorMessage(res, body) {
2127
2131
  const details = typeof body == "string" ? ` (${sliceWithEllipsis(body, 100)})` : "", statusMessage = res.statusMessage ? ` ${res.statusMessage}` : "";
2128
2132
  return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}${details}`;
2129
2133
  }
2134
+ function extractTraceId(res) {
2135
+ const traceparent = res?.headers?.traceparent;
2136
+ if (traceparent)
2137
+ return traceparent.split("-")[1];
2138
+ }
2130
2139
  function stringifyBody(body, res) {
2131
2140
  return (res.headers["content-type"] || "").toLowerCase().indexOf("application/json") !== -1 ? JSON.stringify(body, null, 2) : body;
2132
2141
  }
2142
+ function formatTraceId(traceId) {
2143
+ return traceId ? ` (traceId: ${traceId})` : "";
2144
+ }
2133
2145
  function sliceWithEllipsis(str, max) {
2134
2146
  return str.length > max ? `${str.slice(0, max)}\u2026` : str;
2135
2147
  }