@sanity/client 3.3.2 → 3.4.0-beta.esm.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/dist/sanityClient.browser.mjs +4317 -0
- package/dist/sanityClient.browser.mjs.map +7 -0
- package/dist/sanityClient.node.js +1129 -0
- package/dist/sanityClient.node.js.map +7 -0
- package/package.json +25 -5
- package/src/assets/assetsClient.js +135 -0
- package/src/auth/authClient.js +17 -0
- package/src/config.js +96 -0
- package/src/data/dataMethods.js +183 -0
- package/src/data/encodeQueryString.js +18 -0
- package/src/data/listen.js +160 -0
- package/src/data/patch.js +124 -0
- package/src/data/transaction.js +106 -0
- package/src/datasets/datasetsClient.js +31 -0
- package/src/http/browserMiddleware.js +1 -0
- package/src/http/errors.js +57 -0
- package/src/http/nodeMiddleware.js +13 -0
- package/src/http/queryString.js +10 -0
- package/src/http/request.js +54 -0
- package/src/http/requestOptions.js +31 -0
- package/src/projects/projectsClient.js +17 -0
- package/src/sanityClient.js +119 -0
- package/src/users/usersClient.js +13 -0
- package/src/util/defaults.js +8 -0
- package/src/util/getSelection.js +17 -0
- package/src/util/observable.js +11 -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 +0 -2561
- package/test/encodeQueryString.test.js +0 -36
- package/test/fixtures/horsehead-nebula.jpg +0 -0
- package/test/fixtures/pdf-sample.pdf +0 -0
- package/test/helpers/sseServer.js +0 -26
- package/test/listen.test.js +0 -205
- package/test/warnings.test.disabled.js +0 -80
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const test = require('tape')
|
|
2
|
-
const encode = require('../src/data/encodeQueryString')
|
|
3
|
-
|
|
4
|
-
test('can encode basic query without parameters', (t) => {
|
|
5
|
-
const query = 'gamedb.game[maxPlayers == 64]'
|
|
6
|
-
t.equal(encode({query}), '?query=gamedb.game%5BmaxPlayers%20%3D%3D%2064%5D')
|
|
7
|
-
t.end()
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
test('can encode queries with basic numeric parameters', (t) => {
|
|
11
|
-
const query = 'gamedb.game[maxPlayers == $maxPlayers && score == $score]'
|
|
12
|
-
t.equal(
|
|
13
|
-
encode({query, params: {maxPlayers: 64, score: 3.45678}}),
|
|
14
|
-
'?query=gamedb.game%5BmaxPlayers%20%3D%3D%20%24maxPlayers%20%26%26%20score%20%3D%3D%20%24score%5D' +
|
|
15
|
-
'&%24maxPlayers=64&%24score=3.45678'
|
|
16
|
-
)
|
|
17
|
-
t.end()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test('can encode queries with basic string parameters', (t) => {
|
|
21
|
-
const query = 'gamedb.game[name == $name]'
|
|
22
|
-
t.equal(
|
|
23
|
-
encode({query, params: {name: 'foobar'}}),
|
|
24
|
-
'?query=gamedb.game%5Bname%20%3D%3D%20%24name%5D&%24name=%22foobar%22'
|
|
25
|
-
)
|
|
26
|
-
t.end()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test('can encode queries with booleans', (t) => {
|
|
30
|
-
const query = 'gamedb.game[isReleased == $released]'
|
|
31
|
-
t.equal(
|
|
32
|
-
encode({query, params: {released: true}}),
|
|
33
|
-
'?query=gamedb.game%5BisReleased%20%3D%3D%20%24released%5D&%24released=true'
|
|
34
|
-
)
|
|
35
|
-
t.end()
|
|
36
|
-
})
|
|
Binary file
|
|
Binary file
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/* eslint-disable strict */
|
|
2
|
-
// (Node 4 compat)
|
|
3
|
-
|
|
4
|
-
'use strict'
|
|
5
|
-
|
|
6
|
-
const http = require('http')
|
|
7
|
-
const SseChannel = require('sse-channel')
|
|
8
|
-
|
|
9
|
-
module.exports = (onRequest, cb) => {
|
|
10
|
-
const server = http.createServer((request, response) => {
|
|
11
|
-
let channel
|
|
12
|
-
if (
|
|
13
|
-
request.url.indexOf('/v1/data/listen/') === 0 ||
|
|
14
|
-
request.url.indexOf('/listen/beerns?query=') === 0
|
|
15
|
-
) {
|
|
16
|
-
channel = new SseChannel({jsonEncode: true})
|
|
17
|
-
channel.addClient(request, response)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
onRequest({request, channel, response})
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
server.listen(0, '127.0.0.1', (err) => {
|
|
24
|
-
cb(err, err ? null : server)
|
|
25
|
-
})
|
|
26
|
-
}
|
package/test/listen.test.js
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
/* eslint-disable strict */
|
|
2
|
-
// (Node 4 compat)
|
|
3
|
-
|
|
4
|
-
'use strict'
|
|
5
|
-
|
|
6
|
-
const test = require('tape')
|
|
7
|
-
const assign = require('xtend')
|
|
8
|
-
const sanityClient = require('../src/sanityClient')
|
|
9
|
-
const sseServer = require('./helpers/sseServer')
|
|
10
|
-
|
|
11
|
-
const getClient = (options) =>
|
|
12
|
-
sanityClient(
|
|
13
|
-
assign(
|
|
14
|
-
{
|
|
15
|
-
dataset: 'prod',
|
|
16
|
-
namespace: 'beerns',
|
|
17
|
-
apiHost: `http://127.0.0.1:${options.port}`,
|
|
18
|
-
useProjectHostname: false,
|
|
19
|
-
useCdn: false,
|
|
20
|
-
apiVersion: '1',
|
|
21
|
-
},
|
|
22
|
-
options
|
|
23
|
-
)
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
const testSse = (onRequest, options) =>
|
|
27
|
-
new Promise((resolve, reject) => {
|
|
28
|
-
sseServer(onRequest, (err, server) => {
|
|
29
|
-
if (err) {
|
|
30
|
-
return reject(err)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const client = getClient(assign({port: server.address().port}, options))
|
|
34
|
-
return resolve({server, client})
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
/*****************
|
|
39
|
-
* LISTENER *
|
|
40
|
-
*****************/
|
|
41
|
-
test('[listener] can listen for mutations', (t) => {
|
|
42
|
-
const eventData = {
|
|
43
|
-
documentId: 'beer-123',
|
|
44
|
-
eventId: 'blah#beer-123',
|
|
45
|
-
identity: 'uid',
|
|
46
|
-
mutations: [{patch: {id: 'beer-123', set: {abv: 8}}}],
|
|
47
|
-
previousRev: 'MOmofa',
|
|
48
|
-
result: {
|
|
49
|
-
_id: 'beer-123',
|
|
50
|
-
_type: 'beer',
|
|
51
|
-
brewery: 'Trillium',
|
|
52
|
-
title: 'Headroom Double IPA',
|
|
53
|
-
abv: 8,
|
|
54
|
-
},
|
|
55
|
-
resultRev: 'Blatti',
|
|
56
|
-
timestamp: '2017-03-29T12:36:20.506516Z',
|
|
57
|
-
transactionId: 'foo',
|
|
58
|
-
transition: 'update',
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
testSse(({request, channel}) => {
|
|
62
|
-
t.equal(
|
|
63
|
-
request.url,
|
|
64
|
-
[
|
|
65
|
-
'/v1/data/listen/prod',
|
|
66
|
-
'?query=*%5B_type%20%3D%3D%20%22beer%22%20%26%26%20title%20%3D%3D%20%24beerName%5D',
|
|
67
|
-
'&%24beerName=%22Headroom%20Double%20IPA%22&includeResult=true',
|
|
68
|
-
].join(''),
|
|
69
|
-
'url should be correct'
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
channel.send({event: 'mutation', data: eventData})
|
|
73
|
-
process.nextTick(() => channel.close())
|
|
74
|
-
})
|
|
75
|
-
.then(({server, client}) => {
|
|
76
|
-
const query = '*[_type == "beer" && title == $beerName]'
|
|
77
|
-
const params = {beerName: 'Headroom Double IPA'}
|
|
78
|
-
|
|
79
|
-
const subscription = client.listen(query, params).subscribe({
|
|
80
|
-
next: (msg) => {
|
|
81
|
-
t.deepEqual(
|
|
82
|
-
msg,
|
|
83
|
-
assign({}, eventData, {type: 'mutation'}),
|
|
84
|
-
'event data should be correct'
|
|
85
|
-
)
|
|
86
|
-
subscription.unsubscribe()
|
|
87
|
-
server.close()
|
|
88
|
-
t.end()
|
|
89
|
-
},
|
|
90
|
-
error: (err) => {
|
|
91
|
-
subscription.unsubscribe()
|
|
92
|
-
server.close()
|
|
93
|
-
t.end(err)
|
|
94
|
-
},
|
|
95
|
-
})
|
|
96
|
-
})
|
|
97
|
-
.catch(t.end)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
test('[listener] listener sends auth token if given (node)', (t) => {
|
|
101
|
-
let httpServer = null
|
|
102
|
-
testSse(
|
|
103
|
-
({request, channel}) => {
|
|
104
|
-
t.equal(request.headers.authorization, 'Bearer foobar', 'should send token')
|
|
105
|
-
channel.send({event: 'disconnect'})
|
|
106
|
-
process.nextTick(() => {
|
|
107
|
-
channel.close()
|
|
108
|
-
httpServer.close()
|
|
109
|
-
t.end()
|
|
110
|
-
})
|
|
111
|
-
},
|
|
112
|
-
{token: 'foobar'}
|
|
113
|
-
)
|
|
114
|
-
.then(({server, client}) => {
|
|
115
|
-
httpServer = server
|
|
116
|
-
const subscription = client.listen('*').subscribe({
|
|
117
|
-
error: (err) => {
|
|
118
|
-
subscription.unsubscribe()
|
|
119
|
-
server.close()
|
|
120
|
-
t.end(err)
|
|
121
|
-
},
|
|
122
|
-
})
|
|
123
|
-
})
|
|
124
|
-
.catch(t.end)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
test('[listener] reconnects if disconnected', (t) => {
|
|
128
|
-
testSse(({request, channel}) => {
|
|
129
|
-
channel.send({event: 'welcome'})
|
|
130
|
-
channel.close()
|
|
131
|
-
process.nextTick(() => channel.close())
|
|
132
|
-
})
|
|
133
|
-
.then(({server, client}) => {
|
|
134
|
-
const subscription = client.listen('*', {}, {events: ['reconnect']}).subscribe({
|
|
135
|
-
next: (msg) => {
|
|
136
|
-
t.equal(msg.type, 'reconnect', 'emits reconnect events if told to')
|
|
137
|
-
subscription.unsubscribe()
|
|
138
|
-
server.close()
|
|
139
|
-
t.end()
|
|
140
|
-
},
|
|
141
|
-
error: (err) => {
|
|
142
|
-
subscription.unsubscribe()
|
|
143
|
-
server.close()
|
|
144
|
-
t.end(err)
|
|
145
|
-
},
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
.catch(t.end)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
test('[listener] emits channel errors', (t) => {
|
|
152
|
-
testSse(({request, channel}) => {
|
|
153
|
-
channel.send({event: 'channelError', data: {message: 'Unfortunate error'}})
|
|
154
|
-
channel.close()
|
|
155
|
-
process.nextTick(() => channel.close())
|
|
156
|
-
})
|
|
157
|
-
.then(({server, client}) => {
|
|
158
|
-
const subscription = client.listen('*').subscribe({
|
|
159
|
-
error: (err) => {
|
|
160
|
-
t.equal(err.message, 'Unfortunate error', 'should have passed error message')
|
|
161
|
-
subscription.unsubscribe()
|
|
162
|
-
server.close()
|
|
163
|
-
t.end()
|
|
164
|
-
},
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
.catch(t.end)
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
test('[listener] emits channel errors with deep error description', (t) => {
|
|
171
|
-
testSse(({request, channel}) => {
|
|
172
|
-
channel.send({event: 'channelError', data: {error: {description: 'Expected error'}}})
|
|
173
|
-
channel.close()
|
|
174
|
-
process.nextTick(() => channel.close())
|
|
175
|
-
})
|
|
176
|
-
.then(({server, client}) => {
|
|
177
|
-
const subscription = client.listen('*').subscribe({
|
|
178
|
-
error: (err) => {
|
|
179
|
-
t.equal(err.message, 'Expected error', 'should have passed error message')
|
|
180
|
-
subscription.unsubscribe()
|
|
181
|
-
server.close()
|
|
182
|
-
t.end()
|
|
183
|
-
},
|
|
184
|
-
})
|
|
185
|
-
})
|
|
186
|
-
.catch(t.end)
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
test('[listener] emits error if request URL is too large', (t) => {
|
|
190
|
-
testSse(({request, channel}) => {
|
|
191
|
-
channel.close()
|
|
192
|
-
process.nextTick(() => channel.close())
|
|
193
|
-
})
|
|
194
|
-
.then(({server, client}) => {
|
|
195
|
-
const pad = '_'.repeat(16000)
|
|
196
|
-
client.listen(`*{"foo":"${pad}"`).subscribe({
|
|
197
|
-
error: (err) => {
|
|
198
|
-
t.equal(err.message, 'Query too large for listener', 'should have passed error message')
|
|
199
|
-
server.close()
|
|
200
|
-
t.end()
|
|
201
|
-
},
|
|
202
|
-
})
|
|
203
|
-
})
|
|
204
|
-
.catch(t.end)
|
|
205
|
-
})
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// This test suite fails using tape but should pass if running with as a node script
|
|
2
|
-
const test = require('tape')
|
|
3
|
-
const nock = require('nock')
|
|
4
|
-
const sanityClient = require('../src/sanityClient')
|
|
5
|
-
|
|
6
|
-
const stub = (target, prop, stubbed) => {
|
|
7
|
-
const original = target[prop]
|
|
8
|
-
target[prop] = stubbed
|
|
9
|
-
return () => {
|
|
10
|
-
target[prop] = original
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const combine = (...fns) => () => {
|
|
15
|
-
const [head, ...tail] = fns
|
|
16
|
-
return tail.reduce((acc, fn) => fn(acc), head())
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**************************
|
|
20
|
-
* CLIENT CONFIG WARNINGS *
|
|
21
|
-
**************************/
|
|
22
|
-
|
|
23
|
-
test('warns if useCdn is not given', (t) => {
|
|
24
|
-
const restore = combine(
|
|
25
|
-
stub(console, 'warn', (message) => {
|
|
26
|
-
t.equal(
|
|
27
|
-
message,
|
|
28
|
-
'You are not using the Sanity CDN. That means your data is always fresh, but the CDN is faster and cheaper. Think about it! For more info, see https://docs.sanity.io/help/js-client-cdn-configuration. To hide this warning, please set the `useCdn` option to either `true` or `false` when creating the client.'
|
|
29
|
-
)
|
|
30
|
-
restore()
|
|
31
|
-
t.end()
|
|
32
|
-
})
|
|
33
|
-
)
|
|
34
|
-
sanityClient({projectId: 'abc123', apiVersion: '1'})
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test('warns if in browser on localhost and a token is provided', (t) => {
|
|
38
|
-
const restore = combine(
|
|
39
|
-
stub(global, 'window', {location: {hostname: 'localhost'}}),
|
|
40
|
-
stub(console, 'warn', (message) => {
|
|
41
|
-
t.equal(
|
|
42
|
-
message,
|
|
43
|
-
'You have configured Sanity client to use a token in the browser. This may cause unintentional security issues. See https://docs.sanity.io/help/js-client-browser-token for more information and how to hide this warning.'
|
|
44
|
-
)
|
|
45
|
-
restore()
|
|
46
|
-
t.end()
|
|
47
|
-
})
|
|
48
|
-
)
|
|
49
|
-
sanityClient({projectId: 'abc123', useCdn: false, token: 'foo', apiVersion: '1'})
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
test('warns a token is provided together with useCdn:true (and not in browser)', (t) => {
|
|
53
|
-
const restore = combine(
|
|
54
|
-
stub(console, 'warn', (message) => {
|
|
55
|
-
t.equal(
|
|
56
|
-
message,
|
|
57
|
-
'You have set `useCdn` to `true` while also specifying a token. This is usually not what you want. The CDN cannot be used with an authorization token, since private data cannot be cached. See https://docs.sanity.io/help/js-client-usecdn-token for more information.'
|
|
58
|
-
)
|
|
59
|
-
restore()
|
|
60
|
-
t.end()
|
|
61
|
-
})
|
|
62
|
-
)
|
|
63
|
-
sanityClient({projectId: 'abc123', token: 'foo', useCdn: true, apiVersion: '1'})
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test('warns if server sends warning back', (t) => {
|
|
67
|
-
const restore = combine(
|
|
68
|
-
stub(console, 'warn', (message) => {
|
|
69
|
-
t.equal(message, 'Friction endures')
|
|
70
|
-
restore()
|
|
71
|
-
t.end()
|
|
72
|
-
})
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
nock('https://abc123.api.sanity.io')
|
|
76
|
-
.get('/v1/users/me')
|
|
77
|
-
.reply(200, {}, {'X-Sanity-Warning': 'Friction endures'})
|
|
78
|
-
|
|
79
|
-
sanityClient({projectId: 'abc123', useCdn: true, apiVersion: '1'}).users.getById('me')
|
|
80
|
-
})
|