@sanity/sdk 2.7.0 → 3.0.0-rc.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/index.d.ts +228 -239
- package/dist/index.js +287 -454
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/_exports/index.ts +16 -17
- package/src/agent/agentActions.test.ts +60 -16
- package/src/agent/agentActions.ts +29 -20
- package/src/auth/authMode.test.ts +0 -25
- package/src/auth/authMode.ts +3 -6
- package/src/auth/authStore.test.ts +129 -66
- package/src/auth/authStore.ts +9 -11
- package/src/auth/dashboardAuth.ts +2 -2
- package/src/auth/getOrganizationVerificationState.test.ts +10 -11
- package/src/auth/handleAuthCallback.test.ts +0 -12
- package/src/auth/handleAuthCallback.ts +9 -3
- package/src/auth/logout.test.ts +0 -6
- package/src/auth/refreshStampedToken.test.ts +121 -17
- package/src/auth/standaloneAuth.ts +9 -3
- package/src/auth/studioAuth.ts +35 -8
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +9 -3
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +1 -1
- package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +0 -2
- package/src/auth/subscribeToStorageEventsAndSetToken.ts +2 -2
- package/src/auth/utils.ts +33 -0
- package/src/client/clientStore.test.ts +14 -61
- package/src/client/clientStore.ts +52 -28
- package/src/comlink/controller/actions/destroyController.test.ts +1 -4
- package/src/comlink/controller/actions/getOrCreateChannel.test.ts +1 -4
- package/src/comlink/controller/actions/getOrCreateController.test.ts +1 -4
- package/src/comlink/controller/actions/releaseChannel.test.ts +1 -1
- package/src/comlink/controller/comlinkControllerStore.test.ts +1 -4
- package/src/comlink/node/actions/getOrCreateNode.test.ts +1 -4
- package/src/comlink/node/actions/releaseNode.test.ts +1 -4
- package/src/comlink/node/comlinkNodeStore.test.ts +2 -2
- package/src/comlink/node/getNodeState.test.ts +1 -1
- package/src/config/__tests__/handles.test.ts +12 -18
- package/src/config/handles.ts +7 -25
- package/src/config/sanityConfig.ts +99 -52
- package/src/datasets/datasets.test.ts +2 -2
- package/src/datasets/datasets.ts +4 -10
- package/src/document/actions.test.ts +33 -4
- package/src/document/actions.ts +3 -10
- package/src/document/applyDocumentActions.test.ts +17 -18
- package/src/document/applyDocumentActions.ts +9 -12
- package/src/document/documentStore.test.ts +303 -133
- package/src/document/documentStore.ts +70 -61
- package/src/document/permissions.test.ts +44 -8
- package/src/document/processActions.test.ts +77 -7
- package/src/document/reducers.test.ts +35 -3
- package/src/document/sharedListener.test.ts +13 -13
- package/src/document/sharedListener.ts +8 -3
- package/src/favorites/favorites.test.ts +10 -2
- package/src/presence/presenceStore.test.ts +34 -9
- package/src/presence/presenceStore.ts +29 -13
- package/src/preview/previewProjectionUtils.test.ts +192 -0
- package/src/preview/previewProjectionUtils.ts +88 -0
- package/src/preview/{previewStore.ts → types.ts} +6 -25
- package/src/project/project.test.ts +1 -1
- package/src/project/project.ts +14 -20
- package/src/projection/getProjectionState.test.ts +4 -2
- package/src/projection/getProjectionState.ts +2 -21
- package/src/projection/projectionQuery.ts +2 -3
- package/src/projection/projectionStore.test.ts +3 -3
- package/src/projection/resolveProjection.test.ts +2 -1
- package/src/projection/resolveProjection.ts +2 -18
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +2 -2
- package/src/projection/subscribeToStateAndFetchBatches.ts +23 -36
- package/src/projection/types.ts +1 -9
- package/src/projects/projects.test.ts +1 -1
- package/src/query/queryStore.test.ts +86 -28
- package/src/query/queryStore.ts +23 -38
- package/src/releases/getPerspectiveState.test.ts +14 -13
- package/src/releases/getPerspectiveState.ts +6 -6
- package/src/releases/releasesStore.test.ts +21 -6
- package/src/releases/releasesStore.ts +18 -8
- package/src/store/createActionBinder.test.ts +114 -111
- package/src/store/createActionBinder.ts +52 -101
- package/src/store/createSanityInstance.test.ts +13 -83
- package/src/store/createSanityInstance.ts +2 -78
- package/src/store/createStateSourceAction.test.ts +2 -2
- package/src/store/createStateSourceAction.ts +5 -5
- package/src/store/createStoreInstance.test.ts +2 -4
- package/src/users/reducers.test.ts +1 -6
- package/src/users/reducers.ts +2 -2
- package/src/users/types.ts +4 -4
- package/src/users/usersStore.test.ts +12 -15
- package/src/utils/createFetcherStore.test.ts +1 -1
- package/src/utils/logger.test.ts +0 -12
- package/src/utils/logger.ts +3 -8
- package/src/preview/getPreviewState.test.ts +0 -120
- package/src/preview/getPreviewState.ts +0 -91
- package/src/preview/previewQuery.test.ts +0 -236
- package/src/preview/previewQuery.ts +0 -153
- package/src/preview/previewStore.test.ts +0 -36
- package/src/preview/resolvePreview.test.ts +0 -47
- package/src/preview/resolvePreview.ts +0 -20
- package/src/preview/subscribeToStateAndFetchBatches.test.ts +0 -221
- package/src/preview/subscribeToStateAndFetchBatches.ts +0 -112
- package/src/preview/util.ts +0 -13
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ClientConfig,
|
|
3
|
+
type ClientPerspective,
|
|
4
|
+
createClient,
|
|
5
|
+
type SanityClient,
|
|
6
|
+
} from '@sanity/client'
|
|
2
7
|
import {pick} from 'lodash-es'
|
|
3
8
|
|
|
4
9
|
import {getAuthMethodState, getTokenState} from '../auth/authStore'
|
|
5
10
|
import {
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
type DocumentResource,
|
|
12
|
+
isCanvasResource,
|
|
13
|
+
isDatasetResource,
|
|
14
|
+
isMediaLibraryResource,
|
|
10
15
|
} from '../config/sanityConfig'
|
|
11
16
|
import {bindActionGlobally} from '../store/createActionBinder'
|
|
12
17
|
import {createStateSourceAction} from '../store/createStateSourceAction'
|
|
@@ -45,16 +50,16 @@ const allowedKeys = Object.keys({
|
|
|
45
50
|
'requestTagPrefix': null,
|
|
46
51
|
'useProjectHostname': null,
|
|
47
52
|
'~experimental_resource': null,
|
|
48
|
-
'
|
|
53
|
+
'resource': null,
|
|
49
54
|
} satisfies Record<keyof ClientOptions, null>) as (keyof ClientOptions)[]
|
|
50
55
|
|
|
51
|
-
const DEFAULT_CLIENT_CONFIG
|
|
56
|
+
const DEFAULT_CLIENT_CONFIG = {
|
|
52
57
|
apiVersion: DEFAULT_API_VERSION,
|
|
53
58
|
useCdn: false,
|
|
54
59
|
ignoreBrowserTokenWarning: true,
|
|
55
60
|
allowReconfigure: false,
|
|
56
61
|
requestTagPrefix: DEFAULT_REQUEST_TAG_PREFIX,
|
|
57
|
-
}
|
|
62
|
+
} satisfies ClientConfig
|
|
58
63
|
|
|
59
64
|
/**
|
|
60
65
|
* States tracked by the client store
|
|
@@ -87,7 +92,15 @@ interface ClientResource {
|
|
|
87
92
|
*
|
|
88
93
|
* @public
|
|
89
94
|
*/
|
|
90
|
-
export interface ClientOptions extends
|
|
95
|
+
export interface ClientOptions extends Omit<
|
|
96
|
+
Pick<ClientConfig, AllowedClientConfigKey>,
|
|
97
|
+
'resource'
|
|
98
|
+
> {
|
|
99
|
+
/**
|
|
100
|
+
* Narrows the inherited `perspective` to exclude stackable perspectives,
|
|
101
|
+
* which are not supported by the SDK.
|
|
102
|
+
*/
|
|
103
|
+
'perspective'?: Exclude<ClientPerspective, readonly unknown[]>
|
|
91
104
|
/**
|
|
92
105
|
* An optional flag to choose between the default client (typically project-level)
|
|
93
106
|
* and the global client ('global'). When set to `'global'`, the global client
|
|
@@ -106,7 +119,7 @@ export interface ClientOptions extends Pick<ClientConfig, AllowedClientConfigKey
|
|
|
106
119
|
/**
|
|
107
120
|
* @internal
|
|
108
121
|
*/
|
|
109
|
-
'
|
|
122
|
+
'resource'?: DocumentResource
|
|
110
123
|
}
|
|
111
124
|
|
|
112
125
|
const clientStore = defineStore<ClientStoreState>({
|
|
@@ -182,22 +195,27 @@ export const getClient = bindActionGlobally(
|
|
|
182
195
|
const {clients, authMethod} = state.get()
|
|
183
196
|
|
|
184
197
|
let resource: ClientResource | undefined
|
|
198
|
+
let projectId: string | undefined = options.projectId
|
|
199
|
+
let dataset: string | undefined = options.dataset
|
|
185
200
|
|
|
186
|
-
if (options.
|
|
187
|
-
if (
|
|
188
|
-
resource = {type: '
|
|
189
|
-
} else if (
|
|
190
|
-
resource = {type: '
|
|
191
|
-
} else if (
|
|
192
|
-
|
|
201
|
+
if (options.resource) {
|
|
202
|
+
if (isMediaLibraryResource(options.resource)) {
|
|
203
|
+
resource = {type: 'media-library', id: options.resource.mediaLibraryId}
|
|
204
|
+
} else if (isCanvasResource(options.resource)) {
|
|
205
|
+
resource = {type: 'canvas', id: options.resource.canvasId}
|
|
206
|
+
} else if (isDatasetResource(options.resource)) {
|
|
207
|
+
projectId = options.resource.projectId
|
|
208
|
+
dataset = options.resource.dataset
|
|
193
209
|
}
|
|
210
|
+
// temporarily excluding dataset resource as a resource for now. Many of the global API endpoints require vX api version.
|
|
211
|
+
// When ready, remove the above check and uncomment the below check.
|
|
212
|
+
// } else if (isDatasetResource(options.resource)) {
|
|
213
|
+
// resource = {type: 'dataset', id: `${options.resource.projectId}.${options.resource.dataset}`}
|
|
194
214
|
}
|
|
195
215
|
|
|
196
|
-
const projectId = options.projectId ?? instance.config.projectId
|
|
197
|
-
const dataset = options.dataset ?? instance.config.dataset
|
|
198
216
|
const apiHost = options.apiHost ?? instance.config.auth?.apiHost
|
|
199
217
|
|
|
200
|
-
const effectiveOptions
|
|
218
|
+
const effectiveOptions = {
|
|
201
219
|
...DEFAULT_CLIENT_CONFIG,
|
|
202
220
|
...((options.scope === 'global' || !projectId || resource) && {useProjectHostname: false}),
|
|
203
221
|
token: authMethod === 'cookie' ? undefined : (tokenFromState ?? undefined),
|
|
@@ -206,20 +224,23 @@ export const getClient = bindActionGlobally(
|
|
|
206
224
|
...(dataset && {dataset}),
|
|
207
225
|
...(apiHost && {apiHost}),
|
|
208
226
|
...(resource && {'~experimental_resource': resource}),
|
|
209
|
-
}
|
|
227
|
+
} as ClientOptions
|
|
210
228
|
|
|
211
|
-
// When a
|
|
212
|
-
// The client code itself will ignore the non-
|
|
229
|
+
// When a MediaLibrary or Canvas resource is provided, don't use projectId/dataset - the client should be "projectless"
|
|
230
|
+
// The client code itself will ignore the non-resource config, so we do this to prevent confusing the user.
|
|
213
231
|
// (ref: https://github.com/sanity-io/client/blob/5c23f81f5ab93a53f5b22b39845c867988508d84/src/data/dataMethods.ts#L691)
|
|
214
|
-
|
|
232
|
+
// Note: DatasetResource is handled differently - it extracts projectId/dataset from the resource and uses those
|
|
233
|
+
if (options.resource) {
|
|
215
234
|
if (options.projectId || options.dataset) {
|
|
216
235
|
// eslint-disable-next-line no-console
|
|
217
236
|
console.warn(
|
|
218
|
-
'Both
|
|
237
|
+
'Both resource and explicit projectId/dataset are provided. The resource will be used and projectId/dataset will be ignored.',
|
|
219
238
|
)
|
|
220
239
|
}
|
|
221
|
-
|
|
222
|
-
|
|
240
|
+
if (resource) {
|
|
241
|
+
delete effectiveOptions.projectId
|
|
242
|
+
delete effectiveOptions.dataset
|
|
243
|
+
}
|
|
223
244
|
}
|
|
224
245
|
|
|
225
246
|
if (effectiveOptions.token === null || typeof effectiveOptions.token === 'undefined') {
|
|
@@ -231,11 +252,14 @@ export const getClient = bindActionGlobally(
|
|
|
231
252
|
delete effectiveOptions.withCredentials
|
|
232
253
|
}
|
|
233
254
|
|
|
255
|
+
// Don't pass our DocumentResource to createClient - we've already derived projectId/dataset or ~experimental_resource
|
|
256
|
+
const {resource: _omitResource, ...clientConfig} = effectiveOptions
|
|
257
|
+
|
|
234
258
|
const key = getClientConfigKey(effectiveOptions)
|
|
235
259
|
|
|
236
260
|
if (clients[key]) return clients[key]
|
|
237
261
|
|
|
238
|
-
const client = createClient(
|
|
262
|
+
const client = createClient(clientConfig as ClientConfig)
|
|
239
263
|
state.set('addClient', (prev) => ({clients: {...prev.clients, [key]: client}}))
|
|
240
264
|
|
|
241
265
|
return client
|
|
@@ -7,10 +7,7 @@ import {type ComlinkControllerState} from '../comlinkControllerStore'
|
|
|
7
7
|
import {destroyController} from './destroyController'
|
|
8
8
|
|
|
9
9
|
describe('destroyController', () => {
|
|
10
|
-
const instance = createSanityInstance(
|
|
11
|
-
projectId: 'test-project-id',
|
|
12
|
-
dataset: 'test-dataset',
|
|
13
|
-
})
|
|
10
|
+
const instance = createSanityInstance()
|
|
14
11
|
let state: ReturnType<typeof createStoreState<ComlinkControllerState>>
|
|
15
12
|
let mockController: {destroy: ReturnType<typeof vi.fn>}
|
|
16
13
|
|
|
@@ -13,10 +13,7 @@ const channelConfig = {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
describe('getOrCreateChannel', () => {
|
|
16
|
-
const instance = createSanityInstance(
|
|
17
|
-
projectId: 'test-project-id',
|
|
18
|
-
dataset: 'test-dataset',
|
|
19
|
-
})
|
|
16
|
+
const instance = createSanityInstance()
|
|
20
17
|
let state: ReturnType<typeof createStoreState<ComlinkControllerState>>
|
|
21
18
|
let mockController: Partial<Controller>
|
|
22
19
|
let mockChannel: Partial<ChannelInstance<FrameMessage, WindowMessage>>
|
|
@@ -21,10 +21,7 @@ describe('getOrCreateController', () => {
|
|
|
21
21
|
let state: ReturnType<typeof createStoreState<ComlinkControllerState>>
|
|
22
22
|
|
|
23
23
|
beforeEach(() => {
|
|
24
|
-
instance = createSanityInstance(
|
|
25
|
-
projectId: 'test-project-id',
|
|
26
|
-
dataset: 'test-dataset',
|
|
27
|
-
})
|
|
24
|
+
instance = createSanityInstance()
|
|
28
25
|
|
|
29
26
|
state = createStoreState<ComlinkControllerState>({
|
|
30
27
|
controller: null,
|
|
@@ -29,7 +29,7 @@ describe('releaseChannel', () => {
|
|
|
29
29
|
let releaseChannel: (inst: SanityInstance, channelName: string) => void
|
|
30
30
|
|
|
31
31
|
beforeEach(() => {
|
|
32
|
-
instance = createSanityInstance(
|
|
32
|
+
instance = createSanityInstance()
|
|
33
33
|
store = createStoreInstance(instance, key, comlinkControllerStore)
|
|
34
34
|
|
|
35
35
|
const bind =
|
|
@@ -16,10 +16,7 @@ describe('comlinkControllerStore', () => {
|
|
|
16
16
|
let instance: SanityInstance
|
|
17
17
|
beforeEach(() => {
|
|
18
18
|
vi.resetModules()
|
|
19
|
-
instance = createSanityInstance(
|
|
20
|
-
projectId: 'test-project-id',
|
|
21
|
-
dataset: 'test-dataset',
|
|
22
|
-
})
|
|
19
|
+
instance = createSanityInstance()
|
|
23
20
|
})
|
|
24
21
|
|
|
25
22
|
afterEach(() => {
|
|
@@ -22,10 +22,7 @@ const nodeConfig = {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
describe('getOrCreateNode', () => {
|
|
25
|
-
const instance = createSanityInstance(
|
|
26
|
-
projectId: 'test-project-id',
|
|
27
|
-
dataset: 'test-dataset',
|
|
28
|
-
})
|
|
25
|
+
const instance = createSanityInstance()
|
|
29
26
|
let state: ReturnType<typeof createStoreState<ComlinkNodeState>>
|
|
30
27
|
let mockNode: Partial<Node<WindowMessage, FrameMessage>> & {
|
|
31
28
|
start: ReturnType<typeof vi.fn>
|
|
@@ -22,10 +22,7 @@ describe('releaseNode', () => {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
beforeEach(() => {
|
|
25
|
-
instance = createSanityInstance(
|
|
26
|
-
projectId: 'test-project-id',
|
|
27
|
-
dataset: 'test-dataset',
|
|
28
|
-
})
|
|
25
|
+
instance = createSanityInstance()
|
|
29
26
|
mockNode = {start: vi.fn(), stop: vi.fn(), onStatus: vi.fn()}
|
|
30
27
|
state = createStoreState<ComlinkNodeState>({nodes: new Map(), subscriptions: new Map()})
|
|
31
28
|
vi.clearAllMocks()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {type Node} from '@sanity/comlink'
|
|
2
|
-
import {beforeEach, describe, expect, it} from 'vitest'
|
|
2
|
+
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
3
3
|
|
|
4
4
|
import {createSanityInstance, type SanityInstance} from '../../store/createSanityInstance'
|
|
5
5
|
import {createStoreState} from '../../store/createStoreState'
|
|
@@ -10,7 +10,7 @@ describe('nodeStore', () => {
|
|
|
10
10
|
let instance: SanityInstance
|
|
11
11
|
|
|
12
12
|
beforeEach(() => {
|
|
13
|
-
instance = createSanityInstance(
|
|
13
|
+
instance = createSanityInstance()
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
it('should have correct initial state', () => {
|
|
@@ -1,30 +1,24 @@
|
|
|
1
1
|
import {describe, expect, it} from 'vitest'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
createDatasetHandle,
|
|
5
|
-
createDocumentHandle,
|
|
6
|
-
createDocumentTypeHandle,
|
|
7
|
-
createProjectHandle,
|
|
8
|
-
} from '../handles'
|
|
3
|
+
import {createDocumentHandle, createDocumentTypeHandle, createResourceHandle} from '../handles'
|
|
9
4
|
|
|
10
5
|
describe('handle creation functions', () => {
|
|
11
|
-
it('createProjectHandle returns input', () => {
|
|
12
|
-
const input = {projectId: 'test'}
|
|
13
|
-
expect(createProjectHandle(input)).toBe(input)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('createDatasetHandle returns input', () => {
|
|
17
|
-
const input = {projectId: 'test', dataset: 'prod'}
|
|
18
|
-
expect(createDatasetHandle(input)).toBe(input)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
6
|
it('createDocumentTypeHandle returns input', () => {
|
|
22
|
-
const input = {documentType: 'movie'}
|
|
7
|
+
const input = {documentType: 'movie', resource: {projectId: 'p', dataset: 'd'}}
|
|
23
8
|
expect(createDocumentTypeHandle(input)).toBe(input)
|
|
24
9
|
})
|
|
25
10
|
|
|
26
11
|
it('createDocumentHandle returns input', () => {
|
|
27
|
-
const input = {
|
|
12
|
+
const input = {
|
|
13
|
+
documentType: 'movie',
|
|
14
|
+
documentId: '123',
|
|
15
|
+
resource: {projectId: 'p', dataset: 'd'},
|
|
16
|
+
}
|
|
28
17
|
expect(createDocumentHandle(input)).toBe(input)
|
|
29
18
|
})
|
|
19
|
+
|
|
20
|
+
it('createResourceHandle returns input', () => {
|
|
21
|
+
const input = {resource: {projectId: 'p', dataset: 'd'}}
|
|
22
|
+
expect(createResourceHandle(input)).toBe(input)
|
|
23
|
+
})
|
|
30
24
|
})
|
package/src/config/handles.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type DatasetHandle,
|
|
3
|
-
type DocumentHandle,
|
|
4
|
-
type DocumentTypeHandle,
|
|
5
|
-
type ProjectHandle,
|
|
6
|
-
} from './sanityConfig'
|
|
1
|
+
import {type DocumentHandle, type DocumentTypeHandle, type ResourceHandle} from './sanityConfig'
|
|
7
2
|
|
|
8
3
|
/**
|
|
9
4
|
* Creates or validates a `DocumentHandle` object.
|
|
@@ -40,28 +35,15 @@ export function createDocumentTypeHandle<
|
|
|
40
35
|
}
|
|
41
36
|
|
|
42
37
|
/**
|
|
43
|
-
* Creates or validates a `
|
|
44
|
-
* Ensures the provided object conforms to the `
|
|
45
|
-
* @param handle - The object containing
|
|
46
|
-
* @returns The validated `
|
|
38
|
+
* Creates or validates a `ResourceHandle` object.
|
|
39
|
+
* Ensures the provided object conforms to the `ResourceHandle` interface.
|
|
40
|
+
* @param handle - The object containing resource identification properties.
|
|
41
|
+
* @returns The validated `ResourceHandle` object.
|
|
47
42
|
* @public
|
|
48
43
|
*/
|
|
49
|
-
export function
|
|
50
|
-
handle: ProjectHandle<TProjectId>,
|
|
51
|
-
): ProjectHandle<TProjectId> {
|
|
52
|
-
return handle
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Creates or validates a `DatasetHandle` object.
|
|
57
|
-
* Ensures the provided object conforms to the `DatasetHandle` interface.
|
|
58
|
-
* @param handle - The object containing dataset identification properties.
|
|
59
|
-
* @returns The validated `DatasetHandle` object.
|
|
60
|
-
* @public
|
|
61
|
-
*/
|
|
62
|
-
export function createDatasetHandle<
|
|
44
|
+
export function createResourceHandle<
|
|
63
45
|
TDataset extends string = string,
|
|
64
46
|
TProjectId extends string = string,
|
|
65
|
-
>(handle:
|
|
47
|
+
>(handle: ResourceHandle<TProjectId, TDataset>): ResourceHandle<TProjectId, TDataset> {
|
|
66
48
|
return handle
|
|
67
49
|
}
|
|
@@ -23,6 +23,12 @@ export interface TokenSource {
|
|
|
23
23
|
* @public
|
|
24
24
|
*/
|
|
25
25
|
export interface StudioConfig {
|
|
26
|
+
/**
|
|
27
|
+
* Whether the Studio has already determined the user is authenticated.
|
|
28
|
+
* When `true` and the token source emits `null`, the SDK infers
|
|
29
|
+
* cookie-based auth is in use rather than transitioning to logged-out.
|
|
30
|
+
*/
|
|
31
|
+
authenticated?: boolean
|
|
26
32
|
/** Reactive auth token source from the Studio's auth store. */
|
|
27
33
|
auth?: {
|
|
28
34
|
/**
|
|
@@ -34,14 +40,12 @@ export interface StudioConfig {
|
|
|
34
40
|
*/
|
|
35
41
|
token?: TokenSource
|
|
36
42
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
export interface ProjectHandle<TProjectId extends string = string> {
|
|
44
|
-
projectId?: TProjectId
|
|
43
|
+
/**
|
|
44
|
+
* The project ID for this Studio workspace.
|
|
45
|
+
* Used to derive the localStorage key for studio auth token discovery
|
|
46
|
+
* (`__studio_auth_token_<projectId>`) and for project-specific API hostname requests.
|
|
47
|
+
*/
|
|
48
|
+
projectId?: string
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
/**
|
|
@@ -56,20 +60,27 @@ export type ReleasePerspective = {
|
|
|
56
60
|
* @public
|
|
57
61
|
*/
|
|
58
62
|
export interface PerspectiveHandle {
|
|
59
|
-
|
|
63
|
+
/**
|
|
64
|
+
* The perspective to use for this operation.
|
|
65
|
+
* Note that the SDK stacks perspectives for you when querying.
|
|
66
|
+
* The SDK automatically fetches all of your content releases, and orders them the way the Sanity Studio does: usually by scheduled date, with ASAP releases coming first.
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
perspective?: Exclude<ClientPerspective, readonly unknown[]> | ReleasePerspective
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
/**
|
|
63
73
|
* @public
|
|
64
74
|
*/
|
|
65
|
-
export interface
|
|
66
|
-
extends
|
|
67
|
-
|
|
75
|
+
export interface ResourceHandle<
|
|
76
|
+
TProjectId extends string = string,
|
|
77
|
+
TDataset extends string = string,
|
|
78
|
+
> extends PerspectiveHandle {
|
|
68
79
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
80
|
+
* Explicit resource object to use for this operation.
|
|
81
|
+
* @public
|
|
71
82
|
*/
|
|
72
|
-
|
|
83
|
+
resource: DocumentResource<TProjectId, TDataset>
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
/**
|
|
@@ -82,7 +93,7 @@ export interface DocumentTypeHandle<
|
|
|
82
93
|
TDocumentType extends string = string,
|
|
83
94
|
TDataset extends string = string,
|
|
84
95
|
TProjectId extends string = string,
|
|
85
|
-
> extends
|
|
96
|
+
> extends ResourceHandle<TDataset, TProjectId> {
|
|
86
97
|
documentId?: string
|
|
87
98
|
documentType: TDocumentType
|
|
88
99
|
/**
|
|
@@ -108,13 +119,44 @@ export interface DocumentHandle<
|
|
|
108
119
|
}
|
|
109
120
|
|
|
110
121
|
/**
|
|
111
|
-
*
|
|
122
|
+
* The key used to identify the default resource in a resources map.
|
|
123
|
+
* When no `resource` or `resourceName` is specified, the SDK resolves
|
|
124
|
+
* the resource registered under this name.
|
|
125
|
+
*
|
|
112
126
|
* @public
|
|
113
127
|
*/
|
|
114
|
-
export
|
|
128
|
+
export const DEFAULT_RESOURCE_NAME = 'default'
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Represents the complete configuration for a Sanity SDK instance.
|
|
132
|
+
*
|
|
133
|
+
* Most apps configure resources via the `resources` prop on `SanityApp`:
|
|
134
|
+
*
|
|
135
|
+
* @example Typical React usage
|
|
136
|
+
* ```tsx
|
|
137
|
+
* <SanityApp
|
|
138
|
+
* resources={{ default: { projectId: 'abc123', dataset: 'production' } }}
|
|
139
|
+
* fallback={<Loading />}
|
|
140
|
+
* >
|
|
141
|
+
* <App />
|
|
142
|
+
* </SanityApp>
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* The `defaultResource` field is set automatically by the React layer from
|
|
146
|
+
* `resources['default']`. It can also be set directly when using the core
|
|
147
|
+
* SDK without React (e.g. in a Node.js script):
|
|
148
|
+
*
|
|
149
|
+
* @example Direct core usage (without React)
|
|
150
|
+
* ```ts
|
|
151
|
+
* const instance = createSanityInstance({
|
|
152
|
+
* defaultResource: { projectId: 'abc123', dataset: 'production' },
|
|
153
|
+
* })
|
|
154
|
+
* ```
|
|
155
|
+
* @public
|
|
156
|
+
*/
|
|
157
|
+
export interface SanityConfig extends PerspectiveHandle {
|
|
115
158
|
/**
|
|
116
159
|
* Authentication configuration for the instance
|
|
117
|
-
* @remarks Merged with parent configurations when using createChild
|
|
118
160
|
*/
|
|
119
161
|
auth?: AuthConfig
|
|
120
162
|
/**
|
|
@@ -126,64 +168,69 @@ export interface SanityConfig extends DatasetHandle, PerspectiveHandle {
|
|
|
126
168
|
* `SDKStudioContext` provider. Can also be set explicitly for programmatic use.
|
|
127
169
|
*/
|
|
128
170
|
studio?: StudioConfig
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Studio mode configuration for use of the SDK in a Sanity Studio.
|
|
132
|
-
* @remarks Controls whether studio mode features are enabled.
|
|
133
|
-
* @deprecated Use `studio` instead, which provides richer integration
|
|
134
|
-
* with the Studio's workspace (auth token sync, etc.).
|
|
135
|
-
*/
|
|
136
|
-
studioMode?: {
|
|
137
|
-
enabled: boolean
|
|
138
|
-
}
|
|
139
|
-
|
|
140
171
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
172
|
+
* The default document resource for this instance. Used by bound actions
|
|
173
|
+
* when no explicit resource is provided.
|
|
174
|
+
*
|
|
175
|
+
* @public
|
|
143
176
|
*/
|
|
144
|
-
|
|
177
|
+
defaultResource?: DocumentResource
|
|
145
178
|
}
|
|
146
179
|
|
|
147
180
|
/**
|
|
148
|
-
* A document
|
|
149
|
-
*
|
|
181
|
+
* A document resource identifies where data is stored and queried from.
|
|
182
|
+
* Can be a dataset (project + dataset pair), a media library, or a canvas.
|
|
150
183
|
*
|
|
151
|
-
* @
|
|
184
|
+
* @public
|
|
152
185
|
*/
|
|
153
|
-
export type
|
|
186
|
+
export type DocumentResource<
|
|
187
|
+
TProjectId extends string = string,
|
|
188
|
+
TDataset extends string = string,
|
|
189
|
+
> = DatasetResource<TProjectId, TDataset> | MediaLibraryResource | CanvasResource
|
|
154
190
|
|
|
155
191
|
/**
|
|
156
|
-
*
|
|
192
|
+
* A resource that targets a specific project and dataset.
|
|
193
|
+
* @public
|
|
157
194
|
*/
|
|
158
|
-
export type
|
|
195
|
+
export type DatasetResource<
|
|
196
|
+
TProjectId extends string = string,
|
|
197
|
+
TDataset extends string = string,
|
|
198
|
+
> = {projectId: TProjectId; dataset: TDataset}
|
|
159
199
|
|
|
160
200
|
/**
|
|
161
|
-
*
|
|
201
|
+
* A resource that targets a media library.
|
|
202
|
+
* @public
|
|
162
203
|
*/
|
|
163
|
-
export type
|
|
204
|
+
export type MediaLibraryResource = {mediaLibraryId: string}
|
|
164
205
|
|
|
165
206
|
/**
|
|
166
|
-
*
|
|
207
|
+
* A resource that targets a canvas.
|
|
208
|
+
* @public
|
|
167
209
|
*/
|
|
168
|
-
export type
|
|
210
|
+
export type CanvasResource = {canvasId: string}
|
|
169
211
|
|
|
170
212
|
/**
|
|
171
|
-
* @
|
|
213
|
+
* Type guard that checks whether a {@link DocumentResource} is a {@link DatasetResource}.
|
|
214
|
+
* @public
|
|
172
215
|
*/
|
|
173
|
-
export function
|
|
174
|
-
return 'projectId' in
|
|
216
|
+
export function isDatasetResource(resource: DocumentResource): resource is DatasetResource {
|
|
217
|
+
return 'projectId' in resource && 'dataset' in resource
|
|
175
218
|
}
|
|
176
219
|
|
|
177
220
|
/**
|
|
178
|
-
* @
|
|
221
|
+
* Type guard that checks whether a {@link DocumentResource} is a {@link MediaLibraryResource}.
|
|
222
|
+
* @public
|
|
179
223
|
*/
|
|
180
|
-
export function
|
|
181
|
-
|
|
224
|
+
export function isMediaLibraryResource(
|
|
225
|
+
resource: DocumentResource,
|
|
226
|
+
): resource is MediaLibraryResource {
|
|
227
|
+
return 'mediaLibraryId' in resource
|
|
182
228
|
}
|
|
183
229
|
|
|
184
230
|
/**
|
|
185
|
-
* @
|
|
231
|
+
* Type guard that checks whether a {@link DocumentResource} is a {@link CanvasResource}.
|
|
232
|
+
* @public
|
|
186
233
|
*/
|
|
187
|
-
export function
|
|
188
|
-
return 'canvasId' in
|
|
234
|
+
export function isCanvasResource(resource: DocumentResource): resource is CanvasResource {
|
|
235
|
+
return 'canvasId' in resource
|
|
189
236
|
}
|
|
@@ -11,7 +11,7 @@ vi.mock('../client/clientStore')
|
|
|
11
11
|
|
|
12
12
|
describe('datasets', () => {
|
|
13
13
|
it('calls the `client.observable.datasets.list` method on the client and returns the result', async () => {
|
|
14
|
-
const instance = createSanityInstance(
|
|
14
|
+
const instance = createSanityInstance()
|
|
15
15
|
const datasets = [{id: 'a'}, {id: 'b'}]
|
|
16
16
|
const list = vi.fn().mockReturnValue(of(datasets))
|
|
17
17
|
|
|
@@ -25,7 +25,7 @@ describe('datasets', () => {
|
|
|
25
25
|
observable: of(mockClient),
|
|
26
26
|
} as StateSource<SanityClient>)
|
|
27
27
|
|
|
28
|
-
const result = await resolveDatasets(instance)
|
|
28
|
+
const result = await resolveDatasets(instance, {projectId: 'p'})
|
|
29
29
|
expect(result).toEqual(datasets)
|
|
30
30
|
expect(list).toHaveBeenCalled()
|
|
31
31
|
})
|
package/src/datasets/datasets.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {switchMap} from 'rxjs'
|
|
2
2
|
|
|
3
3
|
import {getClientState} from '../client/clientStore'
|
|
4
|
-
import {type ProjectHandle} from '../config/sanityConfig'
|
|
5
4
|
import {createFetcherStore} from '../utils/createFetcherStore'
|
|
6
5
|
|
|
7
6
|
const API_VERSION = 'v2025-02-19'
|
|
@@ -9,18 +8,13 @@ const API_VERSION = 'v2025-02-19'
|
|
|
9
8
|
/** @public */
|
|
10
9
|
export const datasets = createFetcherStore({
|
|
11
10
|
name: 'Datasets',
|
|
12
|
-
getKey: (
|
|
13
|
-
|
|
14
|
-
if (!projectId) {
|
|
15
|
-
throw new Error('A projectId is required to use the project API.')
|
|
16
|
-
}
|
|
17
|
-
return projectId
|
|
11
|
+
getKey: (_instance, options: {projectId: string}) => {
|
|
12
|
+
return options.projectId
|
|
18
13
|
},
|
|
19
|
-
fetcher: (instance) => (options
|
|
14
|
+
fetcher: (instance) => (options: {projectId: string}) => {
|
|
20
15
|
return getClientState(instance, {
|
|
21
16
|
apiVersion: API_VERSION,
|
|
22
|
-
|
|
23
|
-
projectId: (options?.projectId ?? instance.config.projectId)!,
|
|
17
|
+
projectId: options.projectId,
|
|
24
18
|
useProjectHostname: true,
|
|
25
19
|
}).observable.pipe(switchMap((client) => client.observable.datasets.list()))
|
|
26
20
|
},
|