@sanity/sdk 0.0.0-chore-react-18-compat.1 → 0.0.0-chore-react-18-compat.3
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/dist/index.d.ts +441 -322
- package/dist/index.js +1685 -1481
- package/dist/index.js.map +1 -1
- package/package.json +13 -15
- package/src/_exports/index.ts +32 -30
- package/src/auth/authStore.test.ts +149 -104
- package/src/auth/authStore.ts +51 -100
- package/src/auth/handleAuthCallback.test.ts +67 -34
- package/src/auth/handleAuthCallback.ts +8 -7
- package/src/auth/logout.test.ts +61 -29
- package/src/auth/logout.ts +26 -28
- package/src/auth/refreshStampedToken.test.ts +197 -91
- package/src/auth/refreshStampedToken.ts +170 -59
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +5 -5
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +45 -47
- package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +4 -5
- package/src/auth/subscribeToStorageEventsAndSetToken.ts +22 -24
- package/src/client/clientStore.test.ts +131 -67
- package/src/client/clientStore.ts +117 -116
- package/src/comlink/controller/actions/destroyController.test.ts +38 -13
- package/src/comlink/controller/actions/destroyController.ts +11 -15
- package/src/comlink/controller/actions/getOrCreateChannel.test.ts +56 -27
- package/src/comlink/controller/actions/getOrCreateChannel.ts +37 -35
- package/src/comlink/controller/actions/getOrCreateController.test.ts +27 -16
- package/src/comlink/controller/actions/getOrCreateController.ts +23 -22
- package/src/comlink/controller/actions/releaseChannel.test.ts +37 -13
- package/src/comlink/controller/actions/releaseChannel.ts +22 -21
- package/src/comlink/controller/comlinkControllerStore.test.ts +65 -36
- package/src/comlink/controller/comlinkControllerStore.ts +44 -5
- package/src/comlink/node/actions/getOrCreateNode.test.ts +31 -15
- package/src/comlink/node/actions/getOrCreateNode.ts +30 -29
- package/src/comlink/node/actions/releaseNode.test.ts +75 -55
- package/src/comlink/node/actions/releaseNode.ts +19 -21
- package/src/comlink/node/comlinkNodeStore.test.ts +6 -11
- package/src/comlink/node/comlinkNodeStore.ts +22 -5
- package/src/config/authConfig.ts +79 -0
- package/src/config/sanityConfig.ts +48 -0
- package/src/datasets/datasets.test.ts +2 -2
- package/src/datasets/datasets.ts +18 -5
- package/src/document/actions.test.ts +22 -10
- package/src/document/actions.ts +44 -56
- package/src/document/applyDocumentActions.test.ts +96 -36
- package/src/document/applyDocumentActions.ts +140 -99
- package/src/document/documentStore.test.ts +103 -155
- package/src/document/documentStore.ts +247 -238
- package/src/document/listen.ts +56 -55
- package/src/document/patchOperations.ts +0 -43
- package/src/document/permissions.test.ts +25 -12
- package/src/document/permissions.ts +11 -4
- package/src/document/processActions.test.ts +41 -8
- package/src/document/reducers.test.ts +87 -16
- package/src/document/reducers.ts +2 -2
- package/src/document/sharedListener.test.ts +34 -16
- package/src/document/sharedListener.ts +33 -11
- package/src/preview/getPreviewState.test.ts +40 -39
- package/src/preview/getPreviewState.ts +68 -56
- package/src/preview/previewConstants.ts +43 -0
- package/src/preview/previewQuery.test.ts +1 -1
- package/src/preview/previewQuery.ts +4 -5
- package/src/preview/previewStore.test.ts +13 -58
- package/src/preview/previewStore.ts +7 -21
- package/src/preview/resolvePreview.test.ts +33 -104
- package/src/preview/resolvePreview.ts +11 -21
- package/src/preview/subscribeToStateAndFetchBatches.test.ts +96 -97
- package/src/preview/subscribeToStateAndFetchBatches.ts +85 -81
- package/src/preview/util.ts +1 -0
- package/src/project/project.test.ts +3 -3
- package/src/project/project.ts +28 -5
- package/src/projection/getProjectionState.test.ts +188 -72
- package/src/projection/getProjectionState.ts +92 -62
- package/src/projection/projectionQuery.test.ts +114 -12
- package/src/projection/projectionQuery.ts +75 -32
- package/src/projection/projectionStore.test.ts +13 -51
- package/src/projection/projectionStore.ts +6 -43
- package/src/projection/resolveProjection.test.ts +32 -127
- package/src/projection/resolveProjection.ts +16 -28
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +203 -116
- package/src/projection/subscribeToStateAndFetchBatches.ts +140 -85
- package/src/projection/types.ts +50 -0
- package/src/projection/util.ts +3 -1
- package/src/projects/projects.test.ts +13 -4
- package/src/projects/projects.ts +6 -1
- package/src/query/queryStore.test.ts +10 -47
- package/src/query/queryStore.ts +151 -133
- package/src/query/queryStoreConstants.ts +2 -0
- package/src/store/createActionBinder.test.ts +153 -0
- package/src/store/createActionBinder.ts +176 -0
- package/src/store/createSanityInstance.test.ts +84 -0
- package/src/store/createSanityInstance.ts +124 -0
- package/src/store/createStateSourceAction.test.ts +196 -0
- package/src/store/createStateSourceAction.ts +260 -0
- package/src/store/createStoreInstance.test.ts +81 -0
- package/src/store/createStoreInstance.ts +80 -0
- package/src/store/createStoreState.test.ts +85 -0
- package/src/store/createStoreState.ts +92 -0
- package/src/store/defineStore.test.ts +18 -0
- package/src/store/defineStore.ts +81 -0
- package/src/users/reducers.test.ts +318 -0
- package/src/users/reducers.ts +88 -0
- package/src/users/types.ts +46 -4
- package/src/users/usersConstants.ts +4 -0
- package/src/users/usersStore.test.ts +350 -223
- package/src/users/usersStore.ts +285 -149
- package/src/utils/createFetcherStore.test.ts +6 -7
- package/src/utils/createFetcherStore.ts +150 -153
- package/src/utils/createGroqSearchFilter.test.ts +75 -0
- package/src/utils/createGroqSearchFilter.ts +85 -0
- package/src/{common/util.test.ts → utils/hashString.test.ts} +1 -1
- package/dist/index.cjs +0 -4888
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -2121
- package/src/auth/fetchLoginUrls.test.ts +0 -163
- package/src/auth/fetchLoginUrls.ts +0 -74
- package/src/common/createLiveEventSubscriber.test.ts +0 -121
- package/src/common/createLiveEventSubscriber.ts +0 -55
- package/src/common/types.ts +0 -4
- package/src/instance/identity.test.ts +0 -46
- package/src/instance/identity.ts +0 -29
- package/src/instance/sanityInstance.test.ts +0 -77
- package/src/instance/sanityInstance.ts +0 -57
- package/src/instance/types.ts +0 -37
- package/src/preview/getPreviewProjection.ts +0 -45
- package/src/resources/README.md +0 -370
- package/src/resources/createAction.test.ts +0 -101
- package/src/resources/createAction.ts +0 -44
- package/src/resources/createResource.test.ts +0 -112
- package/src/resources/createResource.ts +0 -102
- package/src/resources/createStateSourceAction.test.ts +0 -114
- package/src/resources/createStateSourceAction.ts +0 -83
- package/src/resources/createStore.test.ts +0 -67
- package/src/resources/createStore.ts +0 -46
- package/src/store/createStore.test.ts +0 -108
- package/src/store/createStore.ts +0 -106
- /package/src/{common/util.ts → utils/hashString.ts} +0 -0
|
@@ -1,68 +1,179 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
distinctUntilChanged,
|
|
3
|
+
filter,
|
|
4
|
+
firstValueFrom,
|
|
5
|
+
from,
|
|
6
|
+
map,
|
|
7
|
+
Observable,
|
|
8
|
+
type Subscription,
|
|
9
|
+
switchMap,
|
|
10
|
+
takeWhile,
|
|
11
|
+
timer,
|
|
12
|
+
} from 'rxjs'
|
|
2
13
|
|
|
3
|
-
import {type
|
|
14
|
+
import {type StoreContext} from '../store/defineStore'
|
|
4
15
|
import {DEFAULT_API_VERSION} from './authConstants'
|
|
5
16
|
import {AuthStateType} from './authStateType'
|
|
6
17
|
import {type AuthState, type AuthStoreState} from './authStore'
|
|
7
18
|
|
|
19
|
+
const REFRESH_INTERVAL = 12 * 60 * 60 * 1000 // 12 hours in milliseconds
|
|
20
|
+
const LOCK_NAME = 'sanity-token-refresh-lock'
|
|
21
|
+
|
|
22
|
+
function getLastRefreshTime(storageArea: Storage | undefined, storageKey: string): number {
|
|
23
|
+
try {
|
|
24
|
+
const data = storageArea?.getItem(`${storageKey}_last_refresh`)
|
|
25
|
+
return data ? parseInt(data, 10) : 0
|
|
26
|
+
} catch {
|
|
27
|
+
return 0
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function setLastRefreshTime(storageArea: Storage | undefined, storageKey: string): void {
|
|
32
|
+
try {
|
|
33
|
+
storageArea?.setItem(`${storageKey}_last_refresh`, Date.now().toString())
|
|
34
|
+
} catch {
|
|
35
|
+
// Ignore storage errors
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getNextRefreshDelay(storageArea: Storage | undefined, storageKey: string): number {
|
|
40
|
+
const lastRefresh = getLastRefreshTime(storageArea, storageKey)
|
|
41
|
+
if (!lastRefresh) return 0
|
|
42
|
+
|
|
43
|
+
const now = Date.now()
|
|
44
|
+
const nextRefreshTime = lastRefresh + REFRESH_INTERVAL
|
|
45
|
+
return Math.max(0, nextRefreshTime - now)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function createTokenRefreshStream(
|
|
49
|
+
token: string,
|
|
50
|
+
clientFactory: AuthStoreState['options']['clientFactory'],
|
|
51
|
+
apiHost: string | undefined,
|
|
52
|
+
): Observable<{token: string}> {
|
|
53
|
+
return new Observable((subscriber) => {
|
|
54
|
+
const client = clientFactory({
|
|
55
|
+
apiVersion: DEFAULT_API_VERSION,
|
|
56
|
+
requestTagPrefix: 'sdk.token-refresh',
|
|
57
|
+
useProjectHostname: false,
|
|
58
|
+
token,
|
|
59
|
+
ignoreBrowserTokenWarning: true,
|
|
60
|
+
...(apiHost && {apiHost}),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const subscription = client.observable
|
|
64
|
+
.request<{token: string}>({
|
|
65
|
+
uri: 'auth/refresh-token',
|
|
66
|
+
method: 'POST',
|
|
67
|
+
body: {
|
|
68
|
+
token,
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
.subscribe(subscriber)
|
|
72
|
+
|
|
73
|
+
return () => subscription.unsubscribe()
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function acquireTokenRefreshLock(
|
|
78
|
+
refreshFn: () => Promise<void>,
|
|
79
|
+
storageArea: Storage | undefined,
|
|
80
|
+
storageKey: string,
|
|
81
|
+
): Promise<boolean> {
|
|
82
|
+
if (!navigator.locks) {
|
|
83
|
+
return true // If Web Locks API is not supported, proceed with refresh
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
// Hold the lock for the entire session
|
|
88
|
+
const result = await navigator.locks.request(LOCK_NAME, {mode: 'exclusive'}, async (lock) => {
|
|
89
|
+
if (!lock) return false
|
|
90
|
+
|
|
91
|
+
// Start a continuous refresh cycle while we hold the lock
|
|
92
|
+
while (true) {
|
|
93
|
+
const delay = getNextRefreshDelay(storageArea, storageKey)
|
|
94
|
+
if (delay > 0) {
|
|
95
|
+
await new Promise((resolve) => setTimeout(resolve, delay))
|
|
96
|
+
}
|
|
97
|
+
await refreshFn()
|
|
98
|
+
setLastRefreshTime(storageArea, storageKey)
|
|
99
|
+
await new Promise((resolve) => setTimeout(resolve, REFRESH_INTERVAL))
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
return result === true
|
|
103
|
+
} catch {
|
|
104
|
+
return false // If lock acquisition fails, return false
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
8
108
|
/**
|
|
9
109
|
* @internal
|
|
10
110
|
*/
|
|
11
|
-
export const refreshStampedToken =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
111
|
+
export const refreshStampedToken = ({state}: StoreContext<AuthStoreState>): Subscription => {
|
|
112
|
+
const {clientFactory, apiHost, storageArea, storageKey} = state.get().options
|
|
113
|
+
|
|
114
|
+
const refreshToken$ = state.observable.pipe(
|
|
115
|
+
map((storeState) => ({
|
|
116
|
+
authState: storeState.authState,
|
|
117
|
+
dashboardContext: storeState.dashboardContext,
|
|
118
|
+
})),
|
|
119
|
+
filter(
|
|
120
|
+
(
|
|
121
|
+
storeState,
|
|
122
|
+
): storeState is {
|
|
123
|
+
authState: Extract<AuthState, {type: AuthStateType.LOGGED_IN}>
|
|
124
|
+
dashboardContext: AuthStoreState['dashboardContext']
|
|
125
|
+
} => storeState.authState.type === AuthStateType.LOGGED_IN,
|
|
126
|
+
),
|
|
127
|
+
distinctUntilChanged(),
|
|
128
|
+
filter((storeState) => storeState.authState.token.includes('-st')), // Ensure we only try to refresh stamped tokens
|
|
129
|
+
switchMap((storeState) => {
|
|
130
|
+
// Create a function that performs a single refresh
|
|
131
|
+
const performRefresh = async () => {
|
|
132
|
+
const response = await firstValueFrom(
|
|
133
|
+
createTokenRefreshStream(storeState.authState.token, clientFactory, apiHost),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
state.set('setRefreshStampedToken', (prev) => ({
|
|
137
|
+
authState:
|
|
138
|
+
prev.authState.type === AuthStateType.LOGGED_IN
|
|
139
|
+
? {...prev.authState, token: response.token}
|
|
140
|
+
: prev.authState,
|
|
141
|
+
}))
|
|
142
|
+
storageArea?.setItem(storageKey, JSON.stringify({token: response.token}))
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// If in dashboard context, use simple timer-based refresh
|
|
146
|
+
if (storeState.dashboardContext) {
|
|
147
|
+
return timer(0, REFRESH_INTERVAL).pipe(
|
|
148
|
+
takeWhile(() => storeState.authState.type === AuthStateType.LOGGED_IN),
|
|
149
|
+
switchMap(() =>
|
|
150
|
+
createTokenRefreshStream(storeState.authState.token, clientFactory, apiHost),
|
|
46
151
|
),
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// If not in dashboard context, use lock-based refresh with timing coordination
|
|
156
|
+
return from(acquireTokenRefreshLock(performRefresh, storageArea, storageKey)).pipe(
|
|
157
|
+
filter((hasLock) => hasLock),
|
|
158
|
+
// This observable will never emit after the first value
|
|
159
|
+
// because acquireTokenRefreshLock handles the refresh loop internally
|
|
160
|
+
map(() => ({token: storeState.authState.token})),
|
|
161
|
+
)
|
|
162
|
+
}),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return refreshToken$.subscribe({
|
|
166
|
+
next: (response) => {
|
|
167
|
+
state.set('setRefreshStampedToken', (prev) => ({
|
|
168
|
+
authState:
|
|
169
|
+
prev.authState.type === AuthStateType.LOGGED_IN
|
|
170
|
+
? {...prev.authState, token: response.token}
|
|
171
|
+
: prev.authState,
|
|
172
|
+
}))
|
|
173
|
+
storageArea?.setItem(storageKey, JSON.stringify({token: response.token}))
|
|
174
|
+
},
|
|
175
|
+
error: (error) => {
|
|
176
|
+
state.set('setRefreshStampedTokenError', {authState: {type: AuthStateType.ERROR, error}})
|
|
177
|
+
},
|
|
178
|
+
})
|
|
179
|
+
}
|
|
@@ -2,8 +2,8 @@ import {type CurrentUser} from '@sanity/types'
|
|
|
2
2
|
import {delay, of, throwError} from 'rxjs'
|
|
3
3
|
import {beforeEach, describe, it} from 'vitest'
|
|
4
4
|
|
|
5
|
-
import {createSanityInstance} from '../
|
|
6
|
-
import {
|
|
5
|
+
import {createSanityInstance} from '../store/createSanityInstance'
|
|
6
|
+
import {createStoreState} from '../store/createStoreState'
|
|
7
7
|
import {AuthStateType} from './authStateType'
|
|
8
8
|
import {authStore} from './authStore'
|
|
9
9
|
import {subscribeToStateAndFetchCurrentUser} from './subscribeToStateAndFetchCurrentUser'
|
|
@@ -20,7 +20,7 @@ describe('subscribeToStateAndFetchCurrentUser', () => {
|
|
|
20
20
|
const clientFactory = vi.fn().mockReturnValue(mockClient)
|
|
21
21
|
const instance = createSanityInstance({projectId: 'p', dataset: 'd', auth: {clientFactory}})
|
|
22
22
|
|
|
23
|
-
const state =
|
|
23
|
+
const state = createStoreState(authStore.getInitialState(instance))
|
|
24
24
|
const subscription = subscribeToStateAndFetchCurrentUser({state, instance})
|
|
25
25
|
|
|
26
26
|
expect(state.get()).toMatchObject({authState: {type: AuthStateType.LOGGED_OUT}})
|
|
@@ -51,7 +51,7 @@ describe('subscribeToStateAndFetchCurrentUser', () => {
|
|
|
51
51
|
const clientFactory = vi.fn().mockReturnValue(mockClient)
|
|
52
52
|
const instance = createSanityInstance({projectId: 'p', dataset: 'd', auth: {clientFactory}})
|
|
53
53
|
|
|
54
|
-
const state =
|
|
54
|
+
const state = createStoreState(authStore.getInitialState(instance))
|
|
55
55
|
const subscription = subscribeToStateAndFetchCurrentUser({state, instance})
|
|
56
56
|
|
|
57
57
|
expect(state.get()).toMatchObject({authState: {type: AuthStateType.LOGGED_OUT}})
|
|
@@ -86,7 +86,7 @@ describe('subscribeToStateAndFetchCurrentUser', () => {
|
|
|
86
86
|
const clientFactory = vi.fn().mockReturnValue(mockClient)
|
|
87
87
|
const instance = createSanityInstance({projectId: 'p', dataset: 'd', auth: {clientFactory}})
|
|
88
88
|
|
|
89
|
-
const state =
|
|
89
|
+
const state = createStoreState(authStore.getInitialState(instance))
|
|
90
90
|
const subscription = subscribeToStateAndFetchCurrentUser({state, instance})
|
|
91
91
|
|
|
92
92
|
expect(state.get()).toMatchObject({authState: {type: AuthStateType.LOGGED_OUT}})
|
|
@@ -1,55 +1,53 @@
|
|
|
1
1
|
import {type CurrentUser} from '@sanity/types'
|
|
2
|
-
import {distinctUntilChanged, filter, map, switchMap} from 'rxjs'
|
|
2
|
+
import {distinctUntilChanged, filter, map, type Subscription, switchMap} from 'rxjs'
|
|
3
3
|
|
|
4
|
-
import {type
|
|
4
|
+
import {type StoreContext} from '../store/defineStore'
|
|
5
5
|
import {DEFAULT_API_VERSION, REQUEST_TAG_PREFIX} from './authConstants'
|
|
6
6
|
import {AuthStateType} from './authStateType'
|
|
7
7
|
import {type AuthState, type AuthStoreState} from './authStore'
|
|
8
8
|
|
|
9
|
-
export const subscribeToStateAndFetchCurrentUser =
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const subscribeToStateAndFetchCurrentUser = ({
|
|
10
|
+
state,
|
|
11
|
+
}: StoreContext<AuthStoreState>): Subscription => {
|
|
12
|
+
const {clientFactory, apiHost} = state.get().options
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
14
|
+
const currentUser$ = state.observable
|
|
15
|
+
.pipe(
|
|
16
|
+
map(({authState}) => authState),
|
|
17
|
+
filter(
|
|
18
|
+
(authState): authState is Extract<AuthState, {type: AuthStateType.LOGGED_IN}> =>
|
|
19
|
+
authState.type === AuthStateType.LOGGED_IN && !authState.currentUser,
|
|
20
|
+
),
|
|
21
|
+
map((authState) => authState.token),
|
|
22
|
+
distinctUntilChanged(),
|
|
23
|
+
)
|
|
24
|
+
.pipe(
|
|
25
|
+
map((token) =>
|
|
26
|
+
clientFactory({
|
|
27
|
+
apiVersion: DEFAULT_API_VERSION,
|
|
28
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
29
|
+
token,
|
|
30
|
+
ignoreBrowserTokenWarning: true,
|
|
31
|
+
useProjectHostname: false,
|
|
32
|
+
...(apiHost && {apiHost}),
|
|
33
|
+
}),
|
|
34
|
+
),
|
|
35
|
+
switchMap((client) =>
|
|
36
|
+
client.observable.request<CurrentUser>({uri: '/users/me', method: 'GET'}),
|
|
37
|
+
),
|
|
38
|
+
)
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
)
|
|
40
|
+
return currentUser$.subscribe({
|
|
41
|
+
next: (currentUser) => {
|
|
42
|
+
state.set('setCurrentUser', (prev) => ({
|
|
43
|
+
authState:
|
|
44
|
+
prev.authState.type === AuthStateType.LOGGED_IN
|
|
45
|
+
? {...prev.authState, currentUser}
|
|
46
|
+
: prev.authState,
|
|
47
|
+
}))
|
|
48
|
+
},
|
|
49
|
+
error: (error) => {
|
|
50
|
+
state.set('setError', {authState: {type: AuthStateType.ERROR, error}})
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {Observable, Subject} from 'rxjs'
|
|
2
2
|
import {beforeEach, describe, it} from 'vitest'
|
|
3
3
|
|
|
4
|
-
import {createSanityInstance} from '../
|
|
5
|
-
import {
|
|
6
|
-
import {createResourceState} from '../resources/createResource'
|
|
4
|
+
import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
|
|
5
|
+
import {createStoreState} from '../store/createStoreState'
|
|
7
6
|
import {AuthStateType} from './authStateType'
|
|
8
7
|
import {authStore} from './authStore'
|
|
9
8
|
import {subscribeToStorageEventsAndSetToken} from './subscribeToStorageEventsAndSetToken'
|
|
@@ -35,7 +34,7 @@ describe('subscribeToStorageEventsAndSetToken', () => {
|
|
|
35
34
|
})
|
|
36
35
|
|
|
37
36
|
it('sets the state to logged in when a matching storage event returns a token', () => {
|
|
38
|
-
const state =
|
|
37
|
+
const state = createStoreState(authStore.getInitialState(instance))
|
|
39
38
|
const {storageKey} = state.get().options
|
|
40
39
|
const subscription = subscribeToStorageEventsAndSetToken({state, instance})
|
|
41
40
|
|
|
@@ -55,7 +54,7 @@ describe('subscribeToStorageEventsAndSetToken', () => {
|
|
|
55
54
|
|
|
56
55
|
it('sets the state to logged in when a matching storage event returns null', () => {
|
|
57
56
|
vi.mocked(getTokenFromStorage).mockReturnValue('existing-token')
|
|
58
|
-
const state =
|
|
57
|
+
const state = createStoreState(authStore.getInitialState(instance))
|
|
59
58
|
const {storageKey} = state.get().options
|
|
60
59
|
|
|
61
60
|
const subscription = subscribeToStorageEventsAndSetToken({state, instance})
|
|
@@ -1,31 +1,29 @@
|
|
|
1
|
-
import {defer, distinctUntilChanged, filter, map} from 'rxjs'
|
|
1
|
+
import {defer, distinctUntilChanged, filter, map, type Subscription} from 'rxjs'
|
|
2
2
|
|
|
3
|
-
import {type
|
|
3
|
+
import {type StoreContext} from '../store/defineStore'
|
|
4
4
|
import {AuthStateType} from './authStateType'
|
|
5
5
|
import {type AuthStoreState} from './authStore'
|
|
6
6
|
import {getStorageEvents, getTokenFromStorage} from './utils'
|
|
7
7
|
|
|
8
|
-
export const subscribeToStorageEventsAndSetToken =
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export const subscribeToStorageEventsAndSetToken = ({
|
|
9
|
+
state,
|
|
10
|
+
}: StoreContext<AuthStoreState>): Subscription => {
|
|
11
|
+
const {storageArea, storageKey} = state.get().options
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
const tokenFromStorage$ = defer(getStorageEvents).pipe(
|
|
14
|
+
filter(
|
|
15
|
+
(e): e is StorageEvent & {newValue: string} =>
|
|
16
|
+
e.storageArea === storageArea && e.key === storageKey,
|
|
17
|
+
),
|
|
18
|
+
map(() => getTokenFromStorage(storageArea, storageKey)),
|
|
19
|
+
distinctUntilChanged(),
|
|
20
|
+
)
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
)
|
|
22
|
+
return tokenFromStorage$.subscribe((token) => {
|
|
23
|
+
state.set('updateTokenFromStorageEvent', {
|
|
24
|
+
authState: token
|
|
25
|
+
? {type: AuthStateType.LOGGED_IN, token, currentUser: null}
|
|
26
|
+
: {type: AuthStateType.LOGGED_OUT, isDestroyingSession: false},
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
}
|