@umituz/react-native-auth 3.4.30 → 3.4.32
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 +426 -0
- package/package.json +1 -3
- package/src/application/README.md +513 -0
- package/src/domain/ConfigAndErrors.md +545 -0
- package/src/domain/README.md +293 -0
- package/src/domain/entities/AuthUser.md +377 -0
- package/src/domain/entities/UserProfile.md +443 -0
- package/src/infrastructure/README.md +576 -0
- package/src/infrastructure/services/README.md +417 -0
- package/src/presentation/README.md +770 -0
- package/src/presentation/components/AuthBackground.tsx +21 -0
- package/src/presentation/components/AuthContainer.tsx +3 -3
- package/src/presentation/components/LoginForm.md +222 -0
- package/src/presentation/components/PasswordIndicators.md +260 -0
- package/src/presentation/components/ProfileComponents.md +575 -0
- package/src/presentation/components/README.md +117 -0
- package/src/presentation/components/SocialLoginButtons.md +340 -0
- package/src/presentation/hooks/README.md +122 -0
- package/src/presentation/hooks/useAccountManagement.md +386 -0
- package/src/presentation/hooks/useAuth.md +255 -0
- package/src/presentation/hooks/useAuthBottomSheet.md +414 -0
- package/src/presentation/hooks/useAuthRequired.md +248 -0
- package/src/presentation/hooks/useProfileUpdate.md +327 -0
- package/src/presentation/hooks/useSocialLogin.md +356 -0
- package/src/presentation/hooks/useUserProfile.md +230 -0
- package/src/presentation/screens/README.md +198 -0
- package/src/presentation/components/AuthGradientBackground.tsx +0 -33
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
# Infrastructure Layer
|
|
2
|
+
|
|
3
|
+
React Native Auth package infrastructure layer. Contains implementations of application interfaces and external service integrations.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
infrastructure/
|
|
9
|
+
├── providers/
|
|
10
|
+
│ └── FirebaseAuthProvider.ts # Firebase auth implementation
|
|
11
|
+
├── services/
|
|
12
|
+
│ ├── AuthService.ts # Main auth service
|
|
13
|
+
│ ├── initializeAuth.ts # Auth initialization
|
|
14
|
+
│ ├── UserDocumentService.ts # User document management
|
|
15
|
+
│ ├── AnonymousModeService.ts # Anonymous user service
|
|
16
|
+
│ └── AuthEventService.ts # Event handling
|
|
17
|
+
├── adapters/
|
|
18
|
+
│ └── StorageProviderAdapter.ts # Storage adapter
|
|
19
|
+
└── utils/
|
|
20
|
+
└── AuthValidation.ts # Validation utilities
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
The infrastructure layer implements the interfaces defined in the application layer and handles all external integrations:
|
|
26
|
+
|
|
27
|
+
- **Firebase Authentication**: Primary auth provider implementation
|
|
28
|
+
- **Firestore**: User document storage
|
|
29
|
+
- **Firebase Storage**: Profile photo storage
|
|
30
|
+
- **Validation**: Input validation utilities
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# FirebaseAuthProvider
|
|
35
|
+
|
|
36
|
+
Firebase Authentication implementation of `IAuthProvider`.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- Email/Password authentication
|
|
41
|
+
- Google sign-in
|
|
42
|
+
- Apple sign-in
|
|
43
|
+
- Anonymous authentication
|
|
44
|
+
- User state management
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { FirebaseAuthProvider } from '@umituz/react-native-auth';
|
|
50
|
+
import { getAuth } from 'firebase/auth';
|
|
51
|
+
|
|
52
|
+
const firebaseAuth = getAuth();
|
|
53
|
+
const provider = new FirebaseAuthProvider(firebaseAuth);
|
|
54
|
+
|
|
55
|
+
// Sign up
|
|
56
|
+
const user = await provider.signUp({
|
|
57
|
+
email: 'user@example.com',
|
|
58
|
+
password: 'password123',
|
|
59
|
+
displayName: 'John Doe',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Sign in
|
|
63
|
+
const user = await provider.signIn({
|
|
64
|
+
email: 'user@example.com',
|
|
65
|
+
password: 'password123',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Sign out
|
|
69
|
+
await provider.signOut();
|
|
70
|
+
|
|
71
|
+
// Get current user
|
|
72
|
+
const currentUser = provider.getCurrentUser();
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
# AuthService
|
|
78
|
+
|
|
79
|
+
Main authentication service that orchestrates all auth operations.
|
|
80
|
+
|
|
81
|
+
## Features
|
|
82
|
+
|
|
83
|
+
- User authentication flow
|
|
84
|
+
- User document creation
|
|
85
|
+
- Error handling
|
|
86
|
+
- State management
|
|
87
|
+
|
|
88
|
+
## Usage
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import {
|
|
92
|
+
AuthService,
|
|
93
|
+
initializeAuthService,
|
|
94
|
+
getAuthService,
|
|
95
|
+
resetAuthService,
|
|
96
|
+
} from '@umituz/react-native-auth';
|
|
97
|
+
|
|
98
|
+
// Initialize (must be called once)
|
|
99
|
+
initializeAuthService({
|
|
100
|
+
firebaseAuth: getAuth(),
|
|
101
|
+
onAuthStateChanged: (user) => {
|
|
102
|
+
console.log('Auth state changed:', user);
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Get service instance
|
|
107
|
+
const authService = getAuthService();
|
|
108
|
+
|
|
109
|
+
// Sign in
|
|
110
|
+
const user = await authService.signIn({
|
|
111
|
+
email: 'user@example.com',
|
|
112
|
+
password: 'password123',
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Sign up
|
|
116
|
+
const user = await authService.signUp({
|
|
117
|
+
email: 'user@example.com',
|
|
118
|
+
password: 'password123',
|
|
119
|
+
displayName: 'John Doe',
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Sign out
|
|
123
|
+
await authService.signOut();
|
|
124
|
+
|
|
125
|
+
// Reset (testing only)
|
|
126
|
+
resetAuthService();
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## API
|
|
130
|
+
|
|
131
|
+
### Methods
|
|
132
|
+
|
|
133
|
+
| Method | Parameters | Returns | Description |
|
|
134
|
+
|--------|------------|---------|-------------|
|
|
135
|
+
| `signIn` | `{ email, password }` | `Promise<AuthUser>` | Sign in with email/password |
|
|
136
|
+
| `signUp` | `{ email, password, displayName? }` | `Promise<AuthUser>` | Create new account |
|
|
137
|
+
| `signOut` | - | `Promise<void>` | Sign out current user |
|
|
138
|
+
| `getCurrentUser` | - | `AuthUser \| null` | Get current user |
|
|
139
|
+
| `sendPasswordResetEmail` | `email` | `Promise<void>` | Send password reset email |
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
# initializeAuth
|
|
144
|
+
|
|
145
|
+
Initializes the authentication system and sets up Firebase Auth state listener.
|
|
146
|
+
|
|
147
|
+
## Features
|
|
148
|
+
|
|
149
|
+
- Firebase Auth initialization
|
|
150
|
+
- Auth state listener setup
|
|
151
|
+
- Automatic user document creation
|
|
152
|
+
- Error handling
|
|
153
|
+
|
|
154
|
+
## Usage
|
|
155
|
+
|
|
156
|
+
### Basic Initialization
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { initializeAuth } from '@umituz/react-native-auth';
|
|
160
|
+
|
|
161
|
+
function App() {
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
const init = async () => {
|
|
164
|
+
await initializeAuth({
|
|
165
|
+
onAuthStateChanged: (user) => {
|
|
166
|
+
console.log('Auth state changed:', user);
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
init();
|
|
172
|
+
}, []);
|
|
173
|
+
|
|
174
|
+
return <AppNavigator />;
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### With Navigation Integration
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { initializeAuth } from '@umituz/react-native-auth';
|
|
182
|
+
|
|
183
|
+
function App() {
|
|
184
|
+
const navigation = useNavigation();
|
|
185
|
+
|
|
186
|
+
useEffect(() => {
|
|
187
|
+
initializeAuth({
|
|
188
|
+
onAuthStateChanged: (user) => {
|
|
189
|
+
if (user) {
|
|
190
|
+
navigation.reset({
|
|
191
|
+
index: 0,
|
|
192
|
+
routes: [{ name: 'Home' }],
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
navigation.reset({
|
|
196
|
+
index: 0,
|
|
197
|
+
routes: [{ name: 'Login' }],
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
onAuthError: (error) => {
|
|
202
|
+
console.error('Auth error:', error);
|
|
203
|
+
Alert.alert('Auth Error', error.message);
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
}, []);
|
|
207
|
+
|
|
208
|
+
return <NavigationContainer>{/* Routes */}</NavigationContainer>;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Check Initialization Status
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { isAuthInitialized, resetAuthInitialization } from '@umituz/react-native-auth';
|
|
216
|
+
|
|
217
|
+
if (isAuthInitialized()) {
|
|
218
|
+
console.log('Auth is initialized');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Reset (testing only)
|
|
222
|
+
resetAuthInitialization();
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
# UserDocumentService
|
|
228
|
+
|
|
229
|
+
Manages user documents in Firestore.
|
|
230
|
+
|
|
231
|
+
## Features
|
|
232
|
+
|
|
233
|
+
- Automatic user document creation
|
|
234
|
+
- User data updates
|
|
235
|
+
- Account deletion marking
|
|
236
|
+
- Custom configuration
|
|
237
|
+
|
|
238
|
+
## Usage
|
|
239
|
+
|
|
240
|
+
### Ensure User Document
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { ensureUserDocument } from '@umituz/react-native-auth';
|
|
244
|
+
|
|
245
|
+
// After user signs in/up, ensure document exists
|
|
246
|
+
const user = await signInWithEmailAndPassword(auth, email, password);
|
|
247
|
+
await ensureUserDocument(user);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Mark User as Deleted
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { markUserDeleted } from '@umituz/react-native-auth';
|
|
254
|
+
|
|
255
|
+
// When user deletes account
|
|
256
|
+
await markUserDeleted(userId);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Configure Service
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { configureUserDocumentService } from '@umituz/react-native-auth';
|
|
263
|
+
|
|
264
|
+
configureUserDocumentService({
|
|
265
|
+
collection: 'customers', // Default: 'users'
|
|
266
|
+
timestamps: true, // Add createdAt, updatedAt
|
|
267
|
+
userData: {
|
|
268
|
+
source: 'app',
|
|
269
|
+
version: '1.0.0',
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Custom User Data
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
await ensureUserDocument(user, {
|
|
278
|
+
role: 'premium',
|
|
279
|
+
subscription: 'monthly',
|
|
280
|
+
preferences: {
|
|
281
|
+
newsletter: true,
|
|
282
|
+
notifications: true,
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
# AnonymousModeService
|
|
290
|
+
|
|
291
|
+
Handles anonymous user authentication.
|
|
292
|
+
|
|
293
|
+
## Features
|
|
294
|
+
|
|
295
|
+
- Anonymous account creation
|
|
296
|
+
- Anonymous user upgrade to regular account
|
|
297
|
+
- Anonymous state management
|
|
298
|
+
|
|
299
|
+
## Usage
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { AnonymousModeService } from '@umituz/react-native-auth';
|
|
303
|
+
|
|
304
|
+
const anonymousService = new AnonymousModeService();
|
|
305
|
+
|
|
306
|
+
// Sign in anonymously
|
|
307
|
+
const user = await anonymousService.signInAnonymously();
|
|
308
|
+
console.log('Anonymous user:', user.uid);
|
|
309
|
+
|
|
310
|
+
// Convert anonymous user to regular user
|
|
311
|
+
const credential = EmailAuthProvider.credential(email, password);
|
|
312
|
+
await linkWithCredential(user, credential);
|
|
313
|
+
console.log('User upgraded:', user.email);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
# AuthEventService
|
|
319
|
+
|
|
320
|
+
Manages authentication events and provides pub/sub functionality.
|
|
321
|
+
|
|
322
|
+
## Features
|
|
323
|
+
|
|
324
|
+
- Event emission
|
|
325
|
+
- Event subscription
|
|
326
|
+
- Type-safe events
|
|
327
|
+
|
|
328
|
+
## Usage
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { AuthEventService } from '@umituz/react-native-auth';
|
|
332
|
+
|
|
333
|
+
const eventService = new AuthEventService();
|
|
334
|
+
|
|
335
|
+
// Subscribe to events
|
|
336
|
+
const unsubscribe = eventService.on('signIn', (user) => {
|
|
337
|
+
console.log('User signed in:', user);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Emit events
|
|
341
|
+
eventService.emit('signIn', user);
|
|
342
|
+
|
|
343
|
+
// Unsubscribe
|
|
344
|
+
unsubscribe();
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Available Events
|
|
348
|
+
|
|
349
|
+
| Event | Payload | Description |
|
|
350
|
+
|-------|---------|-------------|
|
|
351
|
+
| `signIn` | `AuthUser` | User signed in |
|
|
352
|
+
| `signUp` | `AuthUser` | New user registered |
|
|
353
|
+
| `signOut` | `undefined` | User signed out |
|
|
354
|
+
| `authStateChanged` | `AuthUser \| null` | Auth state changed |
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
# StorageProviderAdapter
|
|
359
|
+
|
|
360
|
+
Adapter for storage providers (AsyncStorage, MMKV, etc.).
|
|
361
|
+
|
|
362
|
+
## Usage
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
import {
|
|
366
|
+
createStorageProvider,
|
|
367
|
+
StorageProviderAdapter,
|
|
368
|
+
} from '@umituz/react-native-auth';
|
|
369
|
+
|
|
370
|
+
// Custom implementation
|
|
371
|
+
class CustomStorageAdapter implements StorageProviderAdapter {
|
|
372
|
+
async getItem(key: string): Promise<string | null> {
|
|
373
|
+
return await AsyncStorage.getItem(key);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async setItem(key: string, value: string): Promise<void> {
|
|
377
|
+
await AsyncStorage.setItem(key, value);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async removeItem(key: string): Promise<void> {
|
|
381
|
+
await AsyncStorage.removeItem(key);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Create provider
|
|
386
|
+
const storageProvider = createStorageProvider(new CustomStorageAdapter());
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
# Validation Utilities
|
|
392
|
+
|
|
393
|
+
Input validation utilities for authentication.
|
|
394
|
+
|
|
395
|
+
## Available Validators
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import {
|
|
399
|
+
validateEmail,
|
|
400
|
+
validatePasswordForLogin,
|
|
401
|
+
validatePasswordForRegister,
|
|
402
|
+
validatePasswordConfirmation,
|
|
403
|
+
validateDisplayName,
|
|
404
|
+
DEFAULT_VAL_CONFIG,
|
|
405
|
+
} from '@umituz/react-native-auth';
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Email Validation
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
const result = validateEmail('test@example.com');
|
|
412
|
+
// { isValid: true }
|
|
413
|
+
|
|
414
|
+
const result = validateEmail('invalid-email');
|
|
415
|
+
// { isValid: false, error: 'Invalid email format' }
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Password Validation (Login)
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
const result = validatePasswordForLogin('password123');
|
|
422
|
+
// { isValid: true }
|
|
423
|
+
|
|
424
|
+
const result = validatePasswordForLogin('');
|
|
425
|
+
// { isValid: false, error: 'Password is required' }
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Password Validation (Register)
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
const result = validatePasswordForRegister('MyPass123!');
|
|
432
|
+
// {
|
|
433
|
+
// isValid: true,
|
|
434
|
+
// requirements: {
|
|
435
|
+
// hasMinLength: true,
|
|
436
|
+
// hasUppercase: true,
|
|
437
|
+
// hasLowercase: true,
|
|
438
|
+
// hasNumber: true,
|
|
439
|
+
// hasSpecialChar: true
|
|
440
|
+
// }
|
|
441
|
+
// }
|
|
442
|
+
|
|
443
|
+
const result = validatePasswordForRegister('weak');
|
|
444
|
+
// {
|
|
445
|
+
// isValid: false,
|
|
446
|
+
// requirements: { ... },
|
|
447
|
+
// error: 'Password does not meet requirements'
|
|
448
|
+
// }
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Password Confirmation
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
const result = validatePasswordConfirmation('password123', 'password123');
|
|
455
|
+
// { isValid: true, matches: true }
|
|
456
|
+
|
|
457
|
+
const result = validatePasswordConfirmation('password123', 'different');
|
|
458
|
+
// { isValid: false, matches: false, error: 'Passwords do not match' }
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Display Name Validation
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
const result = validateDisplayName('John Doe');
|
|
465
|
+
// { isValid: true }
|
|
466
|
+
|
|
467
|
+
const result = validateDisplayName('');
|
|
468
|
+
// { isValid: false, error: 'Display name is required' }
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Custom Validation Config
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
import { DEFAULT_VAL_CONFIG } from '@umituz/react-native-auth';
|
|
475
|
+
|
|
476
|
+
// Default config
|
|
477
|
+
DEFAULT_VAL_CONFIG;
|
|
478
|
+
// {
|
|
479
|
+
// password: {
|
|
480
|
+
// minLength: 8,
|
|
481
|
+
// requireUppercase: true,
|
|
482
|
+
// requireLowercase: true,
|
|
483
|
+
// requireNumber: true,
|
|
484
|
+
// requireSpecialChar: true,
|
|
485
|
+
// }
|
|
486
|
+
// }
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
# Error Handling
|
|
492
|
+
|
|
493
|
+
## Firebase Error Mapping
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
import {
|
|
497
|
+
mapFirebaseError,
|
|
498
|
+
AuthUserNotFoundError,
|
|
499
|
+
AuthWrongPasswordError,
|
|
500
|
+
} from '@umituz/react-native-auth';
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
await signInWithEmailAndPassword(auth, email, password);
|
|
504
|
+
} catch (error) {
|
|
505
|
+
const authError = mapFirebaseError(error);
|
|
506
|
+
|
|
507
|
+
if (authError instanceof AuthUserNotFoundError) {
|
|
508
|
+
Alert.alert('Error', 'User not found');
|
|
509
|
+
} else if (authError instanceof AuthWrongPasswordError) {
|
|
510
|
+
Alert.alert('Error', 'Wrong password');
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
# Best Practices
|
|
518
|
+
|
|
519
|
+
## 1. Initialize Early
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
// ✅ Good - Initialize in app root
|
|
523
|
+
function App() {
|
|
524
|
+
useEffect(() => {
|
|
525
|
+
initializeAuth();
|
|
526
|
+
}, []);
|
|
527
|
+
|
|
528
|
+
return <Navigator />;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// ❌ Bad - Initialize in component
|
|
532
|
+
function LoginComponent() {
|
|
533
|
+
useEffect(() => {
|
|
534
|
+
initializeAuth(); // Too late!
|
|
535
|
+
}, []);
|
|
536
|
+
}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
## 2. Handle Initialization State
|
|
540
|
+
|
|
541
|
+
```typescript
|
|
542
|
+
function App() {
|
|
543
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
544
|
+
|
|
545
|
+
useEffect(() => {
|
|
546
|
+
initializeAuth().then(() => setIsInitialized(true));
|
|
547
|
+
}, []);
|
|
548
|
+
|
|
549
|
+
if (!isInitialized) {
|
|
550
|
+
return <LoadingScreen />;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return <AppNavigator />;
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## 3. Check Auth Before Operations
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
async function protectedOperation() {
|
|
561
|
+
const authService = getAuthService();
|
|
562
|
+
const user = authService.getCurrentUser();
|
|
563
|
+
|
|
564
|
+
if (!user) {
|
|
565
|
+
throw new Error('User not authenticated');
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Proceed with operation
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
## Related Modules
|
|
573
|
+
|
|
574
|
+
- **[Domain](../domain/README.md)** - Domain entities
|
|
575
|
+
- **[Application](../application/README.md)** - Application interfaces
|
|
576
|
+
- **[Presentation](../presentation/README.md)** - UI components and hooks
|