@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authStore-CtE9bLHW.js","names":[],"sources":["../src/utils/getStagingApiHost.ts","../src/auth/authLogger.ts","../src/auth/authConstants.ts","../src/auth/authMode.ts","../src/auth/authStateType.ts","../src/auth/refreshStampedToken.ts","../src/auth/subscribeToStateAndFetchCurrentUser.ts","../src/auth/utils.ts","../src/auth/dashboardAuth.ts","../src/auth/subscribeToStorageEventsAndSetToken.ts","../src/auth/standaloneAuth.ts","../src/auth/studioModeAuth.ts","../src/auth/studioAuth.ts","../src/auth/authStore.ts"],"sourcesContent":["declare const __SANITY_STAGING__: boolean | undefined\n\n/**\n * Returns the staging API host if the `__SANITY_STAGING__` build-time flag is\n * set to `true` (mirroring how Sanity Studio detects staging builds).\n *\n * @internal\n */\nexport function getStagingApiHost(): string | undefined {\n if (typeof __SANITY_STAGING__ !== 'undefined' && __SANITY_STAGING__ === true) {\n return 'https://api.sanity.work'\n }\n return undefined\n}\n","import {type SanityInstance} from '../store/createSanityInstance'\nimport {createLogger, type Logger} from '../utils/logger'\n\nconst loggers = new WeakMap<SanityInstance, Logger>()\n\n/**\n * Returns the auth logger for a Sanity instance, creating it on first use.\n *\n * The logger is cached per instance so repeated action calls (logout,\n * setAuthToken, handleAuthCallback) reuse the same logger instead of\n * rebuilding it. The instance details are nested under `instanceContext`,\n * which is what the logger's formatter reads to render the\n * `[project:x] [dataset:y] [instance:z]` prefix.\n *\n * @internal\n */\nexport function getAuthLogger(instance: SanityInstance): Logger {\n let logger = loggers.get(instance)\n if (!logger) {\n logger = createLogger('auth', {\n instanceContext: {\n instanceId: instance.instanceId,\n projectId: instance.config.projectId,\n dataset: instance.config.dataset,\n },\n })\n loggers.set(instance, logger)\n }\n return logger\n}\n","export const DEFAULT_BASE = 'http://localhost'\nexport const AUTH_CODE_PARAM = 'sid'\nexport const DEFAULT_API_VERSION = '2021-06-07'\nexport const REQUEST_TAG_PREFIX = 'sanity.sdk.auth'\n","import {type SanityConfig} from '../config/sanityConfig'\nimport {DEFAULT_BASE} from './authConstants'\n\n/**\n * The runtime auth mode determines which authentication strategy the SDK uses.\n *\n * - `studio` — Running inside Sanity Studio. Token is discovered from\n * Studio's localStorage entry or via cookie auth.\n * - `dashboard` — Running inside the Sanity Dashboard iframe. Token is\n * provided by the parent frame via Comlink.\n * - `standalone` — Running as an independent app. Token comes from\n * localStorage or the OAuth login flow.\n *\n * @internal\n */\ntype AuthMode = 'studio' | 'dashboard' | 'standalone'\n\n/**\n * Determines the auth mode from instance config and environment.\n *\n * Priority:\n * 1. `studio` config provided → `'studio'`\n * 2. Dashboard context detected (`_context` URL param with content) → `'dashboard'`\n * 3. Otherwise → `'standalone'`\n *\n * @internal\n */\nexport function resolveAuthMode(config: SanityConfig, locationHref: string): AuthMode {\n if (isStudioConfig(config)) return 'studio'\n if (detectDashboardContext(locationHref)) return 'dashboard'\n return 'standalone'\n}\n\n/**\n * Returns `true` when the config indicates the SDK is running inside a Studio.\n *\n * @internal\n */\nexport function isStudioConfig(config: SanityConfig): boolean {\n return !!config.studio\n}\n\n/**\n * Checks whether the given location href contains a `_context` URL parameter\n * with a non-empty JSON object, indicating the SDK is running inside the\n * Sanity Dashboard.\n *\n * @internal\n */\nfunction detectDashboardContext(locationHref: string): boolean {\n try {\n const parsedUrl = new URL(locationHref, DEFAULT_BASE)\n const contextParam = parsedUrl.searchParams.get('_context')\n if (!contextParam) return false\n\n const parsed: unknown = JSON.parse(contextParam)\n return (\n typeof parsed === 'object' &&\n parsed !== null &&\n !Array.isArray(parsed) &&\n Object.keys(parsed as Record<string, unknown>).length > 0\n )\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('Failed to parse dashboard context from initial location:', err)\n return false\n }\n}\n","/**\n * Represents the various states the authentication type can be in.\n *\n * @public\n */\nexport enum AuthStateType {\n LOGGED_IN = 'logged-in',\n LOGGING_IN = 'logging-in',\n ERROR = 'error',\n LOGGED_OUT = 'logged-out',\n}\n","import {\n distinctUntilChanged,\n exhaustMap,\n filter,\n map,\n Observable,\n type Subscription,\n switchMap,\n takeWhile,\n timer,\n} from 'rxjs'\n\nimport {type StoreContext} from '../store/defineStore'\nimport {DEFAULT_API_VERSION, REQUEST_TAG_PREFIX} from './authConstants'\nimport {getAuthLogger} from './authLogger'\nimport {AuthStateType} from './authStateType'\nimport {type AuthState, type AuthStoreState} from './authStore'\n\nconst REFRESH_INTERVAL = 12 * 60 * 60 * 1000 // 12 hours in milliseconds\n\nfunction createTokenRefreshStream(\n token: string,\n clientFactory: AuthStoreState['options']['clientFactory'],\n apiHost: string | undefined,\n): Observable<{token: string}> {\n return new Observable((subscriber) => {\n const client = clientFactory({\n apiVersion: DEFAULT_API_VERSION,\n requestTagPrefix: REQUEST_TAG_PREFIX,\n useProjectHostname: false,\n useCdn: false,\n token,\n ignoreBrowserTokenWarning: true,\n ...(apiHost && {apiHost}),\n })\n\n const subscription = client.observable\n .request<{token: string}>({\n uri: 'auth/refresh-token',\n method: 'POST',\n tag: 'refresh-token',\n body: {\n token,\n },\n })\n .subscribe(subscriber)\n\n return () => subscription.unsubscribe()\n })\n}\n\nfunction shouldRefreshToken(lastRefresh: number | undefined): boolean {\n if (!lastRefresh) return true\n const timeSinceLastRefresh = Date.now() - lastRefresh\n return timeSinceLastRefresh >= REFRESH_INTERVAL\n}\n\n/**\n * Periodically refreshes stamped auth tokens (those containing `-st`).\n *\n * Two triggers cause a refresh while the user stays logged in:\n * - a 12-hour interval timer (only fires while the tab is visible)\n * - the tab becoming visible again after `lastTokenRefresh` has gone stale\n *\n * Non-stamped tokens (e.g. personal access tokens) are never refreshed.\n *\n * @internal\n */\nexport const refreshStampedToken = ({\n state,\n instance,\n}: StoreContext<AuthStoreState>): Subscription => {\n const logger = getAuthLogger(instance)\n\n const {clientFactory, apiHost, storageArea, storageKey} = state.get().options\n\n const refreshToken$ = state.observable.pipe(\n map((storeState) => storeState.authState),\n filter(\n (authState): authState is Extract<AuthState, {type: AuthStateType.LOGGED_IN}> =>\n authState.type === AuthStateType.LOGGED_IN,\n ),\n distinctUntilChanged((prev, curr) => prev.token === curr.token),\n filter((authState) => authState.token.includes('-st')), // Ensure we only try to refresh stamped tokens\n exhaustMap(() =>\n new Observable<{token: string}>((subscriber) => {\n const visibilityHandler = () => {\n const currentState = state.get()\n if (\n document.visibilityState === 'visible' &&\n currentState.authState.type === AuthStateType.LOGGED_IN &&\n shouldRefreshToken(currentState.authState.lastTokenRefresh)\n ) {\n createTokenRefreshStream(\n currentState.authState.token,\n clientFactory,\n apiHost,\n ).subscribe({\n next: (response) => {\n state.set('setRefreshStampedToken', (prev) => ({\n authState:\n prev.authState.type === AuthStateType.LOGGED_IN\n ? {\n ...prev.authState,\n token: response.token,\n lastTokenRefresh: Date.now(),\n }\n : prev.authState,\n }))\n subscriber.next(response)\n },\n error: (error) => subscriber.error(error),\n })\n }\n }\n\n const timerSubscription = timer(REFRESH_INTERVAL, REFRESH_INTERVAL)\n .pipe(\n filter(() => document.visibilityState === 'visible'),\n switchMap(() => {\n const currentState = state.get().authState\n if (currentState.type !== AuthStateType.LOGGED_IN) {\n throw new Error('User logged out before refresh could complete')\n }\n return createTokenRefreshStream(currentState.token, clientFactory, apiHost)\n }),\n )\n .subscribe({\n next: (response) => {\n state.set('setRefreshStampedToken', (prev) => ({\n authState:\n prev.authState.type === AuthStateType.LOGGED_IN\n ? {\n ...prev.authState,\n token: response.token,\n lastTokenRefresh: Date.now(),\n }\n : prev.authState,\n }))\n subscriber.next(response)\n },\n error: (error) => subscriber.error(error),\n })\n\n document.addEventListener('visibilitychange', visibilityHandler)\n\n return () => {\n document.removeEventListener('visibilitychange', visibilityHandler)\n timerSubscription.unsubscribe()\n }\n }).pipe(\n takeWhile(() => state.get().authState.type === AuthStateType.LOGGED_IN),\n map((response: {token: string}) => ({token: response.token})),\n ),\n ),\n )\n\n return refreshToken$.subscribe({\n next: (response: {token: string}) => {\n logger.debug('Token refresh completed, updating state')\n state.set('setRefreshStampedToken', (prev) => ({\n authState:\n prev.authState.type === AuthStateType.LOGGED_IN\n ? {\n ...prev.authState,\n token: response.token,\n lastTokenRefresh: Date.now(),\n }\n : prev.authState,\n }))\n storageArea?.setItem(storageKey, JSON.stringify({token: response.token}))\n },\n error: (error) => {\n logger.error('Token refresh failed', {error})\n state.set('setRefreshStampedTokenError', {authState: {type: AuthStateType.ERROR, error}})\n },\n })\n}\n","import {type CurrentUser} from '@sanity/types'\nimport {\n catchError,\n distinctUntilChanged,\n EMPTY,\n filter,\n map,\n type Subscription,\n switchMap,\n} from 'rxjs'\n\nimport {type StoreContext} from '../store/defineStore'\nimport {DEFAULT_API_VERSION, REQUEST_TAG_PREFIX} from './authConstants'\nimport {getAuthLogger} from './authLogger'\nimport {isStudioConfig} from './authMode'\nimport {AuthStateType} from './authStateType'\nimport {type AuthMethodOptions, type AuthState, type AuthStoreState} from './authStore'\n\n/**\n * Subscribes to auth state changes and fetches the current user when\n * the state transitions to `LOGGED_IN` without a `currentUser`.\n *\n * @param context - The store context for the auth store.\n * @param fetchOptions - Configuration options. When `useProjectHostname` is\n * `true`, requests use the project-specific hostname (required for Studio\n * cookie auth). Set to `true` for studio mode, `false` otherwise.\n *\n * @internal\n */\nexport const subscribeToStateAndFetchCurrentUser = (\n {state, instance}: StoreContext<AuthStoreState>,\n fetchOptions?: {useProjectHostname?: boolean},\n): Subscription => {\n const logger = getAuthLogger(instance)\n\n const {clientFactory, apiHost} = state.get().options\n const useProjectHostname = fetchOptions?.useProjectHostname ?? isStudioConfig(instance.config)\n const projectId = instance.config.projectId\n\n const currentUser$ = state.observable\n .pipe(\n map(({authState, options: storeOptions}) => ({\n authState,\n authMethod: storeOptions.authMethod,\n })),\n filter(\n (\n value,\n ): value is {\n authState: Extract<AuthState, {type: AuthStateType.LOGGED_IN}>\n authMethod: AuthMethodOptions\n } => value.authState.type === AuthStateType.LOGGED_IN && !value.authState.currentUser,\n ),\n map((value) => ({token: value.authState.token, authMethod: value.authMethod})),\n distinctUntilChanged(\n (prev, curr) => prev.token === curr.token && prev.authMethod === curr.authMethod,\n ),\n )\n .pipe(\n map(({token, authMethod}) =>\n clientFactory({\n apiVersion: DEFAULT_API_VERSION,\n requestTagPrefix: REQUEST_TAG_PREFIX,\n token: authMethod === 'cookie' ? undefined : token,\n ignoreBrowserTokenWarning: true,\n useProjectHostname,\n useCdn: false,\n ...(authMethod === 'cookie' ? {withCredentials: true} : {}),\n ...(useProjectHostname && projectId ? {projectId} : {}),\n ...(apiHost && {apiHost}),\n }),\n ),\n switchMap((client) =>\n client.observable\n .request<CurrentUser>({\n uri: '/users/me',\n method: 'GET',\n tag: 'users.get-current',\n })\n .pipe(\n /**\n * Catch inside switchMap so the outer subscription survives.\n * Without this, a 401 terminates the subscription permanently\n * and subsequent token refreshes via comlink never re-fetch /users/me.\n * @see SDK-1409\n */\n catchError((error) => {\n logger.error('Failed to fetch current user', {error})\n state.set('setError', {authState: {type: AuthStateType.ERROR, error}})\n return EMPTY\n }),\n ),\n ),\n )\n\n return currentUser$.subscribe({\n next: (currentUser) => {\n logger.info('Current user fetched successfully', {\n hasEmail: !!currentUser.email,\n })\n // userId is PII, so only surface it at debug level\n logger.debug('Current user details', {userId: currentUser.id})\n state.set('setCurrentUser', (prev) => ({\n authState:\n prev.authState.type === AuthStateType.LOGGED_IN\n ? {...prev.authState, currentUser}\n : prev.authState,\n }))\n },\n })\n}\n","import {type ClientError} from '@sanity/client'\nimport {type CurrentUser} from '@sanity/types'\nimport {EMPTY, fromEvent, Observable} from 'rxjs'\n\nimport {AUTH_CODE_PARAM, DEFAULT_BASE} from './authConstants'\nimport {AuthStateType} from './authStateType'\nimport {type LoggedInAuthState} from './authStore'\n\n/**\n * Creates a properly initialized {@link LoggedInAuthState}.\n *\n * For stamped tokens (containing `\"-st\"`), `lastTokenRefresh` is set to\n * `Date.now()` so that the visibility-change handler in\n * {@link refreshStampedToken} does not trigger an unnecessary refresh the\n * first time the tab becomes visible.\n *\n * @param token - The auth token.\n * @param currentUser - The current user, or `null` if not yet fetched.\n * @param existingLastTokenRefresh - An existing timestamp to preserve\n * (e.g. when updating a token while keeping the previous refresh time).\n * @internal\n */\nexport function createLoggedInAuthState(\n token: string,\n currentUser: CurrentUser | null,\n existingLastTokenRefresh?: number,\n): LoggedInAuthState {\n const isStampedToken = token.includes('-st')\n const lastTokenRefresh = existingLastTokenRefresh ?? (isStampedToken ? Date.now() : undefined)\n\n return {\n type: AuthStateType.LOGGED_IN,\n token,\n currentUser,\n ...(lastTokenRefresh !== undefined && {lastTokenRefresh}),\n }\n}\n\nexport function getAuthCode(callbackUrl: string | undefined, locationHref: string): string | null {\n const loc = new URL(locationHref, DEFAULT_BASE)\n const callbackLocation = callbackUrl ? new URL(callbackUrl, DEFAULT_BASE) : undefined\n const callbackLocationMatches = callbackLocation\n ? loc.pathname.toLowerCase().startsWith(callbackLocation.pathname.toLowerCase())\n : true\n\n // First, try getting the auth code (sid) from hash or search params directly\n let authCode =\n new URLSearchParams(loc.hash.slice(1)).get(AUTH_CODE_PARAM) ||\n new URLSearchParams(loc.search).get(AUTH_CODE_PARAM)\n\n // If not found directly, try extracting it from the _context parameter as a fallback\n if (!authCode) {\n const contextParam = new URLSearchParams(loc.search).get('_context')\n if (contextParam) {\n try {\n const parsedContext = JSON.parse(contextParam)\n if (\n parsedContext &&\n typeof parsedContext === 'object' &&\n typeof parsedContext.sid === 'string' &&\n parsedContext.sid // Ensure it's not an empty string\n ) {\n authCode = parsedContext.sid\n }\n } catch {\n // Silently ignore _context JSON parsing errors; authCode remains null/empty\n }\n }\n }\n\n return authCode && callbackLocationMatches ? authCode : null\n}\n\nexport function getTokenFromLocation(locationHref: string): string | null {\n const loc = new URL(locationHref)\n const token = new URLSearchParams(loc.hash.slice(1)).get('token')\n return token ? token : null\n}\n\n/**\n * Attempts to retrieve a token from the configured storage.\n * If invalid or not present, returns null.\n */\nexport function getTokenFromStorage(\n storageArea: Storage | undefined,\n storageKey: string,\n): string | null {\n if (!storageArea) return null\n const item = storageArea.getItem(storageKey)\n if (item === null) return null\n\n try {\n const parsed: unknown = JSON.parse(item)\n if (\n typeof parsed !== 'object' ||\n parsed === null ||\n !('token' in parsed) ||\n typeof parsed.token !== 'string'\n ) {\n throw new Error('Invalid stored auth data structure')\n }\n return parsed.token\n } catch {\n storageArea.removeItem(storageKey)\n return null\n }\n}\n\n/**\n * Creates an observable stream of storage events. If not in a browser environment,\n * returns an EMPTY observable.\n */\nexport function getStorageEvents(): Observable<StorageEvent> {\n const isBrowser = typeof window !== 'undefined' && typeof window.addEventListener === 'function'\n\n if (!isBrowser) {\n return EMPTY\n }\n\n return fromEvent<StorageEvent>(window, 'storage')\n}\n\n/**\n * Returns a default storage instance (localStorage) if available.\n * If not available or an error occurs, returns undefined.\n */\nexport function getDefaultStorage(): Storage | undefined {\n try {\n if (typeof localStorage !== 'undefined' && typeof localStorage.getItem === 'function') {\n return localStorage\n }\n return undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Returns the default location to use.\n * Tries accessing `location.href`, falls back to a default base if not available or on error.\n */\nexport function getDefaultLocation(): string {\n try {\n if (typeof location === 'undefined') return DEFAULT_BASE\n if (typeof location.href === 'string') return location.href\n return DEFAULT_BASE\n } catch {\n return DEFAULT_BASE\n }\n}\n\n/**\n * Cleans up the URL by removing the `token` from the hash and the `sid` and `url` search params.\n * @internal\n */\nexport function getCleanedUrl(locationUrl: string): string {\n const loc = new URL(locationUrl)\n // Remove only the `token` param from the hash while preserving other fragments\n const rawHash = loc.hash.startsWith('#') ? loc.hash.slice(1) : loc.hash\n if (rawHash && rawHash.includes('=')) {\n const hashParams = new URLSearchParams(rawHash)\n hashParams.delete('token')\n hashParams.delete('withSid')\n const nextHash = hashParams.toString()\n loc.hash = nextHash ? `#${nextHash}` : ''\n }\n loc.searchParams.delete('sid')\n loc.searchParams.delete('url')\n return loc.toString()\n}\n\n// -----------------------------------------------------------------------------\n// ClientError helpers (shared)\n// -----------------------------------------------------------------------------\n\n/** @internal */\nexport type ApiErrorBody = {\n error?: {type?: string; description?: string}\n type?: string\n description?: string\n message?: string\n}\n\n/** @internal Extracts the structured API error body from a ClientError, if present. */\nexport function getClientErrorApiBody(error: ClientError): ApiErrorBody | undefined {\n const body: unknown = (error as ClientError).response?.body\n return body && typeof body === 'object' ? (body as ApiErrorBody) : undefined\n}\n\n/** @internal Returns the error type string from an API error body, if available. */\nexport function getClientErrorApiType(error: ClientError): string | undefined {\n const body = getClientErrorApiBody(error)\n return body?.error?.type ?? body?.type\n}\n\n/** @internal Returns the error description string from an API error body, if available. */\nexport function getClientErrorApiDescription(error: ClientError): string | undefined {\n const body = getClientErrorApiBody(error)\n return body?.error?.description ?? body?.description\n}\n\n/** @internal True if the error represents a projectUserNotFoundError. */\nexport function isProjectUserNotFoundClientError(error: ClientError): boolean {\n return getClientErrorApiType(error) === 'projectUserNotFoundError'\n}\n","import {type Subscription} from 'rxjs'\n\nimport {type StoreContext} from '../store/defineStore'\nimport {DEFAULT_BASE} from './authConstants'\nimport {AuthStateType} from './authStateType'\nimport {type AuthStoreState, type DashboardContext} from './authStore'\nimport {type AuthStrategyOptions, type AuthStrategyResult} from './authStrategy'\nimport {refreshStampedToken} from './refreshStampedToken'\nimport {subscribeToStateAndFetchCurrentUser} from './subscribeToStateAndFetchCurrentUser'\nimport {createLoggedInAuthState, getAuthCode, getTokenFromLocation} from './utils'\n\n/**\n * Parses the dashboard context from a location href's `_context` URL parameter.\n * Strips the `sid` property from the parsed context (it's handled separately).\n *\n * @internal\n */\nfunction parseDashboardContext(locationHref: string): DashboardContext {\n try {\n const parsedUrl = new URL(locationHref, DEFAULT_BASE)\n const contextParam = parsedUrl.searchParams.get('_context')\n if (contextParam) {\n const parsedContext = JSON.parse(contextParam)\n\n if (\n parsedContext &&\n typeof parsedContext === 'object' &&\n !Array.isArray(parsedContext) &&\n Object.keys(parsedContext).length > 0\n ) {\n // Explicitly remove the 'sid' property before assigning\n delete parsedContext.sid\n return parsedContext as DashboardContext\n }\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('Failed to parse dashboard context from initial location:', err)\n }\n return {} // Empty dashboard context if parsing fails\n}\n\n/**\n * Resolves the initial auth state for Dashboard mode.\n *\n * In dashboard mode the token is provided by the parent frame via Comlink,\n * so the SDK starts in a `LOGGED_OUT` state and waits for the token to arrive.\n * The `_context` URL parameter provides dashboard metadata (orgId, mode, env).\n *\n * A provided token (`auth.token`) or an auth code/callback still takes\n * precedence, even when running inside the dashboard.\n *\n * @internal\n */\nexport function getDashboardInitialState(options: AuthStrategyOptions): AuthStrategyResult {\n const {authConfig, initialLocationHref} = options\n const providedToken = authConfig.token\n const callbackUrl = authConfig.callbackUrl\n const storageKey = '__sanity_auth_token'\n\n const dashboardContext = parseDashboardContext(initialLocationHref)\n\n // Dashboard does NOT use localStorage — token comes from the parent frame\n const storageArea = undefined\n\n // Provided token always wins, even in dashboard\n if (providedToken) {\n return {\n authState: createLoggedInAuthState(providedToken, null),\n storageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext,\n }\n }\n\n // Check for auth code or token-from-location (callback handling)\n if (getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref)) {\n return {\n authState: {type: AuthStateType.LOGGING_IN, isExchangingToken: false},\n storageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext,\n }\n }\n\n // Default: logged out, waiting for Comlink to provide token\n return {\n authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},\n storageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext,\n }\n}\n\n/**\n * Initialize Dashboard auth subscriptions:\n * - Subscribe to state changes and fetch current user\n * - Start stamped token refresh\n *\n * Note: storage events are NOT subscribed in dashboard mode since\n * the dashboard does not use localStorage for token persistence.\n *\n * @internal\n */\nexport function initializeDashboardAuth(\n context: StoreContext<AuthStoreState>,\n tokenRefresherRunning: boolean,\n): {dispose: () => void; tokenRefresherStarted: boolean} {\n const subscriptions: Subscription[] = []\n let startedRefresher = false\n\n subscriptions.push(subscribeToStateAndFetchCurrentUser(context, {useProjectHostname: false}))\n\n // Dashboard does not subscribe to storage events\n\n if (!tokenRefresherRunning) {\n startedRefresher = true\n subscriptions.push(refreshStampedToken(context))\n }\n\n return {\n dispose: () => {\n for (const subscription of subscriptions) {\n subscription.unsubscribe()\n }\n },\n tokenRefresherStarted: startedRefresher,\n }\n}\n","import {defer, distinctUntilChanged, filter, map, type Subscription} from 'rxjs'\n\nimport {type StoreContext} from '../store/defineStore'\nimport {AuthStateType} from './authStateType'\nimport {type AuthStoreState} from './authStore'\nimport {createLoggedInAuthState, getStorageEvents, getTokenFromStorage} from './utils'\n\nexport const subscribeToStorageEventsAndSetToken = ({\n state,\n}: StoreContext<AuthStoreState>): Subscription => {\n const {storageArea, storageKey} = state.get().options\n\n const tokenFromStorage$ = defer(getStorageEvents).pipe(\n filter(\n (e): e is StorageEvent & {newValue: string} =>\n e.storageArea === storageArea && e.key === storageKey,\n ),\n map(() => getTokenFromStorage(storageArea, storageKey)),\n distinctUntilChanged(),\n )\n\n return tokenFromStorage$.subscribe((token) => {\n state.set('updateTokenFromStorageEvent', {\n authState: token\n ? createLoggedInAuthState(token, null)\n : {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},\n })\n })\n}\n","import {type Subscription} from 'rxjs'\n\nimport {type StoreContext} from '../store/defineStore'\nimport {AuthStateType} from './authStateType'\nimport {type AuthStoreState} from './authStore'\nimport {type AuthStrategyOptions, type AuthStrategyResult} from './authStrategy'\nimport {refreshStampedToken} from './refreshStampedToken'\nimport {subscribeToStateAndFetchCurrentUser} from './subscribeToStateAndFetchCurrentUser'\nimport {subscribeToStorageEventsAndSetToken} from './subscribeToStorageEventsAndSetToken'\nimport {\n createLoggedInAuthState,\n getAuthCode,\n getDefaultStorage,\n getTokenFromLocation,\n getTokenFromStorage,\n} from './utils'\n\n/**\n * Resolves the initial auth state for Standalone mode.\n *\n * Token discovery order:\n * 1. Provided token (`auth.token` in config)\n * 2. Auth code or token from location (OAuth callback)\n * 3. localStorage: `__sanity_auth_token`\n * 4. Falls back to `LOGGED_OUT`\n *\n * @internal\n */\nexport function getStandaloneInitialState(options: AuthStrategyOptions): AuthStrategyResult {\n const {authConfig, initialLocationHref} = options\n const providedToken = authConfig.token\n const callbackUrl = authConfig.callbackUrl\n const storageKey = '__sanity_auth_token'\n const storageArea = authConfig.storageArea ?? getDefaultStorage()\n\n // Provided token always wins\n if (providedToken) {\n return {\n authState: createLoggedInAuthState(providedToken, null),\n storageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext: {},\n }\n }\n\n // Check for auth code or token-from-location (OAuth callback)\n if (getAuthCode(callbackUrl, initialLocationHref) || getTokenFromLocation(initialLocationHref)) {\n return {\n authState: {type: AuthStateType.LOGGING_IN, isExchangingToken: false},\n storageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext: {},\n }\n }\n\n // Try localStorage\n const token = getTokenFromStorage(storageArea, storageKey)\n if (token) {\n return {\n authState: createLoggedInAuthState(token, null),\n storageKey,\n storageArea,\n authMethod: 'localstorage',\n dashboardContext: {},\n }\n }\n\n // No token found\n return {\n authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},\n storageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext: {},\n }\n}\n\n/**\n * Initialize Standalone auth subscriptions:\n * - Subscribe to state changes and fetch current user\n * - Subscribe to storage events for token key\n * - Start stamped token refresh\n *\n * @internal\n */\nexport function initializeStandaloneAuth(\n context: StoreContext<AuthStoreState>,\n tokenRefresherRunning: boolean,\n): {dispose: () => void; tokenRefresherStarted: boolean} {\n const subscriptions: Subscription[] = []\n let startedRefresher = false\n\n subscriptions.push(subscribeToStateAndFetchCurrentUser(context, {useProjectHostname: false}))\n\n const storageArea = context.state.get().options?.storageArea\n if (storageArea) {\n subscriptions.push(subscribeToStorageEventsAndSetToken(context))\n }\n\n if (!tokenRefresherRunning) {\n startedRefresher = true\n subscriptions.push(refreshStampedToken(context))\n }\n\n return {\n dispose: () => {\n for (const subscription of subscriptions) {\n subscription.unsubscribe()\n }\n },\n tokenRefresherStarted: startedRefresher,\n }\n}\n","import {type ClientConfig, type SanityClient} from '@sanity/client'\n\nimport {REQUEST_TAG_PREFIX} from './authConstants'\nimport {getTokenFromStorage} from './utils'\n\n/**\n * Cookie auth is a best-effort probe — if the API doesn't respond quickly,\n * the user likely isn't cookie-authenticated and we should move on rather\n * than block the auth flow indefinitely.\n */\nconst COOKIE_AUTH_TIMEOUT_MS = 10_000\n\n/**\n * Attempts to check for cookie auth by making a withCredentials request to the users endpoint.\n * @param projectId - The project ID to check for cookie auth.\n * @param clientFactory - A factory function that creates a Sanity client.\n * @returns True if the user is authenticated, false otherwise.\n * @internal\n */\nexport async function checkForCookieAuth(\n projectId: string | undefined,\n clientFactory: (config: ClientConfig) => SanityClient,\n): Promise<boolean> {\n if (!projectId) return false\n try {\n const client = clientFactory({\n projectId,\n useCdn: false,\n requestTagPrefix: REQUEST_TAG_PREFIX,\n timeout: COOKIE_AUTH_TIMEOUT_MS,\n })\n const user = await client.request({\n uri: '/users/me',\n withCredentials: true,\n tag: 'users.get-current',\n })\n return user != null && typeof user === 'object' && typeof user.id === 'string'\n } catch {\n return false\n }\n}\n\n/**\n * Attempts to retrieve a studio token from local storage.\n * @param storageArea - The storage area to retrieve the token from.\n * @param storageKey - The storage key to retrieve the token from.\n * @returns The studio token or null if it does not exist.\n * @internal\n */\nexport function getStudioTokenFromLocalStorage(\n storageArea: Storage | undefined,\n storageKey: string | undefined,\n): string | null {\n if (!storageArea || !storageKey) return null\n const token = getTokenFromStorage(storageArea, storageKey)\n if (token) {\n return token\n }\n return null\n}\n","import {type Subscription} from 'rxjs'\n\nimport {type TokenSource} from '../config/sanityConfig'\nimport {type StoreContext} from '../store/defineStore'\nimport {AuthStateType} from './authStateType'\nimport {type AuthStoreState, type LoggedInAuthState} from './authStore'\nimport {type AuthStrategyOptions, type AuthStrategyResult} from './authStrategy'\nimport {refreshStampedToken} from './refreshStampedToken'\nimport {checkForCookieAuth, getStudioTokenFromLocalStorage} from './studioModeAuth'\nimport {subscribeToStateAndFetchCurrentUser} from './subscribeToStateAndFetchCurrentUser'\nimport {subscribeToStorageEventsAndSetToken} from './subscribeToStorageEventsAndSetToken'\nimport {createLoggedInAuthState, getDefaultStorage} from './utils'\n\n/**\n * Resolves the initial auth state for Studio mode.\n *\n * When a `tokenSource` is provided (via `config.studio.auth.token`), the\n * initial state is `LOGGING_IN` — the actual token arrives asynchronously\n * via the subscription set up in `initializeStudioAuth`.\n *\n * Fallback token discovery order (no tokenSource):\n * 1. Provided token (`auth.token` in config)\n * 2. localStorage: `__studio_auth_token_${projectId}`\n * 3. Falls back to `LOGGED_OUT` (cookie auth is checked async in `initializeStudioAuth`)\n *\n * @internal\n */\nexport function getStudioInitialState(options: AuthStrategyOptions): AuthStrategyResult {\n const {authConfig, projectId, tokenSource} = options\n const storageArea = authConfig.storageArea ?? getDefaultStorage()\n const studioStorageKey = `__studio_auth_token_${projectId ?? ''}`\n\n // When a reactive token source is available, start in LOGGING_IN state.\n // The actual token will arrive via subscription in initializeStudioAuth.\n if (tokenSource) {\n return {\n authState: {type: AuthStateType.LOGGING_IN, isExchangingToken: false},\n storageKey: studioStorageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext: {},\n }\n }\n\n // Fallback: discover token from config or localStorage\n const providedToken = authConfig.token\n\n // Check localStorage first — mirrors original authStore behavior where\n // the localStorage read always runs before the providedToken check.\n let authMethod: AuthStrategyResult['authMethod'] = undefined\n const token = getStudioTokenFromLocalStorage(storageArea, studioStorageKey)\n if (token) {\n authMethod = 'localstorage'\n }\n\n if (providedToken) {\n return {\n authState: createLoggedInAuthState(providedToken, null),\n storageKey: studioStorageKey,\n storageArea,\n authMethod,\n dashboardContext: {},\n }\n }\n\n if (token) {\n return {\n authState: createLoggedInAuthState(token, null),\n storageKey: studioStorageKey,\n storageArea,\n authMethod: 'localstorage',\n dashboardContext: {},\n }\n }\n\n // No token found — start logged out, cookie auth will be checked asynchronously\n return {\n authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},\n storageKey: studioStorageKey,\n storageArea,\n authMethod: undefined,\n dashboardContext: {},\n }\n}\n\n/**\n * Initialize Studio auth subscriptions.\n *\n * When a `tokenSource` is available (reactive path), subscribes to it for\n * ongoing token sync. The Studio is the token authority — no independent\n * token refresh or cookie auth probing is needed.\n *\n * Fallback path (no tokenSource):\n * - Subscribe to state changes and fetch current user\n * - Subscribe to storage events for studio token key\n * - Check for cookie auth asynchronously if no token was found\n * - Start stamped token refresh\n *\n * @internal\n */\nexport function initializeStudioAuth(\n context: StoreContext<AuthStoreState>,\n tokenRefresherRunning: boolean,\n): {dispose: () => void; tokenRefresherStarted: boolean} {\n const tokenSource = context.instance.config.studio?.auth?.token\n\n // Reactive token path — Studio provides the token\n if (tokenSource) {\n return initializeWithTokenSource(context, tokenSource)\n }\n\n // Fallback path — discover token from localStorage/cookies\n return initializeWithFallback(context, tokenRefresherRunning)\n}\n\n/**\n * Subscribe to a reactive token source from the Studio workspace.\n *\n * When the token source emits a non-null token, the SDK uses it directly.\n * When it emits `null`, the behavior depends on the `authenticated` flag\n * from the Studio's workspace config:\n *\n * - `authenticated: true` — the Studio has already verified the user is\n * logged in (e.g. via cookie auth). The SDK treats the null token as\n * cookie-based auth and stays in the LOGGED_IN state.\n *\n * - `authenticated` absent/false — the user is genuinely not authenticated;\n * transition to LOGGED_OUT.\n *\n * No async cookie probing is needed here because this code path only runs\n * when a Studio provides SDKStudioContext, and the Studio's Workspace type\n * always includes `authenticated`. The async `checkForCookieAuth` fallback\n * remains in `initializeWithFallback` for the non-Studio path.\n */\nfunction initializeWithTokenSource(\n context: StoreContext<AuthStoreState>,\n tokenSource: TokenSource,\n): {dispose: () => void; tokenRefresherStarted: boolean} {\n const subscriptions: Subscription[] = []\n const studioAuthenticated = context.instance.config.studio?.authenticated === true\n\n // Subscribe to the current user fetcher — runs whenever auth state changes\n subscriptions.push(subscribeToStateAndFetchCurrentUser(context, {useProjectHostname: true}))\n\n // Subscribe to the Studio's token stream\n const tokenSub = tokenSource.subscribe({\n next: (token) => {\n const {state} = context\n if (token) {\n // Studio provided a real token — use it directly\n state.set('studioTokenSource', (prev) => ({\n options: {...prev.options, authMethod: undefined},\n authState: createLoggedInAuthState(token, null),\n }))\n } else if (studioAuthenticated) {\n // The Studio says the user is authenticated — null token means\n // cookie-based auth is in use. Stay logged in with cookie method.\n state.set('studioTokenSourceCookieAuth', (prev) => ({\n options: {...prev.options, authMethod: 'cookie'},\n authState:\n prev.authState.type === AuthStateType.LOGGED_IN\n ? prev.authState\n : createLoggedInAuthState('', null),\n }))\n } else {\n // No token and Studio doesn't confirm authentication — logged out\n state.set('studioTokenSourceLoggedOut', (prev) => ({\n options: {...prev.options, authMethod: undefined},\n authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},\n }))\n }\n },\n })\n\n return {\n dispose: () => {\n tokenSub.unsubscribe()\n for (const subscription of subscriptions) {\n subscription.unsubscribe()\n }\n },\n // Studio handles token refresh — do not start the SDK's refresher\n tokenRefresherStarted: false,\n }\n}\n\n/**\n * Fallback initialization when no reactive token source is available.\n * Uses localStorage/cookie discovery (existing behavior).\n */\nfunction initializeWithFallback(\n context: StoreContext<AuthStoreState>,\n tokenRefresherRunning: boolean,\n): {dispose: () => void; tokenRefresherStarted: boolean} {\n const subscriptions: Subscription[] = []\n let startedRefresher = false\n\n subscriptions.push(subscribeToStateAndFetchCurrentUser(context, {useProjectHostname: true}))\n\n const storageArea = context.state.get().options?.storageArea\n if (storageArea) {\n subscriptions.push(subscribeToStorageEventsAndSetToken(context))\n }\n\n // If no token found during getInitialState, try cookie auth asynchronously\n try {\n const {instance, state} = context\n const token: string | null =\n state.get().authState?.type === AuthStateType.LOGGED_IN\n ? (state.get().authState as LoggedInAuthState).token\n : null\n\n if (!token) {\n const projectIdValue = instance.config.projectId\n const clientFactory = state.get().options.clientFactory\n checkForCookieAuth(projectIdValue, clientFactory).then((isCookieAuthEnabled) => {\n if (!isCookieAuthEnabled) return\n state.set('enableCookieAuth', (prev) => ({\n options: {...prev.options, authMethod: 'cookie'},\n authState:\n prev.authState.type === AuthStateType.LOGGED_IN\n ? prev.authState\n : createLoggedInAuthState('', null),\n }))\n })\n }\n } catch {\n // best-effort cookie detection\n }\n\n if (!tokenRefresherRunning) {\n startedRefresher = true\n subscriptions.push(refreshStampedToken(context))\n }\n\n return {\n dispose: () => {\n for (const subscription of subscriptions) {\n subscription.unsubscribe()\n }\n },\n tokenRefresherStarted: startedRefresher,\n }\n}\n","import {type ClientConfig, createClient, type SanityClient} from '@sanity/client'\nimport {type CurrentUser} from '@sanity/types'\n\nimport {type AuthConfig, type AuthProvider} from '../config/authConfig'\nimport {bindActionGlobally} from '../store/createActionBinder'\nimport {createStateSourceAction} from '../store/createStateSourceAction'\nimport {defineStore} from '../store/defineStore'\nimport {getStagingApiHost} from '../utils/getStagingApiHost'\nimport {getAuthLogger} from './authLogger'\nimport {resolveAuthMode} from './authMode'\nimport {AuthStateType} from './authStateType'\nimport {type AuthStrategyOptions} from './authStrategy'\nimport {getDashboardInitialState, initializeDashboardAuth} from './dashboardAuth'\nimport {getStandaloneInitialState, initializeStandaloneAuth} from './standaloneAuth'\nimport {getStudioInitialState, initializeStudioAuth} from './studioAuth'\nimport {createLoggedInAuthState, getCleanedUrl, getDefaultLocation} from './utils'\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Represents the various states the authentication can be in.\n *\n * @public\n */\nexport type AuthState = LoggedInAuthState | LoggedOutAuthState | LoggingInAuthState | ErrorAuthState\n\n/**\n * Logged-in state from the auth state.\n * @public\n */\nexport type LoggedInAuthState = {\n type: AuthStateType.LOGGED_IN\n token: string\n currentUser: CurrentUser | null\n lastTokenRefresh?: number\n}\n\n/**\n * Logged-out state from the auth state.\n * @public\n */\nexport type LoggedOutAuthState = {type: AuthStateType.LOGGED_OUT; isDestroyingSession: boolean}\n\n/**\n * Logging-in state from the auth state.\n * @public\n */\nexport type LoggingInAuthState = {type: AuthStateType.LOGGING_IN; isExchangingToken: boolean}\n\n/**\n * Error state from the auth state.\n * @public\n */\nexport type ErrorAuthState = {type: AuthStateType.ERROR; error: unknown}\n\n/**\n * Represents the various states the authentication can be in.\n *\n * @public\n */\nexport interface DashboardContext {\n mode?: string\n env?: string\n orgId?: string\n}\n\n/**\n * The method of authentication used.\n * @internal\n */\nexport type AuthMethodOptions = 'localstorage' | 'cookie' | undefined\n\nlet tokenRefresherRunning = false\n\n/**\n * @public\n */\nexport interface AuthStoreState {\n authState: AuthState\n providers?: AuthProvider[]\n options: {\n initialLocationHref: string\n clientFactory: (config: ClientConfig) => SanityClient\n customProviders: AuthConfig['providers']\n storageKey: string\n storageArea: Storage | undefined\n apiHost: string | undefined\n loginUrl: string\n callbackUrl: string | undefined\n providedToken: string | undefined\n authMethod: AuthMethodOptions\n }\n dashboardContext?: DashboardContext\n}\n\n// ---------------------------------------------------------------------------\n// Store definition — thin orchestrator\n// ---------------------------------------------------------------------------\n\nexport const authStore = defineStore<AuthStoreState>({\n name: 'Auth',\n\n getInitialState(instance) {\n const logger = getAuthLogger(instance)\n\n logger.debug('Initializing auth store', {\n hasProvidedToken: !!instance.config.auth?.token,\n hasCustomProviders: !!(\n instance.config.auth?.providers && instance.config.auth.providers.length > 0\n ),\n })\n\n const {\n apiHost: configApiHost,\n callbackUrl,\n providers: customProviders,\n token: providedToken,\n clientFactory = createClient,\n initialLocationHref = getDefaultLocation(),\n } = instance.config.auth ?? {}\n\n const apiHost = configApiHost ?? getStagingApiHost()\n const authConfig = instance.config.auth ?? {}\n\n // Build login URL (used by standalone mode, but always computed for the\n // public `getLoginUrlState` accessor)\n let loginDomain = 'https://www.sanity.io'\n try {\n if (apiHost && new URL(apiHost).hostname.endsWith('.sanity.work')) {\n loginDomain = 'https://www.sanity.work'\n }\n } catch {\n /* empty */\n }\n const loginUrl = new URL('/login', loginDomain)\n loginUrl.searchParams.set('origin', getCleanedUrl(initialLocationHref))\n loginUrl.searchParams.set('type', 'stampedToken') // Token must be stamped to have an sid passed back\n loginUrl.searchParams.set('withSid', 'true')\n\n // Resolve auth mode and delegate to the appropriate strategy\n const mode = resolveAuthMode(instance.config, initialLocationHref)\n\n const strategyOptions: AuthStrategyOptions = {\n authConfig,\n projectId: instance.config.projectId,\n initialLocationHref,\n clientFactory,\n tokenSource: instance.config.studio?.auth?.token,\n }\n\n let result\n switch (mode) {\n case 'studio':\n result = getStudioInitialState(strategyOptions)\n break\n case 'dashboard':\n result = getDashboardInitialState(strategyOptions)\n break\n case 'standalone':\n result = getStandaloneInitialState(strategyOptions)\n break\n }\n\n logger.debug('Auth state initialized', {\n authStateType: result.authState.type,\n mode,\n authMethod: result.authMethod,\n })\n\n return {\n authState: result.authState,\n dashboardContext: result.dashboardContext,\n options: {\n apiHost,\n loginUrl: loginUrl.toString(),\n callbackUrl,\n customProviders,\n providedToken,\n clientFactory,\n initialLocationHref,\n storageKey: result.storageKey,\n storageArea: result.storageArea,\n authMethod: result.authMethod,\n },\n }\n },\n\n initialize(context) {\n const logger = getAuthLogger(context.instance)\n\n const initialLocationHref =\n context.state.get().options?.initialLocationHref ?? getDefaultLocation()\n const mode = resolveAuthMode(context.instance.config, initialLocationHref)\n\n logger.debug('Setting up auth subscriptions', {mode})\n\n let initResult\n switch (mode) {\n case 'studio':\n initResult = initializeStudioAuth(context, tokenRefresherRunning)\n break\n case 'dashboard':\n initResult = initializeDashboardAuth(context, tokenRefresherRunning)\n break\n case 'standalone':\n initResult = initializeStandaloneAuth(context, tokenRefresherRunning)\n break\n }\n\n if (initResult.tokenRefresherStarted) {\n tokenRefresherRunning = true\n }\n\n return () => {\n logger.debug('Cleaning up auth subscriptions')\n initResult.dispose()\n }\n },\n})\n\n// ---------------------------------------------------------------------------\n// Public bound actions\n// ---------------------------------------------------------------------------\n\n/**\n * @public\n */\nexport const getCurrentUserState = bindActionGlobally(\n authStore,\n createStateSourceAction(({state: {authState}}) =>\n authState.type === AuthStateType.LOGGED_IN ? authState.currentUser : null,\n ),\n)\n\n/**\n * @public\n */\nexport const getTokenState = bindActionGlobally(\n authStore,\n createStateSourceAction(({state: {authState}}) =>\n authState.type === AuthStateType.LOGGED_IN ? authState.token : null,\n ),\n)\n\n/**\n * @internal\n */\nexport const getAuthMethodState = bindActionGlobally(\n authStore,\n createStateSourceAction(({state: {options}}) => options.authMethod),\n)\n\n/**\n * @public\n */\nexport const getLoginUrlState = bindActionGlobally(\n authStore,\n createStateSourceAction(({state: {options}}) => options.loginUrl),\n)\n\n/**\n * @public\n */\nexport const getAuthState = bindActionGlobally(\n authStore,\n createStateSourceAction(({state: {authState}}) => authState),\n)\n\n/**\n * @public\n */\nexport const getDashboardOrganizationId = bindActionGlobally(\n authStore,\n createStateSourceAction(({state: {dashboardContext}}) => dashboardContext?.orgId),\n)\n\n/**\n * Returns a state source indicating if the SDK is running within a dashboard context.\n * @public\n */\nexport const getIsInDashboardState = bindActionGlobally(\n authStore,\n createStateSourceAction(\n ({state: {dashboardContext}}) =>\n // Check if dashboardContext exists and is not empty\n !!dashboardContext && Object.keys(dashboardContext).length > 0,\n ),\n)\n\n/**\n * Action to explicitly set the authentication token.\n * Used internally by the Comlink token refresh.\n * @internal\n */\nexport const setAuthToken = bindActionGlobally(\n authStore,\n ({state, instance}, token: string | null) => {\n const logger = getAuthLogger(instance)\n\n const currentAuthState = state.get().authState\n if (token) {\n // Update state only if the new token is different or currently logged out\n if (currentAuthState.type !== AuthStateType.LOGGED_IN || currentAuthState.token !== token) {\n logger.info('Setting auth token')\n const currentUser =\n currentAuthState.type === AuthStateType.LOGGED_IN ? currentAuthState.currentUser : null\n const preservedLastTokenRefresh =\n currentAuthState.type === AuthStateType.LOGGED_IN\n ? currentAuthState.lastTokenRefresh\n : undefined\n state.set('setToken', {\n authState: createLoggedInAuthState(token, currentUser, preservedLastTokenRefresh),\n })\n }\n } else {\n // Handle setting token to null (logging out)\n if (currentAuthState.type !== AuthStateType.LOGGED_OUT) {\n logger.info('Clearing auth token')\n state.set('setToken', {\n authState: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},\n })\n }\n }\n },\n)\n"],"mappings":"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"}