@umituz/react-native-auth 3.4.32 → 3.4.34
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 +347 -348
- package/package.json +2 -3
- package/src/application/README.md +323 -442
- package/src/domain/ConfigAndErrors.md +296 -431
- package/src/domain/README.md +361 -210
- package/src/domain/entities/AuthUser.md +231 -372
- package/src/domain/entities/UserProfile.md +271 -441
- package/src/index.ts +35 -0
- package/src/infrastructure/README.md +388 -444
- package/src/infrastructure/services/README.md +386 -312
- package/src/infrastructure/utils/validation/BaseValidators.ts +35 -0
- package/src/infrastructure/utils/validation/CollectionValidators.ts +56 -0
- package/src/infrastructure/utils/validation/DateValidators.ts +63 -0
- package/src/infrastructure/utils/validation/FormValidators.ts +22 -0
- package/src/infrastructure/utils/validation/NumberValidators.ts +55 -0
- package/src/infrastructure/utils/validation/StringValidators.ts +55 -0
- package/src/infrastructure/utils/validation/sanitization.ts +98 -0
- package/src/infrastructure/utils/validation/types.ts +15 -0
- package/src/presentation/README.md +631 -563
- package/src/presentation/components/ProfileComponents.md +307 -504
- package/src/presentation/components/README.md +254 -92
- package/src/presentation/hooks/README.md +247 -83
- package/src/presentation/hooks/useAccountManagement.md +295 -344
- package/src/presentation/hooks/useAuth.md +271 -227
- package/src/presentation/hooks/useAuthBottomSheet.md +417 -367
- package/src/presentation/hooks/useAuthRequired.md +308 -194
- package/src/presentation/hooks/useProfileUpdate.md +251 -279
- package/src/presentation/hooks/useSocialLogin.md +312 -287
- package/src/presentation/hooks/useUserProfile.md +259 -192
- package/src/presentation/screens/README.md +151 -153
|
@@ -1,619 +1,684 @@
|
|
|
1
1
|
# Presentation Layer
|
|
2
2
|
|
|
3
|
-
React
|
|
3
|
+
React components, hooks, providers, stores, and navigation for authentication UI.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
│ └── AuthProvider.tsx # Auth context provider
|
|
11
|
-
├── hooks/
|
|
12
|
-
│ ├── useAuth.ts # Main auth hook
|
|
13
|
-
│ ├── useAuthRequired.ts # Auth-required hook
|
|
14
|
-
│ ├── useRequireAuth.ts # Route protection hook
|
|
15
|
-
│ ├── useUserProfile.ts # User profile hook
|
|
16
|
-
│ ├── useProfileUpdate.ts # Profile update hook
|
|
17
|
-
│ ├── useProfileEdit.ts # Profile edit hook
|
|
18
|
-
│ ├── useAccountManagement.ts # Account management hook
|
|
19
|
-
│ ├── useSocialLogin.ts # Social login hook
|
|
20
|
-
│ ├── useGoogleAuth.ts # Google auth hook
|
|
21
|
-
│ ├── useAppleAuth.ts # Apple auth hook
|
|
22
|
-
│ ├── useAuthBottomSheet.ts # Auth bottom sheet hook
|
|
23
|
-
│ ├── useLoginForm.ts # Login form hook
|
|
24
|
-
│ ├── useRegisterForm.ts # Register form hook
|
|
25
|
-
│ └── mutations/
|
|
26
|
-
│ └── useAuthMutations.ts # Auth mutation hooks
|
|
27
|
-
├── components/
|
|
28
|
-
│ ├── AuthContainer.tsx # Main container
|
|
29
|
-
│ ├── AuthHeader.tsx # Header component
|
|
30
|
-
│ ├── AuthFormCard.tsx # Form card
|
|
31
|
-
│ ├── LoginForm.tsx # Login form
|
|
32
|
-
│ ├── RegisterForm.tsx # Register form
|
|
33
|
-
│ ├── EditProfileForm.tsx # Edit profile form
|
|
34
|
-
│ ├── EditProfileAvatar.tsx # Edit profile avatar
|
|
35
|
-
│ ├── PasswordStrengthIndicator.tsx # Password strength
|
|
36
|
-
│ ├── PasswordMatchIndicator.tsx # Password match
|
|
37
|
-
│ ├── SocialLoginButtons.tsx # Social login buttons
|
|
38
|
-
│ ├── ProfileSection.tsx # Profile section
|
|
39
|
-
│ ├── AccountActions.tsx # Account actions
|
|
40
|
-
│ ├── AuthBottomSheet.tsx # Bottom sheet modal
|
|
41
|
-
│ ├── AuthLegalLinks.tsx # Legal links
|
|
42
|
-
│ ├── AuthDivider.tsx # Divider
|
|
43
|
-
│ ├── AuthLink.tsx # Navigation link
|
|
44
|
-
│ ├── AuthErrorDisplay.tsx # Error display
|
|
45
|
-
│ ├── AuthBackground.tsx # Background component
|
|
46
|
-
│ └── icons/
|
|
47
|
-
│ ├── GoogleIconSvg.tsx # Google icon
|
|
48
|
-
│ └── AppleIconSvg.tsx # Apple icon
|
|
49
|
-
├── screens/
|
|
50
|
-
│ ├── LoginScreen.tsx # Login screen
|
|
51
|
-
│ ├── RegisterScreen.tsx # Register screen
|
|
52
|
-
│ ├── AccountScreen.tsx # Account screen
|
|
53
|
-
│ └── EditProfileScreen.tsx # Edit profile screen
|
|
54
|
-
├── navigation/
|
|
55
|
-
│ └── AuthNavigator.tsx # Auth navigator
|
|
56
|
-
├── stores/
|
|
57
|
-
│ ├── authStore.ts # Auth state store (Zustand)
|
|
58
|
-
│ └── authModalStore.ts # Auth modal store
|
|
59
|
-
└── utils/
|
|
60
|
-
└── accountDeleteHandler.util.ts # Account deletion handler
|
|
61
|
-
```
|
|
7
|
+
## Strategy
|
|
8
|
+
|
|
9
|
+
**Purpose**: Provides all UI components and React hooks for authentication features in React Native applications.
|
|
62
10
|
|
|
63
|
-
|
|
11
|
+
**When to Use**:
|
|
12
|
+
- Building authentication UI
|
|
13
|
+
- Need auth hooks and components
|
|
14
|
+
- Integrating auth into navigation
|
|
15
|
+
- Managing auth state in UI
|
|
16
|
+
|
|
17
|
+
**Location**: `src/presentation/`
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Structure
|
|
64
22
|
|
|
65
|
-
|
|
23
|
+
### Providers
|
|
24
|
+
**providers/AuthProvider.tsx** - Root auth context provider
|
|
25
|
+
|
|
26
|
+
### Hooks
|
|
27
|
+
**hooks/useAuth.ts** - Main auth hook
|
|
28
|
+
**hooks/useAuthRequired.ts** - Auth requirement checking
|
|
29
|
+
**hooks/useUserProfile.ts** - Profile data fetching
|
|
30
|
+
**hooks/useProfileUpdate.ts** - Profile updates
|
|
31
|
+
**hooks/useAccountManagement.ts** - Account operations
|
|
32
|
+
**hooks/useSocialLogin.ts** - Social auth management
|
|
33
|
+
**hooks/useAuthBottomSheet.ts** - Modal management
|
|
34
|
+
|
|
35
|
+
### Components
|
|
36
|
+
**components/** - Pre-built UI components
|
|
37
|
+
- Form components (LoginForm, RegisterForm)
|
|
38
|
+
- Password indicators
|
|
39
|
+
- Social login buttons
|
|
40
|
+
- Profile components
|
|
41
|
+
- Layout components
|
|
42
|
+
|
|
43
|
+
### Screens
|
|
44
|
+
**screens/** - Complete authentication screens
|
|
45
|
+
- LoginScreen
|
|
46
|
+
- RegisterScreen
|
|
47
|
+
- AccountScreen
|
|
48
|
+
- EditProfileScreen
|
|
49
|
+
|
|
50
|
+
### Stores
|
|
51
|
+
**stores/authStore.ts** - Auth state (Zustand)
|
|
52
|
+
**stores/authModalStore.ts** - Modal state
|
|
66
53
|
|
|
67
54
|
---
|
|
68
55
|
|
|
69
|
-
|
|
56
|
+
## Providers
|
|
70
57
|
|
|
71
|
-
|
|
58
|
+
### AuthProvider
|
|
72
59
|
|
|
73
|
-
Root provider that wraps
|
|
60
|
+
**PURPOSE**: Root provider that wraps app and provides authentication context
|
|
74
61
|
|
|
62
|
+
**IMPORT PATH**:
|
|
75
63
|
```typescript
|
|
76
64
|
import { AuthProvider } from '@umituz/react-native-auth';
|
|
77
|
-
|
|
78
|
-
function App() {
|
|
79
|
-
return (
|
|
80
|
-
<AuthProvider>
|
|
81
|
-
<AppNavigator />
|
|
82
|
-
</AuthProvider>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
65
|
```
|
|
86
66
|
|
|
67
|
+
**Rules**:
|
|
68
|
+
- MUST wrap app root
|
|
69
|
+
- MUST initialize before using hooks
|
|
70
|
+
- MUST be ancestor of all auth hooks
|
|
71
|
+
- MUST not nest multiple providers
|
|
72
|
+
- MUST configure properly
|
|
73
|
+
|
|
74
|
+
**MUST NOT**:
|
|
75
|
+
- Skip provider initialization
|
|
76
|
+
- Use hooks without provider
|
|
77
|
+
- Create multiple instances
|
|
78
|
+
- Nest AuthProvider inside itself
|
|
79
|
+
|
|
87
80
|
---
|
|
88
81
|
|
|
89
|
-
|
|
82
|
+
## Hooks
|
|
90
83
|
|
|
91
|
-
|
|
84
|
+
### Core Hooks
|
|
92
85
|
|
|
93
|
-
|
|
86
|
+
#### useAuth
|
|
94
87
|
|
|
95
|
-
Main authentication hook for
|
|
88
|
+
**PURPOSE**: Main authentication hook for auth state and operations
|
|
96
89
|
|
|
90
|
+
**IMPORT PATH**:
|
|
97
91
|
```typescript
|
|
98
92
|
import { useAuth } from '@umituz/react-native-auth';
|
|
99
|
-
|
|
100
|
-
function MyComponent() {
|
|
101
|
-
const {
|
|
102
|
-
user,
|
|
103
|
-
userId,
|
|
104
|
-
userType,
|
|
105
|
-
loading,
|
|
106
|
-
isAuthReady,
|
|
107
|
-
isAnonymous,
|
|
108
|
-
isAuthenticated,
|
|
109
|
-
error,
|
|
110
|
-
signIn,
|
|
111
|
-
signUp,
|
|
112
|
-
signOut,
|
|
113
|
-
continueAnonymously,
|
|
114
|
-
setError,
|
|
115
|
-
} = useAuth();
|
|
116
|
-
|
|
117
|
-
if (loading) return <LoadingSpinner />;
|
|
118
|
-
|
|
119
|
-
if (!isAuthenticated) {
|
|
120
|
-
return <LoginScreen />;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return (
|
|
124
|
-
<View>
|
|
125
|
-
<Text>Welcome, {user?.email}</Text>
|
|
126
|
-
<Button onPress={signOut}>Sign Out</Button>
|
|
127
|
-
</View>
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
93
|
```
|
|
131
94
|
|
|
132
|
-
|
|
95
|
+
**RETURNS**:
|
|
96
|
+
- `user: AuthUser | null` - Current user
|
|
97
|
+
- `userId: string | null` - User ID
|
|
98
|
+
- `loading: boolean` - Loading state
|
|
99
|
+
- `isAuthReady: boolean` - Auth initialized
|
|
100
|
+
- `isAuthenticated: boolean` - Authenticated status
|
|
101
|
+
- `isAnonymous: boolean` - Anonymous user
|
|
102
|
+
- `signIn()` - Sign in function
|
|
103
|
+
- `signUp()` - Sign up function
|
|
104
|
+
- `signOut()` - Sign out function
|
|
105
|
+
- `setError()` - Set error state
|
|
106
|
+
|
|
107
|
+
**Rules**:
|
|
108
|
+
- MUST use within AuthProvider
|
|
109
|
+
- MUST handle loading state
|
|
110
|
+
- MUST check auth readiness
|
|
111
|
+
- MUST handle errors appropriately
|
|
112
|
+
- MUST not call operations during loading
|
|
113
|
+
|
|
114
|
+
**MUST NOT**:
|
|
115
|
+
- Use outside AuthProvider
|
|
116
|
+
- Skip loading checks
|
|
117
|
+
- Ignore error handling
|
|
118
|
+
- Call operations prematurely
|
|
119
|
+
|
|
120
|
+
**Documentation**: `hooks/useAuth.md`
|
|
133
121
|
|
|
134
|
-
|
|
122
|
+
---
|
|
135
123
|
|
|
124
|
+
#### useAuthRequired
|
|
125
|
+
|
|
126
|
+
**PURPOSE**: Check auth requirements and show modal if needed
|
|
127
|
+
|
|
128
|
+
**IMPORT PATH**:
|
|
136
129
|
```typescript
|
|
137
130
|
import { useAuthRequired } from '@umituz/react-native-auth';
|
|
138
|
-
|
|
139
|
-
function LikeButton() {
|
|
140
|
-
const { isAllowed, checkAndRequireAuth } = useAuthRequired();
|
|
141
|
-
|
|
142
|
-
const handleLike = () => {
|
|
143
|
-
if (checkAndRequireAuth()) {
|
|
144
|
-
// User is authenticated, proceed
|
|
145
|
-
likePost();
|
|
146
|
-
}
|
|
147
|
-
// Otherwise, auth modal is shown automatically
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
<Button onPress={handleLike}>
|
|
152
|
-
{isAllowed ? 'Like' : 'Sign in to like'}
|
|
153
|
-
</Button>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
131
|
```
|
|
157
132
|
|
|
158
|
-
|
|
133
|
+
**RETURNS**:
|
|
134
|
+
- `isAllowed: boolean` - Operation allowed
|
|
135
|
+
- `checkAndRequireAuth()` - Check and show modal
|
|
136
|
+
|
|
137
|
+
**Rules**:
|
|
138
|
+
- MUST use before protected operations
|
|
139
|
+
- MUST show modal for anonymous users
|
|
140
|
+
- MUST execute callback after auth
|
|
141
|
+
- MUST handle modal state
|
|
159
142
|
|
|
160
|
-
|
|
143
|
+
**MUST NOT**:
|
|
144
|
+
- Skip auth check
|
|
145
|
+
- Show modal for authenticated users
|
|
146
|
+
- Execute operation without auth
|
|
147
|
+
- Ignore modal state
|
|
161
148
|
|
|
149
|
+
**Documentation**: `hooks/useAuthRequired.md`
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
#### useRequireAuth
|
|
154
|
+
|
|
155
|
+
**PURPOSE**: Get userId or throw if not authenticated
|
|
156
|
+
|
|
157
|
+
**IMPORT PATH**:
|
|
162
158
|
```typescript
|
|
163
159
|
import { useRequireAuth } from '@umituz/react-native-auth';
|
|
160
|
+
```
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
**RETURNS**:
|
|
163
|
+
- `userId: string` - Guaranteed user ID
|
|
167
164
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
165
|
+
**Rules**:
|
|
166
|
+
- MUST only use in protected components
|
|
167
|
+
- MUST handle thrown error
|
|
168
|
+
- MUST guarantee parent auth check
|
|
169
|
+
- MUST not use in optional auth contexts
|
|
171
170
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
**MUST NOT**:
|
|
172
|
+
- Use in public components
|
|
173
|
+
- Skip error handling
|
|
174
|
+
- Assume auth without check
|
|
175
|
+
- Use for optional features
|
|
175
176
|
|
|
176
|
-
|
|
177
|
+
---
|
|
177
178
|
|
|
178
|
-
###
|
|
179
|
+
### User Profile Hooks
|
|
179
180
|
|
|
180
|
-
|
|
181
|
+
#### useUserProfile
|
|
181
182
|
|
|
183
|
+
**PURPOSE**: Fetch user profile data for display
|
|
184
|
+
|
|
185
|
+
**IMPORT PATH**:
|
|
182
186
|
```typescript
|
|
183
187
|
import { useUserProfile } from '@umituz/react-native-auth';
|
|
184
|
-
|
|
185
|
-
function ProfileHeader() {
|
|
186
|
-
const profile = useUserProfile({
|
|
187
|
-
accountRoute: '/account',
|
|
188
|
-
anonymousDisplayName: 'Guest User',
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
if (!profile) return <LoadingSpinner />;
|
|
192
|
-
|
|
193
|
-
return (
|
|
194
|
-
<View>
|
|
195
|
-
<Avatar source={{ uri: profile.avatarUrl }} />
|
|
196
|
-
<Text>{profile.displayName}</Text>
|
|
197
|
-
{profile.isAnonymous && <Text>Guest</Text>}
|
|
198
|
-
</View>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
188
|
```
|
|
202
189
|
|
|
203
|
-
|
|
190
|
+
**PARAMETERS**:
|
|
191
|
+
- `accountRoute` - Account screen route
|
|
192
|
+
- `anonymousDisplayName` - Guest display name
|
|
204
193
|
|
|
205
|
-
|
|
194
|
+
**RETURNS**:
|
|
195
|
+
- Profile object or null
|
|
196
|
+
- Loading state
|
|
197
|
+
- Error state
|
|
206
198
|
|
|
207
|
-
|
|
208
|
-
|
|
199
|
+
**Rules**:
|
|
200
|
+
- MUST handle loading state
|
|
201
|
+
- MUST provide anonymous fallback
|
|
202
|
+
- MUST handle errors gracefully
|
|
203
|
+
- MUST not mutate profile data
|
|
209
204
|
|
|
210
|
-
|
|
211
|
-
|
|
205
|
+
**MUST NOT**:
|
|
206
|
+
- Skip loading check
|
|
207
|
+
- Return undefined for anonymous
|
|
208
|
+
- Throw on errors
|
|
209
|
+
- Modify returned profile
|
|
212
210
|
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
await updateProfile(data);
|
|
216
|
-
} catch (err) {
|
|
217
|
-
console.error(err);
|
|
218
|
-
}
|
|
219
|
-
};
|
|
211
|
+
**Documentation**: `hooks/useUserProfile.md`
|
|
220
212
|
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
```
|
|
213
|
+
---
|
|
224
214
|
|
|
225
|
-
|
|
215
|
+
#### useProfileUpdate
|
|
226
216
|
|
|
227
|
-
Profile
|
|
217
|
+
**PURPOSE**: Profile update operations
|
|
228
218
|
|
|
219
|
+
**IMPORT PATH**:
|
|
229
220
|
```typescript
|
|
230
|
-
import {
|
|
231
|
-
|
|
232
|
-
function EditProfileScreen() {
|
|
233
|
-
const {
|
|
234
|
-
formState,
|
|
235
|
-
setDisplayName,
|
|
236
|
-
setEmail,
|
|
237
|
-
setPhotoURL,
|
|
238
|
-
resetForm,
|
|
239
|
-
validateForm,
|
|
240
|
-
} = useProfileEdit({
|
|
241
|
-
displayName: user?.displayName || '',
|
|
242
|
-
email: user?.email || '',
|
|
243
|
-
photoURL: user?.photoURL || null,
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
const handleSave = () => {
|
|
247
|
-
const { isValid, errors } = validateForm();
|
|
248
|
-
if (!isValid) {
|
|
249
|
-
Alert.alert('Error', errors.join('\n'));
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
updateProfile(formState);
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
return <EditProfileForm {...props} />;
|
|
256
|
-
}
|
|
221
|
+
import { useProfileUpdate } from '@umituz/react-native-auth';
|
|
257
222
|
```
|
|
258
223
|
|
|
259
|
-
|
|
224
|
+
**RETURNS**:
|
|
225
|
+
- `updateProfile()` - Update function
|
|
226
|
+
- `isUpdating` - Loading state
|
|
227
|
+
- `error` - Error state
|
|
228
|
+
|
|
229
|
+
**Rules**:
|
|
230
|
+
- MUST validate before update
|
|
231
|
+
- MUST handle loading state
|
|
232
|
+
- MUST show success/error feedback
|
|
233
|
+
- MUST not update during loading
|
|
234
|
+
|
|
235
|
+
**MUST NOT**:
|
|
236
|
+
- Skip validation
|
|
237
|
+
- Update while loading
|
|
238
|
+
- Ignore errors
|
|
239
|
+
- Update without user action
|
|
240
|
+
|
|
241
|
+
**Documentation**: `hooks/useProfileUpdate.md`
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
### Account Management Hooks
|
|
260
246
|
|
|
261
|
-
|
|
247
|
+
#### useAccountManagement
|
|
262
248
|
|
|
263
|
-
Account
|
|
249
|
+
**PURPOSE**: Account operations (logout, delete)
|
|
264
250
|
|
|
251
|
+
**IMPORT PATH**:
|
|
265
252
|
```typescript
|
|
266
253
|
import { useAccountManagement } from '@umituz/react-native-auth';
|
|
267
|
-
|
|
268
|
-
function AccountSettings() {
|
|
269
|
-
const { logout, deleteAccount, isLoading, isDeletingAccount } = useAccountManagement({
|
|
270
|
-
onReauthRequired: async () => {
|
|
271
|
-
const result = await reauthenticateWithGoogle();
|
|
272
|
-
return result.success;
|
|
273
|
-
},
|
|
274
|
-
onPasswordRequired: async () => {
|
|
275
|
-
const password = await showPasswordPrompt();
|
|
276
|
-
return password;
|
|
277
|
-
},
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
return (
|
|
281
|
-
<View>
|
|
282
|
-
<Button onPress={logout}>Sign Out</Button>
|
|
283
|
-
<Button onPress={deleteAccount}>Delete Account</Button>
|
|
284
|
-
</View>
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
254
|
```
|
|
288
255
|
|
|
289
|
-
|
|
256
|
+
**PARAMETERS**:
|
|
257
|
+
- `onReauthRequired` - Reauth callback
|
|
258
|
+
- `onPasswordRequired` - Password prompt callback
|
|
259
|
+
|
|
260
|
+
**RETURNS**:
|
|
261
|
+
- `logout()` - Sign out function
|
|
262
|
+
- `deleteAccount()` - Delete account function
|
|
263
|
+
- `isLoading` - Loading state
|
|
264
|
+
- `isDeletingAccount` - Delete loading state
|
|
265
|
+
|
|
266
|
+
**Rules**:
|
|
267
|
+
- MUST confirm before logout
|
|
268
|
+
- MUST double-confirm deletion
|
|
269
|
+
- MUST require reauthentication for deletion
|
|
270
|
+
- MUST handle reauth callbacks
|
|
271
|
+
- MUST not show for anonymous users
|
|
272
|
+
|
|
273
|
+
**MUST NOT**:
|
|
274
|
+
- Skip confirmation dialogs
|
|
275
|
+
- Delete without reauth
|
|
276
|
+
- Allow anonymous deletion
|
|
277
|
+
- Ignore callback requirements
|
|
278
|
+
|
|
279
|
+
**Documentation**: `hooks/useAccountManagement.md`
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### Social Login Hooks
|
|
290
284
|
|
|
291
|
-
|
|
285
|
+
#### useSocialLogin
|
|
292
286
|
|
|
293
|
-
|
|
287
|
+
**PURPOSE**: Social login management
|
|
294
288
|
|
|
289
|
+
**IMPORT PATH**:
|
|
295
290
|
```typescript
|
|
296
291
|
import { useSocialLogin } from '@umituz/react-native-auth';
|
|
297
|
-
|
|
298
|
-
function LoginScreen() {
|
|
299
|
-
const {
|
|
300
|
-
signInWithGoogle,
|
|
301
|
-
signInWithApple,
|
|
302
|
-
googleLoading,
|
|
303
|
-
appleLoading,
|
|
304
|
-
googleConfigured,
|
|
305
|
-
appleAvailable,
|
|
306
|
-
} = useSocialLogin({
|
|
307
|
-
google: { webClientId: '...', iosClientId: '...' },
|
|
308
|
-
apple: { enabled: true },
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
return (
|
|
312
|
-
<View>
|
|
313
|
-
<Button onPress={signInWithGoogle} disabled={googleLoading}>
|
|
314
|
-
Google
|
|
315
|
-
</Button>
|
|
316
|
-
<Button onPress={signInWithApple} disabled={appleLoading}>
|
|
317
|
-
Apple
|
|
318
|
-
</Button>
|
|
319
|
-
</View>
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
292
|
```
|
|
323
293
|
|
|
324
|
-
|
|
294
|
+
**PARAMETERS**:
|
|
295
|
+
- Social provider configuration
|
|
296
|
+
|
|
297
|
+
**RETURNS**:
|
|
298
|
+
- `signInWithGoogle()` - Google sign in
|
|
299
|
+
- `signInWithApple()` - Apple sign in
|
|
300
|
+
- `googleLoading` - Google loading state
|
|
301
|
+
- `appleLoading` - Apple loading state
|
|
302
|
+
- `googleConfigured` - Google available
|
|
303
|
+
- `appleAvailable` - Apple available
|
|
304
|
+
|
|
305
|
+
**Rules**:
|
|
306
|
+
- MUST configure providers
|
|
307
|
+
- MUST check availability
|
|
308
|
+
- MUST handle platform differences
|
|
309
|
+
- MUST check loading states
|
|
310
|
+
- MUST handle errors
|
|
325
311
|
|
|
326
|
-
|
|
312
|
+
**MUST NOT**:
|
|
313
|
+
- Skip provider configuration
|
|
314
|
+
- Show unavailable providers
|
|
315
|
+
- Ignore platform constraints
|
|
316
|
+
- Call while loading
|
|
327
317
|
|
|
318
|
+
**Documentation**: `hooks/useSocialLogin.md`
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
#### useGoogleAuth
|
|
323
|
+
|
|
324
|
+
**PURPOSE**: Google OAuth flow
|
|
325
|
+
|
|
326
|
+
**IMPORT PATH**:
|
|
328
327
|
```typescript
|
|
329
328
|
import { useGoogleAuth } from '@umituz/react-native-auth';
|
|
330
|
-
|
|
331
|
-
function LoginScreen() {
|
|
332
|
-
const { signInWithGoogle, googleLoading, googleConfigured } = useGoogleAuth({
|
|
333
|
-
iosClientId: Config.GOOGLE_IOS_CLIENT_ID,
|
|
334
|
-
webClientId: Config.GOOGLE_WEB_CLIENT_ID,
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
return (
|
|
338
|
-
<Button onPress={signInWithGoogle} disabled={googleLoading}>
|
|
339
|
-
Sign in with Google
|
|
340
|
-
</Button>
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
329
|
```
|
|
344
330
|
|
|
345
|
-
|
|
331
|
+
**PARAMETERS**:
|
|
332
|
+
- `iosClientId` - iOS client ID
|
|
333
|
+
- `androidClientId` - Android client ID
|
|
334
|
+
- `webClientId` - Web client ID
|
|
346
335
|
|
|
347
|
-
|
|
336
|
+
**RETURNS**:
|
|
337
|
+
- `signInWithGoogle()` - Sign in function
|
|
338
|
+
- `googleLoading` - Loading state
|
|
339
|
+
- `googleConfigured` - Configured status
|
|
348
340
|
|
|
341
|
+
**Rules**:
|
|
342
|
+
- MUST provide at least one client ID
|
|
343
|
+
- MUST check configuration
|
|
344
|
+
- MUST use expo-auth-session
|
|
345
|
+
- MUST handle errors properly
|
|
346
|
+
|
|
347
|
+
**MUST NOT**:
|
|
348
|
+
- Skip client IDs
|
|
349
|
+
- Use without configuration
|
|
350
|
+
- Ignore loading state
|
|
351
|
+
- Skip error handling
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
#### useAppleAuth
|
|
356
|
+
|
|
357
|
+
**PURPOSE**: Apple Sign-In functionality
|
|
358
|
+
|
|
359
|
+
**IMPORT PATH**:
|
|
349
360
|
```typescript
|
|
350
361
|
import { useAppleAuth } from '@umituz/react-native-auth';
|
|
362
|
+
```
|
|
351
363
|
|
|
352
|
-
|
|
353
|
-
|
|
364
|
+
**RETURNS**:
|
|
365
|
+
- `signInWithApple()` - Sign in function
|
|
366
|
+
- `appleLoading` - Loading state
|
|
367
|
+
- `appleAvailable` - Available on iOS
|
|
354
368
|
|
|
355
|
-
|
|
369
|
+
**Rules**:
|
|
370
|
+
- MUST check platform availability
|
|
371
|
+
- MUST only use on iOS
|
|
372
|
+
- MUST respect Apple guidelines
|
|
373
|
+
- MUST handle private relay emails
|
|
356
374
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
375
|
+
**MUST NOT**:
|
|
376
|
+
- Use on Android
|
|
377
|
+
- Use on Web
|
|
378
|
+
- Require as only auth method
|
|
379
|
+
- Skip availability check
|
|
380
|
+
|
|
381
|
+
---
|
|
364
382
|
|
|
365
|
-
|
|
383
|
+
### UI Hooks
|
|
366
384
|
|
|
367
|
-
|
|
385
|
+
#### useAuthBottomSheet
|
|
368
386
|
|
|
369
|
-
Authentication bottom sheet management
|
|
387
|
+
**PURPOSE**: Authentication bottom sheet management
|
|
370
388
|
|
|
389
|
+
**IMPORT PATH**:
|
|
371
390
|
```typescript
|
|
372
391
|
import { useAuthBottomSheet } from '@umituz/react-native-auth';
|
|
373
|
-
|
|
374
|
-
function AuthBottomSheet() {
|
|
375
|
-
const {
|
|
376
|
-
modalRef,
|
|
377
|
-
mode,
|
|
378
|
-
providers,
|
|
379
|
-
googleLoading,
|
|
380
|
-
appleLoading,
|
|
381
|
-
handleDismiss,
|
|
382
|
-
handleGoogleSignIn,
|
|
383
|
-
handleAppleSignIn,
|
|
384
|
-
} = useAuthBottomSheet({
|
|
385
|
-
socialConfig: {
|
|
386
|
-
google: { webClientId: '...', iosClientId: '...' },
|
|
387
|
-
apple: { enabled: true },
|
|
388
|
-
},
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
return (
|
|
392
|
-
<BottomSheetModal ref={modalRef} onDismiss={handleDismiss}>
|
|
393
|
-
{mode === 'login' ? (
|
|
394
|
-
<LoginForm onGoogleSignIn={handleGoogleSignIn} />
|
|
395
|
-
) : (
|
|
396
|
-
<RegisterForm onGoogleSignIn={handleGoogleSignIn} />
|
|
397
|
-
)}
|
|
398
|
-
</BottomSheetModal>
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
392
|
```
|
|
402
393
|
|
|
394
|
+
**PARAMETERS**:
|
|
395
|
+
- Social provider configuration
|
|
396
|
+
- Default callbacks
|
|
397
|
+
|
|
398
|
+
**RETURNS**:
|
|
399
|
+
- `modalRef` - Modal reference
|
|
400
|
+
- `mode` - Current mode (login/register)
|
|
401
|
+
- `handleDismiss()` - Dismiss handler
|
|
402
|
+
- `handleGoogleSignIn()` - Google handler
|
|
403
|
+
- `handleAppleSignIn()` - Apple handler
|
|
404
|
+
- Loading states
|
|
405
|
+
|
|
406
|
+
**Rules**:
|
|
407
|
+
- MUST configure social providers
|
|
408
|
+
- MUST auto-close on success
|
|
409
|
+
- MUST execute pending callbacks
|
|
410
|
+
- MUST handle modal state properly
|
|
411
|
+
|
|
412
|
+
**MUST NOT**:
|
|
413
|
+
- Skip auto-close
|
|
414
|
+
- Leave modal open after auth
|
|
415
|
+
- Ignore pending callbacks
|
|
416
|
+
- Lose callback references
|
|
417
|
+
|
|
418
|
+
**Documentation**: `hooks/useAuthBottomSheet.md`
|
|
419
|
+
|
|
403
420
|
---
|
|
404
421
|
|
|
405
|
-
|
|
422
|
+
## Components
|
|
406
423
|
|
|
407
|
-
|
|
424
|
+
### Layout Components
|
|
408
425
|
|
|
409
|
-
|
|
426
|
+
#### AuthContainer
|
|
410
427
|
|
|
411
|
-
Main auth layout container
|
|
428
|
+
**PURPOSE**: Main auth layout container
|
|
412
429
|
|
|
430
|
+
**IMPORT PATH**:
|
|
413
431
|
```typescript
|
|
414
432
|
import { AuthContainer } from '@umituz/react-native-auth';
|
|
415
|
-
|
|
416
|
-
function LoginScreen() {
|
|
417
|
-
return (
|
|
418
|
-
<AuthContainer>
|
|
419
|
-
<AuthHeader title="Sign In" />
|
|
420
|
-
<LoginForm />
|
|
421
|
-
<SocialLoginButtons />
|
|
422
|
-
</AuthContainer>
|
|
423
|
-
);
|
|
424
|
-
}
|
|
425
433
|
```
|
|
426
434
|
|
|
427
|
-
|
|
435
|
+
**Rules**:
|
|
436
|
+
- MUST wrap auth screen content
|
|
437
|
+
- MUST provide consistent layout
|
|
438
|
+
- MUST handle keyboard avoidance
|
|
439
|
+
- MUST support design system
|
|
440
|
+
|
|
441
|
+
**MUST NOT**:
|
|
442
|
+
- Use without content
|
|
443
|
+
- Override layout styles
|
|
444
|
+
- Break responsive design
|
|
445
|
+
- Skip keyboard handling
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
#### AuthHeader
|
|
428
450
|
|
|
429
|
-
Header component for auth screens
|
|
451
|
+
**PURPOSE**: Header component for auth screens
|
|
430
452
|
|
|
453
|
+
**IMPORT PATH**:
|
|
431
454
|
```typescript
|
|
432
455
|
import { AuthHeader } from '@umituz/react-native-auth';
|
|
433
|
-
|
|
434
|
-
<AuthHeader
|
|
435
|
-
title="Welcome Back"
|
|
436
|
-
subtitle="Sign in to continue"
|
|
437
|
-
/>
|
|
438
456
|
```
|
|
439
457
|
|
|
440
|
-
|
|
458
|
+
**PROPS**:
|
|
459
|
+
- `title` - Screen title
|
|
460
|
+
- `subtitle` - Screen subtitle (optional)
|
|
441
461
|
|
|
442
|
-
|
|
462
|
+
**Rules**:
|
|
463
|
+
- MUST provide clear title
|
|
464
|
+
- MUST use proper typography
|
|
465
|
+
- MUST support design system
|
|
466
|
+
- MUST be optional
|
|
443
467
|
|
|
444
|
-
|
|
445
|
-
|
|
468
|
+
**MUST NOT**:
|
|
469
|
+
- Skip title
|
|
470
|
+
- Use unclear text
|
|
471
|
+
- Override styles improperly
|
|
446
472
|
|
|
447
|
-
|
|
448
|
-
<LoginForm />
|
|
449
|
-
</AuthFormCard>
|
|
450
|
-
```
|
|
473
|
+
---
|
|
451
474
|
|
|
452
|
-
|
|
475
|
+
### Form Components
|
|
453
476
|
|
|
454
|
-
|
|
477
|
+
#### LoginForm & RegisterForm
|
|
455
478
|
|
|
456
|
-
Pre-built authentication forms
|
|
479
|
+
**PURPOSE**: Pre-built authentication forms
|
|
457
480
|
|
|
481
|
+
**IMPORT PATH**:
|
|
458
482
|
```typescript
|
|
459
483
|
import { LoginForm, RegisterForm } from '@umituz/react-native-auth';
|
|
460
|
-
|
|
461
|
-
function LoginScreen() {
|
|
462
|
-
const navigation = useNavigation();
|
|
463
|
-
|
|
464
|
-
return (
|
|
465
|
-
<LoginForm onNavigateToRegister={() => navigation.navigate('Register')} />
|
|
466
|
-
);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
function RegisterScreen() {
|
|
470
|
-
const navigation = useNavigation();
|
|
471
|
-
|
|
472
|
-
return (
|
|
473
|
-
<RegisterForm
|
|
474
|
-
onNavigateToLogin={() => navigation.navigate('Login')}
|
|
475
|
-
onTermsPress={() => navigation.navigate('Terms')}
|
|
476
|
-
onPrivacyPress={() => navigation.navigate('Privacy')}
|
|
477
|
-
/>
|
|
478
|
-
);
|
|
479
|
-
}
|
|
480
484
|
```
|
|
481
485
|
|
|
482
|
-
|
|
486
|
+
**REQUIRED PROPS** (LoginForm):
|
|
487
|
+
- `onNavigateToRegister` - Navigation callback
|
|
488
|
+
|
|
489
|
+
**REQUIRED PROPS** (RegisterForm):
|
|
490
|
+
- `onNavigateToLogin` - Navigation callback
|
|
491
|
+
- `termsUrl` or `onTermsPress` - Terms link
|
|
492
|
+
- `privacyUrl` or `onPrivacyPress` - Privacy link
|
|
483
493
|
|
|
484
|
-
|
|
494
|
+
**Rules**:
|
|
495
|
+
- MUST provide all required props
|
|
496
|
+
- MUST handle navigation callbacks
|
|
497
|
+
- MUST validate before submission
|
|
498
|
+
- MUST not override internal validation
|
|
485
499
|
|
|
486
|
-
|
|
500
|
+
**MUST NOT**:
|
|
501
|
+
- Skip required props
|
|
502
|
+
- Override validation logic
|
|
503
|
+
- Bypass internal state
|
|
504
|
+
- Modify form behavior
|
|
487
505
|
|
|
506
|
+
**Documentation**: `components/LoginForm.md`
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
### Password Indicators
|
|
511
|
+
|
|
512
|
+
#### PasswordStrengthIndicator
|
|
513
|
+
|
|
514
|
+
**PURPOSE**: Visual password requirements display
|
|
515
|
+
|
|
516
|
+
**IMPORT PATH**:
|
|
488
517
|
```typescript
|
|
489
518
|
import { PasswordStrengthIndicator } from '@umituz/react-native-auth';
|
|
490
|
-
|
|
491
|
-
function RegisterForm() {
|
|
492
|
-
const [password, setPassword] = useState('');
|
|
493
|
-
const requirements = validatePasswordRequirements(password);
|
|
494
|
-
|
|
495
|
-
return (
|
|
496
|
-
<View>
|
|
497
|
-
<TextInput
|
|
498
|
-
value={password}
|
|
499
|
-
onChangeText={setPassword}
|
|
500
|
-
placeholder="Password"
|
|
501
|
-
secureTextEntry
|
|
502
|
-
/>
|
|
503
|
-
<PasswordStrengthIndicator requirements={requirements} />
|
|
504
|
-
</View>
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
519
|
```
|
|
508
520
|
|
|
509
|
-
|
|
521
|
+
**PROPS**:
|
|
522
|
+
- `requirements` - PasswordRequirements object
|
|
523
|
+
|
|
524
|
+
**Rules**:
|
|
525
|
+
- MUST calculate requirements object
|
|
526
|
+
- MUST update on password change
|
|
527
|
+
- MUST show before user types
|
|
528
|
+
- MUST not hide requirements
|
|
529
|
+
|
|
530
|
+
**MUST NOT**:
|
|
531
|
+
- Show without requirements
|
|
532
|
+
- Hide after first input
|
|
533
|
+
- Skip validation
|
|
534
|
+
- Use ambiguous colors
|
|
535
|
+
|
|
536
|
+
**Documentation**: `components/PasswordIndicators.md`
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
#### PasswordMatchIndicator
|
|
510
541
|
|
|
511
|
-
Password
|
|
542
|
+
**PURPOSE**: Password confirmation feedback
|
|
512
543
|
|
|
544
|
+
**IMPORT PATH**:
|
|
513
545
|
```typescript
|
|
514
546
|
import { PasswordMatchIndicator } from '@umituz/react-native-auth';
|
|
515
|
-
|
|
516
|
-
function RegisterForm() {
|
|
517
|
-
const [password, setPassword] = useState('');
|
|
518
|
-
const [confirmPassword, setConfirmPassword] = useState('');
|
|
519
|
-
|
|
520
|
-
const passwordsMatch = password === confirmPassword && password.length > 0;
|
|
521
|
-
|
|
522
|
-
return (
|
|
523
|
-
<View>
|
|
524
|
-
<TextInput value={password} onChangeText={setPassword} />
|
|
525
|
-
<TextInput value={confirmPassword} onChangeText={setConfirmPassword} />
|
|
526
|
-
{confirmPassword.length > 0 && (
|
|
527
|
-
<PasswordMatchIndicator isMatch={passwordsMatch} />
|
|
528
|
-
)}
|
|
529
|
-
</View>
|
|
530
|
-
);
|
|
531
|
-
}
|
|
532
547
|
```
|
|
533
548
|
|
|
534
|
-
|
|
549
|
+
**PROPS**:
|
|
550
|
+
- `isMatch` - Match status boolean
|
|
551
|
+
|
|
552
|
+
**Rules**:
|
|
553
|
+
- MUST only show when confirm field has input
|
|
554
|
+
- MUST update in real-time
|
|
555
|
+
- MUST use clear visual feedback
|
|
556
|
+
- MUST not use ambiguous colors
|
|
557
|
+
|
|
558
|
+
**MUST NOT**:
|
|
559
|
+
- Show before confirm input
|
|
560
|
+
- Use ambiguous colors
|
|
561
|
+
- Skip real-time updates
|
|
562
|
+
- Hide feedback
|
|
535
563
|
|
|
536
|
-
|
|
564
|
+
**Documentation**: `components/PasswordIndicators.md`
|
|
537
565
|
|
|
538
|
-
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
### Social Login Components
|
|
569
|
+
|
|
570
|
+
#### SocialLoginButtons
|
|
539
571
|
|
|
572
|
+
**PURPOSE**: Social authentication buttons
|
|
573
|
+
|
|
574
|
+
**IMPORT PATH**:
|
|
540
575
|
```typescript
|
|
541
576
|
import { SocialLoginButtons } from '@umituz/react-native-auth';
|
|
542
|
-
|
|
543
|
-
function LoginScreen() {
|
|
544
|
-
const { signInWithGoogle, googleLoading } = useGoogleAuth({ ... });
|
|
545
|
-
const { signInWithApple, appleLoading } = useAppleAuth();
|
|
546
|
-
|
|
547
|
-
return (
|
|
548
|
-
<SocialLoginButtons
|
|
549
|
-
enabledProviders={['google', 'apple']}
|
|
550
|
-
onGooglePress={signInWithGoogle}
|
|
551
|
-
onApplePress={signInWithApple}
|
|
552
|
-
googleLoading={googleLoading}
|
|
553
|
-
appleLoading={appleLoading}
|
|
554
|
-
/>
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
577
|
```
|
|
558
578
|
|
|
559
|
-
|
|
579
|
+
**REQUIRED PROPS**:
|
|
580
|
+
- `enabledProviders` - Provider array
|
|
581
|
+
- `onGooglePress` - Google handler
|
|
582
|
+
- `onApplePress` - Apple handler
|
|
560
583
|
|
|
561
|
-
|
|
584
|
+
**OPTIONAL PROPS**:
|
|
585
|
+
- `googleLoading` - Loading state
|
|
586
|
+
- `appleLoading` - Loading state
|
|
587
|
+
- `disabled` - Disable all
|
|
562
588
|
|
|
563
|
-
|
|
589
|
+
**Rules**:
|
|
590
|
+
- MUST check provider availability
|
|
591
|
+
- MUST handle platform differences
|
|
592
|
+
- MUST respect Apple guidelines
|
|
593
|
+
- MUST not show unavailable providers
|
|
564
594
|
|
|
595
|
+
**Platform Behavior**:
|
|
596
|
+
- iOS: Google + Apple
|
|
597
|
+
- Android: Google only
|
|
598
|
+
- Web: Google only
|
|
599
|
+
|
|
600
|
+
**MUST NOT**:
|
|
601
|
+
- Show unavailable providers
|
|
602
|
+
- Ignore platform constraints
|
|
603
|
+
- Skip loading states
|
|
604
|
+
- Override platform behavior
|
|
605
|
+
|
|
606
|
+
**Documentation**: `components/SocialLoginButtons.md`
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### Profile Components
|
|
611
|
+
|
|
612
|
+
#### ProfileSection
|
|
613
|
+
|
|
614
|
+
**PURPOSE**: User profile display
|
|
615
|
+
|
|
616
|
+
**IMPORT PATH**:
|
|
565
617
|
```typescript
|
|
566
618
|
import { ProfileSection } from '@umituz/react-native-auth';
|
|
567
|
-
|
|
568
|
-
function SettingsScreen() {
|
|
569
|
-
const profile = useUserProfile();
|
|
570
|
-
|
|
571
|
-
return (
|
|
572
|
-
<ProfileSection
|
|
573
|
-
profile={{
|
|
574
|
-
displayName: profile?.displayName,
|
|
575
|
-
userId: profile?.userId,
|
|
576
|
-
isAnonymous: profile?.isAnonymous || false,
|
|
577
|
-
avatarUrl: profile?.avatarUrl,
|
|
578
|
-
}}
|
|
579
|
-
onPress={() => navigation.navigate('EditProfile')}
|
|
580
|
-
onSignIn={() => navigation.navigate('Login')}
|
|
581
|
-
/>
|
|
582
|
-
);
|
|
583
|
-
}
|
|
584
619
|
```
|
|
585
620
|
|
|
586
|
-
|
|
621
|
+
**REQUIRED PROPS**:
|
|
622
|
+
- `profile` - ProfileSectionConfig object
|
|
587
623
|
|
|
588
|
-
|
|
624
|
+
**OPTIONAL PROPS**:
|
|
625
|
+
- `onPress` - Press handler (authenticated)
|
|
626
|
+
- `onSignIn` - Sign-in handler (anonymous)
|
|
589
627
|
|
|
628
|
+
**Rules**:
|
|
629
|
+
- MUST handle authenticated vs anonymous
|
|
630
|
+
- MUST show avatar fallback
|
|
631
|
+
- MUST indicate anonymous status
|
|
632
|
+
- MUST not expose sensitive info
|
|
633
|
+
|
|
634
|
+
**MUST NOT**:
|
|
635
|
+
- Show sensitive data publicly
|
|
636
|
+
- Skip anonymous handling
|
|
637
|
+
- Break avatar fallback
|
|
638
|
+
- Expose internal IDs
|
|
639
|
+
|
|
640
|
+
**Documentation**: `components/ProfileComponents.md`
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
#### AccountActions
|
|
645
|
+
|
|
646
|
+
**PURPOSE**: Account management buttons
|
|
647
|
+
|
|
648
|
+
**IMPORT PATH**:
|
|
590
649
|
```typescript
|
|
591
650
|
import { AccountActions } from '@umituz/react-native-auth';
|
|
592
|
-
|
|
593
|
-
function AccountSettings() {
|
|
594
|
-
const { logout, deleteAccount } = useAccountManagement();
|
|
595
|
-
|
|
596
|
-
const config = {
|
|
597
|
-
logoutText: 'Sign Out',
|
|
598
|
-
deleteAccountText: 'Delete Account',
|
|
599
|
-
logoutConfirmTitle: 'Sign Out',
|
|
600
|
-
logoutConfirmMessage: 'Are you sure you want to sign out?',
|
|
601
|
-
deleteConfirmTitle: 'Delete Account',
|
|
602
|
-
deleteConfirmMessage: 'This action cannot be undone. Continue?',
|
|
603
|
-
onLogout: logout,
|
|
604
|
-
onDeleteAccount: deleteAccount,
|
|
605
|
-
};
|
|
606
|
-
|
|
607
|
-
return <AccountActions config={config} />;
|
|
608
|
-
}
|
|
609
651
|
```
|
|
610
652
|
|
|
653
|
+
**REQUIRED PROPS**:
|
|
654
|
+
- `config` - AccountActionsConfig object
|
|
655
|
+
|
|
656
|
+
**Rules**:
|
|
657
|
+
- MUST confirm before sign out
|
|
658
|
+
- MUST double-confirm deletion
|
|
659
|
+
- MUST require re-authentication for deletion
|
|
660
|
+
- MUST hide for anonymous users
|
|
661
|
+
|
|
662
|
+
**MUST NOT**:
|
|
663
|
+
- Skip confirmations
|
|
664
|
+
- Allow anonymous deletion
|
|
665
|
+
- Delete without reauth
|
|
666
|
+
- Show for anonymous users
|
|
667
|
+
|
|
668
|
+
**Documentation**: `components/ProfileComponents.md`
|
|
669
|
+
|
|
611
670
|
---
|
|
612
671
|
|
|
613
|
-
|
|
672
|
+
## Screens
|
|
673
|
+
|
|
674
|
+
### Pre-built Screens
|
|
614
675
|
|
|
615
|
-
|
|
676
|
+
**LoginScreen** - Complete login screen
|
|
677
|
+
**RegisterScreen** - Registration screen
|
|
678
|
+
**AccountScreen** - Account settings screen
|
|
679
|
+
**EditProfileScreen** - Profile editing screen
|
|
616
680
|
|
|
681
|
+
**IMPORT PATH**:
|
|
617
682
|
```typescript
|
|
618
683
|
import {
|
|
619
684
|
LoginScreen,
|
|
@@ -621,150 +686,153 @@ import {
|
|
|
621
686
|
AccountScreen,
|
|
622
687
|
EditProfileScreen,
|
|
623
688
|
} from '@umituz/react-native-auth';
|
|
624
|
-
|
|
625
|
-
// Use in navigation
|
|
626
|
-
<Stack.Screen
|
|
627
|
-
name="Login"
|
|
628
|
-
component={LoginScreen}
|
|
629
|
-
options={{ headerShown: false }}
|
|
630
|
-
/>
|
|
631
|
-
<Stack.Screen
|
|
632
|
-
name="Register"
|
|
633
|
-
component={RegisterScreen}
|
|
634
|
-
/>
|
|
635
|
-
<Stack.Screen
|
|
636
|
-
name="Account"
|
|
637
|
-
component={AccountScreen}
|
|
638
|
-
/>
|
|
639
|
-
<Stack.Screen
|
|
640
|
-
name="EditProfile"
|
|
641
|
-
component={EditProfileScreen}
|
|
642
|
-
/>
|
|
643
689
|
```
|
|
644
690
|
|
|
691
|
+
**Rules**:
|
|
692
|
+
- MUST configure navigation properly
|
|
693
|
+
- MUST integrate with app navigation
|
|
694
|
+
- MUST handle callbacks appropriately
|
|
695
|
+
- MUST not bypass AuthProvider
|
|
696
|
+
|
|
697
|
+
**MUST NOT**:
|
|
698
|
+
- Use without navigation setup
|
|
699
|
+
- Skip AuthProvider
|
|
700
|
+
- Ignore navigation callbacks
|
|
701
|
+
- Modify internal screen logic
|
|
702
|
+
|
|
703
|
+
**Documentation**: `screens/README.md`
|
|
704
|
+
|
|
645
705
|
---
|
|
646
706
|
|
|
647
|
-
|
|
707
|
+
## Stores
|
|
648
708
|
|
|
649
|
-
|
|
709
|
+
### authStore
|
|
650
710
|
|
|
651
|
-
Main authentication state
|
|
711
|
+
**PURPOSE**: Main authentication state (Zustand)
|
|
652
712
|
|
|
713
|
+
**IMPORT PATH**:
|
|
653
714
|
```typescript
|
|
654
715
|
import {
|
|
655
716
|
useAuthStore,
|
|
656
717
|
selectIsAuthenticated,
|
|
657
|
-
selectUserId
|
|
658
|
-
getIsAuthenticated,
|
|
659
|
-
getUserId,
|
|
718
|
+
selectUserId
|
|
660
719
|
} from '@umituz/react-native-auth';
|
|
720
|
+
```
|
|
661
721
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
722
|
+
**STATE**:
|
|
723
|
+
- `user` - Current user
|
|
724
|
+
- `loading` - Loading state
|
|
725
|
+
- `isAuthReady` - Ready state
|
|
726
|
+
- `error` - Error state
|
|
666
727
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
728
|
+
**RULES**:
|
|
729
|
+
- MUST use hooks (not direct store access)
|
|
730
|
+
- MUST use selectors for specific values
|
|
731
|
+
- MUST not mutate state directly
|
|
732
|
+
- MUST rely on useAuth hook instead
|
|
670
733
|
|
|
671
|
-
|
|
734
|
+
**MUST NOT**:
|
|
735
|
+
- Access store directly in components
|
|
736
|
+
- Mutate state externally
|
|
737
|
+
- Skip selector usage
|
|
738
|
+
- Bypass useAuth hook
|
|
672
739
|
|
|
673
|
-
|
|
740
|
+
---
|
|
741
|
+
|
|
742
|
+
### authModalStore
|
|
743
|
+
|
|
744
|
+
**PURPOSE**: Auth modal state management
|
|
674
745
|
|
|
746
|
+
**IMPORT PATH**:
|
|
675
747
|
```typescript
|
|
676
748
|
import { useAuthModalStore } from '@umituz/react-native-auth';
|
|
749
|
+
```
|
|
677
750
|
|
|
678
|
-
|
|
679
|
-
|
|
751
|
+
**STATE**:
|
|
752
|
+
- `isVisible` - Modal visibility
|
|
753
|
+
- `mode` - Login/register mode
|
|
754
|
+
- `pendingCallback` - Callback after auth
|
|
680
755
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
};
|
|
756
|
+
**RULES**:
|
|
757
|
+
- MUST use useAuthRequired hook instead
|
|
758
|
+
- MUST not manage manually
|
|
759
|
+
- MUST let hooks handle state
|
|
760
|
+
- MUST not access directly
|
|
687
761
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
762
|
+
**MUST NOT**:
|
|
763
|
+
- Access store directly
|
|
764
|
+
- Manage modal manually
|
|
765
|
+
- Skip hook usage
|
|
766
|
+
- Mutate state externally
|
|
691
767
|
|
|
692
768
|
---
|
|
693
769
|
|
|
694
|
-
|
|
770
|
+
## Best Practices
|
|
695
771
|
|
|
696
|
-
|
|
772
|
+
### Hook Usage
|
|
697
773
|
|
|
698
|
-
|
|
774
|
+
**MUST**:
|
|
775
|
+
- Use useAuth for primary operations
|
|
776
|
+
- Check loading states
|
|
777
|
+
- Handle errors appropriately
|
|
778
|
+
- Use specific hooks for specific tasks
|
|
779
|
+
- Follow hook rules
|
|
699
780
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
<AuthNavigator />
|
|
707
|
-
</NavigationContainer>
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
```
|
|
781
|
+
**MUST NOT**:
|
|
782
|
+
- Access store directly
|
|
783
|
+
- Skip loading checks
|
|
784
|
+
- Use hooks without provider
|
|
785
|
+
- Ignore error handling
|
|
786
|
+
- Break hook rules
|
|
711
787
|
|
|
712
788
|
---
|
|
713
789
|
|
|
714
|
-
|
|
790
|
+
### Component Usage
|
|
715
791
|
|
|
716
|
-
|
|
792
|
+
**MUST**:
|
|
793
|
+
- Follow design system integration
|
|
794
|
+
- Provide required props
|
|
795
|
+
- Handle callbacks appropriately
|
|
796
|
+
- Validate before submission
|
|
797
|
+
- Support accessibility
|
|
717
798
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
799
|
+
**MUST NOT**:
|
|
800
|
+
- Skip required props
|
|
801
|
+
- Override internal logic
|
|
802
|
+
- Break validation
|
|
803
|
+
- Ignore accessibility
|
|
804
|
+
- Modify component behavior
|
|
722
805
|
|
|
723
|
-
|
|
724
|
-
}
|
|
806
|
+
---
|
|
725
807
|
|
|
726
|
-
|
|
727
|
-
function Component() {
|
|
728
|
-
const user = useAuthStore((state) => state.user);
|
|
808
|
+
### State Management
|
|
729
809
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
810
|
+
**MUST**:
|
|
811
|
+
- Use hooks over store access
|
|
812
|
+
- Use selectors for optimization
|
|
813
|
+
- Let hooks manage state
|
|
814
|
+
- Follow React best practices
|
|
815
|
+
- Handle loading states
|
|
733
816
|
|
|
734
|
-
|
|
817
|
+
**MUST NOT**:
|
|
818
|
+
- Access store directly
|
|
819
|
+
- Mutate state externally
|
|
820
|
+
- Skip loading states
|
|
821
|
+
- Ignore React rules
|
|
822
|
+
- Bypass hook abstraction
|
|
735
823
|
|
|
736
|
-
|
|
737
|
-
// ✅ Good
|
|
738
|
-
function App() {
|
|
739
|
-
return (
|
|
740
|
-
<AuthProvider>
|
|
741
|
-
<Navigator />
|
|
742
|
-
</AuthProvider>
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
// ❌ Bad - Missing provider
|
|
747
|
-
function App() {
|
|
748
|
-
return <Navigator />;
|
|
749
|
-
}
|
|
750
|
-
```
|
|
751
|
-
|
|
752
|
-
## 3. Handle Loading States
|
|
824
|
+
---
|
|
753
825
|
|
|
754
|
-
|
|
755
|
-
// ✅ Good
|
|
756
|
-
function Component() {
|
|
757
|
-
const { loading, isAuthReady, user } = useAuth();
|
|
826
|
+
## Related Modules
|
|
758
827
|
|
|
759
|
-
|
|
760
|
-
|
|
828
|
+
- **Domain** (`../domain/README.md`) - AuthUser entity, errors
|
|
829
|
+
- **Application** (`../application/README.md`) - Service interfaces
|
|
830
|
+
- **Infrastructure** (`../infrastructure/README.md`) - Service implementations
|
|
761
831
|
|
|
762
|
-
|
|
763
|
-
}
|
|
764
|
-
```
|
|
832
|
+
---
|
|
765
833
|
|
|
766
|
-
##
|
|
834
|
+
## Subdirectories
|
|
767
835
|
|
|
768
|
-
- **
|
|
769
|
-
- **
|
|
770
|
-
- **
|
|
836
|
+
- **Hooks**: `hooks/README.md`
|
|
837
|
+
- **Components**: `components/README.md`
|
|
838
|
+
- **Screens**: `screens/README.md`
|