@sanity/sdk-react 0.0.0-alpha.1 → 0.0.0-alpha.10
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 +163 -0
- package/dist/_chunks-es/context.js +8 -0
- package/dist/_chunks-es/context.js.map +1 -0
- package/dist/_chunks-es/useLogOut.js +29 -20
- package/dist/_chunks-es/useLogOut.js.map +1 -1
- package/dist/components.d.ts +25 -149
- package/dist/components.js +54 -151
- package/dist/components.js.map +1 -1
- package/dist/context.d.ts +45 -0
- package/dist/context.js +5 -0
- package/dist/context.js.map +1 -0
- package/dist/hooks.d.ts +3401 -12
- package/dist/hooks.js +210 -15
- package/dist/hooks.js.map +1 -1
- package/package.json +43 -32
- package/src/_exports/components.ts +2 -12
- package/src/_exports/context.ts +2 -0
- package/src/_exports/hooks.ts +25 -0
- package/src/components/SanityApp.test.tsx +54 -0
- package/src/components/SanityApp.tsx +53 -0
- package/src/components/auth/AuthBoundary.test.tsx +18 -22
- package/src/components/auth/AuthBoundary.tsx +14 -7
- package/src/components/auth/Login.test.tsx +3 -17
- package/src/components/auth/Login.tsx +27 -31
- package/src/components/auth/LoginCallback.test.tsx +2 -17
- package/src/components/auth/LoginCallback.tsx +8 -10
- package/src/components/auth/LoginError.test.tsx +2 -17
- package/src/components/auth/LoginError.tsx +8 -17
- package/src/components/auth/LoginFooter.test.tsx +2 -16
- package/src/components/auth/LoginFooter.tsx +18 -27
- package/src/components/auth/LoginLayout.test.tsx +2 -16
- package/src/components/auth/LoginLayout.tsx +8 -37
- package/src/components/auth/authTestHelpers.tsx +18 -0
- package/src/{components/context → context}/SanityProvider.test.tsx +1 -1
- package/src/{components/context → context}/SanityProvider.tsx +12 -6
- package/src/hooks/auth/useAuthState.test.tsx +10 -100
- package/src/hooks/auth/useAuthState.tsx +5 -10
- package/src/hooks/auth/useAuthToken.test.tsx +10 -88
- package/src/hooks/auth/useAuthToken.tsx +4 -10
- package/src/hooks/auth/useCurrentUser.test.tsx +10 -44
- package/src/hooks/auth/useCurrentUser.tsx +22 -22
- package/src/hooks/auth/useHandleCallback.test.tsx +10 -19
- package/src/hooks/auth/useHandleCallback.tsx +4 -9
- package/src/hooks/auth/useLogOut.test.tsx +11 -62
- package/src/hooks/auth/useLogOut.tsx +4 -9
- package/src/hooks/auth/useLoginUrls.test.tsx +47 -40
- package/src/hooks/auth/useLoginUrls.tsx +7 -6
- package/src/hooks/client/useClient.test.tsx +1 -1
- package/src/hooks/client/useClient.ts +3 -3
- package/src/hooks/comlink/useFrameConnection.test.tsx +122 -0
- package/src/hooks/comlink/useFrameConnection.ts +111 -0
- package/src/hooks/comlink/useWindowConnection.test.ts +94 -0
- package/src/hooks/comlink/useWindowConnection.ts +82 -0
- package/src/hooks/context/useSanityInstance.test.tsx +1 -1
- package/src/hooks/context/useSanityInstance.ts +4 -4
- package/src/hooks/document/useApplyActions.test.ts +24 -0
- package/src/hooks/document/useApplyActions.ts +24 -0
- package/src/hooks/document/useDocument.test.ts +81 -0
- package/src/hooks/document/useDocument.ts +38 -0
- package/src/hooks/document/useDocumentEvent.test.ts +53 -0
- package/src/hooks/document/useDocumentEvent.ts +22 -0
- package/src/hooks/document/useDocumentSyncStatus.test.ts +16 -0
- package/src/hooks/document/useDocumentSyncStatus.ts +6 -0
- package/src/hooks/document/useEditDocument.test.ts +172 -0
- package/src/hooks/document/useEditDocument.ts +80 -0
- package/src/hooks/documentCollection/useDocuments.test.ts +130 -0
- package/src/hooks/documentCollection/useDocuments.ts +135 -0
- package/src/hooks/helpers/createCallbackHook.test.tsx +106 -0
- package/src/hooks/helpers/createCallbackHook.tsx +15 -0
- package/src/hooks/helpers/createStateSourceHook.test.tsx +130 -0
- package/src/hooks/helpers/createStateSourceHook.tsx +21 -0
- package/src/hooks/preview/usePreview.test.tsx +175 -0
- package/src/hooks/preview/usePreview.tsx +120 -0
- package/src/vite-env.d.ts +10 -0
- package/src/components/DocumentGridLayout/DocumentGridLayout.stories.tsx +0 -95
- package/src/components/DocumentGridLayout/DocumentGridLayout.test.tsx +0 -42
- package/src/components/DocumentGridLayout/DocumentGridLayout.tsx +0 -23
- package/src/components/DocumentListLayout/DocumentListLayout.stories.tsx +0 -95
- package/src/components/DocumentListLayout/DocumentListLayout.test.tsx +0 -42
- package/src/components/DocumentListLayout/DocumentListLayout.tsx +0 -15
- package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.md +0 -49
- package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.stories.tsx +0 -34
- package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.test.tsx +0 -30
- package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.tsx +0 -115
- package/src/components/Login/LoginLinks.test.tsx +0 -100
- package/src/components/Login/LoginLinks.tsx +0 -73
- package/src/hooks/Documents/.keep +0 -0
|
@@ -1,106 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
createSanityInstance,
|
|
5
|
-
getAuthStore,
|
|
6
|
-
type SanityInstance,
|
|
7
|
-
} from '@sanity/sdk'
|
|
8
|
-
import {renderHook} from '@testing-library/react'
|
|
9
|
-
import {describe, expect, it, vi} from 'vitest'
|
|
1
|
+
import {getAuthState} from '@sanity/sdk'
|
|
2
|
+
import {identity} from 'rxjs'
|
|
3
|
+
import {describe, it} from 'vitest'
|
|
10
4
|
|
|
11
|
-
import {
|
|
12
|
-
import * as context from '../context/useSanityInstance'
|
|
13
|
-
import {useAuthState} from './useAuthState'
|
|
5
|
+
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
14
6
|
|
|
15
|
-
|
|
16
|
-
vi.mock('@sanity/sdk')
|
|
17
|
-
vi.mock('../context/useSanityInstance')
|
|
18
|
-
|
|
19
|
-
const createMockAuthStore = (authState: AuthState): AuthStore => ({
|
|
20
|
-
authState: {
|
|
21
|
-
getState: () => authState,
|
|
22
|
-
getInitialState: () => authState,
|
|
23
|
-
subscribe: vi.fn(),
|
|
24
|
-
},
|
|
25
|
-
tokenState: {
|
|
26
|
-
getState: vi.fn(),
|
|
27
|
-
getInitialState: vi.fn(),
|
|
28
|
-
subscribe: vi.fn(),
|
|
29
|
-
},
|
|
30
|
-
currentUserState: {
|
|
31
|
-
getState: vi.fn(),
|
|
32
|
-
getInitialState: vi.fn(),
|
|
33
|
-
subscribe: vi.fn(),
|
|
34
|
-
},
|
|
35
|
-
handleCallback: vi.fn(),
|
|
36
|
-
logout: vi.fn(),
|
|
37
|
-
dispose: vi.fn(),
|
|
38
|
-
getLoginUrls: vi.fn(),
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const mockUser = {
|
|
42
|
-
id: 'user-123',
|
|
43
|
-
name: 'Test User',
|
|
44
|
-
email: 'test@example.com',
|
|
45
|
-
role: 'developer',
|
|
46
|
-
roles: [{name: 'developer', title: 'Developer'}],
|
|
47
|
-
}
|
|
7
|
+
vi.mock('../helpers/createStateSourceHook', () => ({createStateSourceHook: vi.fn(identity)}))
|
|
8
|
+
vi.mock('@sanity/sdk', () => ({getAuthState: vi.fn()}))
|
|
48
9
|
|
|
49
10
|
describe('useAuthState', () => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
dataset: 'dataset-123',
|
|
55
|
-
},
|
|
56
|
-
config: {},
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Setup mock for useSanityInstance
|
|
60
|
-
beforeEach(() => {
|
|
61
|
-
vi.spyOn(context, 'useSanityInstance').mockReturnValue(mockInstance)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('should return the current auth state', () => {
|
|
65
|
-
const mockAuthStore = createMockAuthStore({
|
|
66
|
-
type: 'logged-in',
|
|
67
|
-
token: 'token-123',
|
|
68
|
-
currentUser: mockUser,
|
|
69
|
-
})
|
|
70
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore)
|
|
71
|
-
|
|
72
|
-
const sanityInstance = createSanityInstance({projectId: 'test', dataset: 'test'})
|
|
73
|
-
const {result} = renderHook(() => useAuthState(), {
|
|
74
|
-
wrapper: ({children}) => (
|
|
75
|
-
<SanityProvider sanityInstance={sanityInstance}>{children}</SanityProvider>
|
|
76
|
-
),
|
|
77
|
-
})
|
|
78
|
-
const current = result.current as Extract<AuthState, {type: 'logged-in'}>
|
|
79
|
-
expect(current.type).toBe('logged-in')
|
|
80
|
-
expect(current.token).toBe('token-123')
|
|
81
|
-
expect(current.currentUser).toBe(mockUser)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('should handle signed out state', () => {
|
|
85
|
-
const mockAuthStore = createMockAuthStore({type: 'logged-out', isDestroyingSession: false})
|
|
86
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore)
|
|
87
|
-
|
|
88
|
-
const {result} = renderHook(() => useAuthState())
|
|
89
|
-
expect(result.current.type).toBe('logged-out')
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('should subscribe to auth state changes', () => {
|
|
93
|
-
const subscribe = vi.fn()
|
|
94
|
-
const mockAuthStore = createMockAuthStore({
|
|
95
|
-
type: 'logged-in',
|
|
96
|
-
token: 'token-123',
|
|
97
|
-
currentUser: null,
|
|
98
|
-
})
|
|
99
|
-
mockAuthStore.authState.subscribe = subscribe
|
|
100
|
-
|
|
101
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore)
|
|
102
|
-
|
|
103
|
-
renderHook(() => useAuthState())
|
|
104
|
-
expect(subscribe).toHaveBeenCalled()
|
|
11
|
+
it('calls `createStateSourceHook` with `getAuthState`', async () => {
|
|
12
|
+
const {useAuthState} = await import('./useAuthState')
|
|
13
|
+
expect(createStateSourceHook).toHaveBeenCalledWith(getAuthState)
|
|
14
|
+
expect(useAuthState).toBe(getAuthState)
|
|
105
15
|
})
|
|
106
16
|
})
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {type AuthState,
|
|
2
|
-
import {useStore} from 'zustand/react'
|
|
1
|
+
import {type AuthState, getAuthState} from '@sanity/sdk'
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
5
4
|
|
|
6
5
|
/**
|
|
6
|
+
* @internal
|
|
7
7
|
* A React hook that subscribes to authentication state changes.
|
|
8
8
|
*
|
|
9
9
|
* This hook provides access to the current authentication state type from the Sanity auth store.
|
|
10
|
-
* It automatically re-renders
|
|
10
|
+
* It automatically re-renders when the authentication state changes.
|
|
11
11
|
*
|
|
12
12
|
* @remarks
|
|
13
13
|
* The hook uses `useSyncExternalStore` to safely subscribe to auth state changes
|
|
@@ -25,9 +25,4 @@ import {useSanityInstance} from '../context/useSanityInstance'
|
|
|
25
25
|
*
|
|
26
26
|
* @public
|
|
27
27
|
*/
|
|
28
|
-
export
|
|
29
|
-
const instance = useSanityInstance()
|
|
30
|
-
const {authState} = getAuthStore(instance)
|
|
31
|
-
|
|
32
|
-
return useStore(authState)
|
|
33
|
-
}
|
|
28
|
+
export const useAuthState: () => AuthState = createStateSourceHook(getAuthState)
|
|
@@ -1,94 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {describe,
|
|
1
|
+
import {getTokenState} from '@sanity/sdk'
|
|
2
|
+
import {identity} from 'rxjs'
|
|
3
|
+
import {describe, it} from 'vitest'
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {useAuthToken} from './useAuthToken'
|
|
5
|
+
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
vi.mock('@sanity/sdk', () => ({
|
|
10
|
-
getAuthStore: vi.fn(),
|
|
11
|
-
}))
|
|
12
|
-
|
|
13
|
-
vi.mock('../context/useSanityInstance', () => ({
|
|
14
|
-
useSanityInstance: vi.fn(),
|
|
15
|
-
}))
|
|
7
|
+
vi.mock('../helpers/createStateSourceHook', () => ({createStateSourceHook: vi.fn(identity)}))
|
|
8
|
+
vi.mock('@sanity/sdk', () => ({getTokenState: vi.fn()}))
|
|
16
9
|
|
|
17
10
|
describe('useAuthToken', () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
projectId: 'test-project-id',
|
|
23
|
-
dataset: 'test-dataset',
|
|
24
|
-
},
|
|
25
|
-
config: {},
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
// Helper function to create mock auth store
|
|
29
|
-
const createMockAuthStore = (token: string | null) => {
|
|
30
|
-
const authType = token ? 'logged-in' : 'logged-out'
|
|
31
|
-
return {
|
|
32
|
-
tokenState: {
|
|
33
|
-
getInitialState: () => token,
|
|
34
|
-
getState: () => token,
|
|
35
|
-
subscribe: vi.fn(),
|
|
36
|
-
},
|
|
37
|
-
authState: {
|
|
38
|
-
getInitialState: () => ({
|
|
39
|
-
type: authType,
|
|
40
|
-
isDestroyingSession: false,
|
|
41
|
-
...(token && {token, currentUser: null}),
|
|
42
|
-
}),
|
|
43
|
-
getState: () => ({
|
|
44
|
-
type: authType,
|
|
45
|
-
isDestroyingSession: false,
|
|
46
|
-
...(token && {token, currentUser: null}),
|
|
47
|
-
}),
|
|
48
|
-
subscribe: vi.fn(),
|
|
49
|
-
},
|
|
50
|
-
currentUserState: {
|
|
51
|
-
getInitialState: () => null,
|
|
52
|
-
getState: () => null,
|
|
53
|
-
subscribe: vi.fn(),
|
|
54
|
-
},
|
|
55
|
-
handleCallback: vi.fn(),
|
|
56
|
-
logout: vi.fn(),
|
|
57
|
-
dispose: vi.fn(),
|
|
58
|
-
getLoginUrls: vi.fn(),
|
|
59
|
-
} as unknown as AuthStore
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
beforeEach(() => {
|
|
63
|
-
vi.clearAllMocks()
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('should return null when no token is present', () => {
|
|
67
|
-
const mockInstance = createMockInstance()
|
|
68
|
-
const mockAuthStore = createMockAuthStore(null)
|
|
69
|
-
|
|
70
|
-
vi.mocked(useSanityInstance).mockReturnValue(mockInstance)
|
|
71
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore)
|
|
72
|
-
|
|
73
|
-
const {result} = renderHook(() => useAuthToken())
|
|
74
|
-
|
|
75
|
-
expect(result.current).toBeNull()
|
|
76
|
-
expect(useSanityInstance).toHaveBeenCalled()
|
|
77
|
-
expect(getAuthStore).toHaveBeenCalledWith(mockInstance)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('should return token when authenticated', () => {
|
|
81
|
-
const mockInstance = createMockInstance()
|
|
82
|
-
const mockToken = 'test-auth-token'
|
|
83
|
-
const mockAuthStore = createMockAuthStore(mockToken)
|
|
84
|
-
|
|
85
|
-
vi.mocked(useSanityInstance).mockReturnValue(mockInstance)
|
|
86
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore)
|
|
87
|
-
|
|
88
|
-
const {result} = renderHook(() => useAuthToken())
|
|
89
|
-
|
|
90
|
-
expect(result.current).toBe(mockToken)
|
|
91
|
-
expect(useSanityInstance).toHaveBeenCalled()
|
|
92
|
-
expect(getAuthStore).toHaveBeenCalledWith(mockInstance)
|
|
11
|
+
it('calls `createStateSourceHook` with `getTokenState`', async () => {
|
|
12
|
+
const {useAuthToken} = await import('./useAuthToken')
|
|
13
|
+
expect(createStateSourceHook).toHaveBeenCalledWith(getTokenState)
|
|
14
|
+
expect(useAuthToken).toBe(getTokenState)
|
|
93
15
|
})
|
|
94
16
|
})
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {useStore} from 'zustand'
|
|
1
|
+
import {getTokenState} from '@sanity/sdk'
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Hook to get the currently logged in user
|
|
8
|
-
* @
|
|
7
|
+
* @internal
|
|
9
8
|
* @returns The current user or null if not authenticated
|
|
10
9
|
*/
|
|
11
|
-
export const useAuthToken = ()
|
|
12
|
-
const instance = useSanityInstance()
|
|
13
|
-
const {tokenState} = getAuthStore(instance)
|
|
14
|
-
|
|
15
|
-
return useStore(tokenState)
|
|
16
|
-
}
|
|
10
|
+
export const useAuthToken = createStateSourceHook(getTokenState)
|
|
@@ -1,50 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {describe,
|
|
1
|
+
import {getCurrentUserState} from '@sanity/sdk'
|
|
2
|
+
import {identity} from 'rxjs'
|
|
3
|
+
import {describe, it} from 'vitest'
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {useCurrentUser} from './useCurrentUser'
|
|
5
|
+
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
vi.mock('
|
|
10
|
-
vi.mock('@sanity/sdk')
|
|
11
|
-
|
|
12
|
-
const mockUser: CurrentUser = {
|
|
13
|
-
id: 'user-123',
|
|
14
|
-
name: 'Test User',
|
|
15
|
-
email: 'test@example.com',
|
|
16
|
-
role: 'admin',
|
|
17
|
-
roles: [],
|
|
18
|
-
}
|
|
7
|
+
vi.mock('../helpers/createStateSourceHook', () => ({createStateSourceHook: vi.fn(identity)}))
|
|
8
|
+
vi.mock('@sanity/sdk', () => ({getCurrentUserState: vi.fn()}))
|
|
19
9
|
|
|
20
10
|
describe('useCurrentUser', () => {
|
|
21
|
-
it('
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
vi.mocked(getAuthStore).mockReturnValue({
|
|
26
|
-
currentUserState: {
|
|
27
|
-
getState: () => mockUser,
|
|
28
|
-
subscribe: vi.fn(),
|
|
29
|
-
},
|
|
30
|
-
} as unknown as AuthStore)
|
|
31
|
-
|
|
32
|
-
const {result} = renderHook(() => useCurrentUser())
|
|
33
|
-
expect(result.current).toEqual(mockUser)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('returns null when not authenticated', () => {
|
|
37
|
-
vi.mocked(useSanityInstance).mockReturnValue({} as unknown as SanityInstance)
|
|
38
|
-
|
|
39
|
-
// Mock the auth store with no user
|
|
40
|
-
vi.mocked(getAuthStore).mockReturnValue({
|
|
41
|
-
currentUserState: {
|
|
42
|
-
getState: () => null,
|
|
43
|
-
subscribe: vi.fn(),
|
|
44
|
-
},
|
|
45
|
-
} as unknown as AuthStore)
|
|
46
|
-
|
|
47
|
-
const {result} = renderHook(() => useCurrentUser())
|
|
48
|
-
expect(result.current).toBeNull()
|
|
11
|
+
it('calls `createStateSourceHook` with `getTokenState`', async () => {
|
|
12
|
+
const {useCurrentUser} = await import('./useCurrentUser')
|
|
13
|
+
expect(createStateSourceHook).toHaveBeenCalledWith(getCurrentUserState)
|
|
14
|
+
expect(useCurrentUser).toBe(getCurrentUserState)
|
|
49
15
|
})
|
|
50
16
|
})
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import {type CurrentUser,
|
|
2
|
-
import {useStore} from 'zustand'
|
|
1
|
+
import {type CurrentUser, getCurrentUserState} from '@sanity/sdk'
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import {createStateSourceHook} from '../helpers/createStateSourceHook'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* @TODO This should suspend! And possibly not return `null`?
|
|
7
|
+
*
|
|
8
8
|
* @public
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* The `useCurrentUser` hook returns the currently authenticated user’s profile information (their name, email, roles, etc).
|
|
11
|
+
* If no users are currently logged in, the hook returns null.
|
|
12
|
+
*
|
|
13
|
+
* @returns The current user data, or `null` if not authenticated
|
|
14
|
+
*
|
|
15
|
+
* @example Rendering a basic user profile
|
|
16
|
+
* ```
|
|
17
|
+
* const user = useCurrentUser()
|
|
18
|
+
*
|
|
19
|
+
* return (
|
|
20
|
+
* <figure>
|
|
21
|
+
* <img src={user?.profileImage} alt=`Profile image for ${user?.name}` />
|
|
22
|
+
* <h2>{user?.name}</h2>
|
|
23
|
+
* </figure>
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
10
26
|
*/
|
|
11
|
-
export const useCurrentUser
|
|
12
|
-
const instance = useSanityInstance()
|
|
13
|
-
const {currentUserState} = getAuthStore(instance)
|
|
14
|
-
|
|
15
|
-
// TODO: update this hook so it can never return null
|
|
16
|
-
if (!currentUserState.getState())
|
|
17
|
-
throw new Promise<void>((resolve) => {
|
|
18
|
-
const unsubscribe = currentUserState.subscribe((currentUser) => {
|
|
19
|
-
if (currentUser) {
|
|
20
|
-
unsubscribe()
|
|
21
|
-
resolve()
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
return useStore<CurrentUserSlice>(currentUserState)
|
|
27
|
-
}
|
|
27
|
+
export const useCurrentUser: () => CurrentUser | null = createStateSourceHook(getCurrentUserState)
|
|
@@ -1,25 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {handleCallback} from '@sanity/sdk'
|
|
2
|
+
import {identity} from 'rxjs'
|
|
3
|
+
import {describe, it} from 'vitest'
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {useHandleCallback} from './useHandleCallback'
|
|
5
|
+
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
7
6
|
|
|
8
|
-
vi.mock('../
|
|
9
|
-
vi.mock('@sanity/sdk', () => ({
|
|
7
|
+
vi.mock('../helpers/createCallbackHook', () => ({createCallbackHook: vi.fn(identity)}))
|
|
8
|
+
vi.mock('@sanity/sdk', () => ({handleCallback: vi.fn()}))
|
|
10
9
|
|
|
11
10
|
describe('useHandleCallback', () => {
|
|
12
|
-
it('
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
;(useSanityInstance as Mock).mockReturnValue(mockInstance)
|
|
18
|
-
;(getAuthStore as Mock).mockReturnValue(mockAuthStore)
|
|
19
|
-
|
|
20
|
-
const {result} = renderHook(() => useHandleCallback())
|
|
21
|
-
|
|
22
|
-
expect(getAuthStore).toHaveBeenCalledWith(mockInstance)
|
|
23
|
-
expect(result.current).toBe(mockHandleCallback)
|
|
11
|
+
it('calls `createCallbackHook` with `handleCallback`', async () => {
|
|
12
|
+
const {useHandleCallback} = await import('./useHandleCallback')
|
|
13
|
+
expect(createCallbackHook).toHaveBeenCalledWith(handleCallback)
|
|
14
|
+
expect(useHandleCallback).toBe(handleCallback)
|
|
24
15
|
})
|
|
25
16
|
})
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {useMemo} from 'react'
|
|
1
|
+
import {handleCallback} from '@sanity/sdk'
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
5
4
|
|
|
6
5
|
/**
|
|
6
|
+
* @internal
|
|
7
7
|
* A React hook that returns a function for handling authentication callbacks.
|
|
8
8
|
*
|
|
9
9
|
* @remarks
|
|
@@ -42,9 +42,4 @@ import {useSanityInstance} from '../context/useSanityInstance'
|
|
|
42
42
|
* @returns A callback handler function that processes OAuth redirects
|
|
43
43
|
* @public
|
|
44
44
|
*/
|
|
45
|
-
export
|
|
46
|
-
const instance = useSanityInstance()
|
|
47
|
-
const authStore = useMemo(() => getAuthStore(instance), [instance])
|
|
48
|
-
|
|
49
|
-
return authStore.handleCallback
|
|
50
|
-
}
|
|
45
|
+
export const useHandleCallback = createCallbackHook(handleCallback)
|
|
@@ -1,67 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {describe,
|
|
1
|
+
import {logout} from '@sanity/sdk'
|
|
2
|
+
import {identity} from 'rxjs'
|
|
3
|
+
import {describe, it} from 'vitest'
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {useLogOut} from './useLogOut'
|
|
5
|
+
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
vi.mock('@sanity/sdk', () => ({
|
|
10
|
-
getAuthStore: vi.fn(),
|
|
11
|
-
}))
|
|
7
|
+
vi.mock('../helpers/createCallbackHook', () => ({createCallbackHook: vi.fn(identity)}))
|
|
8
|
+
vi.mock('@sanity/sdk', () => ({logout: vi.fn()}))
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
it('should return logout function from auth store', () => {
|
|
19
|
-
// Setup mocks
|
|
20
|
-
const mockInstance: SanityInstance = {
|
|
21
|
-
identity: {
|
|
22
|
-
id: 'abc123',
|
|
23
|
-
projectId: 'test-project-id',
|
|
24
|
-
dataset: 'test-dataset',
|
|
25
|
-
},
|
|
26
|
-
config: {},
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const mockLogout = vi.fn()
|
|
30
|
-
const mockAuthStore: AuthStore = {
|
|
31
|
-
authState: {
|
|
32
|
-
getInitialState: vi.fn(),
|
|
33
|
-
getState: vi.fn(),
|
|
34
|
-
subscribe: vi.fn(),
|
|
35
|
-
},
|
|
36
|
-
tokenState: {
|
|
37
|
-
getInitialState: vi.fn(),
|
|
38
|
-
getState: vi.fn(),
|
|
39
|
-
subscribe: vi.fn(),
|
|
40
|
-
},
|
|
41
|
-
currentUserState: {
|
|
42
|
-
getInitialState: vi.fn(),
|
|
43
|
-
getState: vi.fn(),
|
|
44
|
-
subscribe: vi.fn(),
|
|
45
|
-
},
|
|
46
|
-
handleCallback: vi.fn(),
|
|
47
|
-
logout: mockLogout,
|
|
48
|
-
dispose: vi.fn(),
|
|
49
|
-
getLoginUrls: vi.fn(),
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
vi.mocked(useSanityInstance).mockReturnValue(mockInstance)
|
|
53
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore)
|
|
54
|
-
|
|
55
|
-
// Test the hook
|
|
56
|
-
const {result} = renderHook(() => useLogOut())
|
|
57
|
-
|
|
58
|
-
// Verify the returned function is the logout function
|
|
59
|
-
expect(result.current).toBe(mockLogout)
|
|
60
|
-
expect(useSanityInstance).toHaveBeenCalled()
|
|
61
|
-
expect(getAuthStore).toHaveBeenCalledWith(mockInstance)
|
|
62
|
-
|
|
63
|
-
// Verify the logout function can be called
|
|
64
|
-
result.current()
|
|
65
|
-
expect(mockLogout).toHaveBeenCalled()
|
|
10
|
+
describe('useHandleCallback', () => {
|
|
11
|
+
it('calls `createCallbackHook` with `handleCallback`', async () => {
|
|
12
|
+
const {useLogOut} = await import('./useLogOut')
|
|
13
|
+
expect(createCallbackHook).toHaveBeenCalledWith(logout)
|
|
14
|
+
expect(useLogOut).toBe(logout)
|
|
66
15
|
})
|
|
67
16
|
})
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {logout} from '@sanity/sdk'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {createCallbackHook} from '../helpers/createCallbackHook'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Hook to log out of the current session
|
|
7
|
-
* @
|
|
7
|
+
* @internal
|
|
8
8
|
* @returns A function to log out of the current session
|
|
9
9
|
*/
|
|
10
|
-
export const useLogOut = ()
|
|
11
|
-
const instance = useSanityInstance()
|
|
12
|
-
const {logout} = getAuthStore(instance)
|
|
13
|
-
|
|
14
|
-
return logout
|
|
15
|
-
}
|
|
10
|
+
export const useLogOut = createCallbackHook(logout)
|
|
@@ -1,61 +1,68 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {renderHook
|
|
3
|
-
import {Suspense} from 'react'
|
|
1
|
+
import {createSanityInstance, fetchLoginUrls, getLoginUrlsState} from '@sanity/sdk'
|
|
2
|
+
import {renderHook} from '@testing-library/react'
|
|
3
|
+
import {act, Suspense} from 'react'
|
|
4
|
+
import {throwError} from 'rxjs'
|
|
4
5
|
import {describe, expect, it, vi} from 'vitest'
|
|
5
6
|
|
|
6
|
-
import {SanityProvider} from '../../components/context/SanityProvider'
|
|
7
7
|
import {useLoginUrls} from './useLoginUrls'
|
|
8
8
|
|
|
9
|
+
vi.mock('../context/useSanityInstance', () => ({
|
|
10
|
+
useSanityInstance: vi.fn().mockReturnValue(createSanityInstance({projectId: 'p', dataset: 'd'})),
|
|
11
|
+
}))
|
|
12
|
+
|
|
9
13
|
vi.mock(import('@sanity/sdk'), async (importOriginal) => {
|
|
10
14
|
const actual = await importOriginal()
|
|
11
|
-
return {
|
|
12
|
-
...actual,
|
|
13
|
-
getAuthStore: vi.fn(),
|
|
14
|
-
}
|
|
15
|
+
return {...actual, getLoginUrlsState: vi.fn(), fetchLoginUrls: vi.fn()}
|
|
15
16
|
})
|
|
16
17
|
|
|
17
18
|
describe('useLoginUrls', () => {
|
|
18
|
-
it('should
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
getLoginUrls: () => mockProviders,
|
|
22
|
-
}
|
|
23
|
-
vi.mocked(getAuthStore).mockReturnValue(mockAuthStore as AuthStore)
|
|
19
|
+
it('should suspend by throwing `fetchLoginUrls` if `getLoginUrlsState().getCurrent()` is falsy', async () => {
|
|
20
|
+
const subscribe = vi.fn()
|
|
21
|
+
const getCurrent = vi.fn().mockReturnValue(undefined)
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
23
|
+
let resolve: () => void
|
|
24
|
+
const promise = new Promise<void>((thisResolve) => {
|
|
25
|
+
resolve = thisResolve
|
|
26
|
+
})
|
|
27
|
+
vi.mocked(fetchLoginUrls).mockReturnValue(
|
|
28
|
+
promise as unknown as ReturnType<typeof fetchLoginUrls>,
|
|
28
29
|
)
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const mockProviders = [{name: 'google', title: 'Google', url: 'http://test.com/auth/google'}]
|
|
36
|
-
|
|
37
|
-
const getLoginUrls = vi
|
|
38
|
-
.fn<AuthStore['getLoginUrls']>()
|
|
39
|
-
.mockResolvedValueOnce(mockProviders)
|
|
40
|
-
.mockReturnValueOnce(mockProviders)
|
|
41
|
-
|
|
42
|
-
vi.mocked(getAuthStore).mockReturnValue({getLoginUrls} as unknown as AuthStore)
|
|
31
|
+
vi.mocked(getLoginUrlsState).mockReturnValue({
|
|
32
|
+
getCurrent,
|
|
33
|
+
subscribe,
|
|
34
|
+
observable: throwError(() => new Error('Unexpected usage of observable')),
|
|
35
|
+
})
|
|
43
36
|
|
|
44
|
-
const sanityInstance = createSanityInstance({projectId: 'test', dataset: 'test'})
|
|
45
37
|
const wrapper = ({children}: {children: React.ReactNode}) => (
|
|
46
|
-
<Suspense fallback={<>Loading…</>}>
|
|
47
|
-
<SanityProvider sanityInstance={sanityInstance}>{children}</SanityProvider>
|
|
48
|
-
</Suspense>
|
|
38
|
+
<Suspense fallback={<>Loading…</>}>{children}</Suspense>
|
|
49
39
|
)
|
|
50
40
|
|
|
51
|
-
const {result} = renderHook(() => useLoginUrls(), {wrapper})
|
|
52
|
-
|
|
53
|
-
// Initially empty
|
|
41
|
+
const {result, rerender} = renderHook(() => useLoginUrls(), {wrapper})
|
|
54
42
|
expect(result.current).toEqual(null)
|
|
55
43
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
44
|
+
const mockProviders = [{name: 'google', title: 'Google', url: 'http://test.com/auth/google'}]
|
|
45
|
+
|
|
46
|
+
await act(async () => {
|
|
47
|
+
getCurrent.mockReturnValue(mockProviders)
|
|
48
|
+
resolve()
|
|
49
|
+
rerender()
|
|
50
|
+
await promise
|
|
59
51
|
})
|
|
52
|
+
|
|
53
|
+
expect(result.current).toEqual(mockProviders)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should render according to `getLoginUrlsState`', () => {
|
|
57
|
+
const subscribe = vi.fn()
|
|
58
|
+
const mockProviders = [{name: 'google', title: 'Google', url: 'http://test.com/auth/google'}]
|
|
59
|
+
vi.mocked(getLoginUrlsState).mockReturnValue({
|
|
60
|
+
getCurrent: () => mockProviders,
|
|
61
|
+
subscribe,
|
|
62
|
+
observable: throwError(() => new Error('Unexpected usage of observable')),
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const {result} = renderHook(() => useLoginUrls())
|
|
66
|
+
expect(result.current).toEqual(mockProviders)
|
|
60
67
|
})
|
|
61
68
|
})
|