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

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 (197) hide show
  1. package/dist/_chunks-dts/createGroqSearchFilter.d.ts +1147 -0
  2. package/dist/_chunks-dts/createGroqSearchFilter.d.ts.map +1 -0
  3. package/dist/_chunks-es/_internal.js +134 -0
  4. package/dist/_chunks-es/_internal.js.map +1 -0
  5. package/dist/_chunks-es/createGroqSearchFilter.js +1864 -0
  6. package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -0
  7. package/dist/_chunks-es/telemetryManager.js +93 -0
  8. package/dist/_chunks-es/telemetryManager.js.map +1 -0
  9. package/dist/_exports/_internal.d.ts +95 -0
  10. package/dist/_exports/_internal.d.ts.map +1 -0
  11. package/dist/_exports/_internal.js +24 -0
  12. package/dist/_exports/_internal.js.map +1 -0
  13. package/dist/index.d.ts +1079 -1076
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +1967 -2302
  16. package/dist/index.js.map +1 -1
  17. package/package.json +48 -47
  18. package/src/_exports/_internal.ts +26 -0
  19. package/src/_exports/index.ts +120 -11
  20. package/src/access/checkPermissions.test.ts +55 -0
  21. package/src/access/checkPermissions.ts +54 -0
  22. package/src/agent/agentActions.test.ts +16 -60
  23. package/src/agent/agentActions.ts +25 -38
  24. package/src/applications/applications.test-d.ts +83 -0
  25. package/src/applications/applications.test.ts +130 -0
  26. package/src/applications/applications.ts +364 -0
  27. package/src/applications/userApplications.test.ts +126 -0
  28. package/src/applications/userApplications.ts +261 -0
  29. package/src/auth/authLogger.ts +30 -0
  30. package/src/auth/authMode.test.ts +25 -0
  31. package/src/auth/authMode.ts +6 -3
  32. package/src/auth/authStore.test.ts +194 -13
  33. package/src/auth/authStore.ts +59 -26
  34. package/src/auth/getOrganizationVerificationState.test.ts +18 -17
  35. package/src/auth/getOrganizationVerificationState.ts +4 -4
  36. package/src/auth/handleAuthCallback.test.ts +35 -1
  37. package/src/auth/handleAuthCallback.ts +25 -6
  38. package/src/auth/logout.test.ts +75 -2
  39. package/src/auth/logout.ts +23 -4
  40. package/src/auth/refreshStampedToken.test.ts +219 -469
  41. package/src/auth/refreshStampedToken.ts +79 -195
  42. package/src/auth/studioAuth.ts +1 -1
  43. package/src/auth/studioModeAuth.ts +2 -1
  44. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +146 -13
  45. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +37 -6
  46. package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +2 -0
  47. package/src/client/clientStore.test.ts +62 -37
  48. package/src/client/clientStore.ts +45 -75
  49. package/src/client/liveEvents.test.ts +151 -0
  50. package/src/client/liveEvents.ts +107 -0
  51. package/src/comlink/controller/actions/destroyController.test.ts +4 -1
  52. package/src/comlink/controller/actions/getOrCreateChannel.test.ts +4 -1
  53. package/src/comlink/controller/actions/getOrCreateChannel.ts +2 -2
  54. package/src/comlink/controller/actions/getOrCreateController.test.ts +4 -1
  55. package/src/comlink/controller/actions/releaseChannel.test.ts +1 -1
  56. package/src/comlink/controller/comlinkControllerStore.test.ts +4 -1
  57. package/src/comlink/node/actions/getOrCreateNode.test.ts +9 -3
  58. package/src/comlink/node/actions/getOrCreateNode.ts +2 -2
  59. package/src/comlink/node/actions/releaseNode.test.ts +7 -4
  60. package/src/comlink/node/comlinkNodeStore.test.ts +2 -2
  61. package/src/comlink/node/getNodeState.test.ts +1 -1
  62. package/src/comlink/node/getNodeState.ts +2 -1
  63. package/src/config/__tests__/handles.test.ts +18 -12
  64. package/src/config/handles.ts +25 -7
  65. package/src/config/sanityConfig.ts +109 -79
  66. package/src/datasets/datasets.test.ts +2 -2
  67. package/src/datasets/datasets.ts +10 -4
  68. package/src/document/actions.test.ts +115 -33
  69. package/src/document/actions.ts +212 -15
  70. package/src/document/applyDocumentActions.test.ts +38 -12
  71. package/src/document/applyDocumentActions.ts +30 -9
  72. package/src/document/documentConstants.ts +7 -0
  73. package/src/document/documentStore.concurrency.test.ts +1306 -0
  74. package/src/document/documentStore.test.ts +673 -278
  75. package/src/document/documentStore.ts +162 -71
  76. package/src/document/events.test.ts +57 -2
  77. package/src/document/events.ts +82 -26
  78. package/src/document/listen.test.ts +56 -0
  79. package/src/document/listen.ts +74 -21
  80. package/src/document/listenerEventOperators.test.ts +311 -0
  81. package/src/document/listenerEventOperators.ts +217 -0
  82. package/src/document/patchOperations.test.ts +49 -2
  83. package/src/document/patchOperations.ts +50 -0
  84. package/src/document/permissions.test.ts +105 -60
  85. package/src/document/permissions.ts +44 -19
  86. package/src/document/processActions/create.ts +138 -0
  87. package/src/document/processActions/delete.ts +100 -0
  88. package/src/document/processActions/discard.ts +63 -0
  89. package/src/document/processActions/edit.ts +154 -0
  90. package/src/document/processActions/processActions.ts +218 -0
  91. package/src/document/processActions/publish.ts +120 -0
  92. package/src/document/processActions/releaseArchive.ts +77 -0
  93. package/src/document/processActions/releaseCreate.ts +59 -0
  94. package/src/document/processActions/releaseDelete.ts +65 -0
  95. package/src/document/processActions/releaseEdit.ts +37 -0
  96. package/src/document/processActions/releasePublish.ts +45 -0
  97. package/src/document/processActions/releaseSchedule.ts +87 -0
  98. package/src/document/processActions/releaseUtil.ts +31 -0
  99. package/src/document/processActions/shared.ts +308 -0
  100. package/src/document/processActions/unpublish.ts +85 -0
  101. package/src/document/processActions.test.ts +1129 -121
  102. package/src/document/reducers.test.ts +639 -64
  103. package/src/document/reducers.ts +187 -48
  104. package/src/document/resourceRules.test.ts +178 -0
  105. package/src/document/resourceRules.ts +117 -0
  106. package/src/document/sharedListener.test.ts +16 -14
  107. package/src/document/sharedListener.ts +24 -8
  108. package/src/document/util.ts +14 -0
  109. package/src/favorites/favorites.test.ts +5 -6
  110. package/src/installations/installations.test-d.ts +68 -0
  111. package/src/installations/installations.test.ts +62 -0
  112. package/src/installations/installations.ts +202 -0
  113. package/src/organization/organization.test-d.ts +36 -0
  114. package/src/organization/organization.test.ts +138 -0
  115. package/src/organization/organization.ts +138 -0
  116. package/src/organizations/organizations.test-d.ts +56 -0
  117. package/src/organizations/organizations.test.ts +150 -0
  118. package/src/organizations/organizations.ts +107 -0
  119. package/src/presence/bifurTransport.test.ts +46 -6
  120. package/src/presence/bifurTransport.ts +19 -2
  121. package/src/presence/presenceStore.test.ts +94 -23
  122. package/src/presence/presenceStore.ts +85 -29
  123. package/src/preview/getPreviewState.test.ts +137 -0
  124. package/src/preview/getPreviewState.ts +69 -0
  125. package/src/preview/previewProjectionUtils.test.ts +9 -22
  126. package/src/preview/previewProjectionUtils.ts +7 -3
  127. package/src/preview/resolvePreview.test.ts +64 -0
  128. package/src/preview/resolvePreview.ts +43 -0
  129. package/src/preview/types.ts +10 -0
  130. package/src/project/project.test-d.ts +37 -0
  131. package/src/project/project.test.ts +157 -12
  132. package/src/project/project.ts +138 -25
  133. package/src/projection/getProjectionState.test.ts +18 -20
  134. package/src/projection/getProjectionState.ts +23 -3
  135. package/src/projection/projectionQuery.ts +5 -5
  136. package/src/projection/projectionStore.test.ts +1 -1
  137. package/src/projection/resolveProjection.test.ts +1 -2
  138. package/src/projection/resolveProjection.ts +16 -0
  139. package/src/projection/subscribeToStateAndFetchBatches.test.ts +1 -1
  140. package/src/projection/subscribeToStateAndFetchBatches.ts +32 -23
  141. package/src/projection/types.ts +8 -0
  142. package/src/projects/projects.test-d.ts +32 -0
  143. package/src/projects/projects.test.ts +108 -42
  144. package/src/projects/projects.ts +63 -27
  145. package/src/query/queryStore.test.ts +259 -123
  146. package/src/query/queryStore.ts +78 -63
  147. package/src/query/reducers.test.ts +0 -42
  148. package/src/query/reducers.ts +2 -18
  149. package/src/releases/getPerspectiveState.test.ts +17 -23
  150. package/src/releases/getPerspectiveState.ts +8 -20
  151. package/src/releases/observeReleases.test.ts +127 -0
  152. package/src/releases/observeReleases.ts +102 -0
  153. package/src/releases/releasesStore.test.ts +100 -53
  154. package/src/releases/releasesStore.ts +69 -44
  155. package/src/releases/utils/sortReleases.test.ts +38 -2
  156. package/src/releases/utils/sortReleases.ts +15 -10
  157. package/src/store/createActionBinder.test.ts +87 -90
  158. package/src/store/createActionBinder.ts +79 -25
  159. package/src/store/createSanityInstance.test.ts +83 -13
  160. package/src/store/createSanityInstance.ts +77 -2
  161. package/src/store/createStateSourceAction.test.ts +64 -2
  162. package/src/store/createStateSourceAction.ts +39 -44
  163. package/src/store/createStoreInstance.test.ts +4 -2
  164. package/src/store/fetcherStore.test-d.ts +121 -0
  165. package/src/store/fetcherStore.test.ts +299 -0
  166. package/src/store/fetcherStore.ts +801 -0
  167. package/src/telemetry/environment.test.ts +119 -0
  168. package/src/telemetry/environment.ts +92 -0
  169. package/src/telemetry/events.ts +42 -0
  170. package/src/telemetry/initTelemetry.test.ts +432 -0
  171. package/src/telemetry/initTelemetry.ts +218 -0
  172. package/src/telemetry/telemetryManager.test.ts +327 -0
  173. package/src/telemetry/telemetryManager.ts +199 -0
  174. package/src/users/reducers.test.ts +6 -1
  175. package/src/users/reducers.ts +5 -6
  176. package/src/users/types.ts +4 -4
  177. package/src/users/usersStore.test.ts +16 -12
  178. package/src/users/usersStore.ts +5 -1
  179. package/src/utils/buildQuery.test.ts +14 -0
  180. package/src/utils/buildQuery.ts +17 -0
  181. package/src/utils/createFetcherStore.test.ts +7 -5
  182. package/src/utils/createFetcherStore.ts +8 -5
  183. package/src/utils/getStagingApiHost.test.ts +21 -0
  184. package/src/utils/getStagingApiHost.ts +14 -0
  185. package/src/utils/ids.test.ts +1 -29
  186. package/src/utils/ids.ts +0 -10
  187. package/src/utils/includeShape.ts +36 -0
  188. package/src/utils/isImportError.test.ts +72 -0
  189. package/src/utils/isImportError.ts +34 -0
  190. package/src/utils/logger.test.ts +12 -0
  191. package/src/utils/logger.ts +8 -3
  192. package/src/utils/object.test.ts +95 -0
  193. package/src/utils/object.ts +142 -0
  194. package/src/utils/setCleanupTimeout.ts +37 -0
  195. package/src/document/processActions.ts +0 -707
  196. package/src/utils/defineIntent.test.ts +0 -477
  197. package/src/utils/defineIntent.ts +0 -244
