@umituz/react-native-auth 1.5.2 → 1.6.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 +1 -1
- package/src/domain/value-objects/AuthConfig.ts +1 -15
- package/src/index.ts +9 -0
- package/src/infrastructure/services/AuthService.ts +22 -41
- package/src/presentation/components/AuthLegalLinks.tsx +1 -1
- package/src/presentation/components/AuthLink.tsx +1 -1
- package/src/presentation/components/LoginForm.tsx +1 -1
- package/src/presentation/components/RegisterForm.tsx +1 -1
- package/src/presentation/hooks/useAuth.ts +16 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
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",
|
|
@@ -14,23 +14,9 @@ export interface AuthConfig {
|
|
|
14
14
|
requireNumbers?: boolean;
|
|
15
15
|
/** Require special characters in password */
|
|
16
16
|
requireSpecialChars?: boolean;
|
|
17
|
-
/** Callback for user profile creation after signup */
|
|
18
|
-
onUserCreated?: (user: any) => Promise<void> | void;
|
|
19
|
-
/** Callback for user profile update */
|
|
20
|
-
onUserUpdated?: (user: any) => Promise<void> | void;
|
|
21
|
-
/** Callback for sign out cleanup */
|
|
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;
|
|
31
17
|
}
|
|
32
18
|
|
|
33
|
-
export const DEFAULT_AUTH_CONFIG: Required<
|
|
19
|
+
export const DEFAULT_AUTH_CONFIG: Required<AuthConfig> = {
|
|
34
20
|
minPasswordLength: 6,
|
|
35
21
|
requireUppercase: false,
|
|
36
22
|
requireLowercase: false,
|
package/src/index.ts
CHANGED
|
@@ -71,6 +71,15 @@ export type {
|
|
|
71
71
|
AuthStackParamList,
|
|
72
72
|
AuthNavigatorProps,
|
|
73
73
|
} from './presentation/navigation/AuthNavigator';
|
|
74
|
+
|
|
75
|
+
// PRESENTATION LAYER - Components
|
|
76
|
+
// =============================================================================
|
|
77
|
+
|
|
78
|
+
export { AuthContainer } from './presentation/components/AuthContainer';
|
|
79
|
+
export { AuthHeader } from './presentation/components/AuthHeader';
|
|
80
|
+
export { AuthFormCard } from './presentation/components/AuthFormCard';
|
|
81
|
+
export { LoginForm } from './presentation/components/LoginForm';
|
|
82
|
+
export { RegisterForm } from './presentation/components/RegisterForm';
|
|
74
83
|
export { AuthLegalLinks } from './presentation/components/AuthLegalLinks';
|
|
75
84
|
export type { AuthLegalLinksProps } from './presentation/components/AuthLegalLinks';
|
|
76
85
|
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from "../../domain/errors/AuthError";
|
|
28
28
|
import type { AuthConfig } from "../../domain/value-objects/AuthConfig";
|
|
29
29
|
import { DEFAULT_AUTH_CONFIG } from "../../domain/value-objects/AuthConfig";
|
|
30
|
+
import { DeviceEventEmitter } from "react-native";
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Validate email format
|
|
@@ -203,18 +204,8 @@ export class AuthService implements IAuthService {
|
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
206
|
|
|
206
|
-
// Call user created callback if provided
|
|
207
|
-
// User state is managed by Firebase Auth's onAuthStateChanged
|
|
208
|
-
if (this.config.onUserCreated) {
|
|
209
|
-
try {
|
|
210
|
-
await this.config.onUserCreated(userCredential.user);
|
|
211
|
-
} catch (callbackError) {
|
|
212
|
-
// Don't fail signup if callback fails
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
207
|
// Emit event for AppNavigator to handle navigation
|
|
217
|
-
|
|
208
|
+
DeviceEventEmitter.emit("user-authenticated", { userId: userCredential.user.uid });
|
|
218
209
|
|
|
219
210
|
return userCredential.user;
|
|
220
211
|
} catch (error: any) {
|
|
@@ -248,20 +239,13 @@ export class AuthService implements IAuthService {
|
|
|
248
239
|
params.password
|
|
249
240
|
);
|
|
250
241
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// User state is managed by Firebase Auth's onAuthStateChanged
|
|
255
|
-
if (this.config.onSignIn) {
|
|
256
|
-
try {
|
|
257
|
-
await this.config.onSignIn("email");
|
|
258
|
-
} catch (callbackError) {
|
|
259
|
-
// Don't fail signin if analytics callback fails
|
|
260
|
-
}
|
|
242
|
+
// Clear guest mode when user signs in
|
|
243
|
+
if (this.isGuestMode) {
|
|
244
|
+
this.isGuestMode = false;
|
|
261
245
|
}
|
|
262
246
|
|
|
263
247
|
// Emit event for AppNavigator to handle navigation
|
|
264
|
-
|
|
248
|
+
DeviceEventEmitter.emit("user-authenticated", { userId: userCredential.user.uid });
|
|
265
249
|
|
|
266
250
|
return userCredential.user;
|
|
267
251
|
} catch (error: any) {
|
|
@@ -284,15 +268,6 @@ export class AuthService implements IAuthService {
|
|
|
284
268
|
await firebaseSignOut(auth);
|
|
285
269
|
this.isGuestMode = false;
|
|
286
270
|
|
|
287
|
-
// Call sign out callback if provided
|
|
288
|
-
// User state is managed by Firebase Auth's onAuthStateChanged
|
|
289
|
-
if (this.config.onSignOut) {
|
|
290
|
-
try {
|
|
291
|
-
await this.config.onSignOut();
|
|
292
|
-
} catch (callbackError) {
|
|
293
|
-
// Don't fail signout if callback fails
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
271
|
} catch (error: any) {
|
|
297
272
|
throw mapFirebaseAuthError(error);
|
|
298
273
|
}
|
|
@@ -315,15 +290,8 @@ export class AuthService implements IAuthService {
|
|
|
315
290
|
|
|
316
291
|
this.isGuestMode = true;
|
|
317
292
|
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
if (this.config.onGuestModeEnabled) {
|
|
321
|
-
try {
|
|
322
|
-
await this.config.onGuestModeEnabled();
|
|
323
|
-
} catch (callbackError) {
|
|
324
|
-
// Don't fail guest mode if analytics callback fails
|
|
325
|
-
}
|
|
326
|
-
}
|
|
293
|
+
// Emit event for AppNavigator to handle navigation
|
|
294
|
+
DeviceEventEmitter.emit("guest-mode-enabled");
|
|
327
295
|
}
|
|
328
296
|
|
|
329
297
|
/**
|
|
@@ -374,13 +342,26 @@ let authServiceInstance: AuthService | null = null;
|
|
|
374
342
|
/**
|
|
375
343
|
* Initialize auth service with Firebase Auth instance
|
|
376
344
|
* Must be called before using any auth methods
|
|
345
|
+
*
|
|
346
|
+
* Uses DEFAULT_AUTH_CONFIG if no config is provided:
|
|
347
|
+
* - minPasswordLength: 6
|
|
348
|
+
* - requireUppercase: false
|
|
349
|
+
* - requireLowercase: false
|
|
350
|
+
* - requireNumbers: false
|
|
351
|
+
* - requireSpecialChars: false
|
|
352
|
+
*
|
|
353
|
+
* @param auth - Firebase Auth instance
|
|
354
|
+
* @param config - Optional auth configuration (defaults to permissive settings)
|
|
377
355
|
*/
|
|
378
356
|
export function initializeAuthService(
|
|
379
357
|
auth: Auth,
|
|
380
358
|
config?: AuthConfig
|
|
381
359
|
): AuthService {
|
|
360
|
+
// Use default config if not provided (permissive settings for better UX)
|
|
361
|
+
const finalConfig = config || DEFAULT_AUTH_CONFIG;
|
|
362
|
+
|
|
382
363
|
if (!authServiceInstance) {
|
|
383
|
-
authServiceInstance = new AuthService(
|
|
364
|
+
authServiceInstance = new AuthService(finalConfig);
|
|
384
365
|
}
|
|
385
366
|
authServiceInstance.initialize(auth);
|
|
386
367
|
return authServiceInstance;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, StyleSheet, Linking } from "react-native";
|
|
8
|
-
import { AtomicButton, AtomicText } from "@umituz/react-native-design-system";
|
|
8
|
+
import { AtomicButton, AtomicText } from "@umituz/react-native-design-system-atoms";
|
|
9
9
|
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
10
10
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
11
11
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, Text, StyleSheet } from "react-native";
|
|
8
|
-
import { AtomicButton } from "@umituz/react-native-design-system";
|
|
8
|
+
import { AtomicButton } from "@umituz/react-native-design-system-atoms";
|
|
9
9
|
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
10
10
|
|
|
11
11
|
interface AuthLinkProps {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import React, { useState } from "react";
|
|
7
7
|
import { View, StyleSheet } from "react-native";
|
|
8
|
-
import { AtomicInput, AtomicButton } from "@umituz/react-native-design-system";
|
|
8
|
+
import { AtomicInput, AtomicButton } from "@umituz/react-native-design-system-atoms";
|
|
9
9
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
10
10
|
import { useAuth } from "../hooks/useAuth";
|
|
11
11
|
import { AuthErrorDisplay } from "./AuthErrorDisplay";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import React, { useState } from "react";
|
|
7
7
|
import { View, StyleSheet } from "react-native";
|
|
8
|
-
import { AtomicInput, AtomicButton } from "@umituz/react-native-design-system";
|
|
8
|
+
import { AtomicInput, AtomicButton } from "@umituz/react-native-design-system-atoms";
|
|
9
9
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
10
10
|
import {
|
|
11
11
|
validateEmail,
|
|
@@ -52,7 +52,11 @@ export function useAuth(): UseAuthResult {
|
|
|
52
52
|
const { user: firebaseUser, loading: firebaseLoading } = useFirebaseAuth();
|
|
53
53
|
|
|
54
54
|
// App-specific state
|
|
55
|
-
|
|
55
|
+
// Initialize isGuest from service if available
|
|
56
|
+
const [isGuest, setIsGuest] = useState(() => {
|
|
57
|
+
const service = getAuthService();
|
|
58
|
+
return service ? service.getIsGuestMode() : false;
|
|
59
|
+
});
|
|
56
60
|
const [error, setError] = useState<string | null>(null);
|
|
57
61
|
const [loading, setLoading] = useState(false);
|
|
58
62
|
const prevAuthState = useRef({ isAuthenticated: false, isGuest: false });
|
|
@@ -94,6 +98,17 @@ export function useAuth(): UseAuthResult {
|
|
|
94
98
|
}
|
|
95
99
|
}, [firebaseUser, isGuest]);
|
|
96
100
|
|
|
101
|
+
// Sync isGuest state with service on mount
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
const service = getAuthService();
|
|
104
|
+
if (service) {
|
|
105
|
+
const serviceIsGuest = service.getIsGuestMode();
|
|
106
|
+
if (serviceIsGuest !== isGuest) {
|
|
107
|
+
setIsGuest(serviceIsGuest);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}, []);
|
|
111
|
+
|
|
97
112
|
const signUp = useCallback(async (
|
|
98
113
|
email: string,
|
|
99
114
|
password: string,
|