@sanity/client 3.2.2 → 4.0.0-alpha.esm.2
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 +43 -26
- package/dist/browser/sanityClient.js +956 -0
- package/dist/node/sanityClient.js +969 -0
- package/lib/assets/assetsClient.js +132 -106
- package/lib/auth/authClient.js +38 -19
- package/lib/config.js +25 -13
- package/lib/data/dataMethods.js +35 -30
- package/lib/data/encodeQueryString.js +8 -2
- package/lib/data/listen.js +25 -21
- package/lib/data/patch.js +169 -118
- package/lib/data/transaction.js +134 -88
- package/lib/datasets/datasetsClient.js +63 -32
- package/lib/http/browserMiddleware.js +6 -1
- package/lib/http/errors.js +12 -8
- package/lib/http/nodeMiddleware.js +16 -9
- package/lib/http/queryString.js +9 -2
- package/lib/http/request.js +27 -24
- package/lib/http/requestOptions.js +10 -6
- package/lib/projects/projectsClient.js +37 -18
- package/lib/sanityClient.js +143 -105
- package/lib/users/usersClient.js +28 -11
- package/lib/util/defaults.js +12 -4
- package/lib/util/getSelection.js +7 -2
- package/lib/util/observable.js +24 -13
- package/lib/util/once.js +9 -2
- package/lib/util/pick.js +9 -2
- package/lib/validators.js +38 -15
- package/lib/warnings.js +14 -6
- package/package.json +22 -3
- package/sanityClient.d.ts +3 -13
- package/src/assets/assetsClient.js +132 -0
- package/src/auth/authClient.js +13 -0
- package/src/config.js +93 -0
- package/src/data/dataMethods.js +182 -0
- package/src/data/encodeQueryString.js +18 -0
- package/src/data/listen.js +159 -0
- package/src/data/patch.js +119 -0
- package/src/data/transaction.js +103 -0
- package/src/datasets/datasetsClient.js +28 -0
- package/src/http/browserMiddleware.js +1 -0
- package/src/http/errors.js +53 -0
- package/src/http/nodeMiddleware.js +11 -0
- package/src/http/queryString.js +10 -0
- package/src/http/request.js +50 -0
- package/src/http/requestOptions.js +29 -0
- package/src/projects/projectsClient.js +13 -0
- package/src/sanityClient.js +124 -0
- package/src/users/usersClient.js +9 -0
- package/src/util/defaults.js +9 -0
- package/src/util/getSelection.js +17 -0
- package/src/util/observable.js +6 -0
- package/src/util/once.js +12 -0
- package/src/util/pick.js +9 -0
- package/src/validators.js +76 -0
- package/src/warnings.js +25 -0
- package/test/client.test.js +188 -41
- package/test/encodeQueryString.test.js +3 -1
- package/test/helpers/sseServer.js +2 -1
- package/test/listen.test.js +4 -2
- package/test/warnings.test.disabled.js +8 -4
- package/umd/sanityClient.js +38 -38
- package/umd/sanityClient.min.js +1 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {getSelection} from '../util/getSelection'
|
|
2
|
+
import {validateObject, validateInsert} from '../validators'
|
|
3
|
+
|
|
4
|
+
export class Patch {
|
|
5
|
+
constructor(selection, operations = {}, client = null) {
|
|
6
|
+
this.selection = selection
|
|
7
|
+
this.operations = Object.assign({}, operations)
|
|
8
|
+
this.client = client
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
clone() {
|
|
12
|
+
return new Patch(this.selection, Object.assign({}, this.operations), this.client)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
set(props) {
|
|
16
|
+
return this._assign('set', props)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
diffMatchPatch(props) {
|
|
20
|
+
validateObject('diffMatchPatch', props)
|
|
21
|
+
return this._assign('diffMatchPatch', props)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
unset(attrs) {
|
|
25
|
+
if (!Array.isArray(attrs)) {
|
|
26
|
+
throw new Error('unset(attrs) takes an array of attributes to unset, non-array given')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.operations = Object.assign({}, this.operations, {unset: attrs})
|
|
30
|
+
return this
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setIfMissing(props) {
|
|
34
|
+
return this._assign('setIfMissing', props)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
replace(props) {
|
|
38
|
+
validateObject('replace', props)
|
|
39
|
+
return this._set('set', {$: props}) // eslint-disable-line id-length
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
inc(props) {
|
|
43
|
+
return this._assign('inc', props)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
dec(props) {
|
|
47
|
+
return this._assign('dec', props)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
insert(at, selector, items) {
|
|
51
|
+
validateInsert(at, selector, items)
|
|
52
|
+
return this._assign('insert', {[at]: selector, items})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
append(selector, items) {
|
|
56
|
+
return this.insert('after', `${selector}[-1]`, items)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
prepend(selector, items) {
|
|
60
|
+
return this.insert('before', `${selector}[0]`, items)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
splice(selector, start, deleteCount, items) {
|
|
64
|
+
// Negative indexes doesn't mean the same in Sanity as they do in JS;
|
|
65
|
+
// -1 means "actually at the end of the array", which allows inserting
|
|
66
|
+
// at the end of the array without knowing its length. We therefore have
|
|
67
|
+
// to substract negative indexes by one to match JS. If you want Sanity-
|
|
68
|
+
// behaviour, just use `insert('replace', selector, items)` directly
|
|
69
|
+
const delAll = typeof deleteCount === 'undefined' || deleteCount === -1
|
|
70
|
+
const startIndex = start < 0 ? start - 1 : start
|
|
71
|
+
const delCount = delAll ? -1 : Math.max(0, start + deleteCount)
|
|
72
|
+
const delRange = startIndex < 0 && delCount >= 0 ? '' : delCount
|
|
73
|
+
const rangeSelector = `${selector}[${startIndex}:${delRange}]`
|
|
74
|
+
return this.insert('replace', rangeSelector, items || [])
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ifRevisionId(rev) {
|
|
78
|
+
this.operations.ifRevisionID = rev
|
|
79
|
+
return this
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
serialize() {
|
|
83
|
+
return Object.assign(getSelection(this.selection), this.operations)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
toJSON() {
|
|
87
|
+
return this.serialize()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
commit(options = {}) {
|
|
91
|
+
if (!this.client) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
'No `client` passed to patch, either provide one or pass the ' +
|
|
94
|
+
'patch to a clients `mutate()` method'
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const returnFirst = typeof this.selection === 'string'
|
|
99
|
+
const opts = Object.assign({returnFirst, returnDocuments: true}, options)
|
|
100
|
+
return this.client.mutate({patch: this.serialize()}, opts)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
reset() {
|
|
104
|
+
this.operations = {}
|
|
105
|
+
return this
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
_set(op, props) {
|
|
109
|
+
return this._assign(op, props, false)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_assign(op, props, merge = true) {
|
|
113
|
+
validateObject(op, props)
|
|
114
|
+
this.operations = Object.assign({}, this.operations, {
|
|
115
|
+
[op]: Object.assign({}, (merge && this.operations[op]) || {}, props),
|
|
116
|
+
})
|
|
117
|
+
return this
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as validators from '../validators'
|
|
2
|
+
import {Patch} from './patch'
|
|
3
|
+
|
|
4
|
+
const defaultMutateOptions = {returnDocuments: false}
|
|
5
|
+
|
|
6
|
+
export class Transaction {
|
|
7
|
+
constructor(operations = [], client, transactionId) {
|
|
8
|
+
this.trxId = transactionId
|
|
9
|
+
this.operations = operations
|
|
10
|
+
this.client = client
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
clone() {
|
|
14
|
+
return new Transaction(this.operations.slice(0), this.client, this.trxId)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
create(doc) {
|
|
18
|
+
validators.validateObject('create', doc)
|
|
19
|
+
return this._add({create: doc})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
createIfNotExists(doc) {
|
|
23
|
+
const op = 'createIfNotExists'
|
|
24
|
+
validators.validateObject(op, doc)
|
|
25
|
+
validators.requireDocumentId(op, doc)
|
|
26
|
+
return this._add({[op]: doc})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
createOrReplace(doc) {
|
|
30
|
+
const op = 'createOrReplace'
|
|
31
|
+
validators.validateObject(op, doc)
|
|
32
|
+
validators.requireDocumentId(op, doc)
|
|
33
|
+
return this._add({[op]: doc})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
delete(documentId) {
|
|
37
|
+
validators.validateDocumentId('delete', documentId)
|
|
38
|
+
return this._add({delete: {id: documentId}})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
patch(documentId, patchOps) {
|
|
42
|
+
const isBuilder = typeof patchOps === 'function'
|
|
43
|
+
const isPatch = documentId instanceof Patch
|
|
44
|
+
|
|
45
|
+
// transaction.patch(client.patch('documentId').inc({visits: 1}))
|
|
46
|
+
if (isPatch) {
|
|
47
|
+
return this._add({patch: documentId.serialize()})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// patch => patch.inc({visits: 1}).set({foo: 'bar'})
|
|
51
|
+
if (isBuilder) {
|
|
52
|
+
const patch = patchOps(new Patch(documentId, {}, this.client))
|
|
53
|
+
if (!(patch instanceof Patch)) {
|
|
54
|
+
throw new Error('function passed to `patch()` must return the patch')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return this._add({patch: patch.serialize()})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return this._add({patch: Object.assign({id: documentId}, patchOps)})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
transactionId(id) {
|
|
64
|
+
if (!id) {
|
|
65
|
+
return this.trxId
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.trxId = id
|
|
69
|
+
return this
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
serialize() {
|
|
73
|
+
return this.operations.slice()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
toJSON() {
|
|
77
|
+
return this.serialize()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
commit(options) {
|
|
81
|
+
if (!this.client) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
'No `client` passed to transaction, either provide one or pass the ' +
|
|
84
|
+
'transaction to a clients `mutate()` method'
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return this.client.mutate(
|
|
89
|
+
this.serialize(),
|
|
90
|
+
Object.assign({transactionId: this.trxId}, defaultMutateOptions, options || {})
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
reset() {
|
|
95
|
+
this.operations = []
|
|
96
|
+
return this
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_add(mut) {
|
|
100
|
+
this.operations.push(mut)
|
|
101
|
+
return this
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as validate from '../validators'
|
|
2
|
+
|
|
3
|
+
export class DatasetsClient {
|
|
4
|
+
constructor(client) {
|
|
5
|
+
this.request = client.request.bind(client)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
create(name, options) {
|
|
9
|
+
return this._modify('PUT', name, options)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
edit(name, options) {
|
|
13
|
+
return this._modify('PATCH', name, options)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
delete(name) {
|
|
17
|
+
return this._modify('DELETE', name)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
list() {
|
|
21
|
+
return this.request({uri: '/datasets'})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_modify(method, name, body) {
|
|
25
|
+
validate.dataset(name)
|
|
26
|
+
return this.request({method, uri: `/datasets/${name}`, body})
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const middleware = []
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import makeError from 'make-error'
|
|
2
|
+
|
|
3
|
+
export function ClientError(res) {
|
|
4
|
+
const props = extractErrorProps(res)
|
|
5
|
+
ClientError.super.call(this, props.message)
|
|
6
|
+
Object.assign(this, props)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ServerError(res) {
|
|
10
|
+
const props = extractErrorProps(res)
|
|
11
|
+
ServerError.super.call(this, props.message)
|
|
12
|
+
Object.assign(this, props)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function extractErrorProps(res) {
|
|
16
|
+
const body = res.body
|
|
17
|
+
const props = {
|
|
18
|
+
response: res,
|
|
19
|
+
statusCode: res.statusCode,
|
|
20
|
+
responseBody: stringifyBody(body, res),
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// API/Boom style errors ({statusCode, error, message})
|
|
24
|
+
if (body.error && body.message) {
|
|
25
|
+
props.message = `${body.error} - ${body.message}`
|
|
26
|
+
return props
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Query/database errors ({error: {description, other, arb, props}})
|
|
30
|
+
if (body.error && body.error.description) {
|
|
31
|
+
props.message = body.error.description
|
|
32
|
+
props.details = body.error
|
|
33
|
+
return props
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Other, more arbitrary errors
|
|
37
|
+
props.message = body.error || body.message || httpErrorMessage(res)
|
|
38
|
+
return props
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function httpErrorMessage(res) {
|
|
42
|
+
const statusMessage = res.statusMessage ? ` ${res.statusMessage}` : ''
|
|
43
|
+
return `${res.method}-request to ${res.url} resulted in HTTP ${res.statusCode}${statusMessage}`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function stringifyBody(body, res) {
|
|
47
|
+
const contentType = (res.headers['content-type'] || '').toLowerCase()
|
|
48
|
+
const isJson = contentType.indexOf('application/json') !== -1
|
|
49
|
+
return isJson ? JSON.stringify(body, null, 2) : body
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
makeError(ClientError)
|
|
53
|
+
makeError(ServerError)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import retry from 'get-it/lib-node/middleware/retry'
|
|
2
|
+
import debug from 'get-it/lib-node/middleware/debug'
|
|
3
|
+
import headers from 'get-it/lib-node/middleware/headers'
|
|
4
|
+
|
|
5
|
+
import {name, version} from '../../package.json'
|
|
6
|
+
|
|
7
|
+
export const middleware = [
|
|
8
|
+
debug({verbose: true, namespace: 'sanity:client'}),
|
|
9
|
+
headers({'User-Agent': `${name} ${version}`}),
|
|
10
|
+
retry({maxRetries: 3}),
|
|
11
|
+
]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const queryString = (params) => {
|
|
2
|
+
const qs = []
|
|
3
|
+
for (const key in params) {
|
|
4
|
+
if (params.hasOwnProperty(key)) {
|
|
5
|
+
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return qs.length > 0 ? `?${qs.join('&')}` : ''
|
|
10
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* eslint-disable no-empty-function, no-process-env */
|
|
2
|
+
import getIt from 'get-it'
|
|
3
|
+
import observable from 'get-it/lib/middleware/observable'
|
|
4
|
+
import jsonRequest from 'get-it/lib/middleware/jsonRequest'
|
|
5
|
+
import jsonResponse from 'get-it/lib/middleware/jsonResponse'
|
|
6
|
+
import progress from 'get-it/lib/middleware/progress'
|
|
7
|
+
import {Observable} from '../util/observable'
|
|
8
|
+
import {ClientError, ServerError} from './errors'
|
|
9
|
+
// Environment-specific middleware.
|
|
10
|
+
import {middleware as envSpecific} from './nodeMiddleware'
|
|
11
|
+
|
|
12
|
+
const httpError = {
|
|
13
|
+
onResponse: (res) => {
|
|
14
|
+
if (res.statusCode >= 500) {
|
|
15
|
+
throw new ServerError(res)
|
|
16
|
+
} else if (res.statusCode >= 400) {
|
|
17
|
+
throw new ClientError(res)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return res
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const printWarnings = {
|
|
25
|
+
onResponse: (res) => {
|
|
26
|
+
const warn = res.headers['x-sanity-warning']
|
|
27
|
+
const warnings = Array.isArray(warn) ? warn : [warn]
|
|
28
|
+
warnings.filter(Boolean).forEach((msg) => console.warn(msg)) // eslint-disable-line no-console
|
|
29
|
+
return res
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const middleware = envSpecific.concat([
|
|
34
|
+
printWarnings,
|
|
35
|
+
jsonRequest(),
|
|
36
|
+
jsonResponse(),
|
|
37
|
+
progress(),
|
|
38
|
+
httpError,
|
|
39
|
+
observable({implementation: Observable}),
|
|
40
|
+
])
|
|
41
|
+
|
|
42
|
+
const request = getIt(middleware)
|
|
43
|
+
|
|
44
|
+
export function httpRequest(options, requester = request) {
|
|
45
|
+
return requester(Object.assign({maxRedirects: 0}, options))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
httpRequest.defaultRequester = request
|
|
49
|
+
httpRequest.ClientError = ClientError
|
|
50
|
+
httpRequest.ServerError = ServerError
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const projectHeader = 'X-Sanity-Project-ID'
|
|
2
|
+
|
|
3
|
+
export const requestOptions = (config, overrides = {}) => {
|
|
4
|
+
const headers = {}
|
|
5
|
+
|
|
6
|
+
const token = overrides.token || config.token
|
|
7
|
+
if (token) {
|
|
8
|
+
headers.Authorization = `Bearer ${token}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (!overrides.useGlobalApi && !config.useProjectHostname && config.projectId) {
|
|
12
|
+
headers[projectHeader] = config.projectId
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const withCredentials = Boolean(
|
|
16
|
+
typeof overrides.withCredentials === 'undefined'
|
|
17
|
+
? config.token || config.withCredentials
|
|
18
|
+
: overrides.withCredentials
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const timeout = typeof overrides.timeout === 'undefined' ? config.timeout : overrides.timeout
|
|
22
|
+
return Object.assign({}, overrides, {
|
|
23
|
+
headers: Object.assign({}, headers, overrides.headers || {}),
|
|
24
|
+
timeout: typeof timeout === 'undefined' ? 5 * 60 * 1000 : timeout,
|
|
25
|
+
proxy: overrides.proxy || config.proxy,
|
|
26
|
+
json: true,
|
|
27
|
+
withCredentials,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {Observable, map, filter} from './util/observable'
|
|
2
|
+
import {Patch} from './data/patch'
|
|
3
|
+
import {Transaction} from './data/transaction'
|
|
4
|
+
import {dataMethods} from './data/dataMethods'
|
|
5
|
+
import {DatasetsClient} from './datasets/datasetsClient'
|
|
6
|
+
import {ProjectsClient} from './projects/projectsClient'
|
|
7
|
+
import {AssetsClient} from './assets/assetsClient'
|
|
8
|
+
import {UsersClient} from './users/usersClient'
|
|
9
|
+
import {AuthClient} from './auth/authClient'
|
|
10
|
+
import {httpRequest} from './http/request'
|
|
11
|
+
import {requestOptions} from './http/requestOptions'
|
|
12
|
+
import {defaultConfig, initConfig} from './config'
|
|
13
|
+
import * as validate from './validators'
|
|
14
|
+
|
|
15
|
+
const toPromise = (observable) => observable.toPromise()
|
|
16
|
+
|
|
17
|
+
export class SanityClient {
|
|
18
|
+
constructor(config = defaultConfig) {
|
|
19
|
+
this.config(config)
|
|
20
|
+
|
|
21
|
+
this.assets = new AssetsClient(this)
|
|
22
|
+
this.datasets = new DatasetsClient(this)
|
|
23
|
+
this.projects = new ProjectsClient(this)
|
|
24
|
+
this.users = new UsersClient(this)
|
|
25
|
+
this.auth = new AuthClient(this)
|
|
26
|
+
|
|
27
|
+
if (this.clientConfig.isPromiseAPI) {
|
|
28
|
+
const observableConfig = Object.assign({}, this.clientConfig, {isPromiseAPI: false})
|
|
29
|
+
this.observable = new SanityClient(observableConfig)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
clone() {
|
|
34
|
+
return new SanityClient(this.config())
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
config(newConfig) {
|
|
38
|
+
if (typeof newConfig === 'undefined') {
|
|
39
|
+
return Object.assign({}, this.clientConfig)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (this.observable) {
|
|
43
|
+
const observableConfig = Object.assign({}, newConfig, {isPromiseAPI: false})
|
|
44
|
+
this.observable.config(observableConfig)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.clientConfig = initConfig(newConfig, this.clientConfig || {})
|
|
48
|
+
return this
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
withConfig(newConfig) {
|
|
52
|
+
return this.clone().config(newConfig)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getUrl(uri, useCdn = false) {
|
|
56
|
+
const base = useCdn ? this.clientConfig.cdnUrl : this.clientConfig.url
|
|
57
|
+
return `${base}/${uri.replace(/^\//, '')}`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
isPromiseAPI() {
|
|
61
|
+
return this.clientConfig.isPromiseAPI
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_requestObservable(options) {
|
|
65
|
+
const uri = options.url || options.uri
|
|
66
|
+
|
|
67
|
+
// If the `canUseCdn`-option is not set we detect it automatically based on the method + URL.
|
|
68
|
+
// Only the /data endpoint is currently available through API-CDN.
|
|
69
|
+
const canUseCdn =
|
|
70
|
+
typeof options.canUseCdn === 'undefined'
|
|
71
|
+
? ['GET', 'HEAD'].indexOf(options.method || 'GET') >= 0 && uri.indexOf('/data/') === 0
|
|
72
|
+
: options.canUseCdn
|
|
73
|
+
|
|
74
|
+
const useCdn = this.clientConfig.useCdn && canUseCdn
|
|
75
|
+
|
|
76
|
+
const tag =
|
|
77
|
+
options.tag && this.clientConfig.requestTagPrefix
|
|
78
|
+
? [this.clientConfig.requestTagPrefix, options.tag].join('.')
|
|
79
|
+
: options.tag || this.clientConfig.requestTagPrefix
|
|
80
|
+
|
|
81
|
+
if (tag) {
|
|
82
|
+
options.query = {tag: validate.requestTag(tag), ...options.query}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const reqOptions = requestOptions(
|
|
86
|
+
this.clientConfig,
|
|
87
|
+
Object.assign({}, options, {
|
|
88
|
+
url: this.getUrl(uri, useCdn),
|
|
89
|
+
})
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
return new Observable((subscriber) =>
|
|
93
|
+
httpRequest(reqOptions, this.clientConfig.requester).subscribe(subscriber)
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
request(options) {
|
|
98
|
+
const observable = this._requestObservable(options).pipe(
|
|
99
|
+
filter((event) => event.type === 'response'),
|
|
100
|
+
map((event) => event.body)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return this.isPromiseAPI() ? toPromise(observable) : observable
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Object.assign(SanityClient.prototype, dataMethods)
|
|
108
|
+
|
|
109
|
+
SanityClient.Patch = Patch
|
|
110
|
+
SanityClient.Transaction = Transaction
|
|
111
|
+
SanityClient.ClientError = httpRequest.ClientError
|
|
112
|
+
SanityClient.ServerError = httpRequest.ServerError
|
|
113
|
+
SanityClient.requester = httpRequest.defaultRequester
|
|
114
|
+
|
|
115
|
+
// Not using default exports is intentional, as it permits importing from both ESM and CJS node envs with less hazards
|
|
116
|
+
// https://nodejs.org/docs/latest/api/packages.html#writing-dual-packages-while-avoiding-or-minimizing-hazards
|
|
117
|
+
export function createClient(config) {
|
|
118
|
+
return new SanityClient(config)
|
|
119
|
+
}
|
|
120
|
+
createClient.Patch = Patch
|
|
121
|
+
createClient.Transaction = Transaction
|
|
122
|
+
createClient.ClientError = httpRequest.ClientError
|
|
123
|
+
createClient.ServerError = httpRequest.ServerError
|
|
124
|
+
createClient.requester = httpRequest.defaultRequester
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// eslint-disable-next-line no-shadow
|
|
2
|
+
export const defaults = (obj, defaults) =>
|
|
3
|
+
Object.keys(defaults)
|
|
4
|
+
.concat(Object.keys(obj))
|
|
5
|
+
.reduce((target, prop) => {
|
|
6
|
+
target[prop] = typeof obj[prop] === 'undefined' ? defaults[prop] : obj[prop]
|
|
7
|
+
|
|
8
|
+
return target
|
|
9
|
+
}, {})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function getSelection(sel) {
|
|
2
|
+
if (typeof sel === 'string' || Array.isArray(sel)) {
|
|
3
|
+
return {id: sel}
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if (sel && sel.query) {
|
|
7
|
+
return 'params' in sel ? {query: sel.query, params: sel.params} : {query: sel.query}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const selectionOpts = [
|
|
11
|
+
'* Document ID (<docId>)',
|
|
12
|
+
'* Array of document IDs',
|
|
13
|
+
'* Object containing `query`',
|
|
14
|
+
].join('\n')
|
|
15
|
+
|
|
16
|
+
throw new Error(`Unknown selection - must be one of:\n\n${selectionOpts}`)
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Since `@sanity/client` doesn't offer ESM exports (yet) const {filter} = require('rxjs/operators') will cause the the whole of rxjs to be included in the bundle.
|
|
2
|
+
// The internal import paths here is a stop-gap measure and will become less of a problem when @sanity/client export tree-shakeable esm bundles
|
|
3
|
+
|
|
4
|
+
export {Observable} from 'rxjs/internal/Observable'
|
|
5
|
+
export {filter} from 'rxjs/internal/operators/filter'
|
|
6
|
+
export {map} from 'rxjs/internal/operators/map'
|
package/src/util/once.js
ADDED