@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
@@ -11,16 +11,13 @@ import {
11
11
  } from './agentActions'
12
12
 
13
13
  let mockClient: any
14
- const mockGetClientState = vi.fn()
15
14
 
16
15
  vi.mock('../client/clientStore', () => {
17
16
  return {
18
- getClientState: (...args: unknown[]) => mockGetClientState(...args),
17
+ getClientState: () => ({observable: of(mockClient)}),
19
18
  }
20
19
  })
21
20
 
22
- const testResource = {projectId: 'p', dataset: 'd'}
23
-
24
21
  describe('agent actions', () => {
25
22
  beforeEach(() => {
26
23
  mockClient = {
@@ -40,86 +37,45 @@ describe('agent actions', () => {
40
37
  },
41
38
  },
42
39
  }
43
- mockGetClientState.mockReturnValue({observable: of(mockClient)})
44
40
  })
45
41
 
46
- it('agentGenerate passes resource to getClientState and strips it from agent options', async () => {
42
+ it('agentGenerate returns observable from client', async () => {
47
43
  mockClient.observable.agent.action.generate.mockReturnValue(of('gen'))
48
- const instance = {config: {}} as any
49
- const value = await firstValueFrom(
50
- agentGenerate(instance, {foo: 'bar', resource: testResource} as any),
51
- )
44
+ const instance = {config: {projectId: 'p', dataset: 'd'}} as any
45
+ const value = await firstValueFrom(agentGenerate(instance, {foo: 'bar'} as any))
52
46
  expect(value).toBe('gen')
53
- expect(mockGetClientState).toHaveBeenCalledWith(instance, {
54
- apiVersion: 'vX',
55
- resource: testResource,
56
- })
57
47
  expect(mockClient.observable.agent.action.generate).toHaveBeenCalledWith({foo: 'bar'})
58
48
  })
59
49
 
60
- it('agentTransform passes resource to getClientState and strips it from agent options', async () => {
50
+ it('agentTransform returns observable from client', async () => {
61
51
  mockClient.observable.agent.action.transform.mockReturnValue(of('xform'))
62
- const instance = {config: {}} as any
63
- const value = await firstValueFrom(
64
- agentTransform(instance, {a: 1, resource: testResource} as any),
65
- )
52
+ const instance = {config: {projectId: 'p', dataset: 'd'}} as any
53
+ const value = await firstValueFrom(agentTransform(instance, {a: 1} as any))
66
54
  expect(value).toBe('xform')
67
- expect(mockGetClientState).toHaveBeenCalledWith(instance, {
68
- apiVersion: 'vX',
69
- resource: testResource,
70
- })
71
55
  expect(mockClient.observable.agent.action.transform).toHaveBeenCalledWith({a: 1})
72
56
  })
73
57
 
74
- it('agentTranslate passes resource to getClientState and strips it from agent options', async () => {
58
+ it('agentTranslate returns observable from client', async () => {
75
59
  mockClient.observable.agent.action.translate.mockReturnValue(of('xlate'))
76
- const instance = {config: {}} as any
77
- const value = await firstValueFrom(
78
- agentTranslate(instance, {b: 2, resource: testResource} as any),
79
- )
60
+ const instance = {config: {projectId: 'p', dataset: 'd'}} as any
61
+ const value = await firstValueFrom(agentTranslate(instance, {b: 2} as any))
80
62
  expect(value).toBe('xlate')
81
- expect(mockGetClientState).toHaveBeenCalledWith(instance, {
82
- apiVersion: 'vX',
83
- resource: testResource,
84
- })
85
63
  expect(mockClient.observable.agent.action.translate).toHaveBeenCalledWith({b: 2})
86
64
  })
87
65
 
88
- it('agentPrompt passes resource to getClientState and strips it from agent options', async () => {
66
+ it('agentPrompt wraps promise into observable', async () => {
89
67
  mockClient.agent.action.prompt.mockResolvedValue('prompted')
90
- const instance = {config: {}} as any
91
- const value = await firstValueFrom(
92
- agentPrompt(instance, {p: true, resource: testResource} as any),
93
- )
68
+ const instance = {config: {projectId: 'p', dataset: 'd'}} as any
69
+ const value = await firstValueFrom(agentPrompt(instance, {p: true} as any))
94
70
  expect(value).toBe('prompted')
95
- expect(mockGetClientState).toHaveBeenCalledWith(instance, {
96
- apiVersion: 'vX',
97
- resource: testResource,
98
- })
99
71
  expect(mockClient.agent.action.prompt).toHaveBeenCalledWith({p: true})
100
72
  })
101
73
 
102
- it('agentPatch passes resource to getClientState and strips it from agent options', async () => {
74
+ it('agentPatch wraps promise into observable', async () => {
103
75
  mockClient.agent.action.patch.mockResolvedValue('patched')
104
- const instance = {config: {}} as any
105
- const value = await firstValueFrom(
106
- agentPatch(instance, {q: false, resource: testResource} as any),
107
- )
76
+ const instance = {config: {projectId: 'p', dataset: 'd'}} as any
77
+ const value = await firstValueFrom(agentPatch(instance, {q: false} as any))
108
78
  expect(value).toBe('patched')
109
- expect(mockGetClientState).toHaveBeenCalledWith(instance, {
110
- apiVersion: 'vX',
111
- resource: testResource,
112
- })
113
79
  expect(mockClient.agent.action.patch).toHaveBeenCalledWith({q: false})
114
80
  })
115
-
116
- it('works without an explicit resource (falls back via getClientState)', async () => {
117
- mockClient.observable.agent.action.generate.mockReturnValue(of('gen'))
118
- const instance = {config: {}} as any
119
- await firstValueFrom(agentGenerate(instance, {foo: 'bar'} as any))
120
- expect(mockGetClientState).toHaveBeenCalledWith(instance, {
121
- apiVersion: 'vX',
122
- resource: undefined,
123
- })
124
- })
125
81
  })
@@ -7,14 +7,6 @@ import {type SanityInstance} from '../store/createSanityInstance'
7
7
 
8
8
  const API_VERSION = 'vX'
9
9
 
10
- /**
11
- * Options that all agent actions accept for targeting a specific resource.
12
- * @alpha
13
- */
14
- export interface AgentResourceOptions {
15
- resource: DocumentResource
16
- }
17
-
18
10
  /** @alpha */
19
11
  export type AgentGenerateOptions = Parameters<
20
12
  SanityClient['observable']['agent']['action']['generate']
@@ -66,13 +58,12 @@ export type AgentPatchResult = Awaited<ReturnType<SanityClient['agent']['action'
66
58
  */
67
59
  export function agentGenerate(
68
60
  instance: SanityInstance,
69
- options: AgentGenerateOptions & AgentResourceOptions,
61
+ options: AgentGenerateOptions,
62
+ resource?: DocumentResource,
70
63
  ): AgentGenerateResult {
71
- const {resource, ...agentOptions} = options
72
- return getClientState(instance, {
73
- apiVersion: API_VERSION,
74
- resource,
75
- }).observable.pipe(switchMap((client) => client.observable.agent.action.generate(agentOptions)))
64
+ return getClientState(instance, {apiVersion: API_VERSION, resource}).observable.pipe(
65
+ switchMap((client) => client.observable.agent.action.generate(options)),
66
+ )
76
67
  }
77
68
 
78
69
  /**
@@ -84,13 +75,12 @@ export function agentGenerate(
84
75
  */
85
76
  export function agentTransform(
86
77
  instance: SanityInstance,
87
- options: AgentTransformOptions & AgentResourceOptions,
78
+ options: AgentTransformOptions,
79
+ resource?: DocumentResource,
88
80
  ): AgentTransformResult {
89
- const {resource, ...agentOptions} = options
90
- return getClientState(instance, {
91
- apiVersion: API_VERSION,
92
- resource,
93
- }).observable.pipe(switchMap((client) => client.observable.agent.action.transform(agentOptions)))
81
+ return getClientState(instance, {apiVersion: API_VERSION, resource}).observable.pipe(
82
+ switchMap((client) => client.observable.agent.action.transform(options)),
83
+ )
94
84
  }
95
85
 
96
86
  /**
@@ -102,13 +92,12 @@ export function agentTransform(
102
92
  */
103
93
  export function agentTranslate(
104
94
  instance: SanityInstance,
105
- options: AgentTranslateOptions & AgentResourceOptions,
95
+ options: AgentTranslateOptions,
96
+ resource?: DocumentResource,
106
97
  ): AgentTranslateResult {
107
- const {resource, ...agentOptions} = options
108
- return getClientState(instance, {
109
- apiVersion: API_VERSION,
110
- resource,
111
- }).observable.pipe(switchMap((client) => client.observable.agent.action.translate(agentOptions)))
98
+ return getClientState(instance, {apiVersion: API_VERSION, resource}).observable.pipe(
99
+ switchMap((client) => client.observable.agent.action.translate(options)),
100
+ )
112
101
  }
113
102
 
114
103
  /**
@@ -120,13 +109,12 @@ export function agentTranslate(
120
109
  */
121
110
  export function agentPrompt(
122
111
  instance: SanityInstance,
123
- options: AgentPromptOptions & AgentResourceOptions,
112
+ options: AgentPromptOptions,
113
+ resource?: DocumentResource,
124
114
  ): Observable<AgentPromptResult> {
125
- const {resource, ...agentOptions} = options
126
- return getClientState(instance, {
127
- apiVersion: API_VERSION,
128
- resource,
129
- }).observable.pipe(switchMap((client) => from(client.agent.action.prompt(agentOptions))))
115
+ return getClientState(instance, {apiVersion: API_VERSION, resource}).observable.pipe(
116
+ switchMap((client) => from(client.agent.action.prompt(options))),
117
+ )
130
118
  }
131
119
 
132
120
  /**
@@ -138,11 +126,10 @@ export function agentPrompt(
138
126
  */
139
127
  export function agentPatch(
140
128
  instance: SanityInstance,
141
- options: AgentPatchOptions & AgentResourceOptions,
129
+ options: AgentPatchOptions,
130
+ resource?: DocumentResource,
142
131
  ): Observable<AgentPatchResult> {
143
- const {resource, ...agentOptions} = options
144
- return getClientState(instance, {
145
- apiVersion: API_VERSION,
146
- resource,
147
- }).observable.pipe(switchMap((client) => from(client.agent.action.patch(agentOptions))))
132
+ return getClientState(instance, {apiVersion: API_VERSION, resource}).observable.pipe(
133
+ switchMap((client) => from(client.agent.action.patch(options))),
134
+ )
148
135
  }
@@ -0,0 +1,88 @@
1
+ import {expectTypeOf, test} from 'vitest'
2
+
3
+ import {type SanityInstance} from '../store/createSanityInstance'
4
+ import {type StateSource} from '../store/createStateSourceAction'
5
+ import {type FetcherSnapshot} from '../store/fetcherStore'
6
+ import {
7
+ type Application,
8
+ application,
9
+ type ApplicationBase,
10
+ type ApplicationDeployment,
11
+ type ApplicationInclude,
12
+ type ApplicationInterface,
13
+ applications,
14
+ type ApplicationsResponse,
15
+ type ApplicationStudioConfig,
16
+ } from './applications'
17
+
18
+ const instance = {} as SanityInstance
19
+
20
+ type ChildKeys = 'config' | 'activeDeployment'
21
+ type DeploymentChildKeys = 'interfaces' | 'workspaces' | 'access'
22
+
23
+ // Whether key `K` of `T` is optional, without an `{}`-based check.
24
+ type KeyModifier<T, K extends keyof T> =
25
+ Pick<T, K> extends Required<Pick<T, K>> ? 'required' : 'optional'
26
+
27
+ test('Application — no includes: only the base shape, no config or activeDeployment', () => {
28
+ expectTypeOf<Application>().toEqualTypeOf<ApplicationBase>()
29
+ expectTypeOf<Application<never>>().toEqualTypeOf<ApplicationBase>()
30
+ expectTypeOf<Extract<keyof Application, ChildKeys>>().toEqualTypeOf<never>()
31
+ })
32
+
33
+ test('ApplicationBase — carries name and reference as strings', () => {
34
+ expectTypeOf<ApplicationBase['name']>().toEqualTypeOf<string>()
35
+ expectTypeOf<ApplicationBase['reference']>().toEqualTypeOf<string>()
36
+ })
37
+
38
+ test('Application — config.studio adds a required config.studio', () => {
39
+ expectTypeOf<
40
+ Application<'config.studio'>['config']['studio']
41
+ >().toEqualTypeOf<ApplicationStudioConfig>()
42
+ // mfManifest not requested → not present under config
43
+ expectTypeOf<
44
+ Extract<keyof Application<'config.studio'>['config'], 'mfManifest'>
45
+ >().toEqualTypeOf<never>()
46
+ // requesting only config does not pull in the deployment
47
+ expectTypeOf<
48
+ Extract<keyof Application<'config.studio'>, 'activeDeployment'>
49
+ >().toEqualTypeOf<never>()
50
+ })
51
+
52
+ test('Application — both config tokens merge under a single config', () => {
53
+ type Config = Application<'config.studio' | 'config.mfManifest'>['config']
54
+ expectTypeOf<Config['studio']>().toEqualTypeOf<ApplicationStudioConfig>()
55
+ expectTypeOf<Config['mfManifest']>().toEqualTypeOf<unknown>()
56
+ })
57
+
58
+ test('Application — activeDeployment token adds the deployment summary, no children', () => {
59
+ expectTypeOf<
60
+ Application<'activeDeployment'>['activeDeployment']
61
+ >().toEqualTypeOf<ApplicationDeployment<'activeDeployment'> | null>()
62
+ type Deployment = NonNullable<Application<'activeDeployment'>['activeDeployment']>
63
+ expectTypeOf<Extract<keyof Deployment, DeploymentChildKeys>>().toEqualTypeOf<never>()
64
+ })
65
+
66
+ test('Application — a child token forces the deployment in and adds only that child', () => {
67
+ type Deployment = NonNullable<Application<'interfaces'>['activeDeployment']>
68
+ expectTypeOf<Deployment['interfaces']>().toEqualTypeOf<ApplicationInterface[]>()
69
+ expectTypeOf<Extract<keyof Deployment, 'workspaces' | 'access'>>().toEqualTypeOf<never>()
70
+ })
71
+
72
+ test('Application — a wide include array makes config and activeDeployment optional', () => {
73
+ type Wide = Application<ApplicationInclude>
74
+ expectTypeOf<KeyModifier<Wide, 'activeDeployment'>>().toEqualTypeOf<'optional'>()
75
+ expectTypeOf<KeyModifier<Wide, 'config'>>().toEqualTypeOf<'optional'>()
76
+ })
77
+
78
+ test('applications.resolveState — resolves the wide list envelope', () => {
79
+ expectTypeOf(
80
+ applications.resolveState(instance, {organizationId: 'org_1'}),
81
+ ).resolves.toEqualTypeOf<ApplicationsResponse<ApplicationInclude>>()
82
+ })
83
+
84
+ test('application.getState — exposes the snapshot envelope', () => {
85
+ expectTypeOf(application.getState(instance, 'app_1')).toEqualTypeOf<
86
+ StateSource<FetcherSnapshot<Application<ApplicationInclude>>>
87
+ >()
88
+ })
@@ -0,0 +1,130 @@
1
+ import {type SanityClient} from '@sanity/client'
2
+ import {of} from 'rxjs'
3
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'
4
+
5
+ import {getClientState} from '../client/clientStore'
6
+ import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
7
+ import {type StateSource} from '../store/createStateSourceAction'
8
+ import {defineMutation} from '../store/fetcherStore'
9
+ import {application, applications, deleteApplication, updateApplication} from './applications'
10
+
11
+ vi.mock('../client/clientStore')
12
+
13
+ describe('applications', () => {
14
+ let instance: SanityInstance
15
+ const request = vi.fn()
16
+
17
+ beforeEach(() => {
18
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
19
+ request.mockReset()
20
+ vi.mocked(getClientState).mockReturnValue({
21
+ observable: of({observable: {request}} as unknown as SanityClient),
22
+ } as StateSource<SanityClient>)
23
+ })
24
+
25
+ afterEach(() => {
26
+ instance.dispose()
27
+ })
28
+
29
+ it('lists applications for an organization, serialising include as a sorted CSV', async () => {
30
+ const response = {nextCursor: null, data: [{id: 'app1'}]}
31
+ request.mockReturnValue(of(response))
32
+
33
+ const result = await applications.resolveState(instance, {
34
+ organizationId: 'org1',
35
+ include: ['workspaces', 'access'],
36
+ limit: 'none',
37
+ })
38
+
39
+ expect(result).toEqual(response)
40
+ expect(getClientState).toHaveBeenCalledWith(instance, {
41
+ apiVersion: 'vX',
42
+ scope: 'global',
43
+ })
44
+ expect(request).toHaveBeenCalledWith({
45
+ uri: '/applications',
46
+ query: {organizationId: 'org1', include: 'access,workspaces', limit: 'none'},
47
+ tag: 'applications.list',
48
+ })
49
+ })
50
+
51
+ it('fetches a single application by id', async () => {
52
+ const app = {id: 'app1', title: 'One'}
53
+ request.mockReturnValue(of(app))
54
+
55
+ const result = await application.resolveState(instance, 'app1')
56
+
57
+ expect(result).toEqual(app)
58
+ expect(request).toHaveBeenCalledWith({
59
+ uri: '/applications/app1',
60
+ query: {},
61
+ tag: 'applications.get',
62
+ })
63
+ })
64
+
65
+ it('refetches the list when a mutation invalidates the LIST tag', async () => {
66
+ let n = 0
67
+ request.mockImplementation(() => of({nextCursor: null, data: [{id: `app-${++n}`}]}))
68
+
69
+ const source = applications.getState(instance, {organizationId: 'org1'})
70
+ const unsubscribe = source.subscribe()
71
+ await vi.waitFor(() => expect(source.getCurrent().status).toBe('success'))
72
+ expect(request).toHaveBeenCalledTimes(1)
73
+
74
+ const install = defineMutation<undefined, {ok: boolean}>({
75
+ name: 'test-install-application',
76
+ mutationFn: () => () => of({ok: true}),
77
+ invalidates: [{type: 'application', id: 'LIST'}],
78
+ })
79
+
80
+ const {invalidated} = await install(instance, undefined)
81
+ await invalidated
82
+
83
+ expect(request).toHaveBeenCalledTimes(2)
84
+ expect(source.getCurrent().data).toEqual({nextCursor: null, data: [{id: 'app-2'}]})
85
+ unsubscribe()
86
+ })
87
+
88
+ it('updates an application via PATCH and refetches the invalidated list', async () => {
89
+ request.mockImplementation((opts) => {
90
+ const {method} = opts as {method?: string}
91
+ return method === 'PATCH'
92
+ ? of({id: 'app1', title: 'New'})
93
+ : of({nextCursor: null, data: [{id: 'app1'}]})
94
+ })
95
+
96
+ const source = applications.getState(instance, {organizationId: 'org1'})
97
+ const unsubscribe = source.subscribe()
98
+ await vi.waitFor(() => expect(source.getCurrent().status).toBe('success'))
99
+
100
+ const {data, invalidated} = await updateApplication(instance, {
101
+ applicationId: 'app1',
102
+ title: 'New',
103
+ })
104
+ await invalidated
105
+
106
+ expect(data).toEqual({id: 'app1', title: 'New'})
107
+ expect(request).toHaveBeenCalledWith({
108
+ uri: '/applications/app1',
109
+ method: 'PATCH',
110
+ body: {title: 'New'},
111
+ tag: 'applications.update',
112
+ })
113
+ // initial list GET + PATCH + list refetch after invalidation
114
+ expect(request).toHaveBeenCalledTimes(3)
115
+ unsubscribe()
116
+ })
117
+
118
+ it('deletes an application via DELETE with no body', async () => {
119
+ request.mockReturnValue(of({deleted: true}))
120
+
121
+ const {data} = await deleteApplication(instance, {applicationId: 'app1'})
122
+
123
+ expect(data).toEqual({deleted: true})
124
+ expect(request).toHaveBeenCalledWith({
125
+ uri: '/applications/app1',
126
+ method: 'DELETE',
127
+ tag: 'applications.delete',
128
+ })
129
+ })
130
+ })