@umituz/react-native-auth 1.3.2 → 1.4.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/README.md CHANGED
@@ -15,6 +15,7 @@ npm install @umituz/react-native-auth
15
15
  - `firebase` >= 11.0.0
16
16
  - `react` >= 18.2.0
17
17
  - `react-native` >= 0.74.0
18
+ - `@umituz/react-native-firebase-auth` >= 1.0.0 (for Firebase Auth initialization)
18
19
 
19
20
  ## Features
20
21
 
@@ -46,9 +47,10 @@ Initialize the service early in your app (e.g., in `App.tsx`):
46
47
 
47
48
  ```typescript
48
49
  import { initializeAuthService } from '@umituz/react-native-auth';
49
- import { getFirebaseAuth } from '@umituz/react-native-firebase';
50
+ import { getFirebaseAuth } from '@umituz/react-native-firebase-auth';
50
51
 
51
- // Initialize Firebase first (using @umituz/react-native-firebase)
52
+ // Initialize Firebase App first (using @umituz/react-native-firebase)
53
+ // Then initialize Firebase Auth (using @umituz/react-native-firebase-auth)
52
54
  const auth = getFirebaseAuth();
53
55
 
54
56
  // Initialize auth service
@@ -189,15 +191,16 @@ await authService.setGuestMode();
189
191
  3. **Guest Mode**: Use guest mode for offline-first apps that don't require authentication
190
192
  4. **User Callbacks**: Use `onUserCreated` and `onSignOut` callbacks for app-specific logic
191
193
 
192
- ## Integration with @umituz/react-native-firebase
194
+ ## Integration with Firebase Packages
193
195
 
194
- This package works seamlessly with `@umituz/react-native-firebase`:
196
+ This package works seamlessly with Firebase initialization packages:
195
197
 
196
198
  ```typescript
197
- import { initializeFirebase, getFirebaseAuth } from '@umituz/react-native-firebase';
199
+ import { initializeFirebase } from '@umituz/react-native-firebase';
200
+ import { initializeFirebaseAuth, getFirebaseAuth } from '@umituz/react-native-firebase-auth';
198
201
  import { initializeAuthService } from '@umituz/react-native-auth';
199
202
 
