@sanity/sdk 2.8.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.
Files changed (99) hide show
  1. package/dist/index.d.ts +228 -239
  2. package/dist/index.js +287 -454
  3. package/dist/index.js.map +1 -1
  4. package/package.json +4 -4
  5. package/src/_exports/index.ts +16 -17
  6. package/src/agent/agentActions.test.ts +60 -16
  7. package/src/agent/agentActions.ts +29 -20
  8. package/src/auth/authMode.test.ts +0 -25
  9. package/src/auth/authMode.ts +3 -6
  10. package/src/auth/authStore.test.ts +129 -66
  11. package/src/auth/authStore.ts +9 -11
  12. package/src/auth/dashboardAuth.ts +2 -2
  13. package/src/auth/getOrganizationVerificationState.test.ts +10 -11
  14. package/src/auth/handleAuthCallback.test.ts +0 -12
  15. package/src/auth/handleAuthCallback.ts +9 -3
  16. package/src/auth/logout.test.ts +0 -6
  17. package/src/auth/refreshStampedToken.test.ts +121 -17
  18. package/src/auth/standaloneAuth.ts +9 -3
  19. package/src/auth/studioAuth.ts +35 -8
  20. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +9 -3
  21. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +1 -1
  22. package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +0 -2
  23. package/src/auth/subscribeToStorageEventsAndSetToken.ts +2 -2
  24. package/src/auth/utils.ts +33 -0
  25. package/src/client/clientStore.test.ts +14 -61
  26. package/src/client/clientStore.ts +52 -28
  27. package/src/comlink/controller/actions/destroyController.test.ts +1 -4
  28. package/src/comlink/controller/actions/getOrCreateChannel.test.ts +1 -4
  29. package/src/comlink/controller/actions/getOrCreateController.test.ts +1 -4
  30. package/src/comlink/controller/actions/releaseChannel.test.ts +1 -1
  31. package/src/comlink/controller/comlinkControllerStore.test.ts +1 -4
  32. package/src/comlink/node/actions/getOrCreateNode.test.ts +1 -4
  33. package/src/comlink/node/actions/releaseNode.test.ts +1 -4
  34. package/src/comlink/node/comlinkNodeStore.test.ts +2 -2
  35. package/src/comlink/node/getNodeState.test.ts +1 -1
  36. package/src/config/__tests__/handles.test.ts +12 -18
  37. package/src/config/handles.ts +7 -25
  38. package/src/config/sanityConfig.ts +99 -52
  39. package/src/datasets/datasets.test.ts +2 -2
  40. package/src/datasets/datasets.ts +4 -10
  41. package/src/document/actions.test.ts +33 -4
  42. package/src/document/actions.ts +3 -10
  43. package/src/document/applyDocumentActions.test.ts +17 -18
  44. package/src/document/applyDocumentActions.ts +9 -12
  45. package/src/document/documentStore.test.ts +303 -133
  46. package/src/document/documentStore.ts +70 -61
  47. package/src/document/permissions.test.ts +44 -8
  48. package/src/document/processActions.test.ts +77 -7
  49. package/src/document/reducers.test.ts +35 -3
  50. package/src/document/sharedListener.test.ts +13 -13
  51. package/src/document/sharedListener.ts +8 -3
  52. package/src/favorites/favorites.test.ts +10 -2
  53. package/src/presence/presenceStore.test.ts +34 -9
  54. package/src/presence/presenceStore.ts +29 -13
  55. package/src/preview/previewProjectionUtils.test.ts +192 -0
  56. package/src/preview/previewProjectionUtils.ts +88 -0
  57. package/src/preview/{previewStore.ts → types.ts} +6 -25
  58. package/src/project/project.test.ts +1 -1
  59. package/src/project/project.ts +14 -20
  60. package/src/projection/getProjectionState.test.ts +4 -2
  61. package/src/projection/getProjectionState.ts +2 -21
  62. package/src/projection/projectionQuery.ts +2 -3
  63. package/src/projection/projectionStore.test.ts +3 -3
  64. package/src/projection/resolveProjection.test.ts +2 -1
  65. package/src/projection/resolveProjection.ts +2 -18
  66. package/src/projection/subscribeToStateAndFetchBatches.test.ts +2 -2
  67. package/src/projection/subscribeToStateAndFetchBatches.ts +23 -36
  68. package/src/projection/types.ts +1 -9
  69. package/src/projects/projects.test.ts +1 -1
  70. package/src/query/queryStore.test.ts +86 -28
  71. package/src/query/queryStore.ts +23 -38
  72. package/src/releases/getPerspectiveState.test.ts +14 -13
  73. package/src/releases/getPerspectiveState.ts +6 -6
  74. package/src/releases/releasesStore.test.ts +21 -6
  75. package/src/releases/releasesStore.ts +18 -8
  76. package/src/store/createActionBinder.test.ts +114 -111
  77. package/src/store/createActionBinder.ts +52 -101
  78. package/src/store/createSanityInstance.test.ts +13 -83
  79. package/src/store/createSanityInstance.ts +2 -78
  80. package/src/store/createStateSourceAction.test.ts +2 -2
  81. package/src/store/createStateSourceAction.ts +5 -5
  82. package/src/store/createStoreInstance.test.ts +2 -4
  83. package/src/users/reducers.test.ts +1 -6
  84. package/src/users/reducers.ts +2 -2
  85. package/src/users/types.ts +4 -4
  86. package/src/users/usersStore.test.ts +12 -15
  87. package/src/utils/createFetcherStore.test.ts +1 -1
  88. package/src/utils/logger.test.ts +0 -12
  89. package/src/utils/logger.ts +3 -8
  90. package/src/preview/getPreviewState.test.ts +0 -120
  91. package/src/preview/getPreviewState.ts +0 -91
  92. package/src/preview/previewQuery.test.ts +0 -236
  93. package/src/preview/previewQuery.ts +0 -153
  94. package/src/preview/previewStore.test.ts +0 -36
  95. package/src/preview/resolvePreview.test.ts +0 -47
  96. package/src/preview/resolvePreview.ts +0 -20
  97. package/src/preview/subscribeToStateAndFetchBatches.test.ts +0 -221
  98. package/src/preview/subscribeToStateAndFetchBatches.ts +0 -112
  99. package/src/preview/util.ts +0 -13