@@ -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
+ })
@@ -1,9 +1,15 @@
1
+ import {type ReleaseDocument} from '@sanity/client'
1
2
  import {SanityEncoder} from '@sanity/mutate'
2
3
  import {type PatchMutation as SanityMutatePatchMutation} from '@sanity/mutate/_unstable_store'
3
- import {type PatchMutation, type PatchOperations, type SanityDocument} from '@sanity/types'
4
+ import {type PatchMutation, type PatchOperations} from '@sanity/types'
5
+ import {type SanityDocument} from 'groq'
4
6
 
5
- import {type DocumentHandle, type DocumentTypeHandle} from '../config/sanityConfig'
6
- import {getPublishedId} from '../utils/ids'
7
+ import {
8
+ type DocumentHandle,
9
+ type DocumentTypeHandle,
10
+ type ReleaseHandle,
11
+ } from '../config/sanityConfig'
12
+ import {getEffectiveDocumentId} from './util'
7
13
 
8
14
  const isSanityMutatePatch = (value: unknown): value is SanityMutatePatchMutation => {
9
15
  if (typeof value !== 'object' || !value) return false
@@ -30,7 +36,10 @@ export interface CreateDocumentAction<
30
36
  * System fields (_id, _type, _rev, _createdAt, _updatedAt) are omitted as they are set automatically.
31
37
  */
32
38
  initialValue?: Partial<
33
- Omit<SanityDocument, '_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'>
39
+ Omit<
40
+ SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`>,
41
+ '_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'
42
+ >
34
43
  >
35
44
  }
36
45
 
@@ -59,6 +68,21 @@ export interface EditDocumentAction<
59
68
  > extends DocumentHandle<TDocumentType, TDataset, TProjectId> {
60
69
  type: 'document.edit'
61
70
  patches?: PatchOperations[]
71
+ /**
72
+ * When `true`, the given `patches` are forwarded verbatim to the server and
73
+ * applied as-is locally, instead of being re-derived by diffing document
74
+ * snapshots. This preserves the operational intent of the patches (e.g.
75
+ * keyed array inserts/unsets), which lets concurrent edits from other
76
+ * clients interleave coherently instead of being overwritten by
77
+ * position-based patches computed from a stale snapshot.
78
+ *
79
+ * Use this when the patches were produced by an editor that tracks its own
80
+ * operations (e.g. a collaborative text editor). During a rebase onto a
81
+ * changed remote document, preserved patches are re-applied operationally;
82
+ * if a patch can no longer apply, the transaction is skipped and reported
83
+ * as a `rebase-error` document event.
84
+ */
85
+ preserveOperations?: boolean
62
86
  }
63
87
 
64
88
  /**
@@ -116,6 +140,17 @@ export type DocumentAction<
116
140
  | UnpublishDocumentAction<TDocumentType, TDataset, TProjectId>
117
141
  | DiscardDocumentAction<TDocumentType, TDataset, TProjectId>
118
142
 
143
+ /**
144
+ * Union of every action accepted by `applyDocumentActions` — both document-
145
+ * level actions and release-lifecycle actions.
146
+ * @beta
147
+ */
148
+ export type Action<
149
+ TDocumentType extends string = string,
150
+ TDataset extends string = string,
151
+ TProjectId extends string = string,
152
+ > = DocumentAction<TDocumentType, TDataset, TProjectId> | ReleaseAction
153
+
119
154
  /**
120
155
  * Creates a `CreateDocumentAction` object.
121
156
  * @param doc - A handle identifying the document type, dataset, and project. An optional `documentId` can be provided.
@@ -130,15 +165,21 @@ export function createDocument<
130
165
  >(
131
166
  doc: DocumentTypeHandle<TDocumentType, TDataset, TProjectId>,
132
167
  initialValue?: Partial<
133
- Omit<SanityDocument, '_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'>
168
+ Omit<
169
+ SanityDocument<TDocumentType, `${TProjectId}.${TDataset}`>,
170
+ '_id' | '_type' | '_rev' | '_createdAt' | '_updatedAt'
171
+ >
134
172
  >,
135
173
  ): CreateDocumentAction<TDocumentType, TDataset, TProjectId> {
174
+ // users may pass in an explicit documentId -- make sure we format it correctly for the action
175
+ let effectiveDocumentId
176
+ if (typeof doc.documentId === 'string') {
177
+ effectiveDocumentId = getEffectiveDocumentId({...doc, documentId: doc.documentId})
178
+ }
136
179
  return {
137
180
  type: 'document.create',
138
181
  ...doc,
139
- ...(doc.documentId && {
140
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId),
141
- }),
182
+ ...(effectiveDocumentId && {documentId: effectiveDocumentId}),
142
183
  ...(initialValue && {initialValue}),
143
184
  }
144
185
  }
@@ -156,10 +197,11 @@ export function deleteDocument<
156
197
  >(
157
198
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
158
199
  ): DeleteDocumentAction<TDocumentType, TDataset, TProjectId> {
200
+ const effectiveDocumentId = getEffectiveDocumentId(doc)
159
201
  return {
160
202
  type: 'document.delete',
161
203
  ...doc,
162
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId),
204
+ documentId: effectiveDocumentId,
163
205
  }
164
206
  }
165
207
 
@@ -174,12 +216,25 @@ function convertSanityMutatePatch(
174
216
  })
175
217
  }
176
218
 
219
+ /**
220
+ * Options for creating an `EditDocumentAction`.
221
+ * @beta
222
+ */
223
+ export interface EditDocumentOptions {
224
+ /**
225
+ * Forward the given patches verbatim instead of re-deriving them by
226
+ * diffing document snapshots. See {@link EditDocumentAction.preserveOperations}.
227
+ */
228
+ preserveOperations?: boolean
229
+ }
230
+
177
231
  /**
178
232
  * Creates an `EditDocumentAction` object with patches for modifying a document.
179
233
  * Accepts patches in either the standard `PatchOperations` format or as a `SanityMutatePatchMutation` from `@sanity/mutate`.
180
234
  *
181
235
  * @param doc - A handle uniquely identifying the document to be edited.
182
236
  * @param sanityMutatePatch - A patch mutation object from `@sanity/mutate`.
237
+ * @param options - Options controlling how the patches are processed.
183
238
  * @returns An `EditDocumentAction` object ready for dispatch.
184
239
  * @beta
185
240
  */
@@ -190,12 +245,14 @@ export function editDocument<
190
245
  >(
191
246
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
192
247
  sanityMutatePatch: SanityMutatePatchMutation,
248
+ options?: EditDocumentOptions,
193
249
  ): EditDocumentAction<TDocumentType, TDataset, TProjectId>
194
250
  /**
195
251
  * Creates an `EditDocumentAction` object with patches for modifying a document.
196
252
  *
197
253
  * @param doc - A handle uniquely identifying the document to be edited.
198
254
  * @param patches - A single patch operation or an array of patch operations.
255
+ * @param options - Options controlling how the patches are processed.
199
256
  * @returns An `EditDocumentAction` object ready for dispatch.
200
257
  * @beta
201
258
  */
@@ -206,6 +263,7 @@ export function editDocument<
206
263
  >(
207
264
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
208
265
  patches?: PatchOperations | PatchOperations[],
266
+ options?: EditDocumentOptions,
209
267
  ): EditDocumentAction<TDocumentType, TDataset, TProjectId>
210
268
  /**
211
269
  * Creates an `EditDocumentAction` object with patches for modifying a document.
@@ -213,6 +271,7 @@ export function editDocument<
213
271
  *
214
272
  * @param doc - A handle uniquely identifying the document to be edited.
215
273
  * @param patches - Patches in various formats (`PatchOperations`, `PatchOperations[]`, or `SanityMutatePatchMutation`).
274
+ * @param options - Options controlling how the patches are processed.
216
275
  * @returns An `EditDocumentAction` object ready for dispatch.
217
276
  */
218
277
  export function editDocument<
@@ -222,24 +281,28 @@ export function editDocument<
222
281
  >(
223
282
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
224
283
  patches?: PatchOperations | PatchOperations[] | SanityMutatePatchMutation,
284
+ options?: EditDocumentOptions,
225
285
  ): EditDocumentAction<TDocumentType, TDataset, TProjectId> {
226
- const documentId = doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
286
+ const effectiveDocumentId = getEffectiveDocumentId(doc)
287
+ const preserveOperations = options?.preserveOperations && {preserveOperations: true as const}
227
288
 
228
289
  if (isSanityMutatePatch(patches)) {
229
290
  const converted = convertSanityMutatePatch(patches) ?? []
230
291
  return {
231
292
  ...doc,
232
293
  type: 'document.edit',
233
- documentId,
294
+ documentId: effectiveDocumentId,
234
295
  patches: converted,
296
+ ...preserveOperations,
235
297
  }
236
298
  }
237
299
 
238
300
  return {
239
301
  ...doc,
240
302
  type: 'document.edit',
241
- documentId,
303
+ documentId: effectiveDocumentId,
242
304
  ...(patches && {patches: Array.isArray(patches) ? patches : [patches]}),
305
+ ...preserveOperations,
243
306
  }
244
307
  }
245
308
 
@@ -256,10 +319,11 @@ export function publishDocument<
256
319
  >(
257
320
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
258
321
  ): PublishDocumentAction<TDocumentType, TDataset, TProjectId> {
322
+ const effectiveDocumentId = getEffectiveDocumentId(doc)
259
323
  return {
260
324
  type: 'document.publish',
261
325
  ...doc,
262
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId),
326
+ documentId: effectiveDocumentId,
263
327
  }
264
328
  }
265
329
 
@@ -276,10 +340,11 @@ export function unpublishDocument<
276
340
  >(
277
341
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
278
342
  ): UnpublishDocumentAction<TDocumentType, TDataset, TProjectId> {
343
+ const effectiveDocumentId = getEffectiveDocumentId(doc)
279
344
  return {
280
345
  type: 'document.unpublish',
281
346
  ...doc,
282
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId),
347
+ documentId: effectiveDocumentId,
283
348
  }
284
349
  }
285
350
 
@@ -296,9 +361,141 @@ export function discardDocument<
296
361
  >(
297
362
  doc: DocumentHandle<TDocumentType, TDataset, TProjectId>,
298
363
  ): DiscardDocumentAction<TDocumentType, TDataset, TProjectId> {
364
+ const effectiveDocumentId = getEffectiveDocumentId(doc)
299
365
  return {
300
366
  type: 'document.discard',
301
367
  ...doc,
302
- documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId),
368
+ documentId: effectiveDocumentId,
303
369
  }
304
370
  }
371
+
372
+ /**
373
+ * Creates a new release. The `releaseId` must be unique within the current
374
+ * retention period.
375
+ * @beta
376
+ */
377
+ export interface CreateReleaseAction extends ReleaseHandle {
378
+ type: 'release.create'
379
+ metadata: ReleaseDocument['metadata']
380
+ }
381
+
382
+ /**
383
+ * Patches the metadata of an existing release.
384
+ * @beta
385
+ */
386
+ export interface EditReleaseAction extends ReleaseHandle {
387
+ type: 'release.edit'
388
+ patch: PatchOperations
389
+ }
390
+
391
+ /**
392
+ * Publishes all version documents in a release.
393
+ * @beta
394
+ */
395
+ export interface PublishReleaseAction extends ReleaseHandle {
396
+ type: 'release.publish'
397
+ }
398
+
399
+ /**
400
+ * Schedules a release to be published at the given UTC time. Locks the
401
+ * version documents server-side until the release is unscheduled or published.
402
+ * @beta
403
+ */
404
+ export interface ScheduleReleaseAction extends ReleaseHandle {
405
+ type: 'release.schedule'
406
+ publishAt: string
407
+ }
408
+
409
+ /**
410
+ * Unschedules a release that was previously scheduled, returning it to the
411
+ * active editable state.
412
+ * @beta
413
+ */
414
+ export interface UnscheduleReleaseAction extends ReleaseHandle {
415
+ type: 'release.unschedule'
416
+ }
417
+
418
+ /**
419
+ * Archives an active release. Version documents within the release are
420
+ * removed and no longer queryable, though still recoverable through history
421
+ * during the retention period.
422
+ * @beta
423
+ */
424
+ export interface ArchiveReleaseAction extends ReleaseHandle {
425
+ type: 'release.archive'
426
+ }
427
+
428
+ /**
429
+ * Restores an archived release. Only possible during the retention period.
430
+ * @beta
431
+ */
432
+ export interface UnarchiveReleaseAction extends ReleaseHandle {
433
+ type: 'release.unarchive'
434
+ }
435
+
436
+ /**
437
+ * Permanently deletes an archived or published release. To remove an active
438
+ * release, use the archive action first.
439
+ * @beta
440
+ */
441
+ export interface DeleteReleaseAction extends ReleaseHandle {
442
+ type: 'release.delete'
443
+ }
444
+
445
+ /**
446
+ * Union of all release actions that can be dispatched alongside document
447
+ * actions through `applyDocumentActions`.
448
+ * @beta
449
+ */
450
+ export type ReleaseAction =
451
+ | CreateReleaseAction
452
+ | EditReleaseAction
453
+ | PublishReleaseAction
454
+ | ScheduleReleaseAction
455
+ | UnscheduleReleaseAction
456
+ | ArchiveReleaseAction
457
+ | UnarchiveReleaseAction
458
+ | DeleteReleaseAction
459
+
460
+ /** @beta */
461
+ export function createRelease(
462
+ handle: ReleaseHandle,
463
+ metadata: ReleaseDocument['metadata'] = {releaseType: 'undecided'},
464
+ ): CreateReleaseAction {
465
+ return {type: 'release.create', ...handle, metadata}
466
+ }
467
+
468
+ /** @beta */
469
+ export function editRelease(handle: ReleaseHandle, patch: PatchOperations): EditReleaseAction {
470
+ return {type: 'release.edit', ...handle, patch}
471
+ }
472
+
473
+ /** @beta */
474
+ export function publishRelease(handle: ReleaseHandle): PublishReleaseAction {
475
+ return {type: 'release.publish', ...handle}
476
+ }
477
+
478
+ /** @beta */
479
+ export function scheduleRelease(handle: ReleaseHandle, publishAt: string): ScheduleReleaseAction {
480
+ return {type: 'release.schedule', ...handle, publishAt}
481
+ }
482
+
483
+ /** @beta */
484
+ export function unscheduleRelease(handle: ReleaseHandle): UnscheduleReleaseAction {
485
+ return {type: 'release.unschedule', ...handle}
486
+ }
487
+
488
+ /** @beta */
489
+ export function archiveRelease(handle: ReleaseHandle): ArchiveReleaseAction {
490
+ return {type: 'release.archive', ...handle}
491
+ }
492
+
493
+ /** @beta */
494
+ export function unarchiveRelease(handle: ReleaseHandle): UnarchiveReleaseAction {
495
+ return {type: 'release.unarchive', ...handle}
496
+ }
497
+
498
+ /** @beta */
499
+ export function deleteRelease(handle: ReleaseHandle): DeleteReleaseAction {
500
+ return {type: 'release.delete', ...handle}
501
+ }