@sanity/client 0.0.0-dev.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.
- package/LICENSE +21 -0
- package/README.md +1225 -0
- package/dist/index.browser.cjs +1760 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.js +1737 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.cjs +1769 -0
- package/dist/index.cjs.js +16 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2234 -0
- package/dist/index.js +1746 -0
- package/dist/index.js.map +1 -0
- package/package.json +127 -0
- package/src/SanityClient.ts +1253 -0
- package/src/assets/AssetsClient.ts +191 -0
- package/src/config.ts +96 -0
- package/src/data/dataMethods.ts +416 -0
- package/src/data/encodeQueryString.ts +29 -0
- package/src/data/listen.ts +196 -0
- package/src/data/patch.ts +345 -0
- package/src/data/transaction.ts +358 -0
- package/src/datasets/DatasetsClient.ts +115 -0
- package/src/generateHelpUrl.ts +5 -0
- package/src/http/browserMiddleware.ts +1 -0
- package/src/http/errors.ts +68 -0
- package/src/http/nodeMiddleware.ts +11 -0
- package/src/http/request.ts +48 -0
- package/src/http/requestOptions.ts +33 -0
- package/src/index.browser.ts +28 -0
- package/src/index.ts +28 -0
- package/src/projects/ProjectsClient.ts +61 -0
- package/src/types.ts +575 -0
- package/src/users/UsersClient.ts +55 -0
- package/src/util/defaults.ts +10 -0
- package/src/util/getSelection.ts +21 -0
- package/src/util/once.ts +14 -0
- package/src/util/pick.ts +11 -0
- package/src/validators.ts +78 -0
- package/src/warnings.ts +30 -0
- package/umd/.gitkeep +1 -0
- package/umd/sanityClient.js +4840 -0
- package/umd/sanityClient.min.js +14 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import type {Observable} from 'rxjs'
|
|
2
|
+
|
|
3
|
+
import type {ObservableSanityClient, SanityClient} from '../SanityClient'
|
|
4
|
+
import type {
|
|
5
|
+
Any,
|
|
6
|
+
BaseMutationOptions,
|
|
7
|
+
IdentifiedSanityDocumentStub,
|
|
8
|
+
MultipleMutationResult,
|
|
9
|
+
Mutation,
|
|
10
|
+
PatchOperations,
|
|
11
|
+
SanityDocument,
|
|
12
|
+
SanityDocumentStub,
|
|
13
|
+
SingleMutationResult,
|
|
14
|
+
TransactionAllDocumentIdsMutationOptions,
|
|
15
|
+
TransactionAllDocumentsMutationOptions,
|
|
16
|
+
TransactionFirstDocumentIdMutationOptions,
|
|
17
|
+
TransactionFirstDocumentMutationOptions,
|
|
18
|
+
} from '../types'
|
|
19
|
+
import * as validators from '../validators'
|
|
20
|
+
import {ObservablePatch, Patch} from './patch'
|
|
21
|
+
|
|
22
|
+
/** @public */
|
|
23
|
+
export type PatchBuilder = (patch: Patch) => Patch
|
|
24
|
+
/** @public */
|
|
25
|
+
export type ObservablePatchBuilder = (patch: ObservablePatch) => ObservablePatch
|
|
26
|
+
|
|
27
|
+
const defaultMutateOptions = {returnDocuments: false}
|
|
28
|
+
|
|
29
|
+
/** @internal */
|
|
30
|
+
export class BaseTransaction {
|
|
31
|
+
protected operations: Mutation[]
|
|
32
|
+
protected trxId?: string
|
|
33
|
+
constructor(operations: Mutation[] = [], transactionId?: string) {
|
|
34
|
+
this.operations = operations
|
|
35
|
+
this.trxId = transactionId
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new Sanity document. If `_id` is provided and already exists, the mutation will fail. If no `_id` is given, one will automatically be generated by the database.
|
|
39
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
40
|
+
*
|
|
41
|
+
* @param doc - Document to create. Requires a `_type` property.
|
|
42
|
+
*/
|
|
43
|
+
create<R extends Record<string, Any> = Record<string, Any>>(doc: SanityDocumentStub<R>): this {
|
|
44
|
+
validators.validateObject('create', doc)
|
|
45
|
+
return this._add({create: doc})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates a new Sanity document. If a document with the same `_id` already exists, the create operation will be ignored.
|
|
50
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
51
|
+
*
|
|
52
|
+
* @param doc - Document to create if it does not already exist. Requires `_id` and `_type` properties.
|
|
53
|
+
*/
|
|
54
|
+
createIfNotExists<R extends Record<string, Any> = Record<string, Any>>(
|
|
55
|
+
doc: IdentifiedSanityDocumentStub<R>
|
|
56
|
+
): this {
|
|
57
|
+
const op = 'createIfNotExists'
|
|
58
|
+
validators.validateObject(op, doc)
|
|
59
|
+
validators.requireDocumentId(op, doc)
|
|
60
|
+
return this._add({[op]: doc})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new Sanity document, or replaces an existing one if the same `_id` is already used.
|
|
65
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
66
|
+
*
|
|
67
|
+
* @param doc - Document to create or replace. Requires `_id` and `_type` properties.
|
|
68
|
+
*/
|
|
69
|
+
createOrReplace<R extends Record<string, Any> = Record<string, Any>>(
|
|
70
|
+
doc: IdentifiedSanityDocumentStub<R>
|
|
71
|
+
): this {
|
|
72
|
+
const op = 'createOrReplace'
|
|
73
|
+
validators.validateObject(op, doc)
|
|
74
|
+
validators.requireDocumentId(op, doc)
|
|
75
|
+
return this._add({[op]: doc})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Deletes the document with the given document ID
|
|
80
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
81
|
+
*
|
|
82
|
+
* @param documentId - Document ID to delete
|
|
83
|
+
*/
|
|
84
|
+
delete(documentId: string): this {
|
|
85
|
+
validators.validateDocumentId('delete', documentId)
|
|
86
|
+
return this._add({delete: {id: documentId}})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Gets the current transaction ID, if any
|
|
91
|
+
*/
|
|
92
|
+
transactionId(): string | undefined
|
|
93
|
+
/**
|
|
94
|
+
* Set the ID of this transaction.
|
|
95
|
+
*
|
|
96
|
+
* @param id - Transaction ID
|
|
97
|
+
*/
|
|
98
|
+
transactionId(id: string): this
|
|
99
|
+
transactionId(id?: string): this | string | undefined {
|
|
100
|
+
if (!id) {
|
|
101
|
+
return this.trxId
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.trxId = id
|
|
105
|
+
return this
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Return a plain JSON representation of the transaction
|
|
110
|
+
*/
|
|
111
|
+
serialize(): Mutation[] {
|
|
112
|
+
return [...this.operations]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Return a plain JSON representation of the transaction
|
|
117
|
+
*/
|
|
118
|
+
toJSON(): Mutation[] {
|
|
119
|
+
return this.serialize()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Clears the transaction of all operations
|
|
124
|
+
*/
|
|
125
|
+
reset(): this {
|
|
126
|
+
this.operations = []
|
|
127
|
+
return this
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
protected _add(mut: Mutation): this {
|
|
131
|
+
this.operations.push(mut)
|
|
132
|
+
return this
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** @public */
|
|
137
|
+
export class Transaction extends BaseTransaction {
|
|
138
|
+
#client?: SanityClient
|
|
139
|
+
constructor(operations?: Mutation[], client?: SanityClient, transactionId?: string) {
|
|
140
|
+
super(operations, transactionId)
|
|
141
|
+
this.#client = client
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Clones the transaction
|
|
146
|
+
*/
|
|
147
|
+
clone(): Transaction {
|
|
148
|
+
return new Transaction([...this.operations], this.#client, this.trxId)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Commit the transaction, returning a promise that resolves to the first mutated document
|
|
153
|
+
*
|
|
154
|
+
* @param options - Options for the mutation operation
|
|
155
|
+
*/
|
|
156
|
+
commit<R extends Record<string, Any>>(
|
|
157
|
+
options: TransactionFirstDocumentMutationOptions
|
|
158
|
+
): Promise<SanityDocument<R>>
|
|
159
|
+
/**
|
|
160
|
+
* Commit the transaction, returning a promise that resolves to an array of the mutated documents
|
|
161
|
+
*
|
|
162
|
+
* @param options - Options for the mutation operation
|
|
163
|
+
*/
|
|
164
|
+
commit<R extends Record<string, Any>>(
|
|
165
|
+
options: TransactionAllDocumentsMutationOptions
|
|
166
|
+
): Promise<SanityDocument<R>[]>
|
|
167
|
+
/**
|
|
168
|
+
* Commit the transaction, returning a promise that resolves to a mutation result object
|
|
169
|
+
*
|
|
170
|
+
* @param options - Options for the mutation operation
|
|
171
|
+
*/
|
|
172
|
+
commit(options: TransactionFirstDocumentIdMutationOptions): Promise<SingleMutationResult>
|
|
173
|
+
/**
|
|
174
|
+
* Commit the transaction, returning a promise that resolves to a mutation result object
|
|
175
|
+
*
|
|
176
|
+
* @param options - Options for the mutation operation
|
|
177
|
+
*/
|
|
178
|
+
commit(options: TransactionAllDocumentIdsMutationOptions): Promise<MultipleMutationResult>
|
|
179
|
+
/**
|
|
180
|
+
* Commit the transaction, returning a promise that resolves to a mutation result object
|
|
181
|
+
*
|
|
182
|
+
* @param options - Options for the mutation operation
|
|
183
|
+
*/
|
|
184
|
+
commit(options?: BaseMutationOptions): Promise<MultipleMutationResult>
|
|
185
|
+
commit<R extends Record<string, Any> = Record<string, Any>>(
|
|
186
|
+
options?:
|
|
187
|
+
| TransactionFirstDocumentMutationOptions
|
|
188
|
+
| TransactionAllDocumentsMutationOptions
|
|
189
|
+
| TransactionFirstDocumentIdMutationOptions
|
|
190
|
+
| TransactionAllDocumentIdsMutationOptions
|
|
191
|
+
| BaseMutationOptions
|
|
192
|
+
): Promise<
|
|
193
|
+
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
|
|
194
|
+
> {
|
|
195
|
+
if (!this.#client) {
|
|
196
|
+
throw new Error(
|
|
197
|
+
'No `client` passed to transaction, either provide one or pass the ' +
|
|
198
|
+
'transaction to a clients `mutate()` method'
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return this.#client.mutate<R>(
|
|
203
|
+
this.serialize() as Any,
|
|
204
|
+
Object.assign({transactionId: this.trxId}, defaultMutateOptions, options || {})
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Performs a patch on the given document ID. Can either be a builder function or an object of patch operations.
|
|
210
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
211
|
+
*
|
|
212
|
+
* @param documentId - Document ID to perform the patch operation on
|
|
213
|
+
* @param patchOps - Operations to perform, or a builder function
|
|
214
|
+
*/
|
|
215
|
+
patch(documentId: string, patchOps?: PatchBuilder | PatchOperations): this
|
|
216
|
+
/**
|
|
217
|
+
* Adds the given patch instance to the transaction.
|
|
218
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
219
|
+
*
|
|
220
|
+
* @param patch - Patch to execute
|
|
221
|
+
*/
|
|
222
|
+
patch(patch: Patch): this
|
|
223
|
+
patch(patchOrDocumentId: Patch | string, patchOps?: PatchBuilder | PatchOperations): this {
|
|
224
|
+
const isBuilder = typeof patchOps === 'function'
|
|
225
|
+
const isPatch = typeof patchOrDocumentId !== 'string' && patchOrDocumentId instanceof Patch
|
|
226
|
+
|
|
227
|
+
// transaction.patch(client.patch('documentId').inc({visits: 1}))
|
|
228
|
+
if (isPatch) {
|
|
229
|
+
return this._add({patch: patchOrDocumentId.serialize()})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// patch => patch.inc({visits: 1}).set({foo: 'bar'})
|
|
233
|
+
if (isBuilder) {
|
|
234
|
+
const patch = patchOps(new Patch(patchOrDocumentId, {}, this.#client))
|
|
235
|
+
if (!(patch instanceof Patch)) {
|
|
236
|
+
throw new Error('function passed to `patch()` must return the patch')
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return this._add({patch: patch.serialize()})
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return this._add({patch: {id: patchOrDocumentId, ...patchOps}})
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** @public */
|
|
247
|
+
export class ObservableTransaction extends BaseTransaction {
|
|
248
|
+
#client?: ObservableSanityClient
|
|
249
|
+
constructor(operations?: Mutation[], client?: ObservableSanityClient, transactionId?: string) {
|
|
250
|
+
super(operations, transactionId)
|
|
251
|
+
this.#client = client
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Clones the transaction
|
|
256
|
+
*/
|
|
257
|
+
clone(): ObservableTransaction {
|
|
258
|
+
return new ObservableTransaction([...this.operations], this.#client, this.trxId)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Commit the transaction, returning an observable that produces the first mutated document
|
|
263
|
+
*
|
|
264
|
+
* @param options - Options for the mutation operation
|
|
265
|
+
*/
|
|
266
|
+
commit<R extends Record<string, Any>>(
|
|
267
|
+
options: TransactionFirstDocumentMutationOptions
|
|
268
|
+
): Observable<SanityDocument<R>>
|
|
269
|
+
/**
|
|
270
|
+
* Commit the transaction, returning an observable that produces an array of the mutated documents
|
|
271
|
+
*
|
|
272
|
+
* @param options - Options for the mutation operation
|
|
273
|
+
*/
|
|
274
|
+
commit<R extends Record<string, Any>>(
|
|
275
|
+
options: TransactionAllDocumentsMutationOptions
|
|
276
|
+
): Observable<SanityDocument<R>[]>
|
|
277
|
+
/**
|
|
278
|
+
* Commit the transaction, returning an observable that produces a mutation result object
|
|
279
|
+
*
|
|
280
|
+
* @param options - Options for the mutation operation
|
|
281
|
+
*/
|
|
282
|
+
commit(options: TransactionFirstDocumentIdMutationOptions): Observable<SingleMutationResult>
|
|
283
|
+
/**
|
|
284
|
+
* Commit the transaction, returning an observable that produces a mutation result object
|
|
285
|
+
*
|
|
286
|
+
* @param options - Options for the mutation operation
|
|
287
|
+
*/
|
|
288
|
+
commit(options: TransactionAllDocumentIdsMutationOptions): Observable<MultipleMutationResult>
|
|
289
|
+
/**
|
|
290
|
+
* Commit the transaction, returning an observable that produces a mutation result object
|
|
291
|
+
*
|
|
292
|
+
* @param options - Options for the mutation operation
|
|
293
|
+
*/
|
|
294
|
+
commit(options?: BaseMutationOptions): Observable<MultipleMutationResult>
|
|
295
|
+
commit<R extends Record<string, Any> = Record<string, Any>>(
|
|
296
|
+
options?:
|
|
297
|
+
| TransactionFirstDocumentMutationOptions
|
|
298
|
+
| TransactionAllDocumentsMutationOptions
|
|
299
|
+
| TransactionFirstDocumentIdMutationOptions
|
|
300
|
+
| TransactionAllDocumentIdsMutationOptions
|
|
301
|
+
| BaseMutationOptions
|
|
302
|
+
): Observable<
|
|
303
|
+
SanityDocument<R> | SanityDocument<R>[] | SingleMutationResult | MultipleMutationResult
|
|
304
|
+
> {
|
|
305
|
+
if (!this.#client) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
'No `client` passed to transaction, either provide one or pass the ' +
|
|
308
|
+
'transaction to a clients `mutate()` method'
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return this.#client.mutate<R>(
|
|
313
|
+
this.serialize() as Any,
|
|
314
|
+
Object.assign({transactionId: this.trxId}, defaultMutateOptions, options || {})
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Performs a patch on the given document ID. Can either be a builder function or an object of patch operations.
|
|
320
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
321
|
+
*
|
|
322
|
+
* @param documentId - Document ID to perform the patch operation on
|
|
323
|
+
* @param patchOps - Operations to perform, or a builder function
|
|
324
|
+
*/
|
|
325
|
+
patch(documentId: string, patchOps?: ObservablePatchBuilder | PatchOperations): this
|
|
326
|
+
/**
|
|
327
|
+
* Adds the given patch instance to the transaction.
|
|
328
|
+
* The operation is added to the current transaction, ready to be commited by `commit()`
|
|
329
|
+
*
|
|
330
|
+
* @param patch - ObservablePatch to execute
|
|
331
|
+
*/
|
|
332
|
+
patch(patch: ObservablePatch): this
|
|
333
|
+
patch(
|
|
334
|
+
patchOrDocumentId: ObservablePatch | string,
|
|
335
|
+
patchOps?: ObservablePatchBuilder | PatchOperations
|
|
336
|
+
): this {
|
|
337
|
+
const isBuilder = typeof patchOps === 'function'
|
|
338
|
+
const isPatch =
|
|
339
|
+
typeof patchOrDocumentId !== 'string' && patchOrDocumentId instanceof ObservablePatch
|
|
340
|
+
|
|
341
|
+
// transaction.patch(client.patch('documentId').inc({visits: 1}))
|
|
342
|
+
if (isPatch) {
|
|
343
|
+
return this._add({patch: patchOrDocumentId.serialize()})
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// patch => patch.inc({visits: 1}).set({foo: 'bar'})
|
|
347
|
+
if (isBuilder) {
|
|
348
|
+
const patch = patchOps(new ObservablePatch(patchOrDocumentId, {}, this.#client))
|
|
349
|
+
if (!(patch instanceof ObservablePatch)) {
|
|
350
|
+
throw new Error('function passed to `patch()` must return the patch')
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return this._add({patch: patch.serialize()})
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return this._add({patch: {id: patchOrDocumentId, ...patchOps}})
|
|
357
|
+
}
|
|
358
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {lastValueFrom, type Observable} from 'rxjs'
|
|
2
|
+
|
|
3
|
+
import {_request} from '../data/dataMethods'
|
|
4
|
+
import type {ObservableSanityClient, SanityClient} from '../SanityClient'
|
|
5
|
+
import type {DatasetAclMode, DatasetResponse, DatasetsResponse, HttpRequest} from '../types'
|
|
6
|
+
import * as validate from '../validators'
|
|
7
|
+
|
|
8
|
+
/** @internal */
|
|
9
|
+
export class ObservableDatasetsClient {
|
|
10
|
+
#client: ObservableSanityClient
|
|
11
|
+
#httpRequest: HttpRequest
|
|
12
|
+
constructor(client: ObservableSanityClient, httpRequest: HttpRequest) {
|
|
13
|
+
this.#client = client
|
|
14
|
+
this.#httpRequest = httpRequest
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create a new dataset with the given name
|
|
19
|
+
*
|
|
20
|
+
* @param name - Name of the dataset to create
|
|
21
|
+
* @param options - Options for the dataset
|
|
22
|
+
*/
|
|
23
|
+
create(name: string, options?: {aclMode?: DatasetAclMode}): Observable<DatasetResponse> {
|
|
24
|
+
return _modify<DatasetResponse>(this.#client, this.#httpRequest, 'PUT', name, options)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Edit a dataset with the given name
|
|
29
|
+
*
|
|
30
|
+
* @param name - Name of the dataset to edit
|
|
31
|
+
* @param options - New options for the dataset
|
|
32
|
+
*/
|
|
33
|
+
edit(name: string, options?: {aclMode?: DatasetAclMode}): Observable<DatasetResponse> {
|
|
34
|
+
return _modify<DatasetResponse>(this.#client, this.#httpRequest, 'PATCH', name, options)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Delete a dataset with the given name
|
|
39
|
+
*
|
|
40
|
+
* @param name - Name of the dataset to delete
|
|
41
|
+
*/
|
|
42
|
+
delete(name: string): Observable<{deleted: true}> {
|
|
43
|
+
return _modify<{deleted: true}>(this.#client, this.#httpRequest, 'DELETE', name)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Fetch a list of datasets for the configured project
|
|
48
|
+
*/
|
|
49
|
+
list(): Observable<DatasetsResponse> {
|
|
50
|
+
return _request<DatasetsResponse>(this.#client, this.#httpRequest, {uri: '/datasets'})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @internal */
|
|
55
|
+
export class DatasetsClient {
|
|
56
|
+
#client: SanityClient
|
|
57
|
+
#httpRequest: HttpRequest
|
|
58
|
+
constructor(client: SanityClient, httpRequest: HttpRequest) {
|
|
59
|
+
this.#client = client
|
|
60
|
+
this.#httpRequest = httpRequest
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a new dataset with the given name
|
|
65
|
+
*
|
|
66
|
+
* @param name - Name of the dataset to create
|
|
67
|
+
* @param options - Options for the dataset
|
|
68
|
+
*/
|
|
69
|
+
create(name: string, options?: {aclMode?: DatasetAclMode}): Promise<DatasetResponse> {
|
|
70
|
+
return lastValueFrom(
|
|
71
|
+
_modify<DatasetResponse>(this.#client, this.#httpRequest, 'PUT', name, options)
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Edit a dataset with the given name
|
|
77
|
+
*
|
|
78
|
+
* @param name - Name of the dataset to edit
|
|
79
|
+
* @param options - New options for the dataset
|
|
80
|
+
*/
|
|
81
|
+
edit(name: string, options?: {aclMode?: DatasetAclMode}): Promise<DatasetResponse> {
|
|
82
|
+
return lastValueFrom(
|
|
83
|
+
_modify<DatasetResponse>(this.#client, this.#httpRequest, 'PATCH', name, options)
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Delete a dataset with the given name
|
|
89
|
+
*
|
|
90
|
+
* @param name - Name of the dataset to delete
|
|
91
|
+
*/
|
|
92
|
+
delete(name: string): Promise<{deleted: true}> {
|
|
93
|
+
return lastValueFrom(_modify<{deleted: true}>(this.#client, this.#httpRequest, 'DELETE', name))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Fetch a list of datasets for the configured project
|
|
98
|
+
*/
|
|
99
|
+
list(): Promise<DatasetsResponse> {
|
|
100
|
+
return lastValueFrom(
|
|
101
|
+
_request<DatasetsResponse>(this.#client, this.#httpRequest, {uri: '/datasets'})
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function _modify<R = unknown>(
|
|
107
|
+
client: SanityClient | ObservableSanityClient,
|
|
108
|
+
httpRequest: HttpRequest,
|
|
109
|
+
method: 'DELETE' | 'PATCH' | 'PUT',
|
|
110
|
+
name: string,
|
|
111
|
+
options?: {aclMode?: DatasetAclMode}
|
|
112
|
+
) {
|
|
113
|
+
validate.dataset(name)
|
|
114
|
+
return _request<R>(client, httpRequest, {method, uri: `/datasets/${name}`, body: options})
|
|
115
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default []
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type {Any, ErrorProps} from '../types'
|
|
2
|
+
|
|
3
|
+
/** @public */
|
|
4
|
+
export class ClientError extends Error {
|
|
5
|
+
response: ErrorProps['response']
|
|
6
|
+
statusCode: ErrorProps['statusCode'] = 400
|
|
7
|
+
responseBody: ErrorProps['responseBody']
|
|
8
|
+
details: ErrorProps['details']
|
|
9
|
+
|
|
10
|
+
constructor(res: Any) {
|
|
11
|
+
const props = extractErrorProps(res)
|
|
12
|
+
super(props.message)
|
|
13
|
+
Object.assign(this, props)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** @public */
|
|
18
|
+
export class ServerError extends Error {
|
|
19
|
+
response: ErrorProps['response']
|
|
20
|
+
statusCode: ErrorProps['statusCode'] = 500
|
|
21
|
+
responseBody: ErrorProps['responseBody']
|
|
22
|
+
details: ErrorProps['details']
|
|
23
|
+
|
|
24
|
+
constructor(res: Any) {
|
|
25
|
+
const props = extractErrorProps(res)
|
|
26
|
+
super(props.message)
|
|
27
|
+
Object.assign(this, props)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function extractErrorProps(res: Any): ErrorProps {
|
|
32
|
+
const body = res.body
|
|
33
|
+
const props = {
|
|
34
|
+
response: res,
|
|
35
|
+
statusCode: res.statusCode,
|
|
36
|
+
responseBody: stringifyBody(body, res),
|
|
37
|
+
message: '',
|
|
38
|
+
details: undefined as Any,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// API/Boom style errors ({statusCode, error, message})
|
|
42
|
+
if (body.error && body.message) {
|
|
43
|
+
props.message = `${body.error} - ${body.message}`
|
|
44
|
+
return props
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Query/database errors ({error: {description, other, arb, props}})
|
|
48
|
+
if (body.error && body.error.description) {
|
|
49
|
+
props.message = body.error.description
|
|
50
|
+
props.details = body.error
|
|
51
|
+
return props
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Other, more arbitrary errors
|
|
55
|
+
props.message = body.error || body.message || httpErrorMessage(res)
|
|
56
|
+
return props
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function httpErrorMessage(res: Any) {
|
|
60
|
+
const statusMessage = res.statusMessage ? ` ${res.statusMessage}` : ''
|
|
61
|
+
return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}`
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function stringifyBody(body: Any, res: Any) {
|
|
65
|
+
const contentType = (res.headers['content-type'] || '').toLowerCase()
|
|
66
|
+
const isJson = contentType.indexOf('application/json') !== -1
|
|
67
|
+
return isJson ? JSON.stringify(body, null, 2) : body
|
|
68
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {debug, headers, retry} from 'get-it/middleware'
|
|
2
|
+
|
|
3
|
+
import {name, version} from '../../package.json'
|
|
4
|
+
|
|
5
|
+
const middleware = [
|
|
6
|
+
debug({verbose: true, namespace: 'sanity:client'}),
|
|
7
|
+
headers({'User-Agent': `${name} ${version}`}),
|
|
8
|
+
retry({maxRetries: 3}),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
export default middleware
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {getIt, type Middlewares} from 'get-it'
|
|
2
|
+
import {jsonRequest, jsonResponse, observable, progress} from 'get-it/middleware'
|
|
3
|
+
import {Observable} from 'rxjs'
|
|
4
|
+
|
|
5
|
+
import type {Any, HttpRequest, RequestOptions} from '../types'
|
|
6
|
+
import {ClientError, ServerError} from './errors'
|
|
7
|
+
|
|
8
|
+
const httpError = {
|
|
9
|
+
onResponse: (res: Any) => {
|
|
10
|
+
if (res.statusCode >= 500) {
|
|
11
|
+
throw new ServerError(res)
|
|
12
|
+
} else if (res.statusCode >= 400) {
|
|
13
|
+
throw new ClientError(res)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return res
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const printWarnings = {
|
|
21
|
+
onResponse: (res: Any) => {
|
|
22
|
+
const warn = res.headers['x-sanity-warning']
|
|
23
|
+
const warnings = Array.isArray(warn) ? warn : [warn]
|
|
24
|
+
warnings.filter(Boolean).forEach((msg) => console.warn(msg)) // eslint-disable-line no-console
|
|
25
|
+
return res
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @internal */
|
|
30
|
+
export function defineHttpRequest(envMiddleware: Middlewares): HttpRequest {
|
|
31
|
+
const request = getIt([
|
|
32
|
+
...envMiddleware,
|
|
33
|
+
printWarnings,
|
|
34
|
+
jsonRequest(),
|
|
35
|
+
jsonResponse(),
|
|
36
|
+
progress(),
|
|
37
|
+
httpError,
|
|
38
|
+
observable({implementation: Observable}),
|
|
39
|
+
])
|
|
40
|
+
|
|
41
|
+
function httpRequest(options: RequestOptions, requester = request) {
|
|
42
|
+
return requester({maxRedirects: 0, ...options} as Any)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
httpRequest.defaultRequester = request
|
|
46
|
+
|
|
47
|
+
return httpRequest
|
|
48
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type {RequestOptions} from 'get-it'
|
|
2
|
+
|
|
3
|
+
import type {Any} from '../types'
|
|
4
|
+
|
|
5
|
+
const projectHeader = 'X-Sanity-Project-ID'
|
|
6
|
+
|
|
7
|
+
export function requestOptions(config: Any, overrides: Any = {}): Omit<RequestOptions, 'url'> {
|
|
8
|
+
const headers: Any = {}
|
|
9
|
+
|
|
10
|
+
const token = overrides.token || config.token
|
|
11
|
+
if (token) {
|
|
12
|
+
headers.Authorization = `Bearer ${token}`
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!overrides.useGlobalApi && !config.useProjectHostname && config.projectId) {
|
|
16
|
+
headers[projectHeader] = config.projectId
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const withCredentials = Boolean(
|
|
20
|
+
typeof overrides.withCredentials === 'undefined'
|
|
21
|
+
? config.token || config.withCredentials
|
|
22
|
+
: overrides.withCredentials
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
const timeout = typeof overrides.timeout === 'undefined' ? config.timeout : overrides.timeout
|
|
26
|
+
return Object.assign({}, overrides, {
|
|
27
|
+
headers: Object.assign({}, headers, overrides.headers || {}),
|
|
28
|
+
timeout: typeof timeout === 'undefined' ? 5 * 60 * 1000 : timeout,
|
|
29
|
+
proxy: overrides.proxy || config.proxy,
|
|
30
|
+
json: true,
|
|
31
|
+
withCredentials,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import envMiddleware from './http/browserMiddleware'
|
|
2
|
+
import {defineHttpRequest} from './http/request'
|
|
3
|
+
import {SanityClient} from './SanityClient'
|
|
4
|
+
import type {ClientConfig} from './types'
|
|
5
|
+
import {printNoDefaultExport} from './warnings'
|
|
6
|
+
|
|
7
|
+
export * from './data/patch'
|
|
8
|
+
export * from './data/transaction'
|
|
9
|
+
export {ClientError, ServerError} from './http/errors'
|
|
10
|
+
export * from './SanityClient'
|
|
11
|
+
export * from './types'
|
|
12
|
+
|
|
13
|
+
// Set the http client to use for requests, and its environment specific middleware
|
|
14
|
+
const httpRequest = defineHttpRequest(envMiddleware)
|
|
15
|
+
/** @public */
|
|
16
|
+
export const requester = httpRequest.defaultRequester
|
|
17
|
+
|
|
18
|
+
/** @public */
|
|
19
|
+
export const createClient = (config: ClientConfig) => new SanityClient(httpRequest, config)
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
* @deprecated Use the named export `createClient` instead of the `default` export
|
|
24
|
+
*/
|
|
25
|
+
export default function deprecatedCreateClient(config: ClientConfig) {
|
|
26
|
+
printNoDefaultExport()
|
|
27
|
+
return new SanityClient(httpRequest, config)
|
|
28
|
+
}
|