@sanity/client 5.2.2 → 5.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/client",
3
- "version": "5.2.2",
3
+ "version": "5.3.1",
4
4
  "description": "Client for retrieving, creating and patching data from Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -88,38 +88,38 @@
88
88
  "singleQuote": true
89
89
  },
90
90
  "dependencies": {
91
- "@sanity/eventsource": "^4",
92
- "get-it": "^8",
93
- "rxjs": "^7"
91
+ "@sanity/eventsource": "5",
92
+ "get-it": "8",
93
+ "rxjs": "7"
94
94
  },
95
95
  "devDependencies": {
96
- "@edge-runtime/types": "^2.0.5",
97
- "@edge-runtime/vm": "^2.0.5",
96
+ "@edge-runtime/types": "^2.0.8",
97
+ "@edge-runtime/vm": "^2.1.2",
98
98
  "@rollup/plugin-commonjs": "^24.0.1",
99
99
  "@rollup/plugin-node-resolve": "^15.0.1",
100
- "@sanity/pkg-utils": "^2.2.5",
101
- "@sanity/semantic-release-preset": "^4.0.0",
102
- "@types/node": "^18.14.0",
103
- "@typescript-eslint/eslint-plugin": "^5.53.0",
104
- "@typescript-eslint/parser": "^5.53.0",
105
- "@vitest/coverage-c8": "^0.28.5",
106
- "eslint": "^8.34.0",
107
- "eslint-config-prettier": "^8.6.0",
100
+ "@sanity/pkg-utils": "^2.2.13",
101
+ "@sanity/semantic-release-preset": "^4.0.1",
102
+ "@types/node": "^18.15.3",
103
+ "@typescript-eslint/eslint-plugin": "^5.56.0",
104
+ "@typescript-eslint/parser": "^5.56.0",
105
+ "@vitest/coverage-c8": "^0.29.5",
106
+ "eslint": "^8.36.0",
107
+ "eslint-config-prettier": "^8.8.0",
108
108
  "eslint-plugin-prettier": "^4.2.1",
109
109
  "eslint-plugin-simple-import-sort": "^10.0.0",
110
110
  "faucet": "^0.0.4",
111
- "happy-dom": "^8.6.0",
111
+ "happy-dom": "^8.9.0",
112
112
  "ls-engines": "^0.9.0",
113
113
  "nock": "^13.3.0",
114
- "prettier": "^2.8.4",
114
+ "prettier": "^2.8.5",
115
115
  "prettier-plugin-packagejson": "^2.4.3",
116
- "rimraf": "^4.1.2",
117
- "rollup": "^3.17.2",
116
+ "rimraf": "^4.4.0",
117
+ "rollup": "^3.20.0",
118
118
  "sse-channel": "^4.0.0",
119
- "terser": "^5.16.4",
120
- "typescript": "^4.9.5",
121
- "vitest": "^0.28.5",
122
- "vitest-github-actions-reporter": "^0.9.0"
119
+ "terser": "^5.16.6",
120
+ "typescript": "^5.0.2",
121
+ "vitest": "^0.29.6",
122
+ "vitest-github-actions-reporter": "^0.10.0"
123
123
  },