200
- // Initialize Firebase
203
+ // 1. Initialize Firebase App
201
204
  const config = {
202
205
  apiKey: 'your-api-key',
203
206
  authDomain: 'your-project.firebaseapp.com',
@@ -205,11 +208,19 @@ const config = {
205
208
  };
206
209
  initializeFirebase(config);
207
210
 
208
- // Initialize Auth Service
211
+ // 2. Initialize Firebase Auth
212
+ initializeFirebaseAuth();
213
+
214
+ // 3. Initialize Auth Service (business logic)
209
215
  const auth = getFirebaseAuth();
210
- initializeAuthService(auth);
216
+ initializeAuthService(auth, {
217
+ minPasswordLength: 6,
218
+ // ... other config
219
+ });
211
220
  ```
212
221
 
222
+ **Note:** This package is provider-agnostic. While it currently uses Firebase Auth, it can be easily adapted to work with Supabase or other authentication providers in the future.
223
+
213
224
  ## License
214
225
 
215
226
  MIT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "1.3.2",
4
- "description": "Firebase Authentication wrapper for React Native apps - Secure, type-safe, and production-ready",
3
+ "version": "1.4.0",
4
+ "description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design supports Firebase Auth and can be adapted for Supabase or other providers.",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
7
7
  "scripts": {
@@ -34,6 +34,7 @@
34
34
  "firebase": ">=11.0.0",
35
35
  "react": ">=18.2.0",
36
36
  "react-native": ">=0.74.0",
37
+ "@umituz/react-native-firebase-auth": ">=1.1.0",
37
38
  "@react-navigation/stack": "^6.0.0",
38
39
  "@react-navigation/native": "^6.0.0",
39
40
  "@umituz/react-native-design-system": "*",
@@ -20,9 +20,17 @@ export interface AuthConfig {
20
20
  onUserUpdated?: (user: any) => Promise<void> | void;
21
21
  /** Callback for sign out cleanup */
22
22
  onSignOut?: () => Promise<void> | void;
23
+ /** Callback for analytics logging on sign in */
24
+ onSignIn?: (method: string) => Promise<void> | void;
25
+ /** Callback for analytics logging on guest mode */
26
+ onGuestModeEnabled?: () => Promise<void> | void;
27
+ /** Callback for analytics initialization when user authenticates */
28
+ onAnalyticsInit?: (userId: string) => Promise<void> | void;
29
+ /** Callback for analytics initialization when guest mode enabled */
30
+ onAnalyticsInitGuest?: () => Promise<void> | void;
23
31
  }
24
32
 
25
- export const DEFAULT_AUTH_CONFIG: Required<Omit<AuthConfig, 'onUserCreated' | 'onUserUpdated' | 'onSignOut'>> = {
33
+ export const DEFAULT_AUTH_CONFIG: Required<Omit<AuthConfig, 'onUserCreated' | 'onUserUpdated' | 'onSignOut' | 'onSignIn' | 'onGuestModeEnabled' | 'onAnalyticsInit' | 'onAnalyticsInitGuest'>> = {
26
34
  minPasswordLength: 6,
27
35
  requireUppercase: false,
28
36
  requireLowercase: false,
@@ -204,6 +204,7 @@ export class AuthService implements IAuthService {
204
204
  }
205
205
 
206
206
  // Call user created callback if provided
207
+ // User state is managed by Firebase Auth's onAuthStateChanged
207
208
  if (this.config.onUserCreated) {
208
209
  try {
209
210
  await this.config.onUserCreated(userCredential.user);
@@ -245,6 +246,17 @@ export class AuthService implements IAuthService {
245
246
  );
246
247
 
247
248
  this.isGuestMode = false;
249
+
250
+ // Call analytics callback if provided
251
+ // User state is managed by Firebase Auth's onAuthStateChanged
252
+ if (this.config.onSignIn) {
253
+ try {
254
+ await this.config.onSignIn("email");
255
+ } catch (callbackError) {
256
+ // Don't fail signin if analytics callback fails
257
+ }
258
+ }
259
+
248
260
  return userCredential.user;
249
261
  } catch (error: any) {
250
262
  throw mapFirebaseAuthError(error);
@@ -267,6 +279,7 @@ export class AuthService implements IAuthService {
267
279
  this.isGuestMode = false;
268
280
 
269
281
  // Call sign out callback if provided
282
+ // User state is managed by Firebase Auth's onAuthStateChanged
270
283
  if (this.config.onSignOut) {
271
284
  try {
272
285
  await this.config.onSignOut();
@@ -295,6 +308,16 @@ export class AuthService implements IAuthService {
295
308
  }
296
309
 
297
310
  this.isGuestMode = true;
311
+
312
+ // Call analytics callback if provided
313
+ // Guest mode state is managed by useAuth hook
314
+ if (this.config.onGuestModeEnabled) {
315
+ try {
316
+ await this.config.onGuestModeEnabled();
317
+ } catch (callbackError) {
318
+ // Don't fail guest mode if analytics callback fails
319
+ }
320
+ }
298
321
  }
299
322
 
300
323
  /**
@@ -59,3 +59,6 @@ const styles = StyleSheet.create({
59
59
  },
60
60
  });
61
61
 
62
+
63
+
64
+
@@ -57,3 +57,6 @@ const styles = StyleSheet.create({
57
57
  },
58
58
  });
59
59
 
60
+
61
+
62
+
@@ -41,3 +41,6 @@ const styles = StyleSheet.create({
41
41
  },
42
42
  });
43
43
 
44
+
45
+
46
+
@@ -36,3 +36,6 @@ const styles = StyleSheet.create({
36
36
  },
37
37
  });
38
38
 
39
+
40
+
41
+
@@ -21,3 +21,6 @@ export const AuthGradientBackground: React.FC = () => {
21
21
  );
22
22
  };
23
23
 
24
+
25
+
26
+
@@ -66,3 +66,6 @@ const styles = StyleSheet.create({
66
66
  },
67
67
  });
68
68
 
69
+
70
+
71
+
@@ -133,3 +133,6 @@ const styles = StyleSheet.create({
133
133
  },
134
134
  });
135
135
 
136
+
137
+
138
+
@@ -62,3 +62,6 @@ const styles = StyleSheet.create({
62
62
  },
63
63
  });
64
64
 
65
+
66
+
67
+
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * useAuth Hook
3
3
  * React hook for authentication state management
4
+ *
5
+ * Uses Firebase Auth's built-in state management via useFirebaseAuth hook.
6
+ * Adds app-specific state (guest mode, error handling) on top of Firebase Auth.
4
7
  */
5
8
 
6
- import { useEffect, useState, useCallback } from "react";
9
+ import { useEffect, useRef, useCallback, useState } from "react";
7
10
  import type { User } from "firebase/auth";
8
11
  import { getAuthService } from "../../infrastructure/services/AuthService";
9
- import { getAuthErrorLocalizationKey } from "../utils/getAuthErrorMessage";
12
+ import { useFirebaseAuth } from "@umituz/react-native-firebase-auth";
10
13
 
11
14
  export interface UseAuthResult {
12
15
  /** Current authenticated user */
@@ -27,58 +30,62 @@ export interface UseAuthResult {
27
30
  signOut: () => Promise<void>;
28
31
  /** Continue as guest function */
29
32
  continueAsGuest: () => Promise<void>;
33
+ /** Set error manually (for form validation, etc.) */
34
+ setError: (error: string | null) => void;
30
35
  }
31
36
 
32
37
  /**
33
38
  * Hook for authentication state management
34
39
  *
40
+ * Uses Firebase Auth's built-in state management and adds app-specific features:
41
+ * - Guest mode support
42
+ * - Error handling
43
+ * - Loading states
44
+ *
35
45
  * @example
36
46
  * ```typescript
37
47
  * const { user, isAuthenticated, signIn, signUp, signOut } = useAuth();
38
48
  * ```
39
49
  */
40
50
  export function useAuth(): UseAuthResult {
41
- const [user, setUser] = useState<User | null>(null);
42
- const [loading, setLoading] = useState(true);
51
+ // Use Firebase Auth's built-in state management
52
+ const { user: firebaseUser, loading: firebaseLoading } = useFirebaseAuth();
53
+
54
+ // App-specific state
43
55
  const [isGuest, setIsGuest] = useState(false);
44
56
  const [error, setError] = useState<string | null>(null);
57
+ const [loading, setLoading] = useState(false);
58
+ const prevAuthState = useRef({ isAuthenticated: false, isGuest: false });
59
+
60
+ // Sync Firebase Auth user with guest mode
61
+ const user = isGuest ? null : firebaseUser;
62
+ const isAuthenticated = !!user && !isGuest;
45
63
 
64
+ // Handle analytics initialization (if callbacks are provided in config)
46
65
  useEffect(() => {
47
- const service = getAuthService();
48
- if (!service) {
49
- // Auth service not initialized
50
- setUser(null);
51
- setIsGuest(false);
52
- setLoading(false);
53
- return () => {};
54
- }
66
+ const authChanged =
67
+ prevAuthState.current.isAuthenticated !== isAuthenticated ||
68
+ prevAuthState.current.isGuest !== isGuest;
55
69
 
56
- try {
57
- const unsubscribe = service.onAuthStateChange((currentUser) => {
58
- setUser(currentUser);
59
- setIsGuest(service.getIsGuestMode());
60
- setLoading(false);
61
- });
70
+ // Analytics initialization is handled by AuthService callbacks (onAnalyticsInit, onAnalyticsInitGuest)
71
+ // This effect is kept for backward compatibility but analytics should be configured via AuthConfig
62
72
 
63
- // Set initial state
64
- const currentUser = service.getCurrentUser();
65
- setUser(currentUser);
66
- setIsGuest(service.getIsGuestMode());
67
- setLoading(false);
73
+ // Update previous state
74
+ prevAuthState.current = { isAuthenticated, isGuest };
75
+ }, [isAuthenticated, isGuest]);
68
76
 
69
- return () => {
70
- unsubscribe();
71
- };
72
- } catch (error) {
73
- // Auth service error
74
- setUser(null);
77
+ // Reset guest mode when user signs in
78
+ useEffect(() => {
79
+ if (firebaseUser && isGuest) {
75
80
  setIsGuest(false);
76
- setLoading(false);
77
- return () => {};
78
81
  }
79
- }, []);
82
+ }, [firebaseUser, isGuest]);
80
83
 
81
- const signUp = useCallback(async (email: string, password: string, displayName?: string) => {
84
+ const signUp = useCallback(async (
85
+ email: string,
86
+ password: string,
87
+ displayName?: string
88
+ ) => {
82
89
  const service = getAuthService();
83
90
  if (!service) {
84
91
  const err = "Auth service is not initialized";
@@ -86,13 +93,16 @@ export function useAuth(): UseAuthResult {
86
93
  throw new Error(err);
87
94
  }
88
95
  try {
96
+ setLoading(true);
89
97
  setError(null);
90
98
  await service.signUp({ email, password, displayName });
91
- // State will be updated via onAuthStateChange
99
+ // User state is updated by Firebase Auth's onAuthStateChanged
92
100
  } catch (err: any) {
93
101
  const errorMessage = err.message || "Sign up failed";
94
102
  setError(errorMessage);
95
103
  throw err;
104
+ } finally {
105
+ setLoading(false);
96
106
  }
97
107
  }, []);
98
108
 
@@ -104,13 +114,16 @@ export function useAuth(): UseAuthResult {
104
114
  throw new Error(err);
105
115
  }
106
116
  try {
117
+ setLoading(true);
107
118
  setError(null);
108
119
  await service.signIn({ email, password });
109
- // State will be updated via onAuthStateChange
120
+ // User state is updated by Firebase Auth's onAuthStateChanged
110
121
  } catch (err: any) {
111
- const errorMessage = err.message || "Sign in failed";
122
+ const errorMessage = err.message || "Failed to sign in";
112
123
  setError(errorMessage);
113
124
  throw err;
125
+ } finally {
126
+ setLoading(false);
114
127
  }
115
128
  }, []);
116
129
 
@@ -119,9 +132,13 @@ export function useAuth(): UseAuthResult {
119
132
  if (!service) {
120
133
  return;
121
134
  }
122
- await service.signOut();
123
- setUser(null);
124
- setIsGuest(false);
135
+ try {
136
+ setLoading(true);
137
+ await service.signOut();
138
+ // User state is updated by Firebase Auth's onAuthStateChanged
139
+ } finally {
140
+ setLoading(false);
141
+ }
125
142
  }, []);
126
143
 
127
144
  const continueAsGuest = useCallback(async () => {
@@ -130,21 +147,25 @@ export function useAuth(): UseAuthResult {
130
147
  setIsGuest(true);
131
148
  return;
132
149
  }
133
- await service.setGuestMode();
134
- setUser(null);
135
- setIsGuest(true);
150
+ try {
151
+ setLoading(true);
152
+ await service.setGuestMode();
153
+ setIsGuest(true);
154
+ } finally {
155
+ setLoading(false);
156
+ }
136
157
  }, []);
137
158
 
138
159
  return {
139
160
  user,
140
- loading,
161
+ loading: loading || firebaseLoading,
141
162
  isGuest,
142
- isAuthenticated: !!user && !isGuest,
163
+ isAuthenticated,
143
164
  error,
144
165
  signUp,
145
166
  signIn,
146
167
  signOut,
147
168
  continueAsGuest,
169
+ setError,
148
170
  };
149
171
  }
150
-
@@ -76,3 +76,6 @@ export function getAuthErrorLocalizationKey(error: Error): string {
76
76
  return "auth.errors.unknownError";
77
77
  }
78
78
 
79
+
80
+
81
+