@sanity/sdk 3.0.0-rc.0 → 3.0.0-rc.2

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 (241) hide show
  1. package/README.md +12 -0
  2. package/dist/_exports/_internal.d.ts +163 -0
  3. package/dist/_exports/_internal.d.ts.map +1 -0
  4. package/dist/_exports/_internal.js +332 -0
  5. package/dist/_exports/_internal.js.map +1 -0
  6. package/dist/_exports/agent.d.ts +65 -0
  7. package/dist/_exports/agent.d.ts.map +1 -0
  8. package/dist/_exports/agent.js +71 -0
  9. package/dist/_exports/agent.js.map +1 -0
  10. package/dist/_exports/comlink.d.ts +118 -0
  11. package/dist/_exports/comlink.d.ts.map +1 -0
  12. package/dist/_exports/comlink.js +69 -0
  13. package/dist/_exports/comlink.js.map +1 -0
  14. package/dist/authStore-CtE9bLHW.js +754 -0
  15. package/dist/authStore-CtE9bLHW.js.map +1 -0
  16. package/dist/authStore-DKFX8fn7.d.ts +3179 -0
  17. package/dist/authStore-DKFX8fn7.d.ts.map +1 -0
  18. package/dist/clientStore-BtE2-q2i.js +90 -0
  19. package/dist/clientStore-BtE2-q2i.js.map +1 -0
  20. package/dist/createSanityInstance-DUI1bGIg.d.ts +278 -0
  21. package/dist/createSanityInstance-DUI1bGIg.d.ts.map +1 -0
  22. package/dist/createStateSourceAction-BOKtqFNm.js +300 -0
  23. package/dist/createStateSourceAction-BOKtqFNm.js.map +1 -0
  24. package/dist/getEnv-D5RGkQLu.js +8 -0
  25. package/dist/getEnv-D5RGkQLu.js.map +1 -0
  26. package/dist/getNodeState-CR3__B2D.js +67 -0
  27. package/dist/getNodeState-CR3__B2D.js.map +1 -0
  28. package/dist/index.d.ts +3 -2332
  29. package/dist/index.js +4171 -4332
  30. package/dist/index.js.map +1 -1
  31. package/dist/logger-DAtJb5RQ.js +173 -0
  32. package/dist/logger-DAtJb5RQ.js.map +1 -0
  33. package/dist/object-CxXlSVg7.js +83 -0
  34. package/dist/object-CxXlSVg7.js.map +1 -0
  35. package/dist/queryStore-DPf9sN3V.js +1346 -0
  36. package/dist/queryStore-DPf9sN3V.js.map +1 -0
  37. package/dist/rolldown-runtime-vyAXikos.js +9 -0
  38. package/dist/setCleanupTimeout-BiM6q1KF.js +31 -0
  39. package/dist/setCleanupTimeout-BiM6q1KF.js.map +1 -0
  40. package/dist/telemetryManager-Dq_qCkeI.js +127 -0
  41. package/dist/telemetryManager-Dq_qCkeI.js.map +1 -0
  42. package/dist/version-BChjsi4u.js +9 -0
  43. package/dist/version-BChjsi4u.js.map +1 -0
  44. package/package.json +47 -52
  45. package/src/_exports/_internal.ts +27 -0
  46. package/src/_exports/agent.ts +19 -0
  47. package/src/_exports/comlink.ts +16 -0
  48. package/src/_exports/index.ts +125 -64
  49. package/src/access/checkPermissions.test.ts +55 -0
  50. package/src/access/checkPermissions.ts +54 -0
  51. package/src/agent/agentActions.test.ts +16 -60
  52. package/src/agent/agentActions.ts +25 -38
  53. package/src/applications/applications.test-d.ts +88 -0
  54. package/src/applications/applications.test.ts +130 -0
  55. package/src/applications/applications.ts +367 -0
  56. package/src/auth/authLogger.ts +30 -0
  57. package/src/auth/authStore.test.ts +194 -13
  58. package/src/auth/authStore.ts +58 -26
  59. package/src/auth/getOrganizationVerificationState.test.ts +18 -17
  60. package/src/auth/getOrganizationVerificationState.ts +4 -4
  61. package/src/auth/handleAuthCallback.test.ts +35 -1
  62. package/src/auth/handleAuthCallback.ts +25 -6
  63. package/src/auth/logout.test.ts +75 -2
  64. package/src/auth/logout.ts +23 -4
  65. package/src/auth/refreshStampedToken.test.ts +219 -469
  66. package/src/auth/refreshStampedToken.ts +79 -195
  67. package/src/auth/studioAuth.ts +1 -1
  68. package/src/auth/studioModeAuth.ts +2 -1
  69. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +146 -13
  70. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +37 -6
  71. package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +2 -0
  72. package/src/client/clientStore.test.ts +62 -37
  73. package/src/client/clientStore.ts +45 -75
  74. package/src/client/liveEvents.test.ts +151 -0
  75. package/src/client/liveEvents.ts +107 -0
  76. package/src/comlink/controller/actions/destroyController.test.ts +4 -1
  77. package/src/comlink/controller/actions/getOrCreateChannel.test.ts +4 -1
  78. package/src/comlink/controller/actions/getOrCreateChannel.ts +2 -2
  79. package/src/comlink/controller/actions/getOrCreateController.test.ts +4 -1
  80. package/src/comlink/controller/actions/releaseChannel.test.ts +1 -1
  81. package/src/comlink/controller/comlinkControllerStore.test.ts +4 -1
  82. package/src/comlink/node/actions/getOrCreateNode.test.ts +9 -3
  83. package/src/comlink/node/actions/getOrCreateNode.ts +2 -2
  84. package/src/comlink/node/actions/releaseNode.test.ts +7 -4
  85. package/src/comlink/node/comlinkNodeStore.test.ts +2 -2
  86. package/src/comlink/node/getNodeState.test.ts +1 -1
  87. package/src/comlink/node/getNodeState.ts +2 -1
  88. package/src/comments/addonDatasetStore.test.ts +215 -0
  89. package/src/comments/addonDatasetStore.ts +249 -0
  90. package/src/comments/buildCommentThreads.test.ts +83 -0
  91. package/src/comments/buildCommentThreads.ts +54 -0
  92. package/src/comments/commentActions.test.ts +540 -0
  93. package/src/comments/commentActions.ts +555 -0
  94. package/src/comments/commentFieldPath.test.ts +40 -0
  95. package/src/comments/commentFieldPath.ts +44 -0
  96. package/src/comments/commentsConstants.ts +80 -0
  97. package/src/comments/commentsStore.test.ts +419 -0
  98. package/src/comments/commentsStore.ts +483 -0
  99. package/src/comments/normalizeComment.test.ts +116 -0
  100. package/src/comments/normalizeComment.ts +45 -0
  101. package/src/comments/observeComments.test.ts +193 -0
  102. package/src/comments/observeComments.ts +113 -0
  103. package/src/comments/reducers.test.ts +277 -0
  104. package/src/comments/reducers.ts +316 -0
  105. package/src/comments/types.ts +249 -0
  106. package/src/comments/weakenReferences.test.ts +47 -0
  107. package/src/comments/weakenReferences.ts +29 -0
  108. package/src/config/__tests__/handles.test.ts +18 -12
  109. package/src/config/handles.ts +25 -7
  110. package/src/config/sanityConfig.ts +40 -82
  111. package/src/datasets/datasets.test.ts +2 -2
  112. package/src/datasets/datasets.ts +10 -4
  113. package/src/document/actions.test.ts +115 -33
  114. package/src/document/actions.ts +212 -15
  115. package/src/document/applyDocumentActions.test.ts +35 -13
  116. package/src/document/applyDocumentActions.ts +30 -9
  117. package/src/document/documentConstants.ts +15 -0
  118. package/src/document/documentStore.concurrency.test.ts +1306 -0
  119. package/src/document/documentStore.test.ts +753 -273
  120. package/src/document/documentStore.ts +197 -75
  121. package/src/document/events.test.ts +57 -2
  122. package/src/document/events.ts +82 -26
  123. package/src/document/listen.test.ts +56 -0
  124. package/src/document/listen.ts +74 -21
  125. package/src/document/listenerEventOperators.test.ts +311 -0
  126. package/src/document/listenerEventOperators.ts +217 -0
  127. package/src/document/patchOperations.test.ts +76 -2
  128. package/src/document/patchOperations.ts +60 -1
  129. package/src/document/permissions.test.ts +107 -60
  130. package/src/document/permissions.ts +44 -19
  131. package/src/document/processActions/create.ts +138 -0
  132. package/src/document/processActions/delete.ts +100 -0
  133. package/src/document/processActions/discard.ts +63 -0
  134. package/src/document/processActions/edit.ts +154 -0
  135. package/src/document/processActions/processActions.ts +218 -0
  136. package/src/document/processActions/publish.ts +120 -0
  137. package/src/document/processActions/releaseArchive.ts +77 -0
  138. package/src/document/processActions/releaseCreate.ts +59 -0
  139. package/src/document/processActions/releaseDelete.ts +65 -0
  140. package/src/document/processActions/releaseEdit.ts +37 -0
  141. package/src/document/processActions/releasePublish.ts +45 -0
  142. package/src/document/processActions/releaseSchedule.ts +87 -0
  143. package/src/document/processActions/releaseUtil.ts +31 -0
  144. package/src/document/processActions/shared.ts +308 -0
  145. package/src/document/processActions/unpublish.ts +85 -0
  146. package/src/document/processActions.test.ts +1129 -121
  147. package/src/document/reducers.test.ts +772 -64
  148. package/src/document/reducers.ts +205 -51
  149. package/src/document/resourceRules.test.ts +178 -0
  150. package/src/document/resourceRules.ts +117 -0
  151. package/src/document/sharedListener.test.ts +16 -14
  152. package/src/document/sharedListener.ts +24 -8
  153. package/src/document/util.test.ts +46 -0
  154. package/src/document/util.ts +50 -0
  155. package/src/favorites/favorites.test.ts +5 -6
  156. package/src/installations/installations.test-d.ts +73 -0
  157. package/src/installations/installations.test.ts +62 -0
  158. package/src/installations/installations.ts +206 -0
  159. package/src/organization/organization.test-d.ts +36 -0
  160. package/src/organization/organization.test.ts +138 -0
  161. package/src/organization/organization.ts +138 -0
  162. package/src/organizations/organizations.test-d.ts +56 -0
  163. package/src/organizations/organizations.test.ts +150 -0
  164. package/src/organizations/organizations.ts +107 -0
  165. package/src/presence/bifurTransport.test.ts +201 -9
  166. package/src/presence/bifurTransport.ts +98 -14
  167. package/src/presence/paths.test.ts +70 -0
  168. package/src/presence/paths.ts +41 -0
  169. package/src/presence/presenceStore.test.ts +915 -24
  170. package/src/presence/presenceStore.ts +576 -104
  171. package/src/presence/types.ts +175 -3
  172. package/src/preview/previewProjectionUtils.test.ts +9 -22
  173. package/src/preview/previewProjectionUtils.ts +7 -3
  174. package/src/preview/types.ts +0 -15
  175. package/src/project/project.test-d.ts +37 -0
  176. package/src/project/project.test.ts +157 -12
  177. package/src/project/project.ts +138 -25
  178. package/src/projection/getProjectionState.test.ts +18 -20
  179. package/src/projection/getProjectionState.ts +23 -3
  180. package/src/projection/projectionQuery.ts +5 -5
  181. package/src/projection/projectionStore.test.ts +1 -9
  182. package/src/projection/resolveProjection.test.ts +1 -2
  183. package/src/projection/resolveProjection.ts +16 -0
  184. package/src/projection/subscribeToStateAndFetchBatches.test.ts +1 -1
  185. package/src/projection/subscribeToStateAndFetchBatches.ts +32 -23
  186. package/src/projects/projects.test-d.ts +32 -0
  187. package/src/projects/projects.test.ts +108 -42
  188. package/src/projects/projects.ts +63 -27
  189. package/src/query/queryStore.test.ts +259 -123
  190. package/src/query/queryStore.ts +85 -69
  191. package/src/query/reducers.test.ts +0 -42
  192. package/src/query/reducers.ts +2 -18
  193. package/src/releases/getPerspectiveState.test.ts +17 -23
  194. package/src/releases/getPerspectiveState.ts +8 -20
  195. package/src/releases/observeReleases.test.ts +127 -0
  196. package/src/releases/observeReleases.ts +102 -0
  197. package/src/releases/releasesStore.test.ts +100 -53
  198. package/src/releases/releasesStore.ts +69 -44
  199. package/src/releases/utils/sortReleases.test.ts +38 -2
  200. package/src/releases/utils/sortReleases.ts +15 -10
  201. package/src/store/createActionBinder.test.ts +109 -90
  202. package/src/store/createActionBinder.ts +36 -28
  203. package/src/store/createSanityInstance.test.ts +15 -13
  204. package/src/store/createSanityInstance.ts +14 -2
  205. package/src/store/createStateSourceAction.test.ts +64 -2
  206. package/src/store/createStateSourceAction.ts +38 -43
  207. package/src/store/createStoreInstance.test.ts +4 -2
  208. package/src/store/fetcherStore.test-d.ts +121 -0
  209. package/src/store/fetcherStore.test.ts +299 -0
  210. package/src/store/fetcherStore.ts +801 -0
  211. package/src/telemetry/environment.test.ts +119 -0
  212. package/src/telemetry/environment.ts +92 -0
  213. package/src/telemetry/events.ts +42 -0
  214. package/src/telemetry/initTelemetry.test.ts +432 -0
  215. package/src/telemetry/initTelemetry.ts +218 -0
  216. package/src/telemetry/telemetryManager.test.ts +327 -0
  217. package/src/telemetry/telemetryManager.ts +199 -0
  218. package/src/users/reducers.test.ts +3 -1
  219. package/src/users/reducers.ts +5 -6
  220. package/src/users/types.ts +4 -4
  221. package/src/users/usersStore.test.ts +16 -12
  222. package/src/users/usersStore.ts +5 -1
  223. package/src/utils/buildQuery.test.ts +14 -0
  224. package/src/utils/buildQuery.ts +17 -0
  225. package/src/utils/createFetcherStore.test.ts +7 -5
  226. package/src/utils/createFetcherStore.ts +8 -5
  227. package/src/utils/getStagingApiHost.test.ts +21 -0
  228. package/src/utils/getStagingApiHost.ts +14 -0
  229. package/src/utils/ids.test.ts +1 -29
  230. package/src/utils/ids.ts +0 -10
  231. package/src/utils/includeShape.ts +36 -0
  232. package/src/utils/isImportError.test.ts +72 -0
  233. package/src/utils/isImportError.ts +34 -0
  234. package/src/utils/logger.test.ts +12 -0
  235. package/src/utils/logger.ts +8 -3
  236. package/src/utils/object.test.ts +95 -0
  237. package/src/utils/object.ts +142 -0
  238. package/src/utils/setCleanupTimeout.ts +37 -0
  239. package/src/document/processActions.ts +0 -707
  240. package/src/utils/defineIntent.test.ts +0 -477
  241. package/src/utils/defineIntent.ts +0 -244
