@sanity/sdk 2.9.0 → 2.10.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/dist/_chunks-dts/utils.d.ts +105 -51
- package/dist/_chunks-es/createGroqSearchFilter.js +131 -54
- package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -1
- package/dist/_chunks-es/version.js +1 -1
- package/dist/_exports/_internal.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +119 -73
- package/dist/index.js.map +1 -1
- package/package.json +8 -10
- package/src/_exports/index.ts +8 -0
- package/src/client/clientStore.test.ts +30 -30
- package/src/client/clientStore.ts +47 -47
- package/src/comlink/controller/actions/getOrCreateChannel.ts +2 -2
- package/src/comlink/node/actions/getOrCreateNode.ts +2 -2
- package/src/config/sanityConfig.ts +72 -12
- package/src/document/applyDocumentActions.test.ts +7 -7
- package/src/document/applyDocumentActions.ts +5 -5
- package/src/document/documentStore.test.ts +68 -62
- package/src/document/documentStore.ts +36 -36
- package/src/document/processActions.ts +2 -2
- package/src/document/reducers.ts +4 -4
- package/src/document/sharedListener.ts +7 -7
- package/src/presence/bifurTransport.test.ts +46 -6
- package/src/presence/bifurTransport.ts +13 -1
- package/src/presence/presenceStore.test.ts +96 -0
- package/src/presence/presenceStore.ts +96 -24
- package/src/preview/getPreviewState.ts +1 -1
- package/src/preview/previewProjectionUtils.test.ts +4 -4
- package/src/preview/previewProjectionUtils.ts +7 -7
- package/src/preview/resolvePreview.ts +5 -1
- package/src/projection/getProjectionState.ts +4 -4
- package/src/projection/projectionStore.test.ts +2 -2
- package/src/projection/resolveProjection.ts +2 -2
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +1 -1
- package/src/projection/subscribeToStateAndFetchBatches.ts +12 -11
- package/src/query/queryStore.test.ts +12 -12
- package/src/query/queryStore.ts +10 -10
- package/src/query/reducers.ts +3 -3
- package/src/releases/getPerspectiveState.ts +5 -5
- package/src/releases/releasesStore.test.ts +6 -6
- package/src/releases/releasesStore.ts +9 -9
- package/src/store/createActionBinder.test.ts +31 -31
- package/src/store/createActionBinder.ts +43 -38
- package/src/store/createSanityInstance.ts +2 -3
- package/src/users/reducers.ts +3 -4
- package/src/utils/createFetcherStore.ts +6 -4
- package/src/utils/isImportError.test.ts +72 -0
- package/src/utils/isImportError.ts +34 -0
- package/src/utils/object.test.ts +95 -0
- package/src/utils/object.ts +142 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Sanity SDK",
|
|
6
6
|
"keywords": [
|
|
@@ -49,29 +49,27 @@
|
|
|
49
49
|
"prettier": "@sanity/prettier-config",
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@sanity/bifur-client": "^0.4.1",
|
|
52
|
-
"@sanity/client": "^7.
|
|
53
|
-
"@sanity/comlink": "^3.
|
|
52
|
+
"@sanity/client": "^7.22.0",
|
|
53
|
+
"@sanity/comlink": "^3.1.1",
|
|
54
54
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
55
55
|
"@sanity/diff-patch": "^6.0.0",
|
|
56
56
|
"@sanity/id-utils": "^1.0.0",
|
|
57
57
|
"@sanity/image-url": "^2.0.3",
|
|
58
58
|
"@sanity/json-match": "^1.0.5",
|
|
59
|
-
"@sanity/message-protocol": "^0.
|
|
59
|
+
"@sanity/message-protocol": "^0.23.0",
|
|
60
60
|
"@sanity/mutate": "^0.16.1",
|
|
61
|
-
"@sanity/telemetry": "^1.
|
|
61
|
+
"@sanity/telemetry": "^1.1.0",
|
|
62
62
|
"@sanity/types": "^5.2.0",
|
|
63
63
|
"groq": "3.88.1-typegen-experimental.0",
|
|
64
64
|
"groq-js": "^1.19.0",
|
|
65
|
-
"lodash-es": "^4.17.21",
|
|
66
65
|
"reselect": "^5.1.1",
|
|
67
66
|
"rxjs": "^7.8.2",
|
|
68
|
-
"zustand": "^5.0.
|
|
67
|
+
"zustand": "^5.0.12"
|
|
69
68
|
},
|
|
70
69
|
"devDependencies": {
|
|
71
70
|
"@sanity/browserslist-config": "^1.0.5",
|
|
72
71
|
"@sanity/pkg-utils": "^8.1.29",
|
|
73
72
|
"@sanity/prettier-config": "^1.0.6",
|
|
74
|
-
"@types/lodash-es": "^4.17.12",
|
|
75
73
|
"@vitest/coverage-v8": "3.2.4",
|
|
76
74
|
"eslint": "^9.22.0",
|
|
77
75
|
"prettier": "^3.7.3",
|
|
@@ -80,10 +78,10 @@
|
|
|
80
78
|
"vite": "^7.0.0",
|
|
81
79
|
"vitest": "^3.2.4",
|
|
82
80
|
"@repo/config-eslint": "0.0.0",
|
|
83
|
-
"@repo/
|
|
81
|
+
"@repo/tsconfig": "0.0.1",
|
|
84
82
|
"@repo/package.bundle": "3.82.0",
|
|
85
83
|
"@repo/package.config": "0.0.1",
|
|
86
|
-
"@repo/
|
|
84
|
+
"@repo/config-test": "0.0.1"
|
|
87
85
|
},
|
|
88
86
|
"engines": {
|
|
89
87
|
"node": ">=20.19"
|
package/src/_exports/index.ts
CHANGED
|
@@ -86,15 +86,22 @@ export {
|
|
|
86
86
|
type LogNamespace,
|
|
87
87
|
} from '../config/loggingConfig'
|
|
88
88
|
export {
|
|
89
|
+
type CanvasResource,
|
|
89
90
|
type CanvasSource,
|
|
90
91
|
type DatasetHandle,
|
|
92
|
+
type DatasetResource,
|
|
91
93
|
type DatasetSource,
|
|
92
94
|
type DocumentHandle,
|
|
95
|
+
type DocumentResource,
|
|
93
96
|
type DocumentSource,
|
|
94
97
|
type DocumentTypeHandle,
|
|
98
|
+
isCanvasResource,
|
|
95
99
|
isCanvasSource,
|
|
100
|
+
isDatasetResource,
|
|
96
101
|
isDatasetSource,
|
|
102
|
+
isMediaLibraryResource,
|
|
97
103
|
isMediaLibrarySource,
|
|
104
|
+
type MediaLibraryResource,
|
|
98
105
|
type MediaLibrarySource,
|
|
99
106
|
type PerspectiveHandle,
|
|
100
107
|
type ProjectHandle,
|
|
@@ -212,6 +219,7 @@ export {type FetcherStore, type FetcherStoreState} from '../utils/createFetcherS
|
|
|
212
219
|
export {createGroqSearchFilter} from '../utils/createGroqSearchFilter'
|
|
213
220
|
export {defineIntent, type Intent, type IntentFilter} from '../utils/defineIntent'
|
|
214
221
|
export {getCorsErrorProjectId} from '../utils/getCorsErrorProjectId'
|
|
222
|
+
export {isImportError} from '../utils/isImportError'
|
|
215
223
|
export {CORE_SDK_VERSION} from '../version'
|
|
216
224
|
export {
|
|
217
225
|
getIndexForKey,
|
|
@@ -190,17 +190,17 @@ describe('clientStore', () => {
|
|
|
190
190
|
})
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
-
describe('
|
|
194
|
-
it('should create client when
|
|
193
|
+
describe('resource handling', () => {
|
|
194
|
+
it('should create client when resource is provided', () => {
|
|
195
195
|
const client = getClient(instance, {
|
|
196
196
|
apiVersion: '2024-11-12',
|
|
197
|
-
|
|
197
|
+
resource: {projectId: 'source-project', dataset: 'source-dataset'},
|
|
198
198
|
})
|
|
199
199
|
|
|
200
200
|
expect(vi.mocked(createClient)).toHaveBeenCalledWith(
|
|
201
201
|
expect.objectContaining({
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
apiVersion: '2024-11-12',
|
|
203
|
+
resource: {type: 'dataset', id: 'source-project.source-dataset'},
|
|
204
204
|
}),
|
|
205
205
|
)
|
|
206
206
|
// Client should be projectless - no projectId/dataset in config
|
|
@@ -208,21 +208,21 @@ describe('clientStore', () => {
|
|
|
208
208
|
expect(client.config()).not.toHaveProperty('dataset')
|
|
209
209
|
expect(client.config()).toEqual(
|
|
210
210
|
expect.objectContaining({
|
|
211
|
-
|
|
211
|
+
resource: {type: 'dataset', id: 'source-project.source-dataset'},
|
|
212
212
|
}),
|
|
213
213
|
)
|
|
214
214
|
})
|
|
215
215
|
|
|
216
|
-
it('should create resource when
|
|
216
|
+
it('should create resource when resource has array resourceId and be projectless', () => {
|
|
217
217
|
const client = getClient(instance, {
|
|
218
218
|
apiVersion: '2024-11-12',
|
|
219
|
-
|
|
219
|
+
resource: {mediaLibraryId: 'media-lib-123'},
|
|
220
220
|
})
|
|
221
221
|
|
|
222
222
|
expect(vi.mocked(createClient)).toHaveBeenCalledWith(
|
|
223
223
|
expect.objectContaining({
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
resource: {type: 'media-library', id: 'media-lib-123'},
|
|
225
|
+
apiVersion: '2024-11-12',
|
|
226
226
|
}),
|
|
227
227
|
)
|
|
228
228
|
// Client should be projectless - no projectId/dataset in config
|
|
@@ -230,21 +230,21 @@ describe('clientStore', () => {
|
|
|
230
230
|
expect(client.config()).not.toHaveProperty('dataset')
|
|
231
231
|
expect(client.config()).toEqual(
|
|
232
232
|
expect.objectContaining({
|
|
233
|
-
|
|
233
|
+
resource: {type: 'media-library', id: 'media-lib-123'},
|
|
234
234
|
}),
|
|
235
235
|
)
|
|
236
236
|
})
|
|
237
237
|
|
|
238
|
-
it('should create resource when canvas
|
|
238
|
+
it('should create resource when canvas resource is provided and be projectless', () => {
|
|
239
239
|
const client = getClient(instance, {
|
|
240
240
|
apiVersion: '2024-11-12',
|
|
241
|
-
|
|
241
|
+
resource: {canvasId: 'canvas-123'},
|
|
242
242
|
})
|
|
243
243
|
|
|
244
244
|
expect(vi.mocked(createClient)).toHaveBeenCalledWith(
|
|
245
245
|
expect.objectContaining({
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
resource: {type: 'canvas', id: 'canvas-123'},
|
|
247
|
+
apiVersion: '2024-11-12',
|
|
248
248
|
}),
|
|
249
249
|
)
|
|
250
250
|
// Client should be projectless - no projectId/dataset in config
|
|
@@ -252,38 +252,38 @@ describe('clientStore', () => {
|
|
|
252
252
|
expect(client.config()).not.toHaveProperty('dataset')
|
|
253
253
|
expect(client.config()).toEqual(
|
|
254
254
|
expect.objectContaining({
|
|
255
|
-
|
|
255
|
+
resource: {type: 'canvas', id: 'canvas-123'},
|
|
256
256
|
}),
|
|
257
257
|
)
|
|
258
258
|
})
|
|
259
259
|
|
|
260
|
-
it('should create projectless client when
|
|
260
|
+
it('should create projectless client when resource is provided, ignoring instance config', () => {
|
|
261
261
|
const client = getClient(instance, {
|
|
262
262
|
apiVersion: '2024-11-12',
|
|
263
|
-
|
|
263
|
+
resource: {projectId: 'source-project', dataset: 'source-dataset'},
|
|
264
264
|
})
|
|
265
265
|
|
|
266
|
-
// Client should be projectless -
|
|
266
|
+
// Client should be projectless - resource takes precedence, instance config is ignored
|
|
267
267
|
expect(client.config()).not.toHaveProperty('projectId')
|
|
268
268
|
expect(client.config()).not.toHaveProperty('dataset')
|
|
269
269
|
expect(client.config()).toEqual(
|
|
270
270
|
expect.objectContaining({
|
|
271
|
-
|
|
271
|
+
resource: {type: 'dataset', id: 'source-project.source-dataset'},
|
|
272
272
|
}),
|
|
273
273
|
)
|
|
274
274
|
})
|
|
275
275
|
|
|
276
|
-
it('should warn when both
|
|
276
|
+
it('should warn when both resource and explicit projectId/dataset are provided', () => {
|
|
277
277
|
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
278
278
|
const client = getClient(instance, {
|
|
279
279
|
apiVersion: '2024-11-12',
|
|
280
|
-
|
|
280
|
+
resource: {projectId: 'source-project', dataset: 'source-dataset'},
|
|
281
281
|
projectId: 'explicit-project',
|
|
282
282
|
dataset: 'explicit-dataset',
|
|
283
283
|
})
|
|
284
284
|
|
|
285
285
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
286
|
-
'Both
|
|
286
|
+
'Both resource and explicit projectId/dataset are provided. The resource will be used and projectId/dataset will be ignored.',
|
|
287
287
|
)
|
|
288
288
|
// Client should still be projectless despite explicit projectId/dataset
|
|
289
289
|
expect(client.config()).not.toHaveProperty('projectId')
|
|
@@ -291,18 +291,18 @@ describe('clientStore', () => {
|
|
|
291
291
|
consoleSpy.mockRestore()
|
|
292
292
|
})
|
|
293
293
|
|
|
294
|
-
it('should create different clients for different
|
|
294
|
+
it('should create different clients for different resources', () => {
|
|
295
295
|
const client1 = getClient(instance, {
|
|
296
296
|
apiVersion: '2024-11-12',
|
|
297
|
-
|
|
297
|
+
resource: {projectId: 'source-project', dataset: 'source-dataset'},
|
|
298
298
|
})
|
|
299
299
|
const client2 = getClient(instance, {
|
|
300
300
|
apiVersion: '2024-11-12',
|
|
301
|
-
|
|
301
|
+
resource: {mediaLibraryId: 'media-lib-123'},
|
|
302
302
|
})
|
|
303
303
|
const client3 = getClient(instance, {
|
|
304
304
|
apiVersion: '2024-11-12',
|
|
305
|
-
|
|
305
|
+
resource: {canvasId: 'canvas-123'},
|
|
306
306
|
})
|
|
307
307
|
|
|
308
308
|
expect(client1).not.toBe(client2)
|
|
@@ -311,14 +311,14 @@ describe('clientStore', () => {
|
|
|
311
311
|
expect(vi.mocked(createClient)).toHaveBeenCalledTimes(3)
|
|
312
312
|
})
|
|
313
313
|
|
|
314
|
-
it('should reuse clients with identical
|
|
314
|
+
it('should reuse clients with identical resource configurations', () => {
|
|
315
315
|
const client1 = getClient(instance, {
|
|
316
316
|
apiVersion: '2024-11-12',
|
|
317
|
-
|
|
317
|
+
resource: {projectId: 'source-project', dataset: 'source-dataset'},
|
|
318
318
|
})
|
|
319
319
|
const client2 = getClient(instance, {
|
|
320
320
|
apiVersion: '2024-11-12',
|
|
321
|
-
|
|
321
|
+
resource: {projectId: 'source-project', dataset: 'source-dataset'},
|
|
322
322
|
})
|
|
323
323
|
|
|
324
324
|
expect(client1).toBe(client2)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {type ClientConfig, createClient, type SanityClient} from '@sanity/client'
|
|
2
|
-
import {pick} from 'lodash-es'
|
|
3
2
|
|
|
4
3
|
import {getAuthMethodState, getTokenState} from '../auth/authStore'
|
|
5
4
|
import {
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
type DocumentResource,
|
|
6
|
+
isCanvasResource,
|
|
7
|
+
isDatasetResource,
|
|
8
|
+
isMediaLibraryResource,
|
|
10
9
|
} from '../config/sanityConfig'
|
|
11
10
|
import {bindActionGlobally} from '../store/createActionBinder'
|
|
12
11
|
import {createStateSourceAction} from '../store/createStateSourceAction'
|
|
13
12
|
import {defineStore, type StoreContext} from '../store/defineStore'
|
|
14
13
|
import {getStagingApiHost} from '../utils/getStagingApiHost'
|
|
14
|
+
import {pickProperties} from '../utils/object'
|
|
15
15
|
|
|
16
16
|
const DEFAULT_API_VERSION = '2024-11-12'
|
|
17
17
|
const DEFAULT_REQUEST_TAG_PREFIX = 'sanity.sdk'
|
|
@@ -31,22 +31,21 @@ type AllowedClientConfigKey =
|
|
|
31
31
|
| 'useProjectHostname'
|
|
32
32
|
|
|
33
33
|
const allowedKeys = Object.keys({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
'source': null,
|
|
34
|
+
apiHost: null,
|
|
35
|
+
useCdn: null,
|
|
36
|
+
token: null,
|
|
37
|
+
perspective: null,
|
|
38
|
+
proxy: null,
|
|
39
|
+
withCredentials: null,
|
|
40
|
+
timeout: null,
|
|
41
|
+
maxRetries: null,
|
|
42
|
+
dataset: null,
|
|
43
|
+
projectId: null,
|
|
44
|
+
scope: null,
|
|
45
|
+
apiVersion: null,
|
|
46
|
+
requestTagPrefix: null,
|
|
47
|
+
useProjectHostname: null,
|
|
48
|
+
resource: null,
|
|
50
49
|
} satisfies Record<keyof ClientOptions, null>) as (keyof ClientOptions)[]
|
|
51
50
|
|
|
52
51
|
const DEFAULT_CLIENT_CONFIG: ClientConfig = {
|
|
@@ -67,11 +66,6 @@ export interface ClientStoreState {
|
|
|
67
66
|
authMethod?: 'localstorage' | 'cookie'
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
interface ClientResource {
|
|
71
|
-
type: 'dataset' | 'media-library' | 'canvas'
|
|
72
|
-
id: string
|
|
73
|
-
}
|
|
74
|
-
|
|
75
69
|
/**
|
|
76
70
|
* Options used when retrieving a client instance from the client store.
|
|
77
71
|
*
|
|
@@ -94,20 +88,17 @@ export interface ClientOptions extends Pick<ClientConfig, AllowedClientConfigKey
|
|
|
94
88
|
* and the global client ('global'). When set to `'global'`, the global client
|
|
95
89
|
* is used.
|
|
96
90
|
*/
|
|
97
|
-
|
|
91
|
+
scope?: 'default' | 'global'
|
|
98
92
|
/**
|
|
99
93
|
* A required string indicating the API version for the client.
|
|
100
94
|
*/
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* @internal
|
|
104
|
-
*/
|
|
105
|
-
'~experimental_resource'?: ClientConfig['~experimental_resource']
|
|
95
|
+
apiVersion: string
|
|
106
96
|
|
|
107
97
|
/**
|
|
108
98
|
* @internal
|
|
99
|
+
* The SDK resource to use for the client -- this will get transformed into a ClientConfig resource.
|
|
109
100
|
*/
|
|
110
|
-
|
|
101
|
+
resource?: DocumentResource
|
|
111
102
|
}
|
|
112
103
|
|
|
113
104
|
const clientStore = defineStore<ClientStoreState>({
|
|
@@ -144,7 +135,13 @@ const listenToAuthMethod = ({instance, state}: StoreContext<ClientStoreState>) =
|
|
|
144
135
|
})
|
|
145
136
|
}
|
|
146
137
|
|
|
147
|
-
|
|
138
|
+
type ClientInstanceCacheKeyInput = ClientConfig &
|
|
139
|
+
Partial<Pick<ClientOptions, 'scope'>> & {
|
|
140
|
+
apiVersion: string
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const getClientConfigKey = (options: ClientInstanceCacheKeyInput) =>
|
|
144
|
+
JSON.stringify(pickProperties(options, allowedKeys))
|
|
148
145
|
|
|
149
146
|
/**
|
|
150
147
|
* Retrieves a Sanity client instance configured with the provided options.
|
|
@@ -182,15 +179,18 @@ export const getClient = bindActionGlobally(
|
|
|
182
179
|
const tokenFromState = state.get().token
|
|
183
180
|
const {clients, authMethod} = state.get()
|
|
184
181
|
|
|
185
|
-
let resource:
|
|
182
|
+
let resource: ClientConfig['resource'] | undefined
|
|
186
183
|
|
|
187
|
-
if (options.
|
|
188
|
-
if (
|
|
189
|
-
resource = {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
184
|
+
if (options.resource) {
|
|
185
|
+
if (isDatasetResource(options.resource)) {
|
|
186
|
+
resource = {
|
|
187
|
+
type: 'dataset',
|
|
188
|
+
id: `${options.resource.projectId}.${options.resource.dataset}`,
|
|
189
|
+
}
|
|
190
|
+
} else if (isMediaLibraryResource(options.resource)) {
|
|
191
|
+
resource = {type: 'media-library', id: options.resource.mediaLibraryId}
|
|
192
|
+
} else if (isCanvasResource(options.resource)) {
|
|
193
|
+
resource = {type: 'canvas', id: options.resource.canvasId}
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -198,25 +198,25 @@ export const getClient = bindActionGlobally(
|
|
|
198
198
|
const dataset = options.dataset ?? instance.config.dataset
|
|
199
199
|
const apiHost = options.apiHost ?? instance.config.auth?.apiHost ?? getStagingApiHost()
|
|
200
200
|
|
|
201
|
-
const effectiveOptions:
|
|
201
|
+
const effectiveOptions: ClientConfig & {apiVersion: string} = {
|
|
202
202
|
...DEFAULT_CLIENT_CONFIG,
|
|
203
203
|
...((options.scope === 'global' || !projectId || resource) && {useProjectHostname: false}),
|
|
204
204
|
token: authMethod === 'cookie' ? undefined : (tokenFromState ?? undefined),
|
|
205
205
|
...options,
|
|
206
206
|
...(projectId && {projectId}),
|
|
207
207
|
...(dataset && {dataset}),
|
|
208
|
+
...(resource ? {resource} : {resource: undefined}),
|
|
208
209
|
...(apiHost && {apiHost}),
|
|
209
|
-
...(resource && {'~experimental_resource': resource}),
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
// When a
|
|
213
|
-
// The client code itself will ignore the non-
|
|
212
|
+
// When a resource is provided, don't use projectId/dataset - the client should be "projectless"
|
|
213
|
+
// The client code itself will ignore the non-resource config, so we do this to prevent confusing the user.
|
|
214
214
|
// (ref: https://github.com/sanity-io/client/blob/5c23f81f5ab93a53f5b22b39845c867988508d84/src/data/dataMethods.ts#L691)
|
|
215
215
|
if (resource) {
|
|
216
216
|
if (options.projectId || options.dataset) {
|
|
217
217
|
// eslint-disable-next-line no-console
|
|
218
218
|
console.warn(
|
|
219
|
-
'Both
|
|
219
|
+
'Both resource and explicit projectId/dataset are provided. The resource will be used and projectId/dataset will be ignored.',
|
|
220
220
|
)
|
|
221
221
|
}
|
|
222
222
|
delete effectiveOptions.projectId
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {type ChannelInput, type ChannelInstance} from '@sanity/comlink'
|
|
2
|
-
import {isEqual} from 'lodash-es'
|
|
3
2
|
|
|
4
3
|
import {type StoreContext} from '../../../store/defineStore'
|
|
4
|
+
import {isDeepEqual} from '../../../utils/object'
|
|
5
5
|
import {type FrameMessage, type WindowMessage} from '../../types'
|
|
6
6
|
import {type ComlinkControllerState} from '../comlinkControllerStore'
|
|
7
7
|
|
|
@@ -25,7 +25,7 @@ export const getOrCreateChannel = (
|
|
|
25
25
|
|
|
26
26
|
// limit channels to one per name
|
|
27
27
|
if (existing) {
|
|
28
|
-
if (!
|
|
28
|
+
if (!isDeepEqual(existing.options, options)) {
|
|
29
29
|
throw new Error(`Channel "${options.name}" already exists with different options`)
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {createNode, type Node, type NodeInput} from '@sanity/comlink'
|
|
2
|
-
import {isEqual} from 'lodash-es'
|
|
3
2
|
|
|
4
3
|
import {type StoreContext} from '../../../store/defineStore'
|
|
4
|
+
import {isDeepEqual} from '../../../utils/object'
|
|
5
5
|
import {type FrameMessage, type WindowMessage} from '../../types'
|
|
6
6
|
import {type ComlinkNodeState} from '../comlinkNodeStore'
|
|
7
7
|
|
|
@@ -14,7 +14,7 @@ export const getOrCreateNode = (
|
|
|
14
14
|
|
|
15
15
|
// limit nodes to one per name
|
|
16
16
|
if (existing) {
|
|
17
|
-
if (!
|
|
17
|
+
if (!isDeepEqual(existing.options, options)) {
|
|
18
18
|
throw new Error(`Node "${options.name}" already exists with different options`)
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -73,9 +73,14 @@ export interface DatasetHandle<TDataset extends string = string, TProjectId exte
|
|
|
73
73
|
dataset?: TDataset
|
|
74
74
|
/**
|
|
75
75
|
* @beta
|
|
76
|
-
* Explicit
|
|
76
|
+
* Explicit resource object to use for this operation.
|
|
77
77
|
*/
|
|
78
|
-
|
|
78
|
+
resource?: DocumentResource
|
|
79
|
+
/**
|
|
80
|
+
* @deprecated Use `resource` instead.
|
|
81
|
+
* @beta
|
|
82
|
+
*/
|
|
83
|
+
source?: DocumentResource
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
/**
|
|
@@ -145,51 +150,106 @@ export interface SanityConfig extends DatasetHandle, PerspectiveHandle {
|
|
|
145
150
|
|
|
146
151
|
/**
|
|
147
152
|
* @beta
|
|
148
|
-
* A list of named
|
|
153
|
+
* A list of named resources to use for this instance.
|
|
154
|
+
*/
|
|
155
|
+
resources?: Record<string, DocumentResource>
|
|
156
|
+
/**
|
|
157
|
+
* @deprecated Use `resources` instead.
|
|
158
|
+
* @beta
|
|
149
159
|
*/
|
|
150
|
-
sources?: Record<string,
|
|
160
|
+
sources?: Record<string, DocumentResource>
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
/**
|
|
154
|
-
* A document
|
|
164
|
+
* A document resource can be used for querying.
|
|
155
165
|
* This will soon be the default way to identify where you are querying from.
|
|
156
166
|
*
|
|
157
167
|
* @beta
|
|
158
168
|
*/
|
|
159
|
-
export type
|
|
169
|
+
export type DocumentResource = DatasetResource | MediaLibraryResource | CanvasResource
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @beta
|
|
173
|
+
*/
|
|
174
|
+
export type DatasetResource = {projectId: string; dataset: string}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @beta
|
|
178
|
+
*/
|
|
179
|
+
export type MediaLibraryResource = {mediaLibraryId: string}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @beta
|
|
183
|
+
*/
|
|
184
|
+
export type CanvasResource = {canvasId: string}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @beta
|
|
188
|
+
*/
|
|
189
|
+
export function isDatasetResource(resource: DocumentResource): resource is DatasetResource {
|
|
190
|
+
return 'projectId' in resource && 'dataset' in resource
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @beta
|
|
195
|
+
*/
|
|
196
|
+
export function isMediaLibraryResource(
|
|
197
|
+
resource: DocumentResource,
|
|
198
|
+
): resource is MediaLibraryResource {
|
|
199
|
+
return 'mediaLibraryId' in resource
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @beta
|
|
204
|
+
*/
|
|
205
|
+
export function isCanvasResource(resource: DocumentResource): resource is CanvasResource {
|
|
206
|
+
return 'canvasId' in resource
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* @deprecated Use `DocumentResource` instead.
|
|
211
|
+
* @beta
|
|
212
|
+
*/
|
|
213
|
+
export type DocumentSource = DocumentResource
|
|
160
214
|
|
|
161
215
|
/**
|
|
216
|
+
* @deprecated Use `DatasetResource` instead.
|
|
162
217
|
* @beta
|
|
163
218
|
*/
|
|
164
|
-
export type DatasetSource =
|
|
219
|
+
export type DatasetSource = DatasetResource
|
|
165
220
|
|
|
166
221
|
/**
|
|
222
|
+
* @deprecated Use `MediaLibraryResource` instead.
|
|
167
223
|
* @beta
|
|
168
224
|
*/
|
|
169
|
-
export type MediaLibrarySource =
|
|
225
|
+
export type MediaLibrarySource = MediaLibraryResource
|
|
170
226
|
|
|
171
227
|
/**
|
|
228
|
+
* @deprecated Use `CanvasResource` instead.
|
|
172
229
|
* @beta
|
|
173
230
|
*/
|
|
174
|
-
export type CanvasSource =
|
|
231
|
+
export type CanvasSource = CanvasResource
|
|
175
232
|
|
|
176
233
|
/**
|
|
234
|
+
* @deprecated Use `isDatasetResource` instead.
|
|
177
235
|
* @beta
|
|
178
236
|
*/
|
|
179
237
|
export function isDatasetSource(source: DocumentSource): source is DatasetSource {
|
|
180
|
-
return
|
|
238
|
+
return isDatasetResource(source)
|
|
181
239
|
}
|
|
182
240
|
|
|
183
241
|
/**
|
|
242
|
+
* @deprecated Use `isMediaLibraryResource` instead.
|
|
184
243
|
* @beta
|
|
185
244
|
*/
|
|
186
245
|
export function isMediaLibrarySource(source: DocumentSource): source is MediaLibrarySource {
|
|
187
|
-
return
|
|
246
|
+
return isMediaLibraryResource(source)
|
|
188
247
|
}
|
|
189
248
|
|
|
190
249
|
/**
|
|
250
|
+
* @deprecated Use `isCanvasResource` instead.
|
|
191
251
|
* @beta
|
|
192
252
|
*/
|
|
193
253
|
export function isCanvasSource(source: DocumentSource): source is CanvasSource {
|
|
194
|
-
return
|
|
254
|
+
return isCanvasResource(source)
|
|
195
255
|
}
|
|
@@ -2,7 +2,7 @@ import {type SanityDocument} from '@sanity/types'
|
|
|
2
2
|
import {Subject} from 'rxjs'
|
|
3
3
|
import {describe, expect, it} from 'vitest'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {bindActionByResource} from '../store/createActionBinder'
|
|
6
6
|
import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
|
|
7
7
|
import {createStoreState, type StoreState} from '../store/createStoreState'
|
|
8
8
|
import {type DocumentAction} from './actions'
|
|
@@ -12,7 +12,7 @@ import {type AppliedTransaction, type OutgoingTransaction} from './reducers'
|
|
|
12
12
|
|
|
13
13
|
vi.mock('../store/createActionBinder', async (importOriginal) => ({
|
|
14
14
|
...(await importOriginal<typeof import('../store/createActionBinder')>()),
|
|
15
|
-
|
|
15
|
+
bindActionByResource: vi.fn(),
|
|
16
16
|
}))
|
|
17
17
|
|
|
18
18
|
type TestState = Pick<
|
|
@@ -46,9 +46,9 @@ describe('applyDocumentActions', () => {
|
|
|
46
46
|
}
|
|
47
47
|
state = createStoreState(initialState)
|
|
48
48
|
instance = createSanityInstance({projectId: 'p', dataset: 'd'})
|
|
49
|
-
const key = {name: 'p.d',
|
|
49
|
+
const key = {name: 'p.d', resource: {projectId: 'p', dataset: 'd'}}
|
|
50
50
|
|
|
51
|
-
vi.mocked(
|
|
51
|
+
vi.mocked(bindActionByResource).mockImplementation(
|
|
52
52
|
(_storeDef, action) => (instanceParam: SanityInstance, options) =>
|
|
53
53
|
action({instance: instanceParam, state, key}, options),
|
|
54
54
|
)
|
|
@@ -73,7 +73,7 @@ describe('applyDocumentActions', () => {
|
|
|
73
73
|
const applyPromise = applyDocumentActions(instance, {
|
|
74
74
|
actions: [action],
|
|
75
75
|
transactionId: 'txn-success',
|
|
76
|
-
|
|
76
|
+
resource: {projectId: 'p', dataset: 'd'},
|
|
77
77
|
})
|
|
78
78
|
|
|
79
79
|
const appliedTx: AppliedTransaction = {
|
|
@@ -131,7 +131,7 @@ describe('applyDocumentActions', () => {
|
|
|
131
131
|
const applyPromise = applyDocumentActions(instance, {
|
|
132
132
|
actions: [action],
|
|
133
133
|
transactionId: 'txn-error',
|
|
134
|
-
|
|
134
|
+
resource: {projectId: 'p', dataset: 'd'},
|
|
135
135
|
})
|
|
136
136
|
|
|
137
137
|
const errorEvent: DocumentEvent = {
|
|
@@ -165,7 +165,7 @@ describe('applyDocumentActions', () => {
|
|
|
165
165
|
const applyPromise = applyDocumentActions(childInstance, {
|
|
166
166
|
actions: [action],
|
|
167
167
|
transactionId: 'txn-child-match',
|
|
168
|
-
|
|
168
|
+
resource: {projectId: 'p', dataset: 'd'},
|
|
169
169
|
})
|
|
170
170
|
|
|
171
171
|
// Simulate an applied transaction on the parent's instance
|