@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.
- package/README.md +12 -0
- package/dist/_exports/_internal.d.ts +163 -0
- package/dist/_exports/_internal.d.ts.map +1 -0
- package/dist/_exports/_internal.js +332 -0
- package/dist/_exports/_internal.js.map +1 -0
- package/dist/_exports/agent.d.ts +65 -0
- package/dist/_exports/agent.d.ts.map +1 -0
- package/dist/_exports/agent.js +71 -0
- package/dist/_exports/agent.js.map +1 -0
- package/dist/_exports/comlink.d.ts +118 -0
- package/dist/_exports/comlink.d.ts.map +1 -0
- package/dist/_exports/comlink.js +69 -0
- package/dist/_exports/comlink.js.map +1 -0
- package/dist/authStore-CtE9bLHW.js +754 -0
- package/dist/authStore-CtE9bLHW.js.map +1 -0
- package/dist/authStore-DKFX8fn7.d.ts +3179 -0
- package/dist/authStore-DKFX8fn7.d.ts.map +1 -0
- package/dist/clientStore-BtE2-q2i.js +90 -0
- package/dist/clientStore-BtE2-q2i.js.map +1 -0
- package/dist/createSanityInstance-DUI1bGIg.d.ts +278 -0
- package/dist/createSanityInstance-DUI1bGIg.d.ts.map +1 -0
- package/dist/createStateSourceAction-BOKtqFNm.js +300 -0
- package/dist/createStateSourceAction-BOKtqFNm.js.map +1 -0
- package/dist/getEnv-D5RGkQLu.js +8 -0
- package/dist/getEnv-D5RGkQLu.js.map +1 -0
- package/dist/getNodeState-CR3__B2D.js +67 -0
- package/dist/getNodeState-CR3__B2D.js.map +1 -0
- package/dist/index.d.ts +3 -2332
- package/dist/index.js +4171 -4332
- package/dist/index.js.map +1 -1
- package/dist/logger-DAtJb5RQ.js +173 -0
- package/dist/logger-DAtJb5RQ.js.map +1 -0
- package/dist/object-CxXlSVg7.js +83 -0
- package/dist/object-CxXlSVg7.js.map +1 -0
- package/dist/queryStore-DPf9sN3V.js +1346 -0
- package/dist/queryStore-DPf9sN3V.js.map +1 -0
- package/dist/rolldown-runtime-vyAXikos.js +9 -0
- package/dist/setCleanupTimeout-BiM6q1KF.js +31 -0
- package/dist/setCleanupTimeout-BiM6q1KF.js.map +1 -0
- package/dist/telemetryManager-Dq_qCkeI.js +127 -0
- package/dist/telemetryManager-Dq_qCkeI.js.map +1 -0
- package/dist/version-BChjsi4u.js +9 -0
- package/dist/version-BChjsi4u.js.map +1 -0
- package/package.json +47 -52
- package/src/_exports/_internal.ts +27 -0
- package/src/_exports/agent.ts +19 -0
- package/src/_exports/comlink.ts +16 -0
- package/src/_exports/index.ts +125 -64
- package/src/access/checkPermissions.test.ts +55 -0
- package/src/access/checkPermissions.ts +54 -0
- package/src/agent/agentActions.test.ts +16 -60
- package/src/agent/agentActions.ts +25 -38
- package/src/applications/applications.test-d.ts +88 -0
- package/src/applications/applications.test.ts +130 -0
- package/src/applications/applications.ts +367 -0
- package/src/auth/authLogger.ts +30 -0
- package/src/auth/authStore.test.ts +194 -13
- package/src/auth/authStore.ts +58 -26
- package/src/auth/getOrganizationVerificationState.test.ts +18 -17
- package/src/auth/getOrganizationVerificationState.ts +4 -4
- package/src/auth/handleAuthCallback.test.ts +35 -1
- package/src/auth/handleAuthCallback.ts +25 -6
- package/src/auth/logout.test.ts +75 -2
- package/src/auth/logout.ts +23 -4
- package/src/auth/refreshStampedToken.test.ts +219 -469
- package/src/auth/refreshStampedToken.ts +79 -195
- package/src/auth/studioAuth.ts +1 -1
- package/src/auth/studioModeAuth.ts +2 -1
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +146 -13
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +37 -6
- package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +2 -0
- package/src/client/clientStore.test.ts +62 -37
- package/src/client/clientStore.ts +45 -75
- package/src/client/liveEvents.test.ts +151 -0
- package/src/client/liveEvents.ts +107 -0
- package/src/comlink/controller/actions/destroyController.test.ts +4 -1
- package/src/comlink/controller/actions/getOrCreateChannel.test.ts +4 -1
- package/src/comlink/controller/actions/getOrCreateChannel.ts +2 -2
- package/src/comlink/controller/actions/getOrCreateController.test.ts +4 -1
- package/src/comlink/controller/actions/releaseChannel.test.ts +1 -1
- package/src/comlink/controller/comlinkControllerStore.test.ts +4 -1
- package/src/comlink/node/actions/getOrCreateNode.test.ts +9 -3
- package/src/comlink/node/actions/getOrCreateNode.ts +2 -2
- package/src/comlink/node/actions/releaseNode.test.ts +7 -4
- package/src/comlink/node/comlinkNodeStore.test.ts +2 -2
- package/src/comlink/node/getNodeState.test.ts +1 -1
- package/src/comlink/node/getNodeState.ts +2 -1
- package/src/comments/addonDatasetStore.test.ts +215 -0
- package/src/comments/addonDatasetStore.ts +249 -0
- package/src/comments/buildCommentThreads.test.ts +83 -0
- package/src/comments/buildCommentThreads.ts +54 -0
- package/src/comments/commentActions.test.ts +540 -0
- package/src/comments/commentActions.ts +555 -0
- package/src/comments/commentFieldPath.test.ts +40 -0
- package/src/comments/commentFieldPath.ts +44 -0
- package/src/comments/commentsConstants.ts +80 -0
- package/src/comments/commentsStore.test.ts +419 -0
- package/src/comments/commentsStore.ts +483 -0
- package/src/comments/normalizeComment.test.ts +116 -0
- package/src/comments/normalizeComment.ts +45 -0
- package/src/comments/observeComments.test.ts +193 -0
- package/src/comments/observeComments.ts +113 -0
- package/src/comments/reducers.test.ts +277 -0
- package/src/comments/reducers.ts +316 -0
- package/src/comments/types.ts +249 -0
- package/src/comments/weakenReferences.test.ts +47 -0
- package/src/comments/weakenReferences.ts +29 -0
- package/src/config/__tests__/handles.test.ts +18 -12
- package/src/config/handles.ts +25 -7
- package/src/config/sanityConfig.ts +40 -82
- package/src/datasets/datasets.test.ts +2 -2
- package/src/datasets/datasets.ts +10 -4
- package/src/document/actions.test.ts +115 -33
- package/src/document/actions.ts +212 -15
- package/src/document/applyDocumentActions.test.ts +35 -13
- package/src/document/applyDocumentActions.ts +30 -9
- package/src/document/documentConstants.ts +15 -0
- package/src/document/documentStore.concurrency.test.ts +1306 -0
- package/src/document/documentStore.test.ts +753 -273
- package/src/document/documentStore.ts +197 -75
- package/src/document/events.test.ts +57 -2
- package/src/document/events.ts +82 -26
- package/src/document/listen.test.ts +56 -0
- package/src/document/listen.ts +74 -21
- package/src/document/listenerEventOperators.test.ts +311 -0
- package/src/document/listenerEventOperators.ts +217 -0
- package/src/document/patchOperations.test.ts +76 -2
- package/src/document/patchOperations.ts +60 -1
- package/src/document/permissions.test.ts +107 -60
- package/src/document/permissions.ts +44 -19
- package/src/document/processActions/create.ts +138 -0
- package/src/document/processActions/delete.ts +100 -0
- package/src/document/processActions/discard.ts +63 -0
- package/src/document/processActions/edit.ts +154 -0
- package/src/document/processActions/processActions.ts +218 -0
- package/src/document/processActions/publish.ts +120 -0
- package/src/document/processActions/releaseArchive.ts +77 -0
- package/src/document/processActions/releaseCreate.ts +59 -0
- package/src/document/processActions/releaseDelete.ts +65 -0
- package/src/document/processActions/releaseEdit.ts +37 -0
- package/src/document/processActions/releasePublish.ts +45 -0
- package/src/document/processActions/releaseSchedule.ts +87 -0
- package/src/document/processActions/releaseUtil.ts +31 -0
- package/src/document/processActions/shared.ts +308 -0
- package/src/document/processActions/unpublish.ts +85 -0
- package/src/document/processActions.test.ts +1129 -121
- package/src/document/reducers.test.ts +772 -64
- package/src/document/reducers.ts +205 -51
- package/src/document/resourceRules.test.ts +178 -0
- package/src/document/resourceRules.ts +117 -0
- package/src/document/sharedListener.test.ts +16 -14
- package/src/document/sharedListener.ts +24 -8
- package/src/document/util.test.ts +46 -0
- package/src/document/util.ts +50 -0
- package/src/favorites/favorites.test.ts +5 -6
- package/src/installations/installations.test-d.ts +73 -0
- package/src/installations/installations.test.ts +62 -0
- package/src/installations/installations.ts +206 -0
- package/src/organization/organization.test-d.ts +36 -0
- package/src/organization/organization.test.ts +138 -0
- package/src/organization/organization.ts +138 -0
- package/src/organizations/organizations.test-d.ts +56 -0
- package/src/organizations/organizations.test.ts +150 -0
- package/src/organizations/organizations.ts +107 -0
- package/src/presence/bifurTransport.test.ts +201 -9
- package/src/presence/bifurTransport.ts +98 -14
- package/src/presence/paths.test.ts +70 -0
- package/src/presence/paths.ts +41 -0
- package/src/presence/presenceStore.test.ts +915 -24
- package/src/presence/presenceStore.ts +576 -104
- package/src/presence/types.ts +175 -3
- package/src/preview/previewProjectionUtils.test.ts +9 -22
- package/src/preview/previewProjectionUtils.ts +7 -3
- package/src/preview/types.ts +0 -15
- package/src/project/project.test-d.ts +37 -0
- package/src/project/project.test.ts +157 -12
- package/src/project/project.ts +138 -25
- package/src/projection/getProjectionState.test.ts +18 -20
- package/src/projection/getProjectionState.ts +23 -3
- package/src/projection/projectionQuery.ts +5 -5
- package/src/projection/projectionStore.test.ts +1 -9
- package/src/projection/resolveProjection.test.ts +1 -2
- package/src/projection/resolveProjection.ts +16 -0
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +1 -1
- package/src/projection/subscribeToStateAndFetchBatches.ts +32 -23
- package/src/projects/projects.test-d.ts +32 -0
- package/src/projects/projects.test.ts +108 -42
- package/src/projects/projects.ts +63 -27
- package/src/query/queryStore.test.ts +259 -123
- package/src/query/queryStore.ts +85 -69
- package/src/query/reducers.test.ts +0 -42
- package/src/query/reducers.ts +2 -18
- package/src/releases/getPerspectiveState.test.ts +17 -23
- package/src/releases/getPerspectiveState.ts +8 -20
- package/src/releases/observeReleases.test.ts +127 -0
- package/src/releases/observeReleases.ts +102 -0
- package/src/releases/releasesStore.test.ts +100 -53
- package/src/releases/releasesStore.ts +69 -44
- package/src/releases/utils/sortReleases.test.ts +38 -2
- package/src/releases/utils/sortReleases.ts +15 -10
- package/src/store/createActionBinder.test.ts +109 -90
- package/src/store/createActionBinder.ts +36 -28
- package/src/store/createSanityInstance.test.ts +15 -13
- package/src/store/createSanityInstance.ts +14 -2
- package/src/store/createStateSourceAction.test.ts +64 -2
- package/src/store/createStateSourceAction.ts +38 -43
- package/src/store/createStoreInstance.test.ts +4 -2
- package/src/store/fetcherStore.test-d.ts +121 -0
- package/src/store/fetcherStore.test.ts +299 -0
- package/src/store/fetcherStore.ts +801 -0
- package/src/telemetry/environment.test.ts +119 -0
- package/src/telemetry/environment.ts +92 -0
- package/src/telemetry/events.ts +42 -0
- package/src/telemetry/initTelemetry.test.ts +432 -0
- package/src/telemetry/initTelemetry.ts +218 -0
- package/src/telemetry/telemetryManager.test.ts +327 -0
- package/src/telemetry/telemetryManager.ts +199 -0
- package/src/users/reducers.test.ts +3 -1
- package/src/users/reducers.ts +5 -6
- package/src/users/types.ts +4 -4
- package/src/users/usersStore.test.ts +16 -12
- package/src/users/usersStore.ts +5 -1
- package/src/utils/buildQuery.test.ts +14 -0
- package/src/utils/buildQuery.ts +17 -0
- package/src/utils/createFetcherStore.test.ts +7 -5
- package/src/utils/createFetcherStore.ts +8 -5
- package/src/utils/getStagingApiHost.test.ts +21 -0
- package/src/utils/getStagingApiHost.ts +14 -0
- package/src/utils/ids.test.ts +1 -29
- package/src/utils/ids.ts +0 -10
- package/src/utils/includeShape.ts +36 -0
- package/src/utils/isImportError.test.ts +72 -0
- package/src/utils/isImportError.ts +34 -0
- package/src/utils/logger.test.ts +12 -0
- package/src/utils/logger.ts +8 -3
- package/src/utils/object.test.ts +95 -0
- package/src/utils/object.ts +142 -0
- package/src/utils/setCleanupTimeout.ts +37 -0
- package/src/document/processActions.ts +0 -707
- package/src/utils/defineIntent.test.ts +0 -477
- 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
|
-
|
|
260
|
-
|
|
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
|
-
|
|
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
|
|
package/src/auth/authStore.ts
CHANGED
|
@@ -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.
|
|
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
|
|
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(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
+
)
|