@@ -1,4 +1,9 @@
1
- import {type DocumentHandle, type DocumentTypeHandle, type ResourceHandle} from './sanityConfig'
1
+ import {
2
+ type DatasetHandle,
3
+ type DocumentHandle,
4
+ type DocumentTypeHandle,
5
+ type ProjectHandle,
6
+ } from './sanityConfig'
2
7
 
3
8
  /**
4
9
  * Creates or validates a `DocumentHandle` object.
@@ -35,15 +40,28 @@ export function createDocumentTypeHandle<
35
40
  }
36
41
 
37
42
  /**
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.
43
+ * Creates or validates a `ProjectHandle` object.
44
+ * Ensures the provided object conforms to the `ProjectHandle` interface.
45
+ * @param handle - The object containing project identification properties.
46
+ * @returns The validated `ProjectHandle` object.
42
47
  * @public
43
48
  */
44
- export function createResourceHandle<
49
+ export function createProjectHandle<TProjectId extends string = string>(
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<
45
63
  TDataset extends string = string,
46
64
  TProjectId extends string = string,
47
- >(handle: ResourceHandle<TProjectId, TDataset>): ResourceHandle<TProjectId, TDataset> {
65
+ >(handle: DatasetHandle<TDataset, TProjectId>): DatasetHandle<TDataset, TProjectId> {
48
66
  return handle
49
67
  }
@@ -40,12 +40,14 @@ export interface StudioConfig {
40
40
  */
41
41
  token?: TokenSource
42
42
  }
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
43
+ }
44
+
45
+ /**
46
+ * Represents the minimal configuration required to identify a Sanity project.
47
+ * @public
48
+ */
49
+ export interface ProjectHandle<TProjectId extends string = string> {
50
+ projectId?: TProjectId
49
51
  }
50
52
 
51
53
  /**
@@ -60,27 +62,22 @@ export type ReleasePerspective = {
60
62
  * @public
61
63
  */
62
64
  export interface PerspectiveHandle {
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
65
+ perspective?: ClientPerspective | ReleasePerspective
70
66
  }
71
67
 
72
68
  /**
73
69
  * @public
74
70
  */
75
- export interface ResourceHandle<
76
- TProjectId extends string = string,
77
- TDataset extends string = string,
78
- > extends PerspectiveHandle {
71
+ export interface DatasetHandle<TDataset extends string = string, TProjectId extends string = string>
72
+ extends ProjectHandle<TProjectId>, PerspectiveHandle {
73
+ dataset?: TDataset
79
74
  /**
80
- * Explicit resource object to use for this operation.
81
- * @public
75
+ * @beta
76
+ * Explicit resource to use. On an individual operation this overrides any default;
77
+ * on a `SanityConfig` it becomes the instance's default resource. Unlike
78
+ * `projectId`/`dataset`, this can also be a media library or canvas resource.
82
79
  */
83
- resource: DocumentResource<TProjectId, TDataset>
80
+ resource?: DocumentResource
84
81
  }
85
82
 
86
83
  /**
@@ -93,7 +90,7 @@ export interface DocumentTypeHandle<
93
90
  TDocumentType extends string = string,
94
91
  TDataset extends string = string,
95
92
  TProjectId extends string = string,
96
- > extends ResourceHandle<TDataset, TProjectId> {
93
+ > extends DatasetHandle<TDataset, TProjectId> {
97
94
  documentId?: string
98
95
  documentType: TDocumentType
99
96
  /**
@@ -119,42 +116,22 @@ export interface DocumentHandle<
119
116
  }
120
117
 
121
118
  /**
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
- *
126
- * @public
119
+ * Identifies a release within a Sanity dataset and project. `releaseId` is the
120
+ * `name` parameter on the release document (e.g. `{name: 'r41035a4'}`).
121
+ * The underlying release document ID is `_.releases.<releaseId>`.
122
+ * It's also the `id` parameter sent to the Actions API.
123
+ * (This type doesn't need to have ProjectId / Dataset generics since it's always the same shape)
124
+ * @beta
127
125
  */
128
- export const DEFAULT_RESOURCE_NAME = 'default'
126
+ export interface ReleaseHandle extends DatasetHandle {
127
+ releaseId: string
128
+ }
129
129
 
130
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
- * ```
131
+ * Represents the complete configuration for a Sanity SDK instance
155
132
  * @public
156
133
  */
157
- export interface SanityConfig extends PerspectiveHandle {
134
+ export interface SanityConfig extends DatasetHandle, PerspectiveHandle {
158
135
  /**
159
136
  * Authentication configuration for the instance
160
137
  */
@@ -168,58 +145,40 @@ export interface SanityConfig extends PerspectiveHandle {
168
145
  * `SDKStudioContext` provider. Can also be set explicitly for programmatic use.
169
146
  */
170
147
  studio?: StudioConfig
171
- /**
172
- * The default document resource for this instance. Used by bound actions
173
- * when no explicit resource is provided.
174
- *
175
- * @public
176
- */
177
- defaultResource?: DocumentResource
178
148
  }
179
149
 
180
150
  /**
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.
151
+ * A document resource can be used for querying.
152
+ * This will soon be the default way to identify where you are querying from.
183
153
  *
184
- * @public
154
+ * @beta
185
155
  */
186
- export type DocumentResource<
187
- TProjectId extends string = string,
188
- TDataset extends string = string,
189
- > = DatasetResource<TProjectId, TDataset> | MediaLibraryResource | CanvasResource
156
+ export type DocumentResource = DatasetResource | MediaLibraryResource | CanvasResource
190
157
 
191
158
  /**
192
- * A resource that targets a specific project and dataset.
193
- * @public
159
+ * @beta
194
160
  */
195
- export type DatasetResource<
196
- TProjectId extends string = string,
197
- TDataset extends string = string,
198
- > = {projectId: TProjectId; dataset: TDataset}
161
+ export type DatasetResource = {projectId: string; dataset: string}
199
162
 
200
163
  /**
201
- * A resource that targets a media library.
202
- * @public
164
+ * @beta
203
165
  */
204
166
  export type MediaLibraryResource = {mediaLibraryId: string}
205
167
 
206
168
  /**
207
- * A resource that targets a canvas.
208
- * @public
169
+ * @beta
209
170
  */
210
171
  export type CanvasResource = {canvasId: string}
211
172
 
212
173
  /**
213
- * Type guard that checks whether a {@link DocumentResource} is a {@link DatasetResource}.
214
- * @public
174
+ * @beta
215
175
  */
216
176
  export function isDatasetResource(resource: DocumentResource): resource is DatasetResource {
217
177
  return 'projectId' in resource && 'dataset' in resource
218
178
  }
219
179
 
220
180
  /**
221
- * Type guard that checks whether a {@link DocumentResource} is a {@link MediaLibraryResource}.
222
- * @public
181
+ * @beta
223
182
  */
224
183
  export function isMediaLibraryResource(
225
184
  resource: DocumentResource,
@@ -228,8 +187,7 @@ export function isMediaLibraryResource(
228
187
  }
229
188
 
230
189
  /**
231
- * Type guard that checks whether a {@link DocumentResource} is a {@link CanvasResource}.
232
- * @public
190
+ * @beta
233
191
  */
234
192
  export function isCanvasResource(resource: DocumentResource): resource is CanvasResource {
235
193
  return 'canvasId' in resource
@@ -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({projectId: 'p', dataset: 'd'})
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, {projectId: 'p'})
28
+ const result = await resolveDatasets(instance)
29
29
  expect(result).toEqual(datasets)
30
30
  expect(list).toHaveBeenCalled()
31
31
  })
@@ -1,6 +1,7 @@
1
1
  import {switchMap} from 'rxjs'
2
2
 
3
3
  import {getClientState} from '../client/clientStore'
4
+ import {type ProjectHandle} from '../config/sanityConfig'
4
5
  import {createFetcherStore} from '../utils/createFetcherStore'
5
6
 
6
7
  const API_VERSION = 'v2025-02-19'
@@ -8,13 +9,18 @@ const API_VERSION = 'v2025-02-19'
8
9
  /** @public */
9
10
  export const datasets = createFetcherStore({
10
11
  name: 'Datasets',
11
- getKey: (_instance, options: {projectId: string}) => {
12
- return options.projectId
12
+ getKey: (instance, options?: ProjectHandle) => {
13
+ const projectId = options?.projectId ?? instance.config.projectId
14
+ if (!projectId) {
15
+ throw new Error('A projectId is required to use the project API.')
16
+ }
17
+ return projectId
13
18
  },
14
- fetcher: (instance) => (options: {projectId: string}) => {
19
+ fetcher: (instance) => (options?: ProjectHandle) => {
15
20
  return getClientState(instance, {
16
21
  apiVersion: API_VERSION,
17
- projectId: options.projectId,
22
+ // non-null assertion is fine because we check above
23
+ projectId: (options?.projectId ?? instance.config.projectId)!,
18
24
  useProjectHostname: true,
19
25
  }).observable.pipe(switchMap((client) => client.observable.datasets.list()))
20
26
  },
@@ -1,32 +1,35 @@
1
+ import {type ReleaseDocument} from '@sanity/client'
1
2
  import {at, patch, set, setIfMissing} from '@sanity/mutate'
2
3
  import {type PatchOperations} from '@sanity/types'
3
4
  import {describe, expect, it} from 'vitest'
4
5
 
5
- import {type DocumentHandle, type DocumentResource} from '../config/sanityConfig'
6
+ import {type DocumentHandle, type ReleaseHandle} from '../config/sanityConfig'
6
7
  import {
8
+ archiveRelease,
7
9
  createDocument,
10
+ createRelease,
8
11
  deleteDocument,
12
+ deleteRelease,
9
13
  discardDocument,
10
14
  editDocument,
15
+ editRelease,
11
16
  publishDocument,
17
+ publishRelease,
18
+ scheduleRelease,
19
+ unarchiveRelease,
12
20
  unpublishDocument,
21
+ unscheduleRelease,
13
22
  } from '../document/actions'
14
23
 
15
24
  const dummyPatch: PatchOperations = {
16
25
  diffMatchPatch: {'dummy.path': 'dummy patch'},
17
26
  }
18
- const dummyDocResource: DocumentResource = {projectId: 'test-project', dataset: 'test-dataset'}
19
27
 
20
- const dummyDocHandle: DocumentHandle = {
21
- documentId: 'drafts.abc123',
22
- documentType: 'testType',
23
- resource: dummyDocResource,
24
- }
25
- const dummyDocString: DocumentHandle = {
26
- documentId: 'drafts.abc123',
27
- documentType: 'testType',
28
- resource: dummyDocResource,
29
- }
28
+ const dummyDocHandle: DocumentHandle = {documentId: 'drafts.abc123', documentType: 'testType'}
29
+ const dummyDocString = {documentId: 'drafts.abc123', documentType: 'testType'}
30
+
31
+ const dummyReleaseHandle: ReleaseHandle = {releaseId: 'my-release'}
32
+ const dummyReleasePatch: PatchOperations = {set: {'metadata.title': 'Updated title'}}
30
33
 
31
34
  describe('document actions', () => {
32
35
  describe('createDocument', () => {
@@ -37,24 +40,18 @@ describe('document actions', () => {
37
40
  // getId returns the input if it does not end with a dot.
38
41
  documentId: 'abc123',
39
42
  documentType: dummyDocHandle.documentType,
40
- resource: dummyDocResource,
41
43
  })
42
44
  })
43
45
 
44
46
  it('creates a document action from a document type handle', () => {
45
47
  // A document type handle is similar to a document handle,
46
48
  // but _id is optional.
47
- const typeHandle = {
48
- documentId: 'abc456',
49
- documentType: 'anotherType',
50
- resource: dummyDocResource,
51
- }
49
+ const typeHandle = {documentId: 'abc456', documentType: 'anotherType'}
52
50
  const action = createDocument(typeHandle)
53
51
  expect(action).toEqual({
54
52
  type: 'document.create',
55
53
  documentId: 'abc456',
56
54
  documentType: typeHandle.documentType,
57
- resource: dummyDocResource,
58
55
  })
59
56
  })
60
57
 
@@ -70,7 +67,6 @@ describe('document actions', () => {
70
67
  documentId: 'abc123',
71
68
  documentType: dummyDocHandle.documentType,
72
69
  initialValue,
73
- resource: dummyDocResource,
74
70
  })
75
71
  })
76
72
 
@@ -80,7 +76,6 @@ describe('document actions', () => {
80
76
  type: 'document.create',
81
77
  documentId: 'abc123',
82
78
  documentType: dummyDocHandle.documentType,
83
- resource: dummyDocResource,
84
79
  })
85
80
  })
86
81
 
@@ -91,7 +86,6 @@ describe('document actions', () => {
91
86
  documentId: 'abc123',
92
87
  documentType: dummyDocHandle.documentType,
93
88
  initialValue: {},
94
- resource: dummyDocResource,
95
89
  })
96
90
  })
97
91
  })
@@ -104,7 +98,6 @@ describe('document actions', () => {
104
98
  type: 'document.delete',
105
99
  documentId: 'abc123',
106
100
  documentType: dummyDocString.documentType,
107
- resource: dummyDocResource,
108
101
  })
109
102
  })
110
103
 
@@ -114,7 +107,6 @@ describe('document actions', () => {
114
107
  type: 'document.delete',
115
108
  documentId: 'abc123',
116
109
  documentType: dummyDocHandle.documentType,
117
- resource: dummyDocResource,
118
110
  })
119
111
  })
120
112
  })
@@ -127,7 +119,6 @@ describe('document actions', () => {
127
119
  documentId: 'abc123',
128
120
  documentType: dummyDocString.documentType,
129
121
  patches: [dummyPatch],
130
- resource: dummyDocResource,
131
122
  })
132
123
  })
133
124
 
@@ -138,7 +129,6 @@ describe('document actions', () => {
138
129
  documentId: 'abc123',
139
130
  documentType: dummyDocHandle.documentType,
140
131
  patches: [dummyPatch],
141
- resource: dummyDocResource,
142
132
  })
143
133
  })
144
134
 
@@ -165,7 +155,6 @@ describe('document actions', () => {
165
155
  {ifRevisionID: 'txn0', set: {'address.city': 'Oslo'}},
166
156
  ],
167
157
  type: 'document.edit',
168
- resource: dummyDocResource,
169
158
  })
170
159
  })
171
160
  })
@@ -177,7 +166,6 @@ describe('document actions', () => {
177
166
  type: 'document.publish',
178
167
  documentId: 'abc123',
179
168
  documentType: dummyDocString.documentType,
180
- resource: dummyDocResource,
181
169
  })
182
170
  })
183
171
 
@@ -187,7 +175,6 @@ describe('document actions', () => {
187
175
  type: 'document.publish',
188
176
  documentId: 'abc123',
189
177
  documentType: dummyDocHandle.documentType,
190
- resource: dummyDocResource,
191
178
  })
192
179
  })
193
180
  })
@@ -199,7 +186,6 @@ describe('document actions', () => {
199
186
  type: 'document.unpublish',
200
187
  documentId: 'abc123',
201
188
  documentType: dummyDocString.documentType,
202
- resource: dummyDocResource,
203
189
  })
204
190
  })
205
191
 
@@ -209,7 +195,6 @@ describe('document actions', () => {
209
195
  type: 'document.unpublish',
210
196
  documentId: 'abc123',
211
197
  documentType: dummyDocHandle.documentType,
212
- resource: dummyDocResource,
213
198
  })
214
199
  })
215
200
  })
@@ -221,7 +206,6 @@ describe('document actions', () => {
221
206
  type: 'document.discard',
222
207
  documentId: 'abc123',
223
208
  documentType: dummyDocString.documentType,
224
- resource: dummyDocResource,
225
209
  })
226
210
  })
227
211
 
@@ -231,8 +215,106 @@ describe('document actions', () => {
231
215
  type: 'document.discard',
232
216
  documentId: 'abc123',
233
217
  documentType: dummyDocHandle.documentType,
234
- resource: dummyDocResource,
235
218
  })
236
219
  })
237
220
  })
238
221
  })
222
+
223
+ describe('release actions', () => {
224
+ describe('createRelease', () => {
225
+ it('creates a release action from a release handle', () => {
226
+ const action = createRelease(dummyReleaseHandle)
227
+ expect(action).toEqual({
228
+ type: 'release.create',
229
+ releaseId: 'my-release',
230
+ metadata: {releaseType: 'undecided'},
231
+ })
232
+ })
233
+
234
+ it('creates a release action with metadata', () => {
235
+ const metadata: ReleaseDocument['metadata'] = {
236
+ title: 'My release',
237
+ description: 'Some description',
238
+ releaseType: 'scheduled',
239
+ intendedPublishAt: '2026-01-01T00:00:00.000Z',
240
+ }
241
+ const action = createRelease(dummyReleaseHandle, metadata)
242
+ expect(action).toEqual({
243
+ type: 'release.create',
244
+ releaseId: 'my-release',
245
+ metadata,
246
+ })
247
+ })
248
+
249
+ it('preserves resource fields from the handle', () => {
250
+ const action = createRelease({
251
+ releaseId: 'my-release',
252
+ resource: {dataset: 'production', projectId: 'abc123'},
253
+ })
254
+ expect(action).toEqual({
255
+ type: 'release.create',
256
+ releaseId: 'my-release',
257
+ resource: {dataset: 'production', projectId: 'abc123'},
258
+ metadata: {releaseType: 'undecided'},
259
+ })
260
+ })
261
+ })
262
+
263
+ describe('editRelease', () => {
264
+ it('creates a release.edit action with a patch', () => {
265
+ const action = editRelease(dummyReleaseHandle, dummyReleasePatch)
266
+ expect(action).toEqual({
267
+ type: 'release.edit',
268
+ releaseId: 'my-release',
269
+ patch: dummyReleasePatch,
270
+ })
271
+ })
272
+ })
273
+
274
+ describe('publishRelease', () => {
275
+ it('creates a release.publish action from a release handle', () => {
276
+ const action = publishRelease(dummyReleaseHandle)
277
+ expect(action).toEqual({type: 'release.publish', releaseId: 'my-release'})
278
+ })
279
+ })
280
+
281
+ describe('scheduleRelease', () => {
282
+ it('creates a release.schedule action with publishAt', () => {
283
+ const publishAt = '2026-01-01T00:00:00.000Z'
284
+ const action = scheduleRelease(dummyReleaseHandle, publishAt)
285
+ expect(action).toEqual({
286
+ type: 'release.schedule',
287
+ releaseId: 'my-release',
288
+ publishAt,
289
+ })
290
+ })
291
+ })
292
+
293
+ describe('unscheduleRelease', () => {
294
+ it('creates a release.unschedule action from a release handle', () => {
295
+ const action = unscheduleRelease(dummyReleaseHandle)
296
+ expect(action).toEqual({type: 'release.unschedule', releaseId: 'my-release'})
297
+ })
298
+ })
299
+
300
+ describe('archiveRelease', () => {
301
+ it('creates a release.archive action from a release handle', () => {
302
+ const action = archiveRelease(dummyReleaseHandle)
303
+ expect(action).toEqual({type: 'release.archive', releaseId: 'my-release'})
304
+ })
305
+ })
306
+
307
+ describe('unarchiveRelease', () => {
308
+ it('creates a release.unarchive action from a release handle', () => {
309
+ const action = unarchiveRelease(dummyReleaseHandle)
310
+ expect(action).toEqual({type: 'release.unarchive', releaseId: 'my-release'})
311
+ })
312
+ })
313
+
314
+ describe('deleteRelease', () => {
315
+ it('creates a release.delete action from a release handle', () => {
316
+ const action = deleteRelease(dummyReleaseHandle)
317
+ expect(action).toEqual({type: 'release.delete', releaseId: 'my-release'})
318
+ })
319
+ })
320
+ })