@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.
Files changed (50) hide show
  1. package/dist/_chunks-dts/utils.d.ts +105 -51
  2. package/dist/_chunks-es/createGroqSearchFilter.js +131 -54
  3. package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -1
  4. package/dist/_chunks-es/version.js +1 -1
  5. package/dist/_exports/_internal.d.ts +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js +119 -73
  8. package/dist/index.js.map +1 -1
  9. package/package.json +8 -10
  10. package/src/_exports/index.ts +8 -0
  11. package/src/client/clientStore.test.ts +30 -30
  12. package/src/client/clientStore.ts +47 -47
  13. package/src/comlink/controller/actions/getOrCreateChannel.ts +2 -2
  14. package/src/comlink/node/actions/getOrCreateNode.ts +2 -2
  15. package/src/config/sanityConfig.ts +72 -12
  16. package/src/document/applyDocumentActions.test.ts +7 -7
  17. package/src/document/applyDocumentActions.ts +5 -5
  18. package/src/document/documentStore.test.ts +68 -62
  19. package/src/document/documentStore.ts +36 -36
  20. package/src/document/processActions.ts +2 -2
  21. package/src/document/reducers.ts +4 -4
  22. package/src/document/sharedListener.ts +7 -7
  23. package/src/presence/bifurTransport.test.ts +46 -6
  24. package/src/presence/bifurTransport.ts +13 -1
  25. package/src/presence/presenceStore.test.ts +96 -0
  26. package/src/presence/presenceStore.ts +96 -24
  27. package/src/preview/getPreviewState.ts +1 -1
  28. package/src/preview/previewProjectionUtils.test.ts +4 -4
  29. package/src/preview/previewProjectionUtils.ts +7 -7
  30. package/src/preview/resolvePreview.ts +5 -1
  31. package/src/projection/getProjectionState.ts +4 -4
  32. package/src/projection/projectionStore.test.ts +2 -2
  33. package/src/projection/resolveProjection.ts +2 -2
  34. package/src/projection/subscribeToStateAndFetchBatches.test.ts +1 -1
  35. package/src/projection/subscribeToStateAndFetchBatches.ts +12 -11
  36. package/src/query/queryStore.test.ts +12 -12
  37. package/src/query/queryStore.ts +10 -10
  38. package/src/query/reducers.ts +3 -3
  39. package/src/releases/getPerspectiveState.ts +5 -5
  40. package/src/releases/releasesStore.test.ts +6 -6
  41. package/src/releases/releasesStore.ts +9 -9
  42. package/src/store/createActionBinder.test.ts +31 -31
  43. package/src/store/createActionBinder.ts +43 -38
  44. package/src/store/createSanityInstance.ts +2 -3
  45. package/src/users/reducers.ts +3 -4
  46. package/src/utils/createFetcherStore.ts +6 -4
  47. package/src/utils/isImportError.test.ts +72 -0
  48. package/src/utils/isImportError.ts +34 -0
  49. package/src/utils/object.test.ts +95 -0
  50. 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.9.0",
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.14.1",
53
- "@sanity/comlink": "^3.0.4",
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.18.0",
59
+ "@sanity/message-protocol": "^0.23.0",
60
60
  "@sanity/mutate": "^0.16.1",
61
- "@sanity/telemetry": "^1.0.0",
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.4"
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/config-test": "0.0.1",
81
+ "@repo/tsconfig": "0.0.1",
84
82
  "@repo/package.bundle": "3.82.0",
85
83
  "@repo/package.config": "0.0.1",
86
- "@repo/tsconfig": "0.0.1"
84
+ "@repo/config-test": "0.0.1"
87
85
  },
88
86
  "engines": {
89
87
  "node": ">=20.19"
@@ -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('source handling', () => {
194
- it('should create client when source is provided', () => {
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
- source: {projectId: 'source-project', dataset: 'source-dataset'},
197
+ resource: {projectId: 'source-project', dataset: 'source-dataset'},
198
198
  })
199
199
 
200
200
  expect(vi.mocked(createClient)).toHaveBeenCalledWith(
201
201
  expect.objectContaining({
202
- 'apiVersion': '2024-11-12',
203
- '~experimental_resource': {type: 'dataset', id: 'source-project.source-dataset'},
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
- '~experimental_resource': {type: 'dataset', id: 'source-project.source-dataset'},
211
+ resource: {type: 'dataset', id: 'source-project.source-dataset'},
212
212
  }),
213
213
  )
214
214
  })
215
215
 
216
- it('should create resource when source has array sourceId and be projectless', () => {
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
- source: {mediaLibraryId: 'media-lib-123'},
219
+ resource: {mediaLibraryId: 'media-lib-123'},
220
220
  })
221
221
 
222
222
  expect(vi.mocked(createClient)).toHaveBeenCalledWith(
223
223
  expect.objectContaining({
224
- '~experimental_resource': {type: 'media-library', id: 'media-lib-123'},
225
- 'apiVersion': '2024-11-12',
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
- '~experimental_resource': {type: 'media-library', id: 'media-lib-123'},
233
+ resource: {type: 'media-library', id: 'media-lib-123'},
234
234
  }),
235
235
  )
236
236
  })
237
237
 
238
- it('should create resource when canvas source is provided and be projectless', () => {
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
- source: {canvasId: 'canvas-123'},
241
+ resource: {canvasId: 'canvas-123'},
242
242
  })
243
243
 
