RepositoryProvider.tsx raw
1 import {
2 FollowListRepository,
3 MuteListRepository,
4 PinnedUsersListRepository
5 } from '@/domain'
6 import {
7 FollowListRepositoryImpl,
8 MuteListRepositoryImpl,
9 PinnedUsersListRepositoryImpl
10 } from '@/infrastructure/persistence'
11 import { createContext, useContext, useMemo } from 'react'
12 import { useNostr } from './NostrProvider'
13
14 /**
15 * Repository context providing access to all domain repositories
16 */
17 type TRepositoryContext = {
18 followListRepository: FollowListRepository
19 muteListRepository: MuteListRepository
20 pinnedUsersListRepository: PinnedUsersListRepository
21 }
22
23 const RepositoryContext = createContext<TRepositoryContext | undefined>(undefined)
24
25 /**
26 * Hook to access repositories
27 * @throws Error if used outside RepositoryProvider
28 */
29 export const useRepositories = () => {
30 const context = useContext(RepositoryContext)
31 if (!context) {
32 throw new Error('useRepositories must be used within a RepositoryProvider')
33 }
34 return context
35 }
36
37 /**
38 * Provider that creates and provides repository instances with injected dependencies.
39 * Must be nested within NostrProvider to access publish and encryption functions.
40 */
41 export function RepositoryProvider({ children }: { children: React.ReactNode }) {
42 const { pubkey, publish, nip04Encrypt, nip04Decrypt } = useNostr()
43
44 const repositories = useMemo<TRepositoryContext | null>(() => {
45 if (!pubkey) return null
46
47 const followListRepository = new FollowListRepositoryImpl({ publish })
48
49 const muteListRepository = new MuteListRepositoryImpl({
50 publish,
51 currentUserPubkey: pubkey,
52 decrypt: async (ciphertext, pk) => nip04Decrypt(pk, ciphertext),
53 encrypt: async (plaintext, pk) => nip04Encrypt(pk, plaintext)
54 })
55
56 const pinnedUsersListRepository = new PinnedUsersListRepositoryImpl({
57 publish,
58 currentUserPubkey: pubkey,
59 decrypt: async (ciphertext, pk) => nip04Decrypt(pk, ciphertext),
60 encrypt: async (plaintext, pk) => nip04Encrypt(pk, plaintext)
61 })
62
63 return {
64 followListRepository,
65 muteListRepository,
66 pinnedUsersListRepository
67 }
68 }, [pubkey, publish, nip04Encrypt, nip04Decrypt])
69
70 // If not logged in, still render children but context will throw if accessed
71 if (!repositories) {
72 return <>{children}</>
73 }
74
75 return (
76 <RepositoryContext.Provider value={repositories}>
77 {children}
78 </RepositoryContext.Provider>
79 )
80 }
81