@@ -1,7 +1,7 @@
1
1
  import {type Action} from '@sanity/client'
2
2
  import {getPublishedId} from '@sanity/client/csm'
3
3
  import {jsonMatch} from '@sanity/json-match'
4
- import {type SanityDocument} from 'groq'
4
+ import {type SanityDocument} from '@sanity/types'
5
5
  import {type ExprNode} from 'groq-js'
6
6
  import {
7
7
  catchError,
@@ -26,11 +26,17 @@ import {
26
26
  withLatestFrom,
27
27
  } from 'rxjs'
28
28
 
29
- import {getClientState} from '../client/clientStore'
30
- import {type DocumentHandle} from '../config/sanityConfig'
29
+ import {type ClientOptions, getClientState} from '../client/clientStore'
31
30
  import {
32
- bindActionByDataset,
33
- type BoundDatasetKey,
31
+ type DocumentHandle,
32
+ type DocumentResource,
33
+ isCanvasResource,
34
+ isDatasetResource,
35
+ isMediaLibraryResource,
36
+ } from '../config/sanityConfig'
37
+ import {
38
+ bindActionByResource,
39
+ type BoundResourceKey,
34
40
  type StoreAction,
35
41
  } from '../store/createActionBinder'
36
42
  import {type SanityInstance} from '../store/createSanityInstance'
@@ -41,8 +47,13 @@ import {type DocumentAction} from './actions'
41
47
  import {API_VERSION, INITIAL_OUTGOING_THROTTLE_TIME} from './documentConstants'
42
48
  import {type DocumentEvent, getDocumentEvents} from './events'
43
49
  import {listen, OutOfSyncError} from './listen'
44
- import {type JsonMatch} from './patchOperations'
45
- import {calculatePermissions, createGrantsLookup, type DatasetAcl, type Grant} from './permissions'
50
+ import {
51
+ calculatePermissions,
52
+ createGrantsLookup,
53
+ type DatasetAcl,
54
+ type DocumentPermissionsResult,
55
+ type Grant,
56
+ } from './permissions'
46
57
  import {ActionError} from './processActions'
47
58
  import {
48
59
  type AppliedTransaction,
@@ -107,15 +118,15 @@ export interface DocumentState {
107
118
  unverifiedRevisions?: {[TTransactionId in string]?: UnverifiedDocumentRevision}
108
119
  }
109
120
 
110
- export const documentStore = defineStore<DocumentStoreState, BoundDatasetKey>({
121
+ export const documentStore = defineStore<DocumentStoreState, BoundResourceKey>({
111
122
  name: 'Document',
112
- getInitialState: (instance) => ({
123
+ getInitialState: (instance, {resource}) => ({
113
124
  documentStates: {},
114
125
  // these can be emptied on refetch
115
126
  queued: [],
116
127
  applied: [],
117
- sharedListener: createSharedListener(instance),
118
- fetchDocument: createFetchDocument(instance),
128
+ sharedListener: createSharedListener(instance, resource),
129
+ fetchDocument: createFetchDocument(instance, resource),
119
130
  events: new Subject(),
120
131
  }),
121
132
  initialize(context) {
@@ -147,29 +158,6 @@ export interface DocumentOptions<
147
158
  path?: TPath
148
159
  }
149
160
 
150
- /** @beta */
151
- export function getDocumentState<
152
- TDocumentType extends string = string,
153
- TDataset extends string = string,
154
- TProjectId extends string = string,
155
- >(
156
- instance: SanityInstance,
157
- options: DocumentOptions<undefined, TDocumentType, TDataset, TProjectId>,
158
- ): StateSource<SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`> | undefined | null>
159
-
160
- /** @beta */
161
- export function getDocumentState<
162
- TPath extends string = string,
163
- TDocumentType extends string = string,
164
- TDataset extends string = string,
165
- TProjectId extends string = string,
166
- >(
167
- instance: SanityInstance,
168
- options: DocumentOptions<TPath, TDocumentType, TDataset, TProjectId>,
169
- ): StateSource<
170
- JsonMatch<SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`>, TPath> | undefined
171
- >
172
-
173
161
  /** @beta */
174
162
  export function getDocumentState<TData>(
175
163
  instance: SanityInstance,
@@ -183,7 +171,7 @@ export function getDocumentState(
183
171
  return _getDocumentState(...args)
184
172
  }
185
173
 
186
- const _getDocumentState = bindActionByDataset(
174
+ const _getDocumentState = bindActionByResource(
187
175
  documentStore,
188
176
  createStateSourceAction({
189
177
  selector: ({state: {error, documentStates}}, options: DocumentOptions<string | undefined>) => {
@@ -221,27 +209,23 @@ const _getDocumentState = bindActionByDataset(
221
209
  }),
222
210
  )
223
211
 
224
- /** @beta */
225
- export function resolveDocument<
226
- TDocumentType extends string = string,
227
- TDataset extends string = string,
228
- TProjectId extends string = string,
229
- >(
230
- instance: SanityInstance,
231
- docHandle: DocumentHandle<TDocumentType, TDataset, TProjectId>,
232
- ): Promise<SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`> | null>
233
212
  /** @beta */
234
213
  export function resolveDocument<TData extends SanityDocument>(
235
214
  instance: SanityInstance,
236
- docHandle: DocumentHandle<string, string, string>,
215
+ docHandle: DocumentHandle,
237
216
  ): Promise<TData | null>
238
217
  /** @beta */
218
+ export function resolveDocument(
219
+ instance: SanityInstance,
220
+ docHandle: DocumentHandle,
221
+ ): Promise<SanityDocument | null>
222
+ /** @beta */
239
223
  export function resolveDocument(
240
224
  ...args: Parameters<typeof _resolveDocument>
241
225
  ): Promise<SanityDocument | null> {
242
226
  return _resolveDocument(...args)
243
227
  }
244
- const _resolveDocument = bindActionByDataset(
228
+ const _resolveDocument = bindActionByResource(
245
229
  documentStore,
246
230
  ({instance}, docHandle: DocumentHandle<string, string, string>) => {
247
231
  return firstValueFrom(
@@ -254,7 +238,7 @@ const _resolveDocument = bindActionByDataset(
254
238
  )
255
239
 
256
240
  /** @beta */
257
- export const getDocumentSyncStatus = bindActionByDataset(
241
+ export const getDocumentSyncStatus = bindActionByResource(
258
242
  documentStore,
259
243
  createStateSourceAction({
260
244
  selector: (
@@ -286,11 +270,12 @@ export const getDocumentSyncStatus = bindActionByDataset(
286
270
  )
287
271
 
288
272
  type PermissionsStateOptions = {
273
+ resource: DocumentResource
289
274
  actions: DocumentAction[]
290
275
  }
291
276
 
292
277
  /** @beta */
293
- export const getPermissionsState = bindActionByDataset(
278
+ export const getPermissionsState = bindActionByResource(
294
279
  documentStore,
295
280
  createStateSourceAction({
296
281
  selector: calculatePermissions,
@@ -299,12 +284,12 @@ export const getPermissionsState = bindActionByDataset(
299
284
  }) as StoreAction<
300
285
  DocumentStoreState,
301
286
  [PermissionsStateOptions],
302
- StateSource<ReturnType<typeof calculatePermissions>>
287
+ StateSource<DocumentPermissionsResult>
303
288
  >,
304
289
  )
305
290
 
306
291
  /** @beta */
307
- export const resolvePermissions = bindActionByDataset(
292
+ export const resolvePermissions = bindActionByResource(
308
293
  documentStore,
309
294
  ({instance}, options: PermissionsStateOptions) => {
310
295
  return firstValueFrom(
@@ -314,16 +299,18 @@ export const resolvePermissions = bindActionByDataset(
314
299
  )
315
300
 
316
301
  /** @beta */
317
- export const subscribeDocumentEvents = bindActionByDataset(
302
+ export const subscribeDocumentEvents = bindActionByResource(
318
303
  documentStore,
319
- ({state}, eventHandler: (e: DocumentEvent) => void) => {
304
+ ({state}, options: {resource: DocumentResource; eventHandler: (e: DocumentEvent) => void}) => {
320
305
  const {events} = state.get()
321
- const subscription = events.subscribe(eventHandler)
306
+ const subscription = events.subscribe(options.eventHandler)
322
307
  return () => subscription.unsubscribe()
323
308
  },
324
309
  )
325
310
 
326
- const subscribeToQueuedAndApplyNextTransaction = ({state}: StoreContext<DocumentStoreState>) => {
311
+ const subscribeToQueuedAndApplyNextTransaction = ({
312
+ state,
313
+ }: StoreContext<DocumentStoreState, BoundResourceKey>) => {
327
314
  const {events} = state.get()
328
315
  return state.observable
329
316
  .pipe(
@@ -354,7 +341,8 @@ const subscribeToQueuedAndApplyNextTransaction = ({state}: StoreContext<Document
354
341
  const subscribeToAppliedAndSubmitNextTransaction = ({
355
342
  state,
356
343
  instance,
357
- }: StoreContext<DocumentStoreState>) => {
344
+ key: {resource},
345
+ }: StoreContext<DocumentStoreState, BoundResourceKey>) => {
358
346
  const {events} = state.get()
359
347
 
360
348
  return state.observable
@@ -374,7 +362,12 @@ const subscribeToAppliedAndSubmitNextTransaction = ({
374
362
  tap((next) => state.set('transitionAppliedTransactionsToOutgoing', next)),
375
363
  map((s) => s.outgoing),
376
364
  distinctUntilChanged(),
377
- withLatestFrom(getClientState(instance, {apiVersion: API_VERSION}).observable),
365
+ withLatestFrom(
366
+ getClientState(instance, {
367
+ apiVersion: API_VERSION,
368
+ ...(resource ? {resource} : {}),
369
+ }).observable,
370
+ ),
378
371
  concatMap(([outgoing, client]) => {
379
372
  if (!outgoing) return EMPTY
380
373
  return client.observable
@@ -401,7 +394,7 @@ const subscribeToAppliedAndSubmitNextTransaction = ({
401
394
  }
402
395
 
403
396
  const subscribeToSubscriptionsAndListenToDocuments = (
404
- context: StoreContext<DocumentStoreState>,
397
+ context: StoreContext<DocumentStoreState, BoundResourceKey>,
405
398
  ) => {
406
399
  const {state} = context
407
400
  const {events} = state.get()
@@ -469,13 +462,29 @@ const subscribeToSubscriptionsAndListenToDocuments = (
469
462
  const subscribeToClientAndFetchDatasetAcl = ({
470
463
  instance,
471
464
  state,
472
- key: {projectId, dataset},
473
- }: StoreContext<DocumentStoreState, BoundDatasetKey>) => {
474
- return getClientState(instance, {apiVersion: API_VERSION})
465
+ key: {resource},
466
+ }: StoreContext<DocumentStoreState, BoundResourceKey>) => {
467
+ const clientOptions: ClientOptions = {apiVersion: API_VERSION}
468
+ if (resource) {
469
+ clientOptions.resource = resource
470
+ }
471
+
472
+ let uri: string
473
+ if (resource && isDatasetResource(resource)) {
474
+ uri = `/projects/${resource.projectId}/datasets/${resource.dataset}/acl`
475
+ } else if (resource && isMediaLibraryResource(resource)) {
476
+ uri = `/media-libraries/${resource.mediaLibraryId}/acl`
477
+ } else if (resource && isCanvasResource(resource)) {
478
+ uri = `/canvases/${resource.canvasId}/acl`
479
+ } else {
480
+ throw new Error(`Received invalid resource: ${JSON.stringify(resource)}`)
481
+ }
482
+
483
+ return getClientState(instance, clientOptions)
475
484
  .observable.pipe(
476
485
  switchMap((client) =>
477
486
  client.observable.request<DatasetAcl>({
478
- uri: `/projects/${projectId}/datasets/${dataset}/acl`,
487
+ uri,
479
488
  tag: 'acl.get',
480
489
  withCredentials: true,
481
490
  }),
@@ -8,7 +8,7 @@ import {type DocumentAction} from './actions'
8
8
  import {calculatePermissions, createGrantsLookup, type DatasetAcl, type Grant} from './permissions'
9
9
  import {type SyncTransactionState} from './reducers'
10
10
 
11
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
11
+ const instance = createSanityInstance()
12
12
 
13
13
  afterAll(() => {
14
14
  instance.dispose()
@@ -73,7 +73,12 @@ describe('calculatePermissions', () => {
73
73
  )
74
74
 
75
75
  const actions: DocumentAction[] = [
76
- {documentId: 'doc1', type: 'document.create', documentType: 'article'},
76
+ {
77
+ documentId: 'doc1',
78
+ type: 'document.create',
79
+ documentType: 'article',
80
+ resource: {projectId: 'p', dataset: 'd'},
81
+ },
77
82
  ]
78
83
  const result = calculatePermissions({instance, state}, {actions})
79
84
  expect(result).toEqual({allowed: true})
@@ -89,7 +94,12 @@ describe('calculatePermissions', () => {
89
94
  defaultGrants,
90
95
  )
91
96
  const actions: DocumentAction[] = [
92
- {documentId: 'doc1', type: 'document.create', documentType: 'article'},
97
+ {
98
+ documentId: 'doc1',
99
+ type: 'document.create',
100
+ documentType: 'article',
101
+ resource: {projectId: 'p', dataset: 'd'},
102
+ },
93
103
  ]
94
104
  expect(calculatePermissions({instance, state}, {actions})).toBeUndefined()
95
105
  })
@@ -105,7 +115,12 @@ describe('calculatePermissions', () => {
105
115
  deniedGrants,
106
116
  )
107
117
  const actions: DocumentAction[] = [
108
- {documentId: 'doc1', type: 'document.create', documentType: 'article'},
118
+ {
119
+ documentId: 'doc1',
120
+ type: 'document.create',
121
+ documentType: 'article',
122
+ resource: {projectId: 'p', dataset: 'd'},
123
+ },
109
124
  ]
110
125
  const result = calculatePermissions({instance, state}, {actions})
111
126
  expect(result).toBeDefined()
@@ -133,7 +148,12 @@ describe('calculatePermissions', () => {
133
148
  defaultGrants,
134
149
  )
135
150
  const actions: DocumentAction[] = [
136
- {documentId: 'doc1', documentType: 'book', type: 'document.edit'},
151
+ {
152
+ documentId: 'doc1',
153
+ documentType: 'book',
154
+ type: 'document.edit',
155
+ resource: {projectId: 'p', dataset: 'd'},
156
+ },
137
157
  ]
138
158
  const result = calculatePermissions({instance, state}, {actions})
139
159
  expect(result).toBeDefined()
@@ -159,7 +179,12 @@ describe('calculatePermissions', () => {
159
179
  deniedGrants,
160
180
  )
161
181
  const actions: DocumentAction[] = [
162
- {documentId: 'doc1', documentType: 'book', type: 'document.edit'},
182
+ {
183
+ documentId: 'doc1',
184
+ documentType: 'book',
185
+ type: 'document.edit',
186
+ resource: {projectId: 'p', dataset: 'd'},
187
+ },
163
188
  ]
164
189
  const result = calculatePermissions({instance, state}, {actions})
165
190
  expect(result).toBeDefined()
@@ -183,7 +208,12 @@ describe('calculatePermissions', () => {
183
208
  [getDraftId('doc1')]: {local: null},
184
209
  })
185
210
  const actions: DocumentAction[] = [
186
- {documentId: 'doc1', type: 'document.create', documentType: 'article'},
211
+ {
212
+ documentId: 'doc1',
213
+ type: 'document.create',
214
+ documentType: 'article',
215
+ resource: {projectId: 'p', dataset: 'd'},
216
+ },
187
217
  ]
188
218
  expect(calculatePermissions({instance, state}, {actions})).toBeUndefined()
189
219
  })
@@ -198,7 +228,12 @@ describe('calculatePermissions', () => {
198
228
  defaultGrants,
199
229
  )
200
230
  const actions: DocumentAction[] = [
201
- {documentId: 'doc1', documentType: 'book', type: 'document.delete'},
231
+ {
232
+ documentId: 'doc1',
233
+ documentType: 'book',
234
+ type: 'document.delete',
235
+ resource: {projectId: 'p', dataset: 'd'},
236
+ },
202
237
  ]
203
238
  const result = calculatePermissions({instance, state}, {actions})
204
239
  expect(result).toBeDefined()
@@ -226,6 +261,7 @@ describe('calculatePermissions', () => {
226
261
  documentId: 'doc1',
227
262
  type: 'document.create',
228
263
  documentType: 'article',
264
+ resource: {projectId: 'p', dataset: 'd'},
229
265
  }
230
266
  // notice how the action is a copy
231
267
  const result1 = calculatePermissions({instance, state}, {actions: [{...action}]})