244
244
  expect(vi.mocked(createClient)).toHaveBeenCalledWith(
245
245
  expect.objectContaining({
246
- '~experimental_resource': {type: 'canvas', id: 'canvas-123'},
247
- 'apiVersion': '2024-11-12',
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
- '~experimental_resource': {type: 'canvas', id: 'canvas-123'},
255
+ resource: {type: 'canvas', id: 'canvas-123'},
256
256
  }),
257
257
  )
258
258
  })
259
259
 
260
- it('should create projectless client when source is provided, ignoring instance config', () => {
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
- source: {projectId: 'source-project', dataset: 'source-dataset'},
263
+ resource: {projectId: 'source-project', dataset: 'source-dataset'},
264
264
  })
265
265
 
266
- // Client should be projectless - source takes precedence, instance config is ignored
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
- '~experimental_resource': {type: 'dataset', id: 'source-project.source-dataset'},
271
+ resource: {type: 'dataset', id: 'source-project.source-dataset'},
272
272
  }),
273
273
  )
274
274
  })
275
275
 
276
- it('should warn when both source and explicit projectId/dataset are provided', () => {
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
- source: {projectId: 'source-project', dataset: 'source-dataset'},
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 source and explicit projectId/dataset are provided. The source will be used and projectId/dataset will be ignored.',
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 sources', () => {
294
+ it('should create different clients for different resources', () => {
295
295
  const client1 = getClient(instance, {
296
296
  apiVersion: '2024-11-12',
297
- source: {projectId: 'source-project', dataset: 'source-dataset'},
297
+ resource: {projectId: 'source-project', dataset: 'source-dataset'},
298
298
  })
299
299
  const client2 = getClient(instance, {
300
300
  apiVersion: '2024-11-12',
301
- source: {mediaLibraryId: 'media-lib-123'},
301
+ resource: {mediaLibraryId: 'media-lib-123'},
302
302
  })
303
303
  const client3 = getClient(instance, {
304
304
  apiVersion: '2024-11-12',
305
- source: {canvasId: 'canvas-123'},
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 source configurations', () => {
314
+ it('should reuse clients with identical resource configurations', () => {
315
315
  const client1 = getClient(instance, {
316
316
  apiVersion: '2024-11-12',
317
- source: {projectId: 'source-project', dataset: 'source-dataset'},
317
+ resource: {projectId: 'source-project', dataset: 'source-dataset'},
318
318
  })
319
319
  const client2 = getClient(instance, {
320
320
  apiVersion: '2024-11-12',
321
- source: {projectId: 'source-project', dataset: 'source-dataset'},
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 DocumentSource,
7
- isCanvasSource,
8
- isDatasetSource,
9
- isMediaLibrarySource,
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
- '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
- '~experimental_resource': null,
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
- 'scope'?: 'default' | 'global'
91
+ scope?: 'default' | 'global'
98
92
  /**
99
93
  * A required string indicating the API version for the client.
100
94
  */
101
- 'apiVersion': string
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
- 'source'?: DocumentSource
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
- const getClientConfigKey = (options: ClientOptions) => JSON.stringify(pick(options, ...allowedKeys))
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: ClientResource | undefined
182
+ let resource: ClientConfig['resource'] | undefined
186
183
 
187
- if (options.source) {
188
- if (isDatasetSource(options.source)) {
189
- resource = {type: 'dataset', id: `${options.source.projectId}.${options.source.dataset}`}
190
- } else if (isMediaLibrarySource(options.source)) {
191
- resource = {type: 'media-library', id: options.source.mediaLibraryId}
192
- } else if (isCanvasSource(options.source)) {
193
- resource = {type: 'canvas', id: options.source.canvasId}
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: ClientOptions = {
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 source is provided, don't use projectId/dataset - the client should be "projectless"
213
- // The client code itself will ignore the non-source config, so we do this to prevent confusing the user.
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 source and explicit projectId/dataset are provided. The source will be used and projectId/dataset will be ignored.',
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 (!isEqual(existing.options, options)) {
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 (!isEqual(existing.options, options)) {
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 source object to use for this operation.
76
+ * Explicit resource object to use for this operation.
77
77
  */
78
- source?: DocumentSource
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 sources to use for this instance.
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, DocumentSource>
160
+ sources?: Record<string, DocumentResource>
151
161
  }
152
162
 
153
163
  /**
154
- * A document source can be used for querying.
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 DocumentSource = DatasetSource | MediaLibrarySource | CanvasSource
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 = {projectId: string; dataset: string}
219
+ export type DatasetSource = DatasetResource
165
220
 
166
221
  /**
222
+ * @deprecated Use `MediaLibraryResource` instead.
167
223
  * @beta
168
224
  */
169
- export type MediaLibrarySource = {mediaLibraryId: string}
225
+ export type MediaLibrarySource = MediaLibraryResource
170
226
 
171
227
  /**
228
+ * @deprecated Use `CanvasResource` instead.
172
229
  * @beta
173
230
  */
174
- export type CanvasSource = {canvasId: string}
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 'projectId' in source && 'dataset' in source
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 'mediaLibraryId' in source
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 'canvasId' in source
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 {bindActionBySource} from '../store/createActionBinder'
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
- bindActionBySource: vi.fn(),
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', source: {projectId: 'p', dataset: 'd'}}
49
+ const key = {name: 'p.d', resource: {projectId: 'p', dataset: 'd'}}
50
50
 
51
- vi.mocked(bindActionBySource).mockImplementation(
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
- source: {projectId: 'p', dataset: 'd'},
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
- source: {projectId: 'p', dataset: 'd'},
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
- source: {projectId: 'p', dataset: 'd'},
168
+ resource: {projectId: 'p', dataset: 'd'},
169
169
  })
170
170
 
171
171
  // Simulate an applied transaction on the parent's instance