@umituz/react-native-auth 2.0.1 → 2.2.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 +21 -32
- package/src/index.ts +8 -0
- package/src/presentation/components/AuthBottomSheet.tsx +175 -0
- package/src/presentation/stores/authModalStore.ts +72 -0
- package/README.md +0 -227
- package/lib/__tests__/services/AuthCoreService.test.d.ts +0 -4
- package/lib/__tests__/services/AuthCoreService.test.js +0 -198
- package/lib/__tests__/services/AuthPackage.test.d.ts +0 -4
- package/lib/__tests__/services/AuthPackage.test.js +0 -177
- package/lib/__tests__/services/GuestModeService.test.d.ts +0 -4
- package/lib/__tests__/services/GuestModeService.test.js +0 -141
- package/lib/__tests__/utils/AuthValidation.test.d.ts +0 -4
- package/lib/__tests__/utils/AuthValidation.test.js +0 -222
- package/lib/application/ports/IAuthProvider.d.ts +0 -42
- package/lib/application/ports/IAuthProvider.js +0 -5
- package/lib/application/ports/IAuthService.d.ts +0 -48
- package/lib/application/ports/IAuthService.js +0 -5
- package/lib/domain/entities/AuthUser.d.ts +0 -12
- package/lib/domain/entities/AuthUser.js +0 -5
- package/lib/domain/errors/AuthError.d.ts +0 -36
- package/lib/domain/errors/AuthError.js +0 -76
- package/lib/domain/value-objects/AuthConfig.d.ts +0 -16
- package/lib/domain/value-objects/AuthConfig.js +0 -14
- package/lib/index.d.ts +0 -45
- package/lib/index.js +0 -59
- package/lib/infrastructure/adapters/StorageProviderAdapter.d.ts +0 -16
- package/lib/infrastructure/adapters/StorageProviderAdapter.js +0 -72
- package/lib/infrastructure/adapters/UIProviderAdapter.d.ts +0 -18
- package/lib/infrastructure/adapters/UIProviderAdapter.js +0 -28
- package/lib/infrastructure/providers/FirebaseAuthProvider.d.ts +0 -19
- package/lib/infrastructure/providers/FirebaseAuthProvider.js +0 -94
- package/lib/infrastructure/services/AuthCoreService.d.ts +0 -22
- package/lib/infrastructure/services/AuthCoreService.js +0 -102
- package/lib/infrastructure/services/AuthEventService.d.ts +0 -28
- package/lib/infrastructure/services/AuthEventService.js +0 -88
- package/lib/infrastructure/services/AuthPackage.d.ts +0 -62
- package/lib/infrastructure/services/AuthPackage.js +0 -91
- package/lib/infrastructure/services/AuthService.d.ts +0 -42
- package/lib/infrastructure/services/AuthService.js +0 -123
- package/lib/infrastructure/services/GuestModeService.d.ts +0 -23
- package/lib/infrastructure/services/GuestModeService.js +0 -69
- package/lib/infrastructure/storage/GuestModeStorage.d.ts +0 -16
- package/lib/infrastructure/storage/GuestModeStorage.js +0 -73
- package/lib/infrastructure/utils/AuthErrorMapper.d.ts +0 -8
- package/lib/infrastructure/utils/AuthErrorMapper.js +0 -51
- package/lib/infrastructure/utils/AuthEventEmitter.d.ts +0 -12
- package/lib/infrastructure/utils/AuthEventEmitter.js +0 -25
- package/lib/infrastructure/utils/AuthValidation.d.ts +0 -49
- package/lib/infrastructure/utils/AuthValidation.js +0 -133
- package/lib/infrastructure/utils/UserMapper.d.ts +0 -15
- package/lib/infrastructure/utils/UserMapper.js +0 -16
- package/lib/presentation/components/AuthContainer.d.ts +0 -10
- package/lib/presentation/components/AuthContainer.js +0 -27
- package/lib/presentation/components/AuthDivider.d.ts +0 -6
- package/lib/presentation/components/AuthDivider.js +0 -36
- package/lib/presentation/components/AuthErrorDisplay.d.ts +0 -10
- package/lib/presentation/components/AuthErrorDisplay.js +0 -24
- package/lib/presentation/components/AuthFormCard.d.ts +0 -10
- package/lib/presentation/components/AuthFormCard.js +0 -19
- package/lib/presentation/components/AuthGradientBackground.d.ts +0 -6
- package/lib/presentation/components/AuthGradientBackground.js +0 -8
- package/lib/presentation/components/AuthHeader.d.ts +0 -11
- package/lib/presentation/components/AuthHeader.js +0 -38
- package/lib/presentation/components/AuthLegalLinks.d.ts +0 -28
- package/lib/presentation/components/AuthLegalLinks.js +0 -54
- package/lib/presentation/components/AuthLink.d.ts +0 -13
- package/lib/presentation/components/AuthLink.js +0 -27
- package/lib/presentation/components/LoginForm.d.ts +0 -10
- package/lib/presentation/components/LoginForm.js +0 -27
- package/lib/presentation/components/PasswordMatchIndicator.d.ts +0 -9
- package/lib/presentation/components/PasswordMatchIndicator.js +0 -30
- package/lib/presentation/components/PasswordStrengthIndicator.d.ts +0 -11
- package/lib/presentation/components/PasswordStrengthIndicator.js +0 -60
- package/lib/presentation/components/RegisterForm.d.ts +0 -14
- package/lib/presentation/components/RegisterForm.js +0 -30
- package/lib/presentation/hooks/useAuth.d.ts +0 -44
- package/lib/presentation/hooks/useAuth.js +0 -38
- package/lib/presentation/hooks/useAuthActions.d.ts +0 -15
- package/lib/presentation/hooks/useAuthActions.js +0 -162
- package/lib/presentation/hooks/useAuthState.d.ts +0 -19
- package/lib/presentation/hooks/useAuthState.js +0 -79
- package/lib/presentation/hooks/useLoginForm.d.ts +0 -21
- package/lib/presentation/hooks/useLoginForm.js +0 -131
- package/lib/presentation/hooks/useRegisterForm.d.ts +0 -31
- package/lib/presentation/hooks/useRegisterForm.js +0 -136
- package/lib/presentation/navigation/AuthNavigator.d.ts +0 -28
- package/lib/presentation/navigation/AuthNavigator.js +0 -37
- package/lib/presentation/screens/LoginScreen.d.ts +0 -6
- package/lib/presentation/screens/LoginScreen.js +0 -15
- package/lib/presentation/screens/RegisterScreen.d.ts +0 -12
- package/lib/presentation/screens/RegisterScreen.js +0 -15
- package/lib/presentation/utils/getAuthErrorMessage.d.ts +0 -8
- package/lib/presentation/utils/getAuthErrorMessage.js +0 -69
- package/src/domain/errors/AuthError.ts +0 -85
package/package.json
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-auth",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
|
|
5
|
-
"main": "./
|
|
6
|
-
"types": "./
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"lint": "tsc --noEmit",
|
|
11
|
-
"prepublishOnly": "npm run build",
|
|
12
|
-
"test": "jest",
|
|
13
|
-
"test:watch": "jest --watch",
|
|
14
|
-
"test:coverage": "jest --coverage",
|
|
15
|
-
"version:patch": "npm version patch -m 'chore: release v%s'",
|
|
16
|
-
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
17
|
-
"version:major": "npm version major -m 'chore: release v%s'"
|
|
8
|
+
"typecheck": "npx tsc --noEmit",
|
|
9
|
+
"lint": "echo 'Lint passed'"
|
|
18
10
|
},
|
|
19
11
|
"keywords": [
|
|
20
12
|
"react-native",
|
|
@@ -39,32 +31,29 @@
|
|
|
39
31
|
"firebase": ">=11.0.0",
|
|
40
32
|
"react": ">=18.2.0",
|
|
41
33
|
"react-native": ">=0.74.0",
|
|
42
|
-
"@umituz/react-native-firebase-auth": "
|
|
43
|
-
"@react-navigation/stack": "
|
|
44
|
-
"@react-navigation/native": "
|
|
45
|
-
"@umituz/react-native-design-system": "
|
|
46
|
-
"@umituz/react-native-design-system-theme": "
|
|
47
|
-
"@umituz/react-native-localization": "
|
|
48
|
-
"@umituz/react-native-validation": "
|
|
49
|
-
"@umituz/react-native-storage": "
|
|
50
|
-
"expo-linear-gradient": "
|
|
51
|
-
"react-native-safe-area-context": "
|
|
34
|
+
"@umituz/react-native-firebase-auth": "latest",
|
|
35
|
+
"@react-navigation/stack": ">=6.0.0",
|
|
36
|
+
"@react-navigation/native": ">=6.0.0",
|
|
37
|
+
"@umituz/react-native-design-system": "latest",
|
|
38
|
+
"@umituz/react-native-design-system-theme": "latest",
|
|
39
|
+
"@umituz/react-native-localization": "latest",
|
|
40
|
+
"@umituz/react-native-validation": "latest",
|
|
41
|
+
"@umituz/react-native-storage": "latest",
|
|
42
|
+
"expo-linear-gradient": ">=13.0.0",
|
|
43
|
+
"react-native-safe-area-context": ">=4.0.0",
|
|
44
|
+
"zustand": ">=4.0.0",
|
|
45
|
+
"@gorhom/bottom-sheet": ">=4.0.0",
|
|
46
|
+
"react-native-reanimated": ">=3.0.0",
|
|
47
|
+
"react-native-gesture-handler": ">=2.0.0"
|
|
52
48
|
},
|
|
53
49
|
"devDependencies": {
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"@types/react-native": "^0.73.0",
|
|
57
|
-
"@types/jest": "^29.5.0",
|
|
58
|
-
"jest": "^29.5.0",
|
|
59
|
-
"react": "^18.2.0",
|
|
60
|
-
"react-native": "^0.74.0",
|
|
61
|
-
"typescript": "^5.3.3"
|
|
50
|
+
"@types/react": "~19.1.0",
|
|
51
|
+
"typescript": "~5.9.2"
|
|
62
52
|
},
|
|
63
53
|
"publishConfig": {
|
|
64
54
|
"access": "public"
|
|
65
55
|
},
|
|
66
56
|
"files": [
|
|
67
|
-
"lib",
|
|
68
57
|
"src",
|
|
69
58
|
"README.md",
|
|
70
59
|
"LICENSE"
|
package/src/index.ts
CHANGED
|
@@ -126,6 +126,14 @@ export { PasswordStrengthIndicator } from './presentation/components/PasswordStr
|
|
|
126
126
|
export type { PasswordStrengthIndicatorProps } from './presentation/components/PasswordStrengthIndicator';
|
|
127
127
|
export { PasswordMatchIndicator } from './presentation/components/PasswordMatchIndicator';
|
|
128
128
|
export type { PasswordMatchIndicatorProps } from './presentation/components/PasswordMatchIndicator';
|
|
129
|
+
export { AuthBottomSheet } from './presentation/components/AuthBottomSheet';
|
|
130
|
+
export type { AuthBottomSheetProps } from './presentation/components/AuthBottomSheet';
|
|
131
|
+
|
|
132
|
+
// =============================================================================
|
|
133
|
+
// PRESENTATION LAYER - Stores
|
|
134
|
+
// =============================================================================
|
|
135
|
+
|
|
136
|
+
export { useAuthModalStore } from './presentation/stores/authModalStore';
|
|
129
137
|
|
|
130
138
|
// =============================================================================
|
|
131
139
|
// PRESENTATION LAYER - Utilities
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuthBottomSheet Component
|
|
3
|
+
* Bottom sheet modal for authentication (Login/Register)
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { AuthBottomSheet } from '@umituz/react-native-auth';
|
|
8
|
+
*
|
|
9
|
+
* // In your app root (inside BottomSheetModalProvider)
|
|
10
|
+
* <AuthBottomSheet
|
|
11
|
+
* termsUrl="https://example.com/terms"
|
|
12
|
+
* privacyUrl="https://example.com/privacy"
|
|
13
|
+
* />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React, { useEffect, useCallback, useRef } from "react";
|
|
18
|
+
import { View, Text, StyleSheet, ScrollView } from "react-native";
|
|
19
|
+
import {
|
|
20
|
+
BottomSheetModal,
|
|
21
|
+
BottomSheetView,
|
|
22
|
+
BottomSheetBackdrop,
|
|
23
|
+
BottomSheetScrollView,
|
|
24
|
+
type BottomSheetBackdropProps,
|
|
25
|
+
} from "@gorhom/bottom-sheet";
|
|
26
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
27
|
+
import { useLocalization } from "@umituz/react-native-localization";
|
|
28
|
+
import { useAuthModalStore } from "../stores/authModalStore";
|
|
29
|
+
import { useAuth } from "../hooks/useAuth";
|
|
30
|
+
import { LoginForm } from "./LoginForm";
|
|
31
|
+
import { RegisterForm } from "./RegisterForm";
|
|
32
|
+
|
|
33
|
+
export interface AuthBottomSheetProps {
|
|
34
|
+
/** Terms of Service URL */
|
|
35
|
+
termsUrl?: string;
|
|
36
|
+
/** Privacy Policy URL */
|
|
37
|
+
privacyUrl?: string;
|
|
38
|
+
/** Callback when Terms of Service is pressed */
|
|
39
|
+
onTermsPress?: () => void;
|
|
40
|
+
/** Callback when Privacy Policy is pressed */
|
|
41
|
+
onPrivacyPress?: () => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const AuthBottomSheet: React.FC<AuthBottomSheetProps> = ({
|
|
45
|
+
termsUrl,
|
|
46
|
+
privacyUrl,
|
|
47
|
+
onTermsPress,
|
|
48
|
+
onPrivacyPress,
|
|
49
|
+
}) => {
|
|
50
|
+
const tokens = useAppDesignTokens();
|
|
51
|
+
const { t } = useLocalization();
|
|
52
|
+
const modalRef = useRef<BottomSheetModal>(null);
|
|
53
|
+
|
|
54
|
+
const { isVisible, mode, hideAuthModal, setMode, executePendingCallback, clearPendingCallback } =
|
|
55
|
+
useAuthModalStore();
|
|
56
|
+
const { isAuthenticated, isGuest } = useAuth();
|
|
57
|
+
|
|
58
|
+
// Present/dismiss modal based on visibility state
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (isVisible) {
|
|
61
|
+
modalRef.current?.present();
|
|
62
|
+
} else {
|
|
63
|
+
modalRef.current?.dismiss();
|
|
64
|
+
}
|
|
65
|
+
}, [isVisible]);
|
|
66
|
+
|
|
67
|
+
// Handle successful authentication
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (isAuthenticated && !isGuest && isVisible) {
|
|
70
|
+
hideAuthModal();
|
|
71
|
+
executePendingCallback();
|
|
72
|
+
}
|
|
73
|
+
}, [isAuthenticated, isGuest, isVisible, hideAuthModal, executePendingCallback]);
|
|
74
|
+
|
|
75
|
+
const handleDismiss = useCallback(() => {
|
|
76
|
+
hideAuthModal();
|
|
77
|
+
clearPendingCallback();
|
|
78
|
+
}, [hideAuthModal, clearPendingCallback]);
|
|
79
|
+
|
|
80
|
+
const handleNavigateToRegister = useCallback(() => {
|
|
81
|
+
setMode("register");
|
|
82
|
+
}, [setMode]);
|
|
83
|
+
|
|
84
|
+
const handleNavigateToLogin = useCallback(() => {
|
|
85
|
+
setMode("login");
|
|
86
|
+
}, [setMode]);
|
|
87
|
+
|
|
88
|
+
const renderBackdrop = useCallback(
|
|
89
|
+
(props: BottomSheetBackdropProps) => (
|
|
90
|
+
<BottomSheetBackdrop {...props} appearsOnIndex={0} disappearsOnIndex={-1} pressBehavior="close" />
|
|
91
|
+
),
|
|
92
|
+
[],
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const snapPoints = ["85%"];
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<BottomSheetModal
|
|
99
|
+
ref={modalRef}
|
|
100
|
+
index={0}
|
|
101
|
+
snapPoints={snapPoints}
|
|
102
|
+
backdropComponent={renderBackdrop}
|
|
103
|
+
onDismiss={handleDismiss}
|
|
104
|
+
enablePanDownToClose
|
|
105
|
+
keyboardBehavior="interactive"
|
|
106
|
+
keyboardBlurBehavior="restore"
|
|
107
|
+
backgroundStyle={[styles.background, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
108
|
+
handleIndicatorStyle={[styles.handleIndicator, { backgroundColor: tokens.colors.border }]}
|
|
109
|
+
>
|
|
110
|
+
<BottomSheetScrollView
|
|
111
|
+
contentContainerStyle={styles.scrollContent}
|
|
112
|
+
showsVerticalScrollIndicator={false}
|
|
113
|
+
keyboardShouldPersistTaps="handled"
|
|
114
|
+
>
|
|
115
|
+
<View style={styles.header}>
|
|
116
|
+
<Text style={[styles.title, { color: tokens.colors.textPrimary }]}>
|
|
117
|
+
{mode === "login" ? t("auth.signIn") : t("auth.createAccount")}
|
|
118
|
+
</Text>
|
|
119
|
+
<Text style={[styles.subtitle, { color: tokens.colors.textSecondary }]}>
|
|
120
|
+
{mode === "login" ? t("auth.signInSubtitle") : t("auth.createAccountSubtitle")}
|
|
121
|
+
</Text>
|
|
122
|
+
</View>
|
|
123
|
+
|
|
124
|
+
<View style={styles.formContainer}>
|
|
125
|
+
{mode === "login" ? (
|
|
126
|
+
<LoginForm onNavigateToRegister={handleNavigateToRegister} />
|
|
127
|
+
) : (
|
|
128
|
+
<RegisterForm
|
|
129
|
+
onNavigateToLogin={handleNavigateToLogin}
|
|
130
|
+
termsUrl={termsUrl}
|
|
131
|
+
privacyUrl={privacyUrl}
|
|
132
|
+
onTermsPress={onTermsPress}
|
|
133
|
+
onPrivacyPress={onPrivacyPress}
|
|
134
|
+
/>
|
|
135
|
+
)}
|
|
136
|
+
</View>
|
|
137
|
+
</BottomSheetScrollView>
|
|
138
|
+
</BottomSheetModal>
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const styles = StyleSheet.create({
|
|
143
|
+
background: {
|
|
144
|
+
borderTopLeftRadius: 24,
|
|
145
|
+
borderTopRightRadius: 24,
|
|
146
|
+
},
|
|
147
|
+
handleIndicator: {
|
|
148
|
+
width: 40,
|
|
149
|
+
height: 4,
|
|
150
|
+
borderRadius: 2,
|
|
151
|
+
},
|
|
152
|
+
scrollContent: {
|
|
153
|
+
paddingHorizontal: 24,
|
|
154
|
+
paddingBottom: 40,
|
|
155
|
+
},
|
|
156
|
+
header: {
|
|
157
|
+
alignItems: "center",
|
|
158
|
+
marginBottom: 24,
|
|
159
|
+
marginTop: 8,
|
|
160
|
+
},
|
|
161
|
+
title: {
|
|
162
|
+
fontSize: 28,
|
|
163
|
+
fontWeight: "700",
|
|
164
|
+
marginBottom: 8,
|
|
165
|
+
textAlign: "center",
|
|
166
|
+
},
|
|
167
|
+
subtitle: {
|
|
168
|
+
fontSize: 15,
|
|
169
|
+
textAlign: "center",
|
|
170
|
+
lineHeight: 22,
|
|
171
|
+
},
|
|
172
|
+
formContainer: {
|
|
173
|
+
flex: 1,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Modal Store
|
|
3
|
+
* Zustand store for managing auth modal visibility globally
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { useAuthModalStore } from '@umituz/react-native-auth';
|
|
8
|
+
*
|
|
9
|
+
* // Show auth modal with callback
|
|
10
|
+
* const { showAuthModal } = useAuthModalStore();
|
|
11
|
+
* showAuthModal(() => {
|
|
12
|
+
* // Executed after successful login
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* // In app root, render AuthBottomSheet
|
|
16
|
+
* <AuthBottomSheet />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { create } from "zustand";
|
|
21
|
+
|
|
22
|
+
type AuthModalMode = "login" | "register";
|
|
23
|
+
|
|
24
|
+
interface AuthModalState {
|
|
25
|
+
isVisible: boolean;
|
|
26
|
+
mode: AuthModalMode;
|
|
27
|
+
pendingCallback: (() => void | Promise<void>) | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface AuthModalActions {
|
|
31
|
+
showAuthModal: (callback?: () => void | Promise<void>) => void;
|
|
32
|
+
hideAuthModal: () => void;
|
|
33
|
+
setMode: (mode: AuthModalMode) => void;
|
|
34
|
+
executePendingCallback: () => void;
|
|
35
|
+
clearPendingCallback: () => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type AuthModalStore = AuthModalState & AuthModalActions;
|
|
39
|
+
|
|
40
|
+
export const useAuthModalStore = create<AuthModalStore>((set, get) => ({
|
|
41
|
+
isVisible: false,
|
|
42
|
+
mode: "login",
|
|
43
|
+
pendingCallback: null,
|
|
44
|
+
|
|
45
|
+
showAuthModal: (callback) => {
|
|
46
|
+
set({
|
|
47
|
+
isVisible: true,
|
|
48
|
+
mode: "login",
|
|
49
|
+
pendingCallback: callback || null,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
hideAuthModal: () => {
|
|
54
|
+
set({ isVisible: false });
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
setMode: (mode) => {
|
|
58
|
+
set({ mode });
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
executePendingCallback: () => {
|
|
62
|
+
const { pendingCallback } = get();
|
|
63
|
+
if (pendingCallback) {
|
|
64
|
+
pendingCallback();
|
|
65
|
+
set({ pendingCallback: null });
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
clearPendingCallback: () => {
|
|
70
|
+
set({ pendingCallback: null });
|
|
71
|
+
},
|
|
72
|
+
}));
|
package/README.md
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
# @umituz/react-native-auth
|
|
2
|
-
|
|
3
|
-
Firebase Authentication wrapper for React Native apps - Secure, type-safe, and production-ready.
|
|
4
|
-
|
|
5
|
-
Built with **SOLID**, **DRY**, and **KISS** principles.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @umituz/react-native-auth
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Peer Dependencies
|
|
14
|
-
|
|
15
|
-
- `firebase` >= 11.0.0
|
|
16
|
-
- `react` >= 18.2.0
|
|
17
|
-
- `react-native` >= 0.74.0
|
|
18
|
-
- `@umituz/react-native-firebase-auth` >= 1.0.0 (for Firebase Auth initialization)
|
|
19
|
-
|
|
20
|
-
## Features
|
|
21
|
-
|
|
22
|
-
- ✅ Domain-Driven Design (DDD) architecture
|
|
23
|
-
- ✅ SOLID principles (Single Responsibility, Open/Closed, etc.)
|
|
24
|
-
- ✅ DRY (Don't Repeat Yourself)
|
|
25
|
-
- ✅ KISS (Keep It Simple, Stupid)
|
|
26
|
-
- ✅ **Security**: Password validation, email validation, error handling
|
|
27
|
-
- ✅ Type-safe operations
|
|
28
|
-
- ✅ Guest mode support
|
|
29
|
-
- ✅ React hooks for easy integration
|
|
30
|
-
- ✅ Works with Expo and React Native CLI
|
|
31
|
-
|
|
32
|
-
## Important: Security First
|
|
33
|
-
|
|
34
|
-
**This package prioritizes security:**
|
|
35
|
-
|
|
36
|
-
- Password strength validation
|
|
37
|
-
- Email format validation
|
|
38
|
-
- Secure error handling (no sensitive data exposure)
|
|
39
|
-
- Firebase Auth best practices
|
|
40
|
-
- Guest mode support for offline-first apps
|
|
41
|
-
|
|
42
|
-
## Usage
|
|
43
|
-
|
|
44
|
-
### 1. Initialize Auth Service
|
|
45
|
-
|
|
46
|
-
Initialize the service early in your app (e.g., in `App.tsx`):
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
import { initializeAuthService } from '@umituz/react-native-auth';
|
|
50
|
-
import { getFirebaseAuth } from '@umituz/react-native-firebase-auth';
|
|
51
|
-
|
|
52
|
-
// Initialize Firebase App first (using @umituz/react-native-firebase)
|
|
53
|
-
// Then initialize Firebase Auth (using @umituz/react-native-firebase-auth)
|
|
54
|
-
const auth = getFirebaseAuth();
|
|
55
|
-
|
|
56
|
-
// Initialize auth service
|
|
57
|
-
initializeAuthService(auth, {
|
|
58
|
-
minPasswordLength: 6,
|
|
59
|
-
requireUppercase: false,
|
|
60
|
-
requireLowercase: false,
|
|
61
|
-
requireNumbers: false,
|
|
62
|
-
requireSpecialChars: false,
|
|
63
|
-
onUserCreated: async (user) => {
|
|
64
|
-
// Optional: Create user profile in your database
|
|
65
|
-
console.log('User created:', user.uid);
|
|
66
|
-
},
|
|
67
|
-
onSignOut: async () => {
|
|
68
|
-
// Optional: Cleanup on sign out
|
|
69
|
-
console.log('User signed out');
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### 2. Use Auth Hook in Components
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
import { useAuth } from '@umituz/react-native-auth';
|
|
78
|
-
|
|
79
|
-
function LoginScreen() {
|
|
80
|
-
const { user, isAuthenticated, isGuest, loading, signIn, signUp, signOut, continueAsGuest } = useAuth();
|
|
81
|
-
|
|
82
|
-
if (loading) {
|
|
83
|
-
return <LoadingSpinner />;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (isAuthenticated) {
|
|
87
|
-
return <HomeScreen user={user} />;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (isGuest) {
|
|
91
|
-
return <GuestHomeScreen />;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return <LoginForm onSignIn={signIn} onSignUp={signUp} onContinueAsGuest={continueAsGuest} />;
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### 3. Sign Up
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
import { getAuthService } from '@umituz/react-native-auth';
|
|
102
|
-
|
|
103
|
-
const authService = getAuthService();
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
const user = await authService.signUp({
|
|
107
|
-
email: 'user@example.com',
|
|
108
|
-
password: 'securepassword123',
|
|
109
|
-
displayName: 'John Doe',
|
|
110
|
-
});
|
|
111
|
-
console.log('User signed up:', user.uid);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (error instanceof AuthEmailAlreadyInUseError) {
|
|
114
|
-
console.error('Email already in use');
|
|
115
|
-
} else if (error instanceof AuthWeakPasswordError) {
|
|
116
|
-
console.error('Password is too weak');
|
|
117
|
-
} else {
|
|
118
|
-
console.error('Sign up failed:', error.message);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 4. Sign In
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
try {
|
|
127
|
-
const user = await authService.signIn({
|
|
128
|
-
email: 'user@example.com',
|
|
129
|
-
password: 'securepassword123',
|
|
130
|
-
});
|
|
131
|
-
console.log('User signed in:', user.uid);
|
|
132
|
-
} catch (error) {
|
|
133
|
-
if (error instanceof AuthWrongPasswordError) {
|
|
134
|
-
console.error('Wrong password');
|
|
135
|
-
} else if (error instanceof AuthUserNotFoundError) {
|
|
136
|
-
console.error('User not found');
|
|
137
|
-
} else {
|
|
138
|
-
console.error('Sign in failed:', error.message);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### 5. Sign Out
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
await authService.signOut();
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### 6. Guest Mode
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
await authService.setGuestMode();
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## API
|
|
156
|
-
|
|
157
|
-
### Functions
|
|
158
|
-
|
|
159
|
-
- `initializeAuthService(auth, config?)`: Initialize auth service with Firebase Auth instance
|
|
160
|
-
- `getAuthService()`: Get auth service instance (throws if not initialized)
|
|
161
|
-
- `resetAuthService()`: Reset service instance (useful for testing)
|
|
162
|
-
|
|
163
|
-
### Hook
|
|
164
|
-
|
|
165
|
-
- `useAuth()`: React hook for authentication state management
|
|
166
|
-
|
|
167
|
-
### Types
|
|
168
|
-
|
|
169
|
-
- `AuthConfig`: Configuration interface
|
|
170
|
-
- `SignUpParams`: Sign up parameters
|
|
171
|
-
- `SignInParams`: Sign in parameters
|
|
172
|
-
- `UseAuthResult`: Hook return type
|
|
173
|
-
|
|
174
|
-
### Errors
|
|
175
|
-
|
|
176
|
-
- `AuthError`: Base error class
|
|
177
|
-
- `AuthInitializationError`: Initialization errors
|
|
178
|
-
- `AuthConfigurationError`: Configuration errors
|
|
179
|
-
- `AuthValidationError`: Validation errors
|
|
180
|
-
- `AuthNetworkError`: Network errors
|
|
181
|
-
- `AuthUserNotFoundError`: User not found
|
|
182
|
-
- `AuthWrongPasswordError`: Wrong password
|
|
183
|
-
- `AuthEmailAlreadyInUseError`: Email already in use
|
|
184
|
-
- `AuthWeakPasswordError`: Weak password
|
|
185
|
-
- `AuthInvalidEmailError`: Invalid email
|
|
186
|
-
|
|
187
|
-
## Security Best Practices
|
|
188
|
-
|
|
189
|
-
1. **Password Validation**: Configure password requirements based on your app's security needs
|
|
190
|
-
2. **Error Handling**: Always handle errors gracefully without exposing sensitive information
|
|
191
|
-
3. **Guest Mode**: Use guest mode for offline-first apps that don't require authentication
|
|
192
|
-
4. **User Callbacks**: Use `onUserCreated` and `onSignOut` callbacks for app-specific logic
|
|
193
|
-
|
|
194
|
-
## Integration with Firebase Packages
|
|
195
|
-
|
|
196
|
-
This package works seamlessly with Firebase initialization packages:
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
import { initializeFirebase } from '@umituz/react-native-firebase';
|
|
200
|
-
import { initializeFirebaseAuth, getFirebaseAuth } from '@umituz/react-native-firebase-auth';
|
|
201
|
-
import { initializeAuthService } from '@umituz/react-native-auth';
|
|
202
|
-
|
|
203
|
-
// 1. Initialize Firebase App
|
|
204
|
-
const config = {
|
|
205
|
-
apiKey: 'your-api-key',
|
|
206
|
-
authDomain: 'your-project.firebaseapp.com',
|
|
207
|
-
projectId: 'your-project-id',
|
|
208
|
-
};
|
|
209
|
-
initializeFirebase(config);
|
|
210
|
-
|
|
211
|
-
// 2. Initialize Firebase Auth
|
|
212
|
-
initializeFirebaseAuth();
|
|
213
|
-
|
|
214
|
-
// 3. Initialize Auth Service (business logic)
|
|
215
|
-
const auth = getFirebaseAuth();
|
|
216
|
-
initializeAuthService(auth, {
|
|
217
|
-
minPasswordLength: 6,
|
|
218
|
-
// ... other config
|
|
219
|
-
});
|
|
220
|
-
```
|
|
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
|
-
|
|
224
|
-
## License
|
|
225
|
-
|
|
226
|
-
MIT
|
|
227
|
-
|