@sanity/client 0.0.0-dev.3 → 0.0.0-dev.4
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/README.md +1 -1
- package/dist/index.browser.cjs +69 -37
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +58 -31
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +70 -38
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +41 -12
- package/dist/index.js +59 -32
- package/dist/index.js.map +1 -1
- package/package.json +21 -20
- package/src/assets/AssetsClient.ts +11 -10
- package/src/data/dataMethods.ts +5 -10
- package/src/data/listen.ts +29 -14
- package/src/http/errors.ts +32 -1
- package/src/index.browser.ts +3 -0
- package/src/index.ts +3 -0
- package/src/types.ts +35 -6
- package/src/validators.ts +1 -1
- package/umd/sanityClient.js +1199 -1149
- package/umd/sanityClient.min.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/client",
|
|
3
|
-
"version": "0.0.0-dev.
|
|
3
|
+
"version": "0.0.0-dev.4",
|
|
4
4
|
"description": "Client for retrieving, creating and patching data from Sanity.io",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"import": "./dist/index.browser.js"
|
|
34
34
|
},
|
|
35
35
|
"deno": "./dist/index.browser.js",
|
|
36
|
+
"edge-light": "./dist/index.browser.js",
|
|
36
37
|
"worker": "./dist/index.browser.js",
|
|
37
38
|
"source": "./src/index.ts",
|
|
38
39
|
"require": "./dist/index.cjs",
|
|
@@ -88,37 +89,37 @@
|
|
|
88
89
|
"singleQuote": true
|
|
89
90
|
},
|
|
90
91
|
"dependencies": {
|
|
91
|
-
"@sanity/eventsource": "
|
|
92
|
-
"get-it": "^8",
|
|
93
|
-
"rxjs": "
|
|
92
|
+
"@sanity/eventsource": "5",
|
|
93
|
+
"get-it": "^8.1",
|
|
94
|
+
"rxjs": "7"
|
|
94
95
|
},
|
|
95
96
|
"devDependencies": {
|
|
96
|
-
"@edge-runtime/types": "^2.0.
|
|
97
|
-
"@edge-runtime/vm": "^2.1.
|
|
97
|
+
"@edge-runtime/types": "^2.0.8",
|
|
98
|
+
"@edge-runtime/vm": "^2.1.2",
|
|
98
99
|
"@rollup/plugin-commonjs": "^24.0.1",
|
|
99
100
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
100
|
-
"@sanity/pkg-utils": "^2.2.
|
|
101
|
-
"@sanity/semantic-release-preset": "^4.
|
|
102
|
-
"@types/node": "^18.
|
|
103
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
104
|
-
"@typescript-eslint/parser": "^5.
|
|
105
|
-
"@vitest/coverage-c8": "^0.29.
|
|
106
|
-
"eslint": "^8.
|
|
107
|
-
"eslint-config-prettier": "^8.
|
|
101
|
+
"@sanity/pkg-utils": "^2.2.13",
|
|
102
|
+
"@sanity/semantic-release-preset": "^4.1.0",
|
|
103
|
+
"@types/node": "^18.15.10",
|
|
104
|
+
"@typescript-eslint/eslint-plugin": "^5.57.0",
|
|
105
|
+
"@typescript-eslint/parser": "^5.57.0",
|
|
106
|
+
"@vitest/coverage-c8": "^0.29.8",
|
|
107
|
+
"eslint": "^8.36.0",
|
|
108
|
+
"eslint-config-prettier": "^8.8.0",
|
|
108
109
|
"eslint-plugin-prettier": "^4.2.1",
|
|
109
110
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
110
111
|
"faucet": "^0.0.4",
|
|
111
112
|
"happy-dom": "^8.9.0",
|
|
112
113
|
"ls-engines": "^0.9.0",
|
|
113
114
|
"nock": "^13.3.0",
|
|
114
|
-
"prettier": "^2.8.
|
|
115
|
+
"prettier": "^2.8.7",
|
|
115
116
|
"prettier-plugin-packagejson": "^2.4.3",
|
|
116
|
-
"rimraf": "^4.1
|
|
117
|
-
"rollup": "^3.
|
|
117
|
+
"rimraf": "^4.4.1",
|
|
118
|
+
"rollup": "^3.20.2",
|
|
118
119
|
"sse-channel": "^4.0.0",
|
|
119
|
-
"terser": "^5.16.
|
|
120
|
-
"typescript": "^
|
|
121
|
-
"vitest": "^0.29.
|
|
120
|
+
"terser": "^5.16.8",
|
|
121
|
+
"typescript": "^5.0.2",
|
|
122
|
+
"vitest": "^0.29.8",
|
|
122
123
|
"vitest-github-actions-reporter": "^0.10.0"
|
|
123
124
|
},
|
|
124
125
|
"engines": {
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
ResponseEvent,
|
|
11
11
|
SanityAssetDocument,
|
|
12
12
|
SanityImageAssetDocument,
|
|
13
|
+
UploadBody,
|
|
13
14
|
UploadClientConfig,
|
|
14
15
|
} from '../types'
|
|
15
16
|
import * as validators from '../validators'
|
|
@@ -32,7 +33,7 @@ export class ObservableAssetsClient {
|
|
|
32
33
|
*/
|
|
33
34
|
upload(
|
|
34
35
|
assetType: 'file',
|
|
35
|
-
body:
|
|
36
|
+
body: UploadBody,
|
|
36
37
|
options?: UploadClientConfig
|
|
37
38
|
): Observable<HttpRequestEvent<{document: SanityAssetDocument}>>
|
|
38
39
|
|
|
@@ -45,7 +46,7 @@ export class ObservableAssetsClient {
|
|
|
45
46
|
*/
|
|
46
47
|
upload(
|
|
47
48
|
assetType: 'image',
|
|
48
|
-
body:
|
|
49
|
+
body: UploadBody,
|
|
49
50
|
options?: UploadClientConfig
|
|
50
51
|
): Observable<HttpRequestEvent<{document: SanityImageAssetDocument}>>
|
|
51
52
|
/**
|
|
@@ -57,12 +58,12 @@ export class ObservableAssetsClient {
|
|
|
57
58
|
*/
|
|
58
59
|
upload(
|
|
59
60
|
assetType: 'file' | 'image',
|
|
60
|
-
body:
|
|
61
|
+
body: UploadBody,
|
|
61
62
|
options?: UploadClientConfig
|
|
62
63
|
): Observable<HttpRequestEvent<{document: SanityAssetDocument | SanityImageAssetDocument}>>
|
|
63
64
|
upload(
|
|
64
65
|
assetType: 'file' | 'image',
|
|
65
|
-
body:
|
|
66
|
+
body: UploadBody,
|
|
66
67
|
options?: UploadClientConfig
|
|
67
68
|
): Observable<HttpRequestEvent<{document: SanityAssetDocument | SanityImageAssetDocument}>> {
|
|
68
69
|
return _upload(this.#client, this.#httpRequest, assetType, body, options)
|
|
@@ -87,7 +88,7 @@ export class AssetsClient {
|
|
|
87
88
|
*/
|
|
88
89
|
upload(
|
|
89
90
|
assetType: 'file',
|
|
90
|
-
body:
|
|
91
|
+
body: UploadBody,
|
|
91
92
|
options?: UploadClientConfig
|
|
92
93
|
): Promise<SanityAssetDocument>
|
|
93
94
|
/**
|
|
@@ -99,7 +100,7 @@ export class AssetsClient {
|
|
|
99
100
|
*/
|
|
100
101
|
upload(
|
|
101
102
|
assetType: 'image',
|
|
102
|
-
body:
|
|
103
|
+
body: UploadBody,
|
|
103
104
|
options?: UploadClientConfig
|
|
104
105
|
): Promise<SanityImageAssetDocument>
|
|
105
106
|
/**
|
|
@@ -111,12 +112,12 @@ export class AssetsClient {
|
|
|
111
112
|
*/
|
|
112
113
|
upload(
|
|
113
114
|
assetType: 'file' | 'image',
|
|
114
|
-
body:
|
|
115
|
+
body: UploadBody,
|
|
115
116
|
options?: UploadClientConfig
|
|
116
117
|
): Promise<SanityAssetDocument | SanityImageAssetDocument>
|
|
117
118
|
upload(
|
|
118
119
|
assetType: 'file' | 'image',
|
|
119
|
-
body:
|
|
120
|
+
body: UploadBody,
|
|
120
121
|
options?: UploadClientConfig
|
|
121
122
|
): Promise<SanityAssetDocument | SanityImageAssetDocument> {
|
|
122
123
|
const observable = _upload(this.#client, this.#httpRequest, assetType, body, options)
|
|
@@ -137,7 +138,7 @@ function _upload(
|
|
|
137
138
|
client: SanityClient | ObservableSanityClient,
|
|
138
139
|
httpRequest: HttpRequest,
|
|
139
140
|
assetType: 'image' | 'file',
|
|
140
|
-
body:
|
|
141
|
+
body: UploadBody,
|
|
141
142
|
opts: UploadClientConfig = {}
|
|
142
143
|
): Observable<HttpRequestEvent<{document: SanityAssetDocument | SanityImageAssetDocument}>> {
|
|
143
144
|
validators.validateAssetType(assetType)
|
|
@@ -177,7 +178,7 @@ function _upload(
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
function optionsFromFile(opts: Record<string, Any>, file: Any) {
|
|
180
|
-
if (typeof
|
|
181
|
+
if (typeof File === 'undefined' || !(file instanceof File)) {
|
|
181
182
|
return opts
|
|
182
183
|
}
|
|
183
184
|
|
package/src/data/dataMethods.ts
CHANGED
|
@@ -64,21 +64,12 @@ export function _fetch<R, Q extends QueryParams>(
|
|
|
64
64
|
client: ObservableSanityClient | SanityClient,
|
|
65
65
|
httpRequest: HttpRequest,
|
|
66
66
|
query: string,
|
|
67
|
-
|
|
67
|
+
params?: Q,
|
|
68
68
|
options: FilteredResponseQueryOptions | UnfilteredResponseQueryOptions = {}
|
|
69
69
|
): Observable<RawQueryResponse<R> | R> {
|
|
70
70
|
const mapResponse =
|
|
71
71
|
options.filterResponse === false ? (res: Any) => res : (res: Any) => res.result
|
|
72
72
|
|
|
73
|
-
let params = _params
|
|
74
|
-
const {unstable_overlayDrafts, apiVersion} = client.config()
|
|
75
|
-
if (unstable_overlayDrafts) {
|
|
76
|
-
if (apiVersion !== 'X') {
|
|
77
|
-
// eslint-disable-next-line no-console
|
|
78
|
-
console.error('You need to set `apiVersion` to `X` to use `unstable_overlayDrafts')
|
|
79
|
-
}
|
|
80
|
-
params = {...params, draftMode: true} as Any
|
|
81
|
-
}
|
|
82
73
|
return _dataRequest(client, httpRequest, 'query', {query, params}, options).pipe(map(mapResponse))
|
|
83
74
|
}
|
|
84
75
|
|
|
@@ -310,6 +301,10 @@ export function _requestObservable<R>(
|
|
|
310
301
|
options.query = {tag: validate.requestTag(tag), ...options.query}
|
|
311
302
|
}
|
|
312
303
|
|
|
304
|
+
if (config.encodeStegaSourceMap) {
|
|
305
|
+
options.query = {encodeHackySourceMap: true, ...options.query}
|
|
306
|
+
}
|
|
307
|
+
|
|
313
308
|
const reqOptions = requestOptions(
|
|
314
309
|
config,
|
|
315
310
|
Object.assign({}, options, {
|
package/src/data/listen.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import polyfilledEventSource from '@sanity/eventsource'
|
|
2
1
|
import {Observable} from 'rxjs'
|
|
3
2
|
|
|
4
3
|
import type {ObservableSanityClient, SanityClient} from '../SanityClient'
|
|
@@ -12,7 +11,6 @@ import {encodeQueryString} from './encodeQueryString'
|
|
|
12
11
|
// unknown range of headers, but an average EventSource request from Chrome seems
|
|
13
12
|
// to have around 700 bytes of cruft, so let us account for 1.2K to be "safe"
|
|
14
13
|
const MAX_URL_LENGTH = 16000 - 1200
|
|
15
|
-
const EventSource = polyfilledEventSource
|
|
16
14
|
|
|
17
15
|
const possibleOptions = [
|
|
18
16
|
'includePreviousRevision',
|
|
@@ -86,7 +84,15 @@ export function _listen<R extends Record<string, Any> = Record<string, Any>>(
|
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
return new Observable((observer) => {
|
|
89
|
-
let es
|
|
87
|
+
let es: InstanceType<typeof import('@sanity/eventsource')>
|
|
88
|
+
getEventSource()
|
|
89
|
+
.then((eventSource) => {
|
|
90
|
+
es = eventSource
|
|
91
|
+
})
|
|
92
|
+
.catch((reason) => {
|
|
93
|
+
observer.error(reason)
|
|
94
|
+
stop()
|
|
95
|
+
})
|
|
90
96
|
let reconnectTimer: NodeJS.Timeout
|
|
91
97
|
let stopped = false
|
|
92
98
|
|
|
@@ -107,7 +113,7 @@ export function _listen<R extends Record<string, Any> = Record<string, Any>>(
|
|
|
107
113
|
// automatically, in which case it sets readyState to `CONNECTING`, but in some cases
|
|
108
114
|
// (like when a laptop lid is closed), it closes the connection. In these cases we need
|
|
109
115
|
// to explicitly reconnect.
|
|
110
|
-
if (es.readyState ===
|
|
116
|
+
if (es.readyState === es.CLOSED) {
|
|
111
117
|
unsubscribe()
|
|
112
118
|
clearTimeout(reconnectTimer)
|
|
113
119
|
reconnectTimer = setTimeout(open, 100)
|
|
@@ -130,10 +136,11 @@ export function _listen<R extends Record<string, Any> = Record<string, Any>>(
|
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
function unsubscribe() {
|
|
133
|
-
es
|
|
134
|
-
es.removeEventListener('
|
|
135
|
-
es.removeEventListener('
|
|
136
|
-
|
|
139
|
+
if (!es) return
|
|
140
|
+
es.removeEventListener('error', onError)
|
|
141
|
+
es.removeEventListener('channelError', onChannelError)
|
|
142
|
+
es.removeEventListener('disconnect', onDisconnect)
|
|
143
|
+
listenFor.forEach((type: string) => es.removeEventListener(type, onMessage))
|
|
137
144
|
es.close()
|
|
138
145
|
}
|
|
139
146
|
|
|
@@ -143,17 +150,25 @@ export function _listen<R extends Record<string, Any> = Record<string, Any>>(
|
|
|
143
150
|
}
|
|
144
151
|
}
|
|
145
152
|
|
|
146
|
-
function getEventSource() {
|
|
153
|
+
async function getEventSource(): Promise<InstanceType<typeof import('@sanity/eventsource')>> {
|
|
154
|
+
const {default: EventSource} = await import('@sanity/eventsource')
|
|
147
155
|
const evs = new EventSource(uri, esOptions)
|
|
148
|
-
evs.addEventListener('error', onError
|
|
149
|
-
evs.addEventListener('channelError', onChannelError
|
|
150
|
-
evs.addEventListener('disconnect', onDisconnect
|
|
151
|
-
listenFor.forEach((type: string) => evs.addEventListener(type, onMessage
|
|
156
|
+
evs.addEventListener('error', onError)
|
|
157
|
+
evs.addEventListener('channelError', onChannelError)
|
|
158
|
+
evs.addEventListener('disconnect', onDisconnect)
|
|
159
|
+
listenFor.forEach((type: string) => evs.addEventListener(type, onMessage))
|
|
152
160
|
return evs
|
|
153
161
|
}
|
|
154
162
|
|
|
155
163
|
function open() {
|
|
156
|
-
|
|
164
|
+
getEventSource()
|
|
165
|
+
.then((eventSource) => {
|
|
166
|
+
es = eventSource
|
|
167
|
+
})
|
|
168
|
+
.catch((reason) => {
|
|
169
|
+
observer.error(reason)
|
|
170
|
+
stop()
|
|
171
|
+
})
|
|
157
172
|
}
|
|
158
173
|
|
|
159
174
|
function stop() {
|
package/src/http/errors.ts
CHANGED
|
@@ -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/index.browser.ts
CHANGED
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// deno-lint-ignore-file no-empty-interface
|
|
1
2
|
import type {Requester} from 'get-it'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -6,6 +7,14 @@ import type {Requester} from 'get-it'
|
|
|
6
7
|
*/
|
|
7
8
|
export type Any = any // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
8
9
|
|
|
10
|
+
declare global {
|
|
11
|
+
// Declare empty stub interfaces for environments where "dom" lib is not included
|
|
12
|
+
interface File {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** @public */
|
|
16
|
+
export type UploadBody = File | Blob | Buffer | NodeJS.ReadableStream
|
|
17
|
+
|
|
9
18
|
/** @public */
|
|
10
19
|
export interface RequestOptions {
|
|
11
20
|
timeout?: number
|
|
@@ -43,12 +52,7 @@ export interface ClientConfig {
|
|
|
43
52
|
*/
|
|
44
53
|
requester?: Requester
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
* Experimental, requires apiVersion: 'X' and will overlay drafts on top of published documents
|
|
48
|
-
* which lets you preview your query on what it'll look like after every document is published.
|
|
49
|
-
* @alpha
|
|
50
|
-
*/
|
|
51
|
-
unstable_overlayDrafts?: boolean
|
|
55
|
+
encodeStegaSourceMap?: boolean
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
/** @public */
|
|
@@ -573,3 +577,28 @@ export interface RawRequestOptions {
|
|
|
573
577
|
body?: Any
|
|
574
578
|
maxRedirects?: number
|
|
575
579
|
}
|
|
580
|
+
|
|
581
|
+
/** @internal */
|
|
582
|
+
export interface ApiError {
|
|
583
|
+
error: string
|
|
584
|
+
message: string
|
|
585
|
+
statusCode: number
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/** @internal */
|
|
589
|
+
export interface MutationError {
|
|
590
|
+
error: {
|
|
591
|
+
type: 'mutationError'
|
|
592
|
+
description: string
|
|
593
|
+
items?: MutationErrorItem[]
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** @internal */
|
|
598
|
+
export interface MutationErrorItem {
|
|
599
|
+
error: {
|
|
600
|
+
type: string
|
|
601
|
+
description: string
|
|
602
|
+
value?: unknown
|
|
603
|
+
}
|
|
604
|
+
}
|
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_.-]
|
|
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
|
}
|