@sanity/sdk 0.0.0-alpha.21 → 0.0.0-alpha.23

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 (127) hide show
  1. package/dist/index.d.ts +428 -325
  2. package/dist/index.js +1618 -1553
  3. package/dist/index.js.map +1 -1
  4. package/package.json +6 -7
  5. package/src/_exports/index.ts +31 -30
  6. package/src/auth/authStore.test.ts +149 -104
  7. package/src/auth/authStore.ts +51 -100
  8. package/src/auth/handleAuthCallback.test.ts +67 -34
  9. package/src/auth/handleAuthCallback.ts +8 -7
  10. package/src/auth/logout.test.ts +61 -29
  11. package/src/auth/logout.ts +26 -28
  12. package/src/auth/refreshStampedToken.test.ts +9 -9
  13. package/src/auth/refreshStampedToken.ts +62 -56
  14. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +5 -5
  15. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +45 -47
  16. package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +4 -5
  17. package/src/auth/subscribeToStorageEventsAndSetToken.ts +22 -24
  18. package/src/client/clientStore.test.ts +131 -67
  19. package/src/client/clientStore.ts +117 -116
  20. package/src/comlink/controller/actions/destroyController.test.ts +38 -13
  21. package/src/comlink/controller/actions/destroyController.ts +11 -15
  22. package/src/comlink/controller/actions/getOrCreateChannel.test.ts +56 -27
  23. package/src/comlink/controller/actions/getOrCreateChannel.ts +37 -35
  24. package/src/comlink/controller/actions/getOrCreateController.test.ts +27 -16
  25. package/src/comlink/controller/actions/getOrCreateController.ts +23 -22
  26. package/src/comlink/controller/actions/releaseChannel.test.ts +37 -13
  27. package/src/comlink/controller/actions/releaseChannel.ts +22 -21
  28. package/src/comlink/controller/comlinkControllerStore.test.ts +65 -36
  29. package/src/comlink/controller/comlinkControllerStore.ts +44 -5
  30. package/src/comlink/node/actions/getOrCreateNode.test.ts +31 -15
  31. package/src/comlink/node/actions/getOrCreateNode.ts +30 -29
  32. package/src/comlink/node/actions/releaseNode.test.ts +75 -55
  33. package/src/comlink/node/actions/releaseNode.ts +19 -21
  34. package/src/comlink/node/comlinkNodeStore.test.ts +6 -11
  35. package/src/comlink/node/comlinkNodeStore.ts +22 -5
  36. package/src/config/authConfig.ts +79 -0
  37. package/src/config/sanityConfig.ts +48 -0
  38. package/src/datasets/datasets.test.ts +2 -2
  39. package/src/datasets/datasets.ts +18 -5
  40. package/src/document/actions.test.ts +22 -10
  41. package/src/document/actions.ts +44 -56
  42. package/src/document/applyDocumentActions.test.ts +96 -36
  43. package/src/document/applyDocumentActions.ts +140 -99
  44. package/src/document/documentStore.test.ts +103 -155
  45. package/src/document/documentStore.ts +247 -237
  46. package/src/document/listen.ts +56 -55
  47. package/src/document/patchOperations.ts +0 -43
  48. package/src/document/permissions.test.ts +25 -12
  49. package/src/document/permissions.ts +11 -4
  50. package/src/document/processActions.test.ts +41 -8
  51. package/src/document/reducers.test.ts +87 -16
  52. package/src/document/reducers.ts +2 -2
  53. package/src/document/sharedListener.test.ts +34 -16
  54. package/src/document/sharedListener.ts +33 -11
  55. package/src/preview/getPreviewState.test.ts +40 -39
  56. package/src/preview/getPreviewState.ts +68 -56
  57. package/src/preview/previewConstants.ts +43 -0
  58. package/src/preview/previewQuery.test.ts +1 -1
  59. package/src/preview/previewQuery.ts +4 -5
  60. package/src/preview/previewStore.test.ts +13 -58
  61. package/src/preview/previewStore.ts +7 -21
  62. package/src/preview/resolvePreview.test.ts +33 -104
  63. package/src/preview/resolvePreview.ts +11 -21
  64. package/src/preview/subscribeToStateAndFetchBatches.test.ts +96 -97
  65. package/src/preview/subscribeToStateAndFetchBatches.ts +85 -81
  66. package/src/preview/util.ts +1 -0
  67. package/src/project/project.test.ts +3 -3
  68. package/src/project/project.ts +28 -5
  69. package/src/projection/getProjectionState.test.ts +69 -49
  70. package/src/projection/getProjectionState.ts +42 -50
  71. package/src/projection/projectionQuery.ts +1 -1
  72. package/src/projection/projectionStore.test.ts +13 -51
  73. package/src/projection/projectionStore.ts +6 -18
  74. package/src/projection/resolveProjection.test.ts +32 -127
  75. package/src/projection/resolveProjection.ts +15 -28
  76. package/src/projection/subscribeToStateAndFetchBatches.test.ts +105 -90
  77. package/src/projection/subscribeToStateAndFetchBatches.ts +94 -81
  78. package/src/projection/util.ts +2 -0
  79. package/src/projects/projects.test.ts +13 -4
  80. package/src/projects/projects.ts +6 -1
  81. package/src/query/queryStore.test.ts +10 -47
  82. package/src/query/queryStore.ts +151 -133
  83. package/src/query/queryStoreConstants.ts +2 -0
  84. package/src/store/createActionBinder.test.ts +153 -0
  85. package/src/store/createActionBinder.ts +176 -0
  86. package/src/store/createSanityInstance.test.ts +84 -0
  87. package/src/store/createSanityInstance.ts +124 -0
  88. package/src/store/createStateSourceAction.test.ts +196 -0
  89. package/src/store/createStateSourceAction.ts +260 -0
  90. package/src/store/createStoreInstance.test.ts +81 -0
  91. package/src/store/createStoreInstance.ts +80 -0
  92. package/src/store/createStoreState.test.ts +85 -0
  93. package/src/store/createStoreState.ts +92 -0
  94. package/src/store/defineStore.test.ts +18 -0
  95. package/src/store/defineStore.ts +81 -0
  96. package/src/users/reducers.test.ts +318 -0
  97. package/src/users/reducers.ts +88 -0
  98. package/src/users/types.ts +46 -4
  99. package/src/users/usersConstants.ts +4 -0
  100. package/src/users/usersStore.test.ts +350 -223
  101. package/src/users/usersStore.ts +285 -149
  102. package/src/utils/createFetcherStore.test.ts +6 -7
  103. package/src/utils/createFetcherStore.ts +150 -153
  104. package/src/{common/util.test.ts → utils/hashString.test.ts} +1 -1
  105. package/src/auth/fetchLoginUrls.test.ts +0 -163
  106. package/src/auth/fetchLoginUrls.ts +0 -74
  107. package/src/common/createLiveEventSubscriber.test.ts +0 -121
  108. package/src/common/createLiveEventSubscriber.ts +0 -55
  109. package/src/common/types.ts +0 -4
  110. package/src/instance/identity.test.ts +0 -46
  111. package/src/instance/identity.ts +0 -29
  112. package/src/instance/sanityInstance.test.ts +0 -77
  113. package/src/instance/sanityInstance.ts +0 -57
  114. package/src/instance/types.ts +0 -37
  115. package/src/preview/getPreviewProjection.ts +0 -45
  116. package/src/resources/README.md +0 -370
  117. package/src/resources/createAction.test.ts +0 -101
  118. package/src/resources/createAction.ts +0 -44
  119. package/src/resources/createResource.test.ts +0 -112
  120. package/src/resources/createResource.ts +0 -102
  121. package/src/resources/createStateSourceAction.test.ts +0 -114
  122. package/src/resources/createStateSourceAction.ts +0 -83
  123. package/src/resources/createStore.test.ts +0 -67
  124. package/src/resources/createStore.ts +0 -46
  125. package/src/store/createStore.test.ts +0 -108
  126. package/src/store/createStore.ts +0 -106
  127. /package/src/{common/util.ts → utils/hashString.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/sdk",
3
- "version": "0.0.0-alpha.21",
3
+ "version": "0.0.0-alpha.23",
4
4
  "private": false,
5
5
  "description": "Sanity SDK",
6
6
  "keywords": [
@@ -55,16 +55,15 @@
55
55
  },
56
56
  "devDependencies": {
57
57
  "@sanity/browserslist-config": "^1.0.5",
58
- "@sanity/pkg-utils": "^6.13.4",
58
+ "@sanity/pkg-utils": "^7.2.2",
59
59
  "@sanity/prettier-config": "^1.0.3",
60
- "@sanity/types": "^3.79.0",
61
- "@vitest/coverage-v8": "3.0.9",
60
+ "@vitest/coverage-v8": "3.1.1",
62
61
  "eslint": "^9.22.0",
63
62
  "groq-js": "^1.16.1",
64
63
  "prettier": "^3.5.3",
65
64
  "typescript": "^5.7.3",
66
- "vite": "^6.2.2",
67
- "vitest": "^3.0.9",
65
+ "vite": "^6.2.4",
66
+ "vitest": "^3.1.1",
68
67
  "@repo/config-eslint": "0.0.0",
69
68
  "@repo/config-test": "0.0.1",
70
69
  "@repo/package.config": "0.0.1",
@@ -80,7 +79,7 @@
80
79
  "build": "pkg build --strict --clean --check",
81
80
  "clean": "rimraf dist",
82
81
  "dev": "pkg watch",
83
- "docs": "typedoc --out docs --tsconfig ../../tsconfig.tsdoc.json",
82
+ "docs": "typedoc --out docs --tsconfig ./tsconfig.dist.json",
84
83
  "format": "prettier --write --cache --ignore-unknown .",
85
84
  "lint": "eslint .",
86
85
  "test": "vitest run",
@@ -1,4 +1,3 @@
1
- // Use import type to access the internal type and re-export it
2
1
  import {type SanityProject as _SanityProject} from '@sanity/client'
3
2
 
4
3
  /**
@@ -8,34 +7,40 @@ export type SanityProject = _SanityProject
8
7
 
9
8
  export {AuthStateType} from '../auth/authStateType'
10
9
  export {
11
- type AuthConfig,
12
- type AuthProvider,
13
10
  type AuthState,
14
11
  type AuthStoreState,
15
12
  type ErrorAuthState,
16
13
  getAuthState,
17
14
  getCurrentUserState,
18
15
  getDashboardOrganizationId,
19
- getLoginUrlsState,
16
+ getLoginUrlState,
20
17
  getTokenState,
21
18
  type LoggedInAuthState,
22
19
  type LoggedOutAuthState,
23
20
  type LoggingInAuthState,
24
21
  } from '../auth/authStore'
25
- export {fetchLoginUrls} from '../auth/fetchLoginUrls'
26
22
  export {handleAuthCallback} from '../auth/handleAuthCallback'
27
23
  export {logout} from '../auth/logout'
28
- export type {ClientState} from '../client/clientStore'
24
+ export type {ClientStoreState as ClientState} from '../client/clientStore'
29
25
  export {type ClientOptions, getClient, getClientState} from '../client/clientStore'
30
- export {destroyController} from '../comlink/controller/actions/destroyController'
31
- export {getOrCreateChannel} from '../comlink/controller/actions/getOrCreateChannel'
32
- export {getOrCreateController} from '../comlink/controller/actions/getOrCreateController'
33
- export {releaseChannel} from '../comlink/controller/actions/releaseChannel'
34
- export type {ComlinkControllerState} from '../comlink/controller/comlinkControllerStore'
35
- export {getOrCreateNode} from '../comlink/node/actions/getOrCreateNode'
36
- export {releaseNode} from '../comlink/node/actions/releaseNode'
26
+ export {
27
+ type ComlinkControllerState,
28
+ destroyController,
29
+ getOrCreateChannel,
30
+ getOrCreateController,
31
+ releaseChannel,
32
+ } from '../comlink/controller/comlinkControllerStore'
37
33
  export type {ComlinkNodeState} from '../comlink/node/comlinkNodeStore'
34
+ export {getOrCreateNode, releaseNode} from '../comlink/node/comlinkNodeStore'
38
35
  export {type FrameMessage, type WindowMessage} from '../comlink/types'
36
+ export {type AuthConfig, type AuthProvider} from '../config/authConfig'
37
+ export {
38
+ type DatasetHandle,
39
+ type DocumentHandle,
40
+ type DocumentTypeHandle,
41
+ type ProjectHandle,
42
+ type SanityConfig,
43
+ } from '../config/sanityConfig'
39
44
  export {getDatasetsState, resolveDatasets} from '../datasets/datasets'
40
45
  export {
41
46
  createDocument,
@@ -77,23 +82,14 @@ export {
77
82
  type TransactionAcceptedEvent,
78
83
  type TransactionRevertedEvent,
79
84
  } from '../document/events'
80
- export {
81
- type DocumentHandle,
82
- type DocumentTypeHandle,
83
- type JsonMatch,
84
- jsonMatch,
85
- type JsonMatchPath,
86
- } from '../document/patchOperations'
87
- export {type DocumentResourceId, getResourceId, type ResourceId} from '../document/patchOperations'
85
+ export {type JsonMatch, jsonMatch, type JsonMatchPath} from '../document/patchOperations'
88
86
  export {type DocumentPermissionsResult, type PermissionDeniedReason} from '../document/permissions'
89
- export {createSanityInstance} from '../instance/sanityInstance'
90
- export type {SanityConfig, SanityInstance, SdkIdentity} from '../instance/types'
91
87
  export {getPreviewState, type GetPreviewStateOptions} from '../preview/getPreviewState'
92
88
  export type {PreviewStoreState, PreviewValue, ValuePending} from '../preview/previewStore'
93
89
  export {resolvePreview, type ResolvePreviewOptions} from '../preview/resolvePreview'
94
90
  export {getProjectState, resolveProject} from '../project/project'
95
91
  export {getProjectionState} from '../projection/getProjectionState'
96
- export type {ProjectionValuePending, ValidProjection} from '../projection/projectionStore'
92
+ export {type ProjectionValuePending, type ValidProjection} from '../projection/projectionStore'
97
93
  export {resolveProjection} from '../projection/resolveProjection'
98
94
  export {getProjectsState, resolveProjects} from '../projects/projects'
99
95
  export {
@@ -103,12 +99,17 @@ export {
103
99
  type QueryOptions,
104
100
  resolveQuery,
105
101
  } from '../query/queryStore'
106
- export {type ActionContext, type ResourceAction} from '../resources/createAction'
107
- export {type ResourceState} from '../resources/createResource'
108
- export type {StateSource} from '../resources/createStateSourceAction'
109
- export {type BoundResourceAction} from '../resources/createStore'
110
- export {type Membership, type ResourceType, type SanityUser, type UserProfile} from '../users/types'
111
- export {createUsersStore, type UsersStoreState} from '../users/usersStore'
102
+ export {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
103
+ export {type Selector, type StateSource} from '../store/createStateSourceAction'
104
+ export {getUsersKey, parseUsersKey} from '../users/reducers'
105
+ export {
106
+ type GetUsersOptions,
107
+ type Membership,
108
+ type ResolveUsersOptions,
109
+ type SanityUser,
110
+ type UserProfile,
111
+ } from '../users/types'
112
+ export {getUsersState, loadMoreUsers, resolveUsers} from '../users/usersStore'
112
113
  export {type FetcherStore, type FetcherStoreState} from '../utils/createFetcherStore'
113
114
  export {CORE_SDK_VERSION} from '../version'
114
115
  export type {CurrentUser, Role, SanityDocument, SanityDocumentLike} from '@sanity/types'
@@ -1,20 +1,19 @@
1
1
  import {type ClientConfig, createClient} from '@sanity/client'
2
2
  import {type CurrentUser} from '@sanity/types'
3
- import {type Subscription} from 'rxjs'
4
- import {beforeEach, describe, it} from 'vitest'
3
+ import {NEVER, type Subscription} from 'rxjs'
4
+ import {afterEach, beforeEach, describe, it} from 'vitest'
5
5
 
6
- import {createSanityInstance} from '../instance/sanityInstance'
7
- import {createResourceState, getOrCreateResource} from '../resources/createResource'
6
+ import {createSanityInstance} from '../store/createSanityInstance'
8
7
  import {AuthStateType} from './authStateType'
9
8
  import {
10
9
  authStore,
11
- type AuthStoreState,
12
10
  getAuthState,
13
11
  getCurrentUserState,
14
12
  getDashboardOrganizationId,
15
- getLoginUrlsState,
13
+ getLoginUrlState,
16
14
  getTokenState,
17
15
  } from './authStore'
16
+ import {handleAuthCallback} from './handleAuthCallback'
18
17
  import {subscribeToStateAndFetchCurrentUser} from './subscribeToStateAndFetchCurrentUser'
19
18
  import {subscribeToStorageEventsAndSetToken} from './subscribeToStorageEventsAndSetToken'
20
19
  import {getAuthCode, getTokenFromStorage} from './utils'
@@ -28,7 +27,25 @@ vi.mock('./subscribeToStateAndFetchCurrentUser')
28
27
  vi.mock('./subscribeToStorageEventsAndSetToken')
29
28
 
30
29
  describe('authStore', () => {
30
+ // Global beforeEach and afterEach for all tests
31
+ beforeEach(() => {
32
+ vi.resetAllMocks()
33
+ vi.mocked(subscribeToStateAndFetchCurrentUser).mockImplementation(() => NEVER.subscribe())
34
+ vi.mocked(subscribeToStorageEventsAndSetToken).mockImplementation(() => NEVER.subscribe())
35
+ })
36
+
31
37
  describe('getInitialState', () => {
38
+ let instance: ReturnType<typeof createSanityInstance>
39
+
40
+ beforeEach(() => {
41
+ vi.mocked(getTokenFromStorage).mockReturnValue(null)
42
+ vi.mocked(getAuthCode).mockReturnValue(null)
43
+ })
44
+
45
+ afterEach(() => {
46
+ instance?.dispose()
47
+ })
48
+
32
49
  it('sets initial options onto state', () => {
33
50
  const apiHost = 'test-api-host'
34
51
  const callbackUrl = '/login/callback'
@@ -40,7 +57,7 @@ describe('authStore', () => {
40
57
  const initialLocationHref = 'https://example.com'
41
58
  const storageArea = {} as Storage
42
59
 
43
- const instance = createSanityInstance({
60
+ instance = createSanityInstance({
44
61
  projectId: 'p',
45
62
  dataset: 'd',
46
63
  auth: {
@@ -54,8 +71,6 @@ describe('authStore', () => {
54
71
  },
55
72
  })
56
73
 
57
- vi.mocked(getTokenFromStorage).mockReturnValue(null)
58
-
59
74
  const {options} = authStore.getInitialState(instance)
60
75
 
61
76
  expect(options.apiHost).toBe(apiHost)
@@ -69,7 +84,7 @@ describe('authStore', () => {
69
84
  })
70
85
 
71
86
  it('sets to logged in if provided token is present', () => {
72
- const instance = createSanityInstance({
87
+ instance = createSanityInstance({
73
88
  projectId: 'p',
74
89
  dataset: 'd',
75
90
  auth: {
@@ -82,7 +97,7 @@ describe('authStore', () => {
82
97
  })
83
98
 
84
99
  it('sets to logging in if `getAuthCode` returns a code', () => {
85
- const instance = createSanityInstance({
100
+ instance = createSanityInstance({
86
101
  projectId: 'p',
87
102
  dataset: 'd',
88
103
  })
@@ -94,7 +109,7 @@ describe('authStore', () => {
94
109
  })
95
110
 
96
111
  it('sets to logged in if `getTokenFromStorage` returns a token', () => {
97
- const instance = createSanityInstance({
112
+ instance = createSanityInstance({
98
113
  projectId: 'p',
99
114
  dataset: 'd',
100
115
  })
@@ -107,7 +122,7 @@ describe('authStore', () => {
107
122
  })
108
123
 
109
124
  it('otherwise it sets the state to logged out', () => {
110
- const instance = createSanityInstance({
125
+ instance = createSanityInstance({
111
126
  projectId: 'p',
112
127
  dataset: 'd',
113
128
  })
@@ -122,9 +137,11 @@ describe('authStore', () => {
122
137
 
123
138
  describe('initialize', () => {
124
139
  let mockLocalStorage: Storage
140
+ let instance: ReturnType<typeof createSanityInstance>
141
+ let stateUnsubscribe: ReturnType<typeof vi.fn>
142
+ let storageEventsUnsubscribe: ReturnType<typeof vi.fn>
125
143
 
126
144
  beforeEach(() => {
127
- vi.clearAllMocks()
128
145
  // Create fresh mock localStorage for each test
129
146
  mockLocalStorage = {
130
147
  getItem: vi.fn(),
@@ -138,26 +155,29 @@ describe('authStore', () => {
138
155
  return Storage
139
156
  },
140
157
  } as unknown as Storage
141
- })
142
158
 
143
- it('subscribes to state and storage events and unsubscribes on dispose', () => {
144
- const instance = createSanityInstance({
145
- projectId: 'p123abc',
146
- dataset: 'production',
147
- auth: {
148
- storageArea: mockLocalStorage,
149
- },
150
- })
159
+ stateUnsubscribe = vi.fn()
160
+ storageEventsUnsubscribe = vi.fn()
151
161
 
152
- const stateUnsubscribe = vi.fn()
153
162
  vi.mocked(subscribeToStateAndFetchCurrentUser).mockReturnValue({
154
163
  unsubscribe: stateUnsubscribe,
155
164
  } as unknown as Subscription)
156
165
 
157
- const storageEventsUnsubscribe = vi.fn()
158
166
  vi.mocked(subscribeToStorageEventsAndSetToken).mockReturnValue({
159
167
  unsubscribe: storageEventsUnsubscribe,
160
168
  } as unknown as Subscription)
169
+ })
170
+
171
+ afterEach(() => {
172
+ instance?.dispose()
173
+ })
174
+
175
+ it('subscribes to state and storage events and unsubscribes on dispose', () => {
176
+ instance = createSanityInstance({
177
+ projectId: 'p',
178
+ dataset: 'd',
179
+ auth: {storageArea: mockLocalStorage},
180
+ })
161
181
 
162
182
  Object.defineProperty(mockLocalStorage, 'constructor', {
163
183
  get: () => Storage,
@@ -166,7 +186,8 @@ describe('authStore', () => {
166
186
  expect(subscribeToStateAndFetchCurrentUser).not.toHaveBeenCalled()
167
187
  expect(subscribeToStorageEventsAndSetToken).not.toHaveBeenCalled()
168
188
 
169
- getOrCreateResource(instance, authStore)
189
+ // call a bound action to lazily create the store
190
+ getAuthState(instance)
170
191
 
171
192
  expect(subscribeToStateAndFetchCurrentUser).toHaveBeenCalled()
172
193
  expect(subscribeToStorageEventsAndSetToken).toHaveBeenCalled()
@@ -178,25 +199,13 @@ describe('authStore', () => {
178
199
  })
179
200
 
180
201
  it('does not subscribe to storage events when not using storage area', () => {
181
- const instance = createSanityInstance({
182
- projectId: 'p123abc',
183
- dataset: 'production',
184
- auth: {
185
- storageArea: undefined,
186
- },
202
+ instance = createSanityInstance({
203
+ projectId: 'p',
204
+ dataset: 'd',
205
+ auth: {storageArea: undefined},
187
206
  })
188
207
 
189
- const stateUnsubscribe = vi.fn()
190
- vi.mocked(subscribeToStateAndFetchCurrentUser).mockReturnValue({
191
- unsubscribe: stateUnsubscribe,
192
- } as unknown as Subscription)
193
-
194
- const storageEventsUnsubscribe = vi.fn()
195
- vi.mocked(subscribeToStorageEventsAndSetToken).mockReturnValue({
196
- unsubscribe: storageEventsUnsubscribe,
197
- } as unknown as Subscription)
198
-
199
- getOrCreateResource(instance, authStore)
208
+ getAuthState(instance)
200
209
 
201
210
  expect(subscribeToStateAndFetchCurrentUser).toHaveBeenCalled()
202
211
  expect(subscribeToStorageEventsAndSetToken).not.toHaveBeenCalled()
@@ -209,43 +218,60 @@ describe('authStore', () => {
209
218
  })
210
219
 
211
220
  describe('getCurrentUserState', () => {
212
- it('returns the current user if logged in and current user is non-null', () => {
213
- const currentUser = {id: 'example-user'} as CurrentUser
214
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
215
- const state = createResourceState<AuthStoreState>({
216
- authState: {type: AuthStateType.LOGGED_IN, token: 'new-token', currentUser},
217
- } as AuthStoreState)
221
+ let instance: ReturnType<typeof createSanityInstance>
222
+ let currentUser: CurrentUser
218
223
 
219
- const currentUserState = getCurrentUserState({instance, state})
220
- expect(currentUserState.getCurrent()).toBe(currentUser)
224
+ beforeEach(() => {
225
+ currentUser = {id: 'example-user'} as CurrentUser
226
+ })
221
227
 
222
- // pureness check
223
- expect(currentUserState.getCurrent()).toBe(currentUserState.getCurrent())
228
+ afterEach(() => {
229
+ instance?.dispose()
224
230
  })
225
231
 
226
- it('returns null otherwise', () => {
227
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
228
- const state = createResourceState<AuthStoreState>({
229
- authState: {type: AuthStateType.LOGGED_OUT},
230
- } as AuthStoreState)
232
+ it('returns the current user if logged in and current user is non-null', () => {
233
+ vi.mocked(subscribeToStateAndFetchCurrentUser).mockImplementation(({state}) => {
234
+ state.set('setCurrentUser', {
235
+ authState: {
236
+ type: AuthStateType.LOGGED_IN,
237
+ token: 'token',
238
+ currentUser,
239
+ },
240
+ })
241
+
242
+ return NEVER.subscribe()
243
+ })
244
+
245
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
231
246
 
232
- const currentUserState = getCurrentUserState({instance, state})
233
- expect(currentUserState.getCurrent()).toBe(null)
247
+ const {getCurrent} = getCurrentUserState(instance)
234
248
 
235
249
  // pureness check
236
- expect(currentUserState.getCurrent()).toBe(currentUserState.getCurrent())
250
+ expect(getCurrent()).toBe(getCurrent())
251
+ })
252
+
253
+ it('returns null otherwise', () => {
254
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
255
+ const {getCurrent} = getCurrentUserState(instance)
256
+ expect(getCurrent()).toBe(null)
237
257
  })
238
258
  })
239
259
 
240
260
  describe('getTokenState', () => {
241
- it('returns the token if logged in', () => {
242
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
243
- const token = 'new-token'
244
- const state = createResourceState<AuthStoreState>({
245
- authState: {type: AuthStateType.LOGGED_IN, token},
246
- } as AuthStoreState)
261
+ let instance: ReturnType<typeof createSanityInstance>
262
+
263
+ afterEach(() => {
264
+ instance?.dispose()
265
+ })
247
266
 
248
- const tokenState = getTokenState({instance, state})
267
+ it('returns the token if logged in', () => {
268
+ const token = 'hard-coded-token'
269
+ instance = createSanityInstance({
270
+ projectId: 'p',
271
+ dataset: 'd',
272
+ auth: {token},
273
+ })
274
+ const tokenState = getTokenState(instance)
249
275
  expect(tokenState.getCurrent()).toBe(token)
250
276
 
251
277
  // pureness check
@@ -253,12 +279,9 @@ describe('authStore', () => {
253
279
  })
254
280
 
255
281
  it('returns null otherwise', () => {
256
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
257
- const state = createResourceState<AuthStoreState>({
258
- authState: {type: AuthStateType.ERROR, error: new Error('test error')},
259
- } as AuthStoreState)
282
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
260
283
 
261
- const tokenState = getTokenState({instance, state})
284
+ const tokenState = getTokenState(instance)
262
285
  expect(tokenState.getCurrent()).toBe(null)
263
286
 
264
287
  // pureness check
@@ -267,55 +290,77 @@ describe('authStore', () => {
267
290
  })
268
291
 
269
292
  describe('getLoginUrlsState', () => {
270
- it('returns the cached auth providers if present', () => {
271
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
272
- const providers = [{name: 'test', title: 'Test', url: 'https://example.com#withSid=true'}]
273
- const state = createResourceState<AuthStoreState>({providers} as AuthStoreState)
293
+ let instance: ReturnType<typeof createSanityInstance>
274
294
 
275
- const loginUrlsState = getLoginUrlsState({instance, state})
276
- expect(loginUrlsState.getCurrent()).toBe(providers)
277
-
278
- // pureness check
279
- expect(loginUrlsState.getCurrent()).toBe(loginUrlsState.getCurrent())
295
+ afterEach(() => {
296
+ instance?.dispose()
280
297
  })
281
298
 
282
- it('returns nulls otherwise', () => {
283
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
284
- const state = createResourceState<AuthStoreState>({} as AuthStoreState)
285
-
286
- const loginUrlsState = getLoginUrlsState({instance, state})
287
- expect(loginUrlsState.getCurrent()).toBe(null)
299
+ it('returns the default login url', () => {
300
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
288
301
 
289
- // pureness check
290
- expect(loginUrlsState.getCurrent()).toBe(loginUrlsState.getCurrent())
302
+ const loginUrlState = getLoginUrlState(instance)
303
+ expect(loginUrlState.getCurrent()).toBe(
304
+ 'https://www.sanity.io/login?origin=http%3A%2F%2Flocalhost&type=stampedToken&withSid=true',
305
+ )
291
306
  })
292
307
  })
293
308
 
294
309
  describe('getAuthState', () => {
310
+ let instance: ReturnType<typeof createSanityInstance>
311
+
312
+ afterEach(() => {
313
+ instance?.dispose()
314
+ })
315
+
295
316
  it('returns the current state in `authState`', () => {
296
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
297
- const authState: AuthStoreState['authState'] = {
298
- type: AuthStateType.LOGGED_OUT,
299
- isDestroyingSession: false,
300
- }
301
- const state = createResourceState<AuthStoreState>({authState} as AuthStoreState)
317
+ instance = createSanityInstance({
318
+ projectId: 'p',
319
+ dataset: 'd',
320
+ auth: {token: 'hard-coded-token'},
321
+ })
302
322
 
303
- const authStateSource = getAuthState({instance, state})
304
- expect(authStateSource.getCurrent()).toBe(authState)
323
+ const {getCurrent} = getAuthState(instance)
324
+ expect(getCurrent()).toEqual({
325
+ currentUser: null,
326
+ token: 'hard-coded-token',
327
+ type: 'logged-in',
328
+ })
305
329
 
306
330
  // pureness check
307
- expect(authStateSource.getCurrent()).toBe(authStateSource.getCurrent())
331
+ expect(getCurrent()).toBe(getCurrent())
308
332
  })
309
333
  })
310
334
 
311
335
  describe('getDashboardOrganizationId', () => {
336
+ let instance: ReturnType<typeof createSanityInstance>
337
+
338
+ beforeEach(() => {
339
+ vi.mocked(getAuthCode).mockReturnValue('test-auth-code')
340
+ })
341
+
342
+ afterEach(() => {
343
+ instance?.dispose()
344
+ })
345
+
312
346
  it('returns the organization id if present', () => {
313
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
314
- const state = createResourceState<AuthStoreState>({
315
- dashboardContext: {orgId: 'org-id'},
316
- } as AuthStoreState)
347
+ instance = createSanityInstance({
348
+ projectId: 'p',
349
+ dataset: 'd',
350
+ auth: {
351
+ clientFactory: vi.fn().mockReturnValue({
352
+ request: vi.fn().mockResolvedValue({token: 'test-token', label: 'tes'}),
353
+ }),
354
+ },
355
+ })
356
+
357
+ // Create a URL with an organization ID in the _context parameter
358
+ const callbackUrl = `https://example.com/login/callback?sid=test-auth-code&_context=${encodeURIComponent(JSON.stringify({orgId: 'org-id'}))}`
359
+
360
+ // Call handleCallback with the URL to set the organization ID in the state
361
+ handleAuthCallback(instance, callbackUrl)
317
362
 
318
- const organizationId = getDashboardOrganizationId({instance, state})
363
+ const organizationId = getDashboardOrganizationId(instance)
319
364
  expect(organizationId.getCurrent()).toBe('org-id')
320
365
  })
321
366
  })