@umituz/web-firebase 2.0.1 → 2.1.1
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/package.json
CHANGED
|
@@ -1,146 +1,100 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auth Hook
|
|
3
3
|
* @description React hook for authentication operations
|
|
4
|
-
*
|
|
5
|
-
* Refactored to use use cases
|
|
4
|
+
* Uses FirebaseProvider context - no repository injection needed
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
|
-
import {
|
|
9
|
-
import { User as FirebaseUser } from 'firebase/auth'
|
|
7
|
+
import { useCallback } from 'react'
|
|
8
|
+
import type { User as FirebaseUser } from 'firebase/auth'
|
|
10
9
|
import type { User } from '../../domain/entities/user.entity'
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
import { AuthAdapter } from '../../infrastructure/firebase/auth.adapter'
|
|
11
|
+
import { FirestoreAdapter } from '../../infrastructure/firebase/firestore.adapter'
|
|
12
|
+
import { useFirebaseContext } from '../providers/FirebaseProvider'
|
|
13
|
+
|
|
14
|
+
export interface UseAuthResult {
|
|
15
|
+
firebaseUser: FirebaseUser | null
|
|
16
|
+
user: User | null
|
|
17
|
+
loading: boolean
|
|
18
|
+
error: Error | null
|
|
19
|
+
isAuthenticated: boolean
|
|
20
|
+
isEmailVerified: boolean
|
|
21
|
+
signIn: (email: string, password: string) => Promise<FirebaseUser>
|
|
22
|
+
signUp: (email: string, password: string, displayName: string) => Promise<FirebaseUser>
|
|
23
|
+
signInWithGoogle: () => Promise<FirebaseUser>
|
|
24
|
+
signOut: () => Promise<void>
|
|
25
|
+
sendPasswordReset: (email: string) => Promise<void>
|
|
26
|
+
resendEmailVerification: () => Promise<void>
|
|
27
|
+
updateProfile: (updates: { displayName?: string; photoURL?: string }) => Promise<void>
|
|
28
|
+
refreshUser: () => Promise<void>
|
|
18
29
|
}
|
|
19
30
|
|
|
20
|
-
export function useAuth(
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
export function useAuth(): UseAuthResult {
|
|
32
|
+
const { instances, user, loading, error } = useFirebaseContext()
|
|
33
|
+
|
|
34
|
+
const authAdapter = new AuthAdapter()
|
|
35
|
+
const firestoreAdapter = new FirestoreAdapter()
|
|
36
|
+
|
|
37
|
+
const signIn = useCallback(async (email: string, password: string) => {
|
|
38
|
+
return await authAdapter.signIn(email, password)
|
|
39
|
+
}, [])
|
|
40
|
+
|
|
41
|
+
const signUp = useCallback(async (email: string, password: string, displayName: string) => {
|
|
42
|
+
const userCredential = await authAdapter.signUp(email, password, displayName)
|
|
43
|
+
|
|
44
|
+
// Create user profile in Firestore
|
|
45
|
+
await firestoreAdapter.createUser(userCredential.user.uid, {
|
|
46
|
+
profile: {
|
|
47
|
+
email: email,
|
|
48
|
+
displayName: displayName,
|
|
49
|
+
createdAt: Date.now(),
|
|
50
|
+
},
|
|
51
|
+
settings: {
|
|
52
|
+
theme: 'light',
|
|
53
|
+
language: 'tr',
|
|
54
|
+
},
|
|
43
55
|
})
|
|
44
56
|
|
|
45
|
-
return
|
|
46
|
-
}, [
|
|
47
|
-
|
|
48
|
-
const signIn = useCallback(async (dto: SignInDTO) => {
|
|
49
|
-
setError(null)
|
|
50
|
-
try {
|
|
51
|
-
return await authRepository.signIn(dto.email, dto.password)
|
|
52
|
-
} catch (err) {
|
|
53
|
-
setError(err as Error)
|
|
54
|
-
throw err
|
|
55
|
-
}
|
|
56
|
-
}, [authRepository])
|
|
57
|
-
|
|
58
|
-
const signUp = useCallback(async (dto: SignUpDTO) => {
|
|
59
|
-
setError(null)
|
|
60
|
-
try {
|
|
61
|
-
return await authRepository.signUp(dto.email, dto.password, dto.displayName)
|
|
62
|
-
} catch (err) {
|
|
63
|
-
setError(err as Error)
|
|
64
|
-
throw err
|
|
65
|
-
}
|
|
66
|
-
}, [authRepository])
|
|
57
|
+
return userCredential.user
|
|
58
|
+
}, [])
|
|
67
59
|
|
|
68
60
|
const signInWithGoogle = useCallback(async () => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return await authRepository.signInWithGoogle()
|
|
72
|
-
} catch (err) {
|
|
73
|
-
setError(err as Error)
|
|
74
|
-
throw err
|
|
75
|
-
}
|
|
76
|
-
}, [authRepository])
|
|
61
|
+
return await authAdapter.signInWithGoogle()
|
|
62
|
+
}, [])
|
|
77
63
|
|
|
78
64
|
const signOut = useCallback(async () => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
await authRepository.signOut()
|
|
82
|
-
setUser(null)
|
|
83
|
-
setFirebaseUser(null)
|
|
84
|
-
} catch (err) {
|
|
85
|
-
setError(err as Error)
|
|
86
|
-
throw err
|
|
87
|
-
}
|
|
88
|
-
}, [authRepository])
|
|
65
|
+
await authAdapter.signOut()
|
|
66
|
+
}, [])
|
|
89
67
|
|
|
90
68
|
const sendPasswordReset = useCallback(async (email: string) => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
await authRepository.sendPasswordReset(email)
|
|
94
|
-
} catch (err) {
|
|
95
|
-
setError(err as Error)
|
|
96
|
-
throw err
|
|
97
|
-
}
|
|
98
|
-
}, [authRepository])
|
|
69
|
+
await authAdapter.sendPasswordReset(email)
|
|
70
|
+
}, [])
|
|
99
71
|
|
|
100
72
|
const resendEmailVerification = useCallback(async () => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
await authRepository.resendEmailVerification()
|
|
104
|
-
} catch (err) {
|
|
105
|
-
setError(err as Error)
|
|
106
|
-
throw err
|
|
107
|
-
}
|
|
108
|
-
}, [authRepository])
|
|
73
|
+
await authAdapter.resendEmailVerification()
|
|
74
|
+
}, [])
|
|
109
75
|
|
|
110
76
|
const updateProfile = useCallback(async (updates: { displayName?: string; photoURL?: string }) => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
setUser(userData)
|
|
117
|
-
}
|
|
118
|
-
} catch (err) {
|
|
119
|
-
setError(err as Error)
|
|
120
|
-
throw err
|
|
77
|
+
await authAdapter.updateProfile(updates)
|
|
78
|
+
|
|
79
|
+
// Refresh user data from Firestore if available
|
|
80
|
+
if (instances?.auth.currentUser) {
|
|
81
|
+
await firestoreAdapter.getUser(instances.auth.currentUser.uid)
|
|
121
82
|
}
|
|
122
|
-
}, [
|
|
83
|
+
}, [instances])
|
|
123
84
|
|
|
124
85
|
const refreshUser = useCallback(async () => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (firebaseUser) {
|
|
128
|
-
const userData = await userRepository.getUser(firebaseUser.uid)
|
|
129
|
-
setUser(userData)
|
|
130
|
-
}
|
|
131
|
-
} catch (err) {
|
|
132
|
-
setError(err as Error)
|
|
133
|
-
throw err
|
|
86
|
+
if (instances?.auth.currentUser) {
|
|
87
|
+
await firestoreAdapter.getUser(instances.auth.currentUser.uid)
|
|
134
88
|
}
|
|
135
|
-
}, [
|
|
89
|
+
}, [instances])
|
|
136
90
|
|
|
137
91
|
return {
|
|
138
|
-
firebaseUser,
|
|
92
|
+
firebaseUser: instances?.auth.currentUser || null,
|
|
139
93
|
user,
|
|
140
94
|
loading,
|
|
141
95
|
error,
|
|
142
|
-
isAuthenticated: !!
|
|
143
|
-
isEmailVerified:
|
|
96
|
+
isAuthenticated: !!instances?.auth.currentUser,
|
|
97
|
+
isEmailVerified: instances?.auth.currentUser?.emailVerified || false,
|
|
144
98
|
signIn,
|
|
145
99
|
signUp,
|
|
146
100
|
signInWithGoogle,
|
|
@@ -151,3 +105,4 @@ export function useAuth({ authRepository, userRepository }: UseAuthOptions) {
|
|
|
151
105
|
refreshUser,
|
|
152
106
|
}
|
|
153
107
|
}
|
|
108
|
+
|
|
@@ -1,40 +1,95 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* FirebaseProvider
|
|
3
|
-
* @description React Context Provider for Firebase
|
|
3
|
+
* @description React Context Provider for Firebase with auth state tracking
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { createContext, useContext, type ReactNode } from 'react'
|
|
6
|
+
import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
|
|
7
|
+
import type { User } from 'firebase/auth'
|
|
7
8
|
import type { FirebaseInstances } from '../../infrastructure/firebase/client'
|
|
8
9
|
import { getFirebaseInstances } from '../../infrastructure/firebase/client'
|
|
10
|
+
import { AuthAdapter } from '../../infrastructure/firebase/auth.adapter'
|
|
9
11
|
|
|
10
|
-
interface FirebaseContextValue {
|
|
12
|
+
export interface FirebaseContextValue {
|
|
11
13
|
instances: FirebaseInstances
|
|
12
14
|
isInitialized: boolean
|
|
15
|
+
user: User | null
|
|
16
|
+
loading: boolean
|
|
17
|
+
error: Error | null
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
const FirebaseContext = createContext<FirebaseContextValue | null>(null)
|
|
16
21
|
|
|
17
22
|
export interface FirebaseProviderProps {
|
|
18
23
|
children: ReactNode
|
|
24
|
+
config?: {
|
|
25
|
+
apiKey: string
|
|
26
|
+
authDomain: string
|
|
27
|
+
projectId: string
|
|
28
|
+
storageBucket: string
|
|
29
|
+
messagingSenderId: string
|
|
30
|
+
appId: string
|
|
31
|
+
}
|
|
19
32
|
}
|
|
20
33
|
|
|
21
|
-
export function FirebaseProvider({ children }: FirebaseProviderProps) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
34
|
+
export function FirebaseProvider({ children, config }: FirebaseProviderProps) {
|
|
35
|
+
const [instances, setInstances] = useState<FirebaseInstances | null>(null)
|
|
36
|
+
const [user, setUser] = useState<User | null>(null)
|
|
37
|
+
const [loading, setLoading] = useState(true)
|
|
38
|
+
const [error, setError] = useState<Error | null>(null)
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
try {
|
|
42
|
+
// Initialize Firebase (singleton - won't re-initialize)
|
|
43
|
+
const firebaseInstances = getFirebaseInstances()
|
|
44
|
+
setInstances(firebaseInstances)
|
|
45
|
+
|
|
46
|
+
// Set up auth state listener
|
|
47
|
+
const authAdapter = new AuthAdapter()
|
|
48
|
+
const unsubscribe = authAdapter.onAuthStateChanged(
|
|
49
|
+
(user) => {
|
|
50
|
+
setUser(user)
|
|
51
|
+
setLoading(false)
|
|
52
|
+
setError(null)
|
|
53
|
+
},
|
|
54
|
+
(err) => {
|
|
55
|
+
setError(err)
|
|
56
|
+
setLoading(false)
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
if (unsubscribe) unsubscribe()
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
setError(err as Error)
|
|
65
|
+
setLoading(false)
|
|
66
|
+
}
|
|
67
|
+
}, [config])
|
|
25
68
|
|
|
26
69
|
const value: FirebaseContextValue = {
|
|
27
|
-
instances
|
|
28
|
-
isInitialized:
|
|
70
|
+
instances: instances!,
|
|
71
|
+
isInitialized: !!instances,
|
|
72
|
+
user,
|
|
73
|
+
loading,
|
|
74
|
+
error,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!instances || loading) {
|
|
78
|
+
return (
|
|
79
|
+
<FirebaseContext.Provider value={{ ...value, isInitialized: false }}>
|
|
80
|
+
{children}
|
|
81
|
+
</FirebaseContext.Provider>
|
|
82
|
+
)
|
|
29
83
|
}
|
|
30
84
|
|
|
31
85
|
return <FirebaseContext.Provider value={value}>{children}</FirebaseContext.Provider>
|
|
32
86
|
}
|
|
33
87
|
|
|
34
|
-
export function useFirebaseContext() {
|
|
88
|
+
export function useFirebaseContext(): FirebaseContextValue {
|
|
35
89
|
const context = useContext(FirebaseContext)
|
|
36
90
|
if (!context) {
|
|
37
91
|
throw new Error('useFirebaseContext must be used within FirebaseProvider')
|
|
38
92
|
}
|
|
39
93
|
return context
|
|
40
94
|
}
|
|
95
|
+
|