@umituz/web-firebase 2.0.1 → 2.1.0

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/web-firebase",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "Comprehensive Firebase integration with DDD architecture for web applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -1,146 +1,100 @@
1
1
  /**
2
2
  * Auth Hook
3
3
  * @description React hook for authentication operations
4
- * Migrated from: /Users/umituz/Desktop/github/umituz/apps/web/app-growth-factory/src/domains/firebase/hooks/useAuth.ts
5
- * Refactored to use use cases
4
+ * Uses FirebaseProvider context - no repository injection needed
6
5
  */
7
6
 
8
- import { useEffect, useState, useCallback } from 'react'
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 type { IAuthRepository } from '../../domain/interfaces/auth.repository.interface'
12
- import type { IUserRepository } from '../../domain/interfaces/user.repository.interface'
13
- import type { SignInDTO, SignUpDTO } from '../../application/dto/auth.dto'
14
-
15
- export interface UseAuthOptions {
16
- authRepository: IAuthRepository
17
- userRepository: IUserRepository
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({ authRepository, userRepository }: UseAuthOptions) {
21
- const [firebaseUser, setFirebaseUser] = useState<FirebaseUser | null>(null)
22
- const [user, setUser] = useState<User | null>(null)
23
- const [loading, setLoading] = useState(true)
24
- const [error, setError] = useState<Error | null>(null)
25
-
26
- useEffect(() => {
27
- const unsubscribe = authRepository.onAuthStateChanged(async (fbUser) => {
28
- setFirebaseUser(fbUser)
29
-
30
- if (fbUser) {
31
- try {
32
- const userData = await userRepository.getUser(fbUser.uid)
33
- setUser(userData)
34
- } catch (err) {
35
- console.error('Error fetching user data:', err)
36
- setError(err as Error)
37
- }
38
- } else {
39
- setUser(null)
40
- }
41
-
42
- setLoading(false)
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 () => unsubscribe()
46
- }, [authRepository, userRepository])
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
- setError(null)
70
- try {
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
- setError(null)
80
- try {
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
- setError(null)
92
- try {
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
- setError(null)
102
- try {
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
- setError(null)
112
- try {
113
- await authRepository.updateProfile(updates)
114
- if (firebaseUser) {
115
- const userData = await userRepository.getUser(firebaseUser.uid)
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
- }, [authRepository, userRepository, firebaseUser])
83
+ }, [instances])
123
84
 
124
85
  const refreshUser = useCallback(async () => {
125
- setError(null)
126
- try {
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
- }, [userRepository, firebaseUser])
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: !!firebaseUser,
143
- isEmailVerified: firebaseUser?.emailVerified || false,
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 initialization
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
- // Note: Firebase is already initialized via environment variables
23
- // This provider just makes instances available via context
24
- const instances = getFirebaseInstances()
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: true,
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
+