124
124
  "engines": {
125
125
  "node": ">=14.18"
@@ -130,10 +130,10 @@ export function _listen<R extends Record<string, Any> = Record<string, Any>>(
130
130
  }
131
131
 
132
132
  function unsubscribe() {
133
- es.removeEventListener('error', onError, false)
134
- es.removeEventListener('channelError', onChannelError, false)
135
- es.removeEventListener('disconnect', onDisconnect, false)
136
- listenFor.forEach((type: string) => es.removeEventListener(type, onMessage, false))
133
+ es.removeEventListener('error', onError)
134
+ es.removeEventListener('channelError', onChannelError)
135
+ es.removeEventListener('disconnect', onDisconnect)
136
+ listenFor.forEach((type: string) => es.removeEventListener(type, onMessage))
137
137
  es.close()
138
138
  }
139
139
 
@@ -145,10 +145,10 @@ export function _listen<R extends Record<string, Any> = Record<string, Any>>(
145
145
 
146
146
  function getEventSource() {
147
147
  const evs = new EventSource(uri, esOptions)
148
- evs.addEventListener('error', onError, false)
149
- evs.addEventListener('channelError', onChannelError, false)
150
- evs.addEventListener('disconnect', onDisconnect, false)
151
- listenFor.forEach((type: string) => evs.addEventListener(type, onMessage, false))
148
+ evs.addEventListener('error', onError)
149
+ evs.addEventListener('channelError', onChannelError)
150
+ evs.addEventListener('disconnect', onDisconnect)
151
+ listenFor.forEach((type: string) => evs.addEventListener(type, onMessage))
152
152
  return evs
153
153
  }
154
154
 
@@ -1,4 +1,6 @@
1
- import type {Any, ErrorProps} from '../types'
1
+ import type {Any, ErrorProps, MutationError} from '../types'
2
+
3
+ const MAX_ITEMS_IN_ERROR_MESSAGE = 5
2
4
 
3
5
  /** @public */
4
6
  export class ClientError extends Error {
@@ -44,6 +46,22 @@ function extractErrorProps(res: Any): ErrorProps {
44
46
  return props
45
47
  }
46
48
 
49
+ // Mutation errors (specifically)
50
+ if (isMutationError(body)) {
51
+ const allItems = body.error.items || []
52
+ const items = allItems
53
+ .slice(0, MAX_ITEMS_IN_ERROR_MESSAGE)
54
+ .map((item) => item.error?.description)
55
+ .filter(Boolean)
56
+ let itemsStr = items.length ? `:\n- ${items.join('\n- ')}` : ''
57
+ if (allItems.length > MAX_ITEMS_IN_ERROR_MESSAGE) {
58
+ itemsStr += `\n...and ${allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE} more`
59
+ }
60
+ props.message = `${body.error.description}${itemsStr}`
61
+ props.details = body.error
62
+ return props
63
+ }
64
+
47
65
  // Query/database errors ({error: {description, other, arb, props}})
48
66
  if (body.error && body.error.description) {
49
67
  props.message = body.error.description
@@ -56,6 +74,19 @@ function extractErrorProps(res: Any): ErrorProps {
56
74
  return props
57
75
  }
58
76
 
77
+ function isMutationError(body: Any): body is MutationError {
78
+ return (
79
+ isPlainObject(body) &&
80
+ isPlainObject(body.error) &&
81
+ body.error.type === 'mutationError' &&
82
+ typeof body.error.description === 'string'
83
+ )
84
+ }
85
+
86
+ function isPlainObject(obj: Any): obj is Record<string, unknown> {
87
+ return typeof obj === 'object' && obj !== null && !Array.isArray(obj)
88
+ }
89
+
59
90
  function httpErrorMessage(res: Any) {
60
91
  const statusMessage = res.statusMessage ? ` ${res.statusMessage}` : ''
61
92
  return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}`
package/src/types.ts CHANGED
@@ -566,3 +566,28 @@ export interface RawRequestOptions {
566
566
  body?: Any
567
567
  maxRedirects?: number
568
568
  }
569
+
570
+ /** @internal */
571
+ export interface ApiError {
572
+ error: string
573
+ message: string
574
+ statusCode: number
575
+ }
576
+
577
+ /** @internal */
578
+ export interface MutationError {
579
+ error: {
580
+ type: 'mutationError'
581
+ description: string
582
+ items?: MutationErrorItem[]
583
+ }
584
+ }
585
+
586
+ /** @internal */
587
+ export interface MutationErrorItem {
588
+ error: {
589
+ type: string
590
+ description: string
591
+ value?: unknown
592
+ }
593
+ }
package/src/validators.ts CHANGED
@@ -30,7 +30,7 @@ export const validateObject = (op: string, val: Any) => {
30
30
  }
31
31
 
32
32
  export const validateDocumentId = (op: string, id: string) => {
33
- if (typeof id !== 'string' || !/^[a-z0-9_.-]+$/i.test(id)) {
33
+ if (typeof id !== 'string' || !/^[a-z0-9_][a-z0-9_.-]{0,127}$/i.test(id) || id.includes('..')) {
34
34
  throw new Error(`${op}(): "${id}" is not a valid document ID`)
35
35
  }
36
36
  }
@@ -1177,7 +1177,7 @@
1177
1177
  return Object.prototype.toString.call(o) === '[object Object]';
1178
1178
  }
1179
1179
 
1180
- function isPlainObject(o) {
1180
+ function isPlainObject$1(o) {
1181
1181
  var ctor,prot;
1182
1182
 
1183
1183
  if (isObject(o) === false) return false;
@@ -1209,7 +1209,7 @@
1209
1209
  return options;
1210
1210
  }
1211
1211
  const isStream = typeof body.pipe === "function";
1212
- const shouldSerialize = !isStream && !isBuffer(body) && (serializeTypes.indexOf(typeof body) !== -1 || Array.isArray(body) || isPlainObject(body));
1212
+ const shouldSerialize = !isStream && !isBuffer(body) && (serializeTypes.indexOf(typeof body) !== -1 || Array.isArray(body) || isPlainObject$1(body));
1213
1213
  if (!shouldSerialize) {
1214
1214
  return options;
1215
1215
  }
@@ -3084,13 +3084,12 @@
3084
3084
  }(typeof globalThis === 'undefined' ? (typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : commonjsGlobal) : globalThis));
3085
3085
  } (eventsource, eventsourceExports));
3086
3086
 
3087
- /* eslint-disable no-var */
3087
+ var browser = eventsourceExports.EventSourcePolyfill;
3088
3088
 
3089
- var evs = eventsourceExports;
3090
-
3091
- var browser = evs.EventSourcePolyfill;
3089
+ var polyfilledEventSource = browser;
3092
3090
 
3093
3091
  var envMiddleware = [];
3092
+ const MAX_ITEMS_IN_ERROR_MESSAGE = 5;
3094
3093
  class ClientError extends Error {
3095
3094
  constructor(res) {
3096
3095
  const props = extractErrorProps(res);
@@ -3120,6 +3119,20 @@
3120
3119
  props.message = "".concat(body.error, " - ").concat(body.message);
3121
3120
  return props;
3122
3121
  }
3122
+ if (isMutationError(body)) {
3123
+ const allItems = body.error.items || [];
3124
+ const items = allItems.slice(0, MAX_ITEMS_IN_ERROR_MESSAGE).map(item => {
3125
+ var _a;
3126
+ return (_a = item.error) == null ? void 0 : _a.description;
3127
+ }).filter(Boolean);
3128
+ let itemsStr = items.length ? ":\n- ".concat(items.join("\n- ")) : "";
3129
+ if (allItems.length > MAX_ITEMS_IN_ERROR_MESSAGE) {
3130
+ itemsStr += "\n...and ".concat(allItems.length - MAX_ITEMS_IN_ERROR_MESSAGE, " more");
3131
+ }
3132
+ props.message = "".concat(body.error.description).concat(itemsStr);
3133
+ props.details = body.error;
3134
+ return props;
3135
+ }
3123
3136
  if (body.error && body.error.description) {
3124
3137
  props.message = body.error.description;
3125
3138
  props.details = body.error;
@@ -3128,6 +3141,12 @@
3128
3141
  props.message = body.error || body.message || httpErrorMessage(res);
3129
3142
  return props;
3130
3143
  }
3144
+ function isMutationError(body) {
3145
+ return isPlainObject(body) && isPlainObject(body.error) && body.error.type === "mutationError" && typeof body.error.description === "string";
3146
+ }
3147
+ function isPlainObject(obj) {
3148
+ return typeof obj === "object" && obj !== null && !Array.isArray(obj);
3149
+ }
3131
3150
  function httpErrorMessage(res) {
3132
3151
  const statusMessage = res.statusMessage ? " ".concat(res.statusMessage) : "";
3133
3152
  return "".concat(res.method, "-request to ").concat(res.url, " resulted in HTTP ").concat(res.statusCode).concat(statusMessage);
@@ -3230,7 +3249,7 @@
3230
3249
  }
3231
3250
  };
3232
3251
  const validateDocumentId = (op, id) => {
3233
- if (typeof id !== "string" || !/^[a-z0-9_.-]+$/i.test(id)) {
3252
+ if (typeof id !== "string" || !/^[a-z0-9_][a-z0-9_.-]{0,127}$/i.test(id) || id.includes("..")) {
3234
3253
  throw new Error("".concat(op, "(): \"").concat(id, "\" is not a valid document ID"));
3235
3254
  }
3236
3255
  };
@@ -4127,7 +4146,7 @@
4127
4146
  return selection;
4128
4147
  }, {});
4129
4148
  const MAX_URL_LENGTH = 16e3 - 1200;
4130
- const EventSource = browser;
4149
+ const EventSource = polyfilledEventSource;
4131
4150
  const possibleOptions = ["includePreviousRevision", "includeResult", "visibility", "effectFormat", "tag"];
4132
4151
  const defaultOptions = {
4133
4152
  includeResult: true
@@ -4200,10 +4219,10 @@
4200
4219
  observer.complete();
4201
4220
  }
4202
4221
  function unsubscribe() {
4203
- es.removeEventListener("error", onError, false);
4204
- es.removeEventListener("channelError", onChannelError, false);
4205
- es.removeEventListener("disconnect", onDisconnect, false);
4206
- listenFor.forEach(type => es.removeEventListener(type, onMessage, false));
4222
+ es.removeEventListener("error", onError);
4223
+ es.removeEventListener("channelError", onChannelError);
4224
+ es.removeEventListener("disconnect", onDisconnect);
4225
+ listenFor.forEach(type => es.removeEventListener(type, onMessage));
4207
4226
  es.close();
4208
4227
  }
4209
4228
  function emitReconnect() {
@@ -4215,10 +4234,10 @@
4215
4234
  }
4216
4235
  function getEventSource() {
4217
4236
  const evs = new EventSource(uri, esOptions);
4218
- evs.addEventListener("error", onError, false);
4219
- evs.addEventListener("channelError", onChannelError, false);
4220
- evs.addEventListener("disconnect", onDisconnect, false);
4221
- listenFor.forEach(type => evs.addEventListener(type, onMessage, false));
4237
+ evs.addEventListener("error", onError);
4238
+ evs.addEventListener("channelError", onChannelError);
4239
+ evs.addEventListener("disconnect", onDisconnect);
4240
+ listenFor.forEach(type => evs.addEventListener(type, onMessage));
4222
4241
  return evs;
4223
4242
  }
4224
4243
  function open() {