@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,7 +1,7 @@
1
1
  import {type ClientConfig, createClient, type SanityClient} from '@sanity/client'
2
2
  import {type CurrentUser} from '@sanity/types'
3
3
  import {NEVER, type Subscription} from 'rxjs'
4
- import {afterEach, beforeEach, describe, it, vi} from 'vitest'
4
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'
5
5
 
6
6
  import {createSanityInstance} from '../store/createSanityInstance'
7
7
  import {AuthStateType} from './authStateType'
@@ -46,6 +46,24 @@ vi.mock('./studioModeAuth', async (importOriginal) => {
46
46
 
47
47
  vi.mock('./subscribeToStateAndFetchCurrentUser')
48
48
  vi.mock('./subscribeToStorageEventsAndSetToken')
49
+ // Mock logger to prevent actual logging during tests
50
+ vi.mock('../utils/logger', async (importOriginal) => {
51
+ const original = await importOriginal<typeof import('../utils/logger')>()
52
+ return {
53
+ ...original,
54
+ createLogger: vi.fn(() => ({
55
+ info: vi.fn(),
56
+ debug: vi.fn(),
57
+ warn: vi.fn(),
58
+ error: vi.fn(),
59
+ trace: vi.fn(),
60
+ })),
61
+ }
62
+ })
63
+
64
+ // Import createLogger after mocking
65
+ // eslint-disable-next-line import-x/first
66
+ import {createLogger} from '../utils/logger'
49
67
 
50
68
  describe('authStore', () => {
51
69
  // Global beforeEach and afterEach for all tests
@@ -73,6 +91,35 @@ describe('authStore', () => {
73
91
  instance?.dispose()
74
92
  })
75
93
 
94
+ it('uses staging apiHost when __SANITY_STAGING__ is true and no explicit apiHost', () => {
95
+ vi.stubGlobal('__SANITY_STAGING__', true)
96
+
97
+ instance = createSanityInstance({
98
+ projectId: 'p',
99
+ dataset: 'd',
100
+ })
101
+
102
+ const {options} = authStore.getInitialState(instance, null)
103
+ expect(options.apiHost).toBe('https://api.sanity.work')
104
+
105
+ vi.unstubAllGlobals()
106
+ })
107
+
108
+ it('prefers explicit apiHost over __SANITY_STAGING__', () => {
109
+ vi.stubGlobal('__SANITY_STAGING__', true)
110
+
111
+ instance = createSanityInstance({
112
+ projectId: 'p',
113
+ dataset: 'd',
114
+ auth: {apiHost: 'https://custom.host'},
115
+ })
116
+
117
+ const {options} = authStore.getInitialState(instance, null)
118
+ expect(options.apiHost).toBe('https://custom.host')
119
+
120
+ vi.unstubAllGlobals()
121
+ })
122
+
76
123
  it('sets initial options onto state', () => {
77
124
  const apiHost = 'test-api-host'
78
125
  const callbackUrl = '/login/callback'
@@ -85,6 +132,8 @@ describe('authStore', () => {
85
132
  const storageArea = {} as Storage
86
133
 
87
134
  instance = createSanityInstance({
135
+ projectId: 'p',
136
+ dataset: 'd',
88
137
  auth: {
89
138
  apiHost,
90
139
  callbackUrl,
@@ -113,6 +162,8 @@ describe('authStore', () => {
113
162
  const context = {mode: 'test', env: 'staging', orgId: 'abc'}
114
163
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
115
164
  instance = createSanityInstance({
165
+ projectId: 'p',
166
+ dataset: 'd',
116
167
  auth: {initialLocationHref},
117
168
  })
118
169
 
@@ -126,6 +177,8 @@ describe('authStore', () => {
126
177
  const expectedContext = {mode: 'test', env: 'staging', orgId: 'abc'}
127
178
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
128
179
  instance = createSanityInstance({
180
+ projectId: 'p',
181
+ dataset: 'd',
129
182
  auth: {initialLocationHref},
130
183
  })
131
184
 
@@ -138,6 +191,8 @@ describe('authStore', () => {
138
191
  const initialLocationHref = `https://example.com/?_context=invalid-json`
139
192
  const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
140
193
  instance = createSanityInstance({
194
+ projectId: 'p',
195
+ dataset: 'd',
141
196
  auth: {initialLocationHref},
142
197
  })
143
198
 
@@ -154,6 +209,8 @@ describe('authStore', () => {
154
209
  it('rejects array _context and falls back to standalone mode', () => {
155
210
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(['a', 'b']))}`
156
211
  instance = createSanityInstance({
212
+ projectId: 'p',
213
+ dataset: 'd',
157
214
  auth: {initialLocationHref},
158
215
  })
159
216
 
@@ -166,6 +223,8 @@ describe('authStore', () => {
166
223
  it('rejects empty object _context and falls back to standalone mode', () => {
167
224
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify({}))}`
168
225
  instance = createSanityInstance({
226
+ projectId: 'p',
227
+ dataset: 'd',
169
228
  auth: {initialLocationHref},
170
229
  })
171
230
 
@@ -180,6 +239,8 @@ describe('authStore', () => {
180
239
  const context = {mode: 'dashboard'}
181
240
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
182
241
  instance = createSanityInstance({
242
+ projectId: 'p',
243
+ dataset: 'd',
183
244
  auth: {
184
245
  token,
185
246
  initialLocationHref,
@@ -195,6 +256,8 @@ describe('authStore', () => {
195
256
  const context = {orgId: 'org1'}
196
257
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
197
258
  instance = createSanityInstance({
259
+ projectId: 'p',
260
+ dataset: 'd',
198
261
  auth: {initialLocationHref},
199
262
  })
200
263
 
@@ -207,7 +270,10 @@ describe('authStore', () => {
207
270
 
208
271
  it('sets to logged in from storage token when NOT in dashboard', () => {
209
272
  const storageToken = 'storage-token'
210
- instance = createSanityInstance()
273
+ instance = createSanityInstance({
274
+ projectId: 'p',
275
+ dataset: 'd',
276
+ })
211
277
 
212
278
  vi.mocked(getAuthCode).mockReturnValue(null)
213
279
  vi.mocked(getTokenFromStorage).mockReturnValue(storageToken)
@@ -222,6 +288,8 @@ describe('authStore', () => {
222
288
  const context = {mode: 'dashboard'}
223
289
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
224
290
  instance = createSanityInstance({
291
+ projectId: 'p',
292
+ dataset: 'd',
225
293
  auth: {initialLocationHref},
226
294
  })
227
295
 
@@ -234,7 +302,10 @@ describe('authStore', () => {
234
302
  })
235
303
 
236
304
  it('sets the state to logged out when no token, code, or context', () => {
237
- instance = createSanityInstance()
305
+ instance = createSanityInstance({
306
+ projectId: 'p',
307
+ dataset: 'd',
308
+ })
238
309
 
239
310
  vi.mocked(getAuthCode).mockReturnValue(null)
240
311
  vi.mocked(getTokenFromStorage).mockReturnValue(null)
@@ -256,8 +327,10 @@ describe('authStore', () => {
256
327
  vi.mocked(getStudioTokenFromLocalStorage).mockReturnValue(studioToken)
257
328
 
258
329
  instance = createSanityInstance({
259
- studio: {projectId},
260
- auth: {storageArea: mockStorage},
330
+ projectId,
331
+ dataset: 'd',
332
+ studio: {},
333
+ auth: {storageArea: mockStorage}, // Provide mock storage
261
334
  })
262
335
 
263
336
  const {authState, options} = authStore.getInitialState(instance, null)
@@ -266,6 +339,54 @@ describe('authStore', () => {
266
339
  expect(options.authMethod).toBe('localstorage')
267
340
  })
268
341
 
342
+ it('logs auth initialized in logged out state when no token available', () => {
343
+ instance = createSanityInstance({
344
+ projectId: 'p',
345
+ dataset: 'd',
346
+ })
347
+
348
+ vi.mocked(getAuthCode).mockReturnValue(null)
349
+ vi.mocked(getTokenFromStorage).mockReturnValue(null)
350
+ vi.mocked(getTokenFromLocation).mockReturnValue(null)
351
+
352
+ const {authState} = authStore.getInitialState(instance, null)
353
+ expect(authState.type).toBe(AuthStateType.LOGGED_OUT)
354
+ // Logger should have been called
355
+ expect(createLogger).toHaveBeenCalled()
356
+ })
357
+
358
+ it('logs when auth initialized with storage token', () => {
359
+ const storageToken = 'storage-token'
360
+ instance = createSanityInstance({
361
+ projectId: 'p',
362
+ dataset: 'd',
363
+ })
364
+
365
+ vi.mocked(getAuthCode).mockReturnValue(null)
366
+ vi.mocked(getTokenFromStorage).mockReturnValue(storageToken)
367
+ vi.mocked(getTokenFromLocation).mockReturnValue(null)
368
+
369
+ const {authState} = authStore.getInitialState(instance, null)
370
+ expect(authState).toMatchObject({type: AuthStateType.LOGGED_IN, token: storageToken})
371
+ // Logger should have been called
372
+ expect(createLogger).toHaveBeenCalled()
373
+ })
374
+
375
+ it('logs when auth initialized with logging in state', () => {
376
+ instance = createSanityInstance({
377
+ projectId: 'p',
378
+ dataset: 'd',
379
+ })
380
+
381
+ vi.mocked(getAuthCode).mockReturnValue('test-code')
382
+ vi.mocked(getTokenFromLocation).mockReturnValue(null)
383
+
384
+ const {authState} = authStore.getInitialState(instance, null)
385
+ expect(authState.type).toBe(AuthStateType.LOGGING_IN)
386
+ // Logger should have been called
387
+ expect(createLogger).toHaveBeenCalled()
388
+ })
389
+
269
390
  it('checks for cookie auth during initialize when studio config is provided and no studio token exists', () => {
270
391
  const projectId = 'studio-project'
271
392
  const studioStorageKey = `__studio_auth_token_${projectId}`
@@ -278,7 +399,9 @@ describe('authStore', () => {
278
399
  vi.mocked(checkForCookieAuth).mockResolvedValue(true)
279
400
 
280
401
  instance = createSanityInstance({
281
- studio: {projectId},
402
+ projectId,
403
+ dataset: 'd',
404
+ studio: {},
282
405
  auth: {storageArea: mockStorage},
283
406
  })
284
407
 
@@ -299,6 +422,8 @@ describe('authStore', () => {
299
422
  }
300
423
 
301
424
  instance = createSanityInstance({
425
+ projectId: 'studio-project',
426
+ dataset: 'production',
302
427
  studio: {
303
428
  auth: {token: mockTokenSource},
304
429
  },
@@ -310,13 +435,15 @@ describe('authStore', () => {
310
435
  expect(getStudioTokenFromLocalStorage).not.toHaveBeenCalled()
311
436
  })
312
437
 
313
- it('resolves to studio mode when studio config is provided', () => {
438
+ it('resolves to studio mode when studio config is provided (without studioMode flag)', () => {
314
439
  instance = createSanityInstance({
440
+ projectId: 'studio-project',
441
+ dataset: 'production',
315
442
  studio: {},
316
443
  })
317
444
 
318
445
  const {authState} = authStore.getInitialState(instance, null)
319
- // Without tokenSource, falls back to localStorage discovery
446
+ // Without tokenSource, falls back to localStorage discovery like studioMode
320
447
  expect(authState.type).toBe(AuthStateType.LOGGED_OUT)
321
448
  expect(getStudioTokenFromLocalStorage).toHaveBeenCalled()
322
449
  })
@@ -327,6 +454,8 @@ describe('authStore', () => {
327
454
  const mockTokenSource = {subscribe: mockSubscribe}
328
455
 
329
456
  instance = createSanityInstance({
457
+ projectId: 'studio-project',
458
+ dataset: 'production',
330
459
  studio: {
331
460
  auth: {token: mockTokenSource},
332
461
  },
@@ -349,6 +478,8 @@ describe('authStore', () => {
349
478
  const mockTokenSource = {subscribe: mockSubscribe}
350
479
 
351
480
  instance = createSanityInstance({
481
+ projectId: 'studio-project',
482
+ dataset: 'production',
352
483
  studio: {
353
484
  authenticated: true,
354
485
  auth: {token: mockTokenSource},
@@ -375,6 +506,8 @@ describe('authStore', () => {
375
506
  const mockTokenSource = {subscribe: mockSubscribe}
376
507
 
377
508
  instance = createSanityInstance({
509
+ projectId: 'studio-project',
510
+ dataset: 'production',
378
511
  studio: {
379
512
  authenticated: false,
380
513
  auth: {token: mockTokenSource},
@@ -395,7 +528,10 @@ describe('authStore', () => {
395
528
  const storageToken = 'regular-storage-token'
396
529
  vi.mocked(getTokenFromStorage).mockReturnValue(storageToken)
397
530
 
398
- instance = createSanityInstance()
531
+ instance = createSanityInstance({
532
+ projectId: 'p',
533
+ dataset: 'd',
534
+ })
399
535
 
400
536
  const {authState, options} = authStore.getInitialState(instance, null)
401
537
  expect(getStudioTokenFromLocalStorage).not.toHaveBeenCalled()
@@ -407,6 +543,8 @@ describe('authStore', () => {
407
543
  it('sets to logging in if getTokenFromLocation returns a token', () => {
408
544
  const initialLocationHref = 'https://example.com/#token=hash-token'
409
545
  instance = createSanityInstance({
546
+ projectId: 'p',
547
+ dataset: 'd',
410
548
  auth: {initialLocationHref},
411
549
  })
412
550
 
@@ -461,6 +599,8 @@ describe('authStore', () => {
461
599
 
462
600
  it('subscribes to state and storage events and unsubscribes on dispose', () => {
463
601
  instance = createSanityInstance({
602
+ projectId: 'p',
603
+ dataset: 'd',
464
604
  auth: {storageArea: mockLocalStorage},
465
605
  })
466
606
 
@@ -485,6 +625,8 @@ describe('authStore', () => {
485
625
 
486
626
  it('does not subscribe to storage events when not using storage area', () => {
487
627
  instance = createSanityInstance({
628
+ projectId: 'p',
629
+ dataset: 'd',
488
630
  auth: {storageArea: undefined},
489
631
  })
490
632
 
@@ -498,6 +640,35 @@ describe('authStore', () => {
498
640
  expect(stateUnsubscribe).toHaveBeenCalled()
499
641
  expect(storageEventsUnsubscribe).not.toHaveBeenCalled()
500
642
  })
643
+
644
+ it('logs when checking for cookie auth in studio mode', async () => {
645
+ const projectId = 'studio-project'
646
+ const mockStorage = {
647
+ getItem: vi.fn(),
648
+ setItem: vi.fn(),
649
+ removeItem: vi.fn(),
650
+ } as unknown as Storage
651
+ vi.mocked(getStudioTokenFromLocalStorage).mockReturnValue(null)
652
+ vi.mocked(checkForCookieAuth).mockResolvedValue(true)
653
+
654
+ instance = createSanityInstance({
655
+ projectId,
656
+ dataset: 'd',
657
+ studio: {},
658
+ auth: {storageArea: mockStorage},
659
+ })
660
+
661
+ // Trigger store initialization
662
+ getAuthState(instance)
663
+
664
+ // Wait for async cookie check
665
+ await vi.waitFor(() => {
666
+ expect(checkForCookieAuth).toHaveBeenCalledWith(projectId, expect.any(Function))
667
+ })
668
+
669
+ // Logger should have been called during initialization
670
+ expect(createLogger).toHaveBeenCalled()
671
+ })
501
672
  })
502
673
 
503
674
  describe('getCurrentUserState', () => {
@@ -525,7 +696,7 @@ describe('authStore', () => {
525
696
  return NEVER.subscribe()
526
697
  })
527
698
 
528
- instance = createSanityInstance()
699
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
529
700
 
530
701
  const {getCurrent} = getCurrentUserState(instance)
531
702
 
@@ -534,7 +705,7 @@ describe('authStore', () => {
534
705
  })
535
706
 
536
707
  it('returns null otherwise', () => {
537
- instance = createSanityInstance()
708
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
538
709
  const {getCurrent} = getCurrentUserState(instance)
539
710
  expect(getCurrent()).toBe(null)
540
711
  })
@@ -550,6 +721,8 @@ describe('authStore', () => {
550
721
  it('returns the token if logged in', () => {
551
722
  const token = 'hard-coded-token'
552
723
  instance = createSanityInstance({
724
+ projectId: 'p',
725
+ dataset: 'd',
553
726
  auth: {token},
554
727
  })
555
728
  const tokenState = getTokenState(instance)
@@ -560,7 +733,7 @@ describe('authStore', () => {
560
733
  })
561
734
 
562
735
  it('returns null otherwise', () => {
563
- instance = createSanityInstance()
736
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
564
737
 
565
738
  const tokenState = getTokenState(instance)
566
739
  expect(tokenState.getCurrent()).toBe(null)
@@ -578,7 +751,7 @@ describe('authStore', () => {
578
751
  })
579
752
 
580
753
  it('returns the default login url', () => {
581
- instance = createSanityInstance()
754
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
582
755
 
583
756
  const loginUrlState = getLoginUrlState(instance)
584
757
  expect(loginUrlState.getCurrent()).toBe(
@@ -596,6 +769,8 @@ describe('authStore', () => {
596
769
 
597
770
  it('returns the current state in `authState`', () => {
598
771
  instance = createSanityInstance({
772
+ projectId: 'p',
773
+ dataset: 'd',
599
774
  auth: {token: 'hard-coded-token'},
600
775
  })
601
776
 
@@ -626,6 +801,8 @@ describe('authStore', () => {
626
801
  const context = {orgId: 'initial-org-id'}
627
802
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
628
803
  instance = createSanityInstance({
804
+ projectId: 'p',
805
+ dataset: 'd',
629
806
  auth: {initialLocationHref},
630
807
  })
631
808
 
@@ -642,6 +819,8 @@ describe('authStore', () => {
642
819
  const authCode = 'test-auth-code'
643
820
 
644
821
  instance = createSanityInstance({
822
+ projectId: 'p',
823
+ dataset: 'd',
645
824
  auth: {
646
825
  clientFactory: () => mockClient as unknown as SanityClient,
647
826
  initialLocationHref, // Set initial context
@@ -670,6 +849,8 @@ describe('authStore', () => {
670
849
  const context = {mode: 'test'} // No orgId
671
850
  const initialLocationHref = `https://example.com/?_context=${encodeURIComponent(JSON.stringify(context))}`
672
851
  instance = createSanityInstance({
852
+ projectId: 'p',
853
+ dataset: 'd',
673
854
  auth: {initialLocationHref},
674
855
  })
675
856
 
@@ -5,6 +5,8 @@ import {type AuthConfig, type AuthProvider} from '../config/authConfig'
5
5
  import {bindActionGlobally} from '../store/createActionBinder'
6
6
  import {createStateSourceAction} from '../store/createStateSourceAction'
7
7
  import {defineStore} from '../store/defineStore'
8
+ import {getStagingApiHost} from '../utils/getStagingApiHost'
9
+ import {getAuthLogger} from './authLogger'
8
10
  import {resolveAuthMode} from './authMode'
9
11
  import {AuthStateType} from './authStateType'
10
12
  import {type AuthStrategyOptions} from './authStrategy'
@@ -101,8 +103,17 @@ export const authStore = defineStore<AuthStoreState>({
101
103
  name: 'Auth',
102
104
 
103
105
  getInitialState(instance) {
106
+ const logger = getAuthLogger(instance)
107
+
108
+ logger.debug('Initializing auth store', {
109
+ hasProvidedToken: !!instance.config.auth?.token,
110
+ hasCustomProviders: !!(
111
+ instance.config.auth?.providers && instance.config.auth.providers.length > 0
112
+ ),
113
+ })
114
+
104
115
  const {
105
- apiHost,
116
+ apiHost: configApiHost,
106
117
  callbackUrl,
107
118
  providers: customProviders,
108
119
  token: providedToken,
@@ -110,6 +121,7 @@ export const authStore = defineStore<AuthStoreState>({
110
121
  initialLocationHref = getDefaultLocation(),
111
122
  } = instance.config.auth ?? {}
112
123
 
124
+ const apiHost = configApiHost ?? getStagingApiHost()
113
125
  const authConfig = instance.config.auth ?? {}
114
126
 
115
127
  // Build login URL (used by standalone mode, but always computed for the
@@ -132,7 +144,7 @@ export const authStore = defineStore<AuthStoreState>({
132
144
 
133
145
  const strategyOptions: AuthStrategyOptions = {
134
146
  authConfig,
135
- projectId: instance.config.studio?.projectId,
147
+ projectId: instance.config.projectId,
136
148
  initialLocationHref,
137
149
  clientFactory,
138
150
  tokenSource: instance.config.studio?.auth?.token,
@@ -151,6 +163,12 @@ export const authStore = defineStore<AuthStoreState>({
151
163
  break
152
164
  }
153
165
 
166
+ logger.debug('Auth state initialized', {
167
+ authStateType: result.authState.type,
168
+ mode,
169
+ authMethod: result.authMethod,
170
+ })
171
+
154
172
  return {
155
173
  authState: result.authState,
156
174
  dashboardContext: result.dashboardContext,
@@ -170,10 +188,14 @@ export const authStore = defineStore<AuthStoreState>({
170
188
  },
171
189
 
172
190
  initialize(context) {
191
+ const logger = getAuthLogger(context.instance)
192
+
173
193
  const initialLocationHref =
174
194
  context.state.get().options?.initialLocationHref ?? getDefaultLocation()
175
195
  const mode = resolveAuthMode(context.instance.config, initialLocationHref)
176
196
 
197
+ logger.debug('Setting up auth subscriptions', {mode})
198
+
177
199
  let initResult
178
200
  switch (mode) {
179
201
  case 'studio':
@@ -191,7 +213,10 @@ export const authStore = defineStore<AuthStoreState>({
191
213
  tokenRefresherRunning = true
192
214
  }
193
215
 
194
- return initResult.dispose
216
+ return () => {
217
+ logger.debug('Cleaning up auth subscriptions')
218
+ initResult.dispose()
219
+ }
195
220
  },
196
221
  })
197
222
 
@@ -269,27 +294,34 @@ export const getIsInDashboardState = bindActionGlobally(
269
294
  * Used internally by the Comlink token refresh.
270
295
  * @internal
271
296
  */
272
- export const setAuthToken = bindActionGlobally(authStore, ({state}, token: string | null) => {
273
- const currentAuthState = state.get().authState
274
- if (token) {
275
- // Update state only if the new token is different or currently logged out
276
- if (currentAuthState.type !== AuthStateType.LOGGED_IN || currentAuthState.token !== token) {
277
- const currentUser =
278
- currentAuthState.type === AuthStateType.LOGGED_IN ? currentAuthState.currentUser : null
279
- const preservedLastTokenRefresh =
280
- currentAuthState.type === AuthStateType.LOGGED_IN
281
- ? currentAuthState.lastTokenRefresh
282
- : undefined
283
- state.set('setToken', {
284
- authState: createLoggedInAuthState(token, currentUser, preservedLastTokenRefresh),
285
- })
286
- }
287
- } else {
288
- // Handle setting token to null (logging out)
289
- if (currentAuthState.type !== AuthStateType.LOGGED_OUT) {
290
- state.set('setToken', {
291
- authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},
292
- })
297
+ export const setAuthToken = bindActionGlobally(
298
+ authStore,
299
+ ({state, instance}, token: string | null) => {
300
+ const logger = getAuthLogger(instance)
301
+
302
+ const currentAuthState = state.get().authState
303
+ if (token) {
304
+ // Update state only if the new token is different or currently logged out
305
+ if (currentAuthState.type !== AuthStateType.LOGGED_IN || currentAuthState.token !== token) {
306
+ logger.info('Setting auth token')
307
+ const currentUser =
308
+ currentAuthState.type === AuthStateType.LOGGED_IN ? currentAuthState.currentUser : null
309
+ const preservedLastTokenRefresh =
310
+ currentAuthState.type === AuthStateType.LOGGED_IN
311
+ ? currentAuthState.lastTokenRefresh
312
+ : undefined
313
+ state.set('setToken', {
314
+ authState: createLoggedInAuthState(token, currentUser, preservedLastTokenRefresh),
315
+ })
316
+ }
317
+ } else {
318
+ // Handle setting token to null (logging out)
319
+ if (currentAuthState.type !== AuthStateType.LOGGED_OUT) {
320
+ logger.info('Clearing auth token')
321
+ state.set('setToken', {
322
+ authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},
323
+ })
324
+ }
293
325
  }
294
- }
295
- })
326
+ },
327
+ )