@umituz/react-native-auth 3.4.30 → 3.4.31
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 +331 -0
- package/src/presentation/components/PasswordIndicators.md +471 -0
- package/src/presentation/components/ProfileComponents.md +432 -0
- package/src/presentation/components/README.md +117 -0
- package/src/presentation/components/SocialLoginButtons.md +303 -0
- package/src/presentation/hooks/README.md +122 -0
- package/src/presentation/hooks/useAccountManagement.md +380 -0
- package/src/presentation/hooks/useAuth.md +255 -0
- package/src/presentation/hooks/useAuthBottomSheet.md +417 -0
- package/src/presentation/hooks/useAuthRequired.md +248 -0
- package/src/presentation/hooks/useProfileUpdate.md +327 -0
- package/src/presentation/hooks/useSocialLogin.md +411 -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,545 @@
|
|
|
1
|
+
# AuthConfig & AuthError
|
|
2
|
+
|
|
3
|
+
Authentication configuration value objects and domain-specific error classes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AuthConfig
|
|
8
|
+
|
|
9
|
+
Authentication configuration value object containing password and social auth settings.
|
|
10
|
+
|
|
11
|
+
## Type Definitions
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import type {
|
|
15
|
+
AuthConfig,
|
|
16
|
+
PasswordConfig,
|
|
17
|
+
SocialAuthConfig,
|
|
18
|
+
GoogleAuthConfig,
|
|
19
|
+
AppleAuthConfig,
|
|
20
|
+
SocialAuthProvider,
|
|
21
|
+
DEFAULT_AUTH_CONFIG,
|
|
22
|
+
DEFAULT_PASSWORD_CONFIG,
|
|
23
|
+
DEFAULT_SOCIAL_CONFIG,
|
|
24
|
+
} from '@umituz/react-native-auth';
|
|
25
|
+
|
|
26
|
+
interface PasswordConfig {
|
|
27
|
+
minLength: number; // Minimum password length
|
|
28
|
+
requireUppercase: boolean; // Require uppercase letter
|
|
29
|
+
requireLowercase: boolean; // Require lowercase letter
|
|
30
|
+
requireNumber: boolean; // Require number
|
|
31
|
+
requireSpecialChar: boolean; // Require special character
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface GoogleAuthConfig {
|
|
35
|
+
enabled?: boolean; // Is enabled
|
|
36
|
+
webClientId?: string; // Web client ID
|
|
37
|
+
iosClientId?: string; // iOS client ID
|
|
38
|
+
androidClientId?: string; // Android client ID
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface AppleAuthConfig {
|
|
42
|
+
enabled?: boolean; // Is enabled (iOS only)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface SocialAuthConfig {
|
|
46
|
+
google?: GoogleAuthConfig;
|
|
47
|
+
apple?: AppleAuthConfig;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface AuthConfig {
|
|
51
|
+
password: PasswordConfig;
|
|
52
|
+
social?: SocialAuthConfig;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
type SocialAuthProvider = 'google' | 'apple';
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Default Values
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import {
|
|
62
|
+
DEFAULT_PASSWORD_CONFIG,
|
|
63
|
+
DEFAULT_SOCIAL_CONFIG,
|
|
64
|
+
DEFAULT_AUTH_CONFIG,
|
|
65
|
+
} from '@umituz/react-native-auth';
|
|
66
|
+
|
|
67
|
+
// Default password configuration
|
|
68
|
+
DEFAULT_PASSWORD_CONFIG;
|
|
69
|
+
// {
|
|
70
|
+
// minLength: 6,
|
|
71
|
+
// requireUppercase: false,
|
|
72
|
+
// requireLowercase: false,
|
|
73
|
+
// requireNumber: false,
|
|
74
|
+
// requireSpecialChar: false,
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
// Default social configuration
|
|
78
|
+
DEFAULT_SOCIAL_CONFIG;
|
|
79
|
+
// {
|
|
80
|
+
// google: { enabled: false },
|
|
81
|
+
// apple: { enabled: false },
|
|
82
|
+
// }
|
|
83
|
+
|
|
84
|
+
// Default auth configuration
|
|
85
|
+
DEFAULT_AUTH_CONFIG;
|
|
86
|
+
// {
|
|
87
|
+
// password: DEFAULT_PASSWORD_CONFIG,
|
|
88
|
+
// social: DEFAULT_SOCIAL_CONFIG,
|
|
89
|
+
// }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
### Custom Password Config
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const strictPasswordConfig: PasswordConfig = {
|
|
98
|
+
minLength: 8,
|
|
99
|
+
requireUppercase: true,
|
|
100
|
+
requireLowercase: true,
|
|
101
|
+
requireNumber: true,
|
|
102
|
+
requireSpecialChar: true,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const authConfig: AuthConfig = {
|
|
106
|
+
password: strictPasswordConfig,
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Social Auth Config
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const socialAuthConfig: SocialAuthConfig = {
|
|
114
|
+
google: {
|
|
115
|
+
enabled: true,
|
|
116
|
+
webClientId: 'your-web-client-id.apps.googleusercontent.com',
|
|
117
|
+
iosClientId: 'your-ios-client-id.apps.googleusercontent.com',
|
|
118
|
+
androidClientId: 'your-android-client-id.apps.googleusercontent.com',
|
|
119
|
+
},
|
|
120
|
+
apple: {
|
|
121
|
+
enabled: Platform.OS === 'ios',
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const authConfig: AuthConfig = {
|
|
126
|
+
password: DEFAULT_PASSWORD_CONFIG,
|
|
127
|
+
social: socialAuthConfig,
|
|
128
|
+
};
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Complete Configuration
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
const productionAuthConfig: AuthConfig = {
|
|
135
|
+
password: {
|
|
136
|
+
minLength: 8,
|
|
137
|
+
requireUppercase: true,
|
|
138
|
+
requireLowercase: true,
|
|
139
|
+
requireNumber: true,
|
|
140
|
+
requireSpecialChar: true,
|
|
141
|
+
},
|
|
142
|
+
social: {
|
|
143
|
+
google: {
|
|
144
|
+
enabled: true,
|
|
145
|
+
webClientId: Config.GOOGLE_WEB_CLIENT_ID,
|
|
146
|
+
iosClientId: Config.GOOGLE_IOS_CLIENT_ID,
|
|
147
|
+
androidClientId: Config.GOOGLE_ANDROID_CLIENT_ID,
|
|
148
|
+
},
|
|
149
|
+
apple: {
|
|
150
|
+
enabled: Platform.OS === 'ios',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Environment-Based Config
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { DEFAULT_AUTH_CONFIG } from '@umituz/react-native-auth';
|
|
160
|
+
|
|
161
|
+
function getAuthConfig(): AuthConfig {
|
|
162
|
+
if (__DEV__) {
|
|
163
|
+
// Development: Weak password requirements
|
|
164
|
+
return {
|
|
165
|
+
password: {
|
|
166
|
+
minLength: 6,
|
|
167
|
+
requireUppercase: false,
|
|
168
|
+
requireLowercase: false,
|
|
169
|
+
requireNumber: false,
|
|
170
|
+
requireSpecialChar: false,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Production: Strict password requirements
|
|
176
|
+
return {
|
|
177
|
+
password: {
|
|
178
|
+
minLength: 12,
|
|
179
|
+
requireUppercase: true,
|
|
180
|
+
requireLowercase: true,
|
|
181
|
+
requireNumber: true,
|
|
182
|
+
requireSpecialChar: true,
|
|
183
|
+
},
|
|
184
|
+
social: {
|
|
185
|
+
google: {
|
|
186
|
+
enabled: true,
|
|
187
|
+
webClientId: Config.GOOGLE_WEB_CLIENT_ID,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Config Validation
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
function validatePasswordConfig(config: PasswordConfig): boolean {
|
|
198
|
+
if (config.minLength < 4) {
|
|
199
|
+
console.error('Minimum length must be at least 4');
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (config.minLength > 128) {
|
|
204
|
+
console.error('Minimum length must be at most 128');
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function validateAuthConfig(config: AuthConfig): {
|
|
212
|
+
valid: boolean;
|
|
213
|
+
errors: string[];
|
|
214
|
+
} {
|
|
215
|
+
const errors: string[] = [];
|
|
216
|
+
|
|
217
|
+
if (!validatePasswordConfig(config.password)) {
|
|
218
|
+
errors.push('Invalid password config');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (config.social?.google?.enabled) {
|
|
222
|
+
if (!config.social.google.webClientId) {
|
|
223
|
+
errors.push('Google webClientId is required when enabled');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
valid: errors.length === 0,
|
|
229
|
+
errors,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
# AuthError
|
|
237
|
+
|
|
238
|
+
Domain-specific error classes for authentication.
|
|
239
|
+
|
|
240
|
+
## Error Hierarchy
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
AuthError (base)
|
|
244
|
+
├── AuthInitializationError
|
|
245
|
+
├── AuthConfigurationError
|
|
246
|
+
├── AuthValidationError
|
|
247
|
+
├── AuthNetworkError
|
|
248
|
+
├── AuthUserNotFoundError
|
|
249
|
+
├── AuthWrongPasswordError
|
|
250
|
+
├── AuthEmailAlreadyInUseError
|
|
251
|
+
├── AuthWeakPasswordError
|
|
252
|
+
└── AuthInvalidEmailError
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Error Classes
|
|
256
|
+
|
|
257
|
+
### AuthError (Base)
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import { AuthError } from '@umituz/react-native-auth';
|
|
261
|
+
|
|
262
|
+
throw new AuthError('Authentication failed');
|
|
263
|
+
// { name: 'AuthError', message: 'Authentication failed', code: 'AUTH_ERROR' }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### AuthInitializationError
|
|
267
|
+
|
|
268
|
+
When auth service is not initialized:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { AuthInitializationError } from '@umituz/react-native-auth';
|
|
272
|
+
|
|
273
|
+
if (!authService) {
|
|
274
|
+
throw new AuthInitializationError('Auth service not initialized');
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### AuthConfigurationError
|
|
279
|
+
|
|
280
|
+
Invalid configuration:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import { AuthConfigurationError } from '@umituz/react-native-auth';
|
|
284
|
+
|
|
285
|
+
if (!config.google.webClientId) {
|
|
286
|
+
throw new AuthConfigurationError('Google webClientId is required');
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### AuthValidationError
|
|
291
|
+
|
|
292
|
+
Validation error:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { AuthValidationError } from '@umituz/react-native-auth';
|
|
296
|
+
|
|
297
|
+
if (!email) {
|
|
298
|
+
throw new AuthValidationError('Email is required', 'email');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (password.length < 8) {
|
|
302
|
+
throw new AuthValidationError('Password too short', 'password');
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### AuthNetworkError
|
|
307
|
+
|
|
308
|
+
Network error:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { AuthNetworkError } from '@umituz/react-native-auth';
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
await signIn({ email, password });
|
|
315
|
+
} catch (error) {
|
|
316
|
+
if (error.code === 'auth/network-request-failed') {
|
|
317
|
+
throw new AuthNetworkError('No internet connection');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### AuthUserNotFoundError
|
|
323
|
+
|
|
324
|
+
User not found:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
import { AuthUserNotFoundError } from '@umituz/react-native-auth';
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
await signIn({ email, password });
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (error.code === 'auth/user-not-found') {
|
|
333
|
+
throw new AuthUserNotFoundError('No user found with this email');
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### AuthWrongPasswordError
|
|
339
|
+
|
|
340
|
+
Wrong password:
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
import { AuthWrongPasswordError } from '@umituz/react-native-auth';
|
|
344
|
+
|
|
345
|
+
try {
|
|
346
|
+
await signIn({ email, password });
|
|
347
|
+
} catch (error) {
|
|
348
|
+
if (error.code === 'auth/wrong-password') {
|
|
349
|
+
throw new AuthWrongPasswordError('Incorrect password');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### AuthEmailAlreadyInUseError
|
|
355
|
+
|
|
356
|
+
Email already in use:
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
import { AuthEmailAlreadyInUseError } from '@umituz/react-native-auth';
|
|
360
|
+
|
|
361
|
+
try {
|
|
362
|
+
await signUp({ email, password });
|
|
363
|
+
} catch (error) {
|
|
364
|
+
if (error.code === 'auth/email-already-in-use') {
|
|
365
|
+
throw new AuthEmailAlreadyInUseError('Email already registered');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### AuthWeakPasswordError
|
|
371
|
+
|
|
372
|
+
Weak password:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { AuthWeakPasswordError } from '@umituz/react-native-auth';
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
await signUp({ email, password });
|
|
379
|
+
} catch (error) {
|
|
380
|
+
if (error.code === 'auth/weak-password') {
|
|
381
|
+
throw new AuthWeakPasswordError('Password is too weak');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### AuthInvalidEmailError
|
|
387
|
+
|
|
388
|
+
Invalid email:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import { AuthInvalidEmailError } from '@umituz/react-native-auth';
|
|
392
|
+
|
|
393
|
+
try {
|
|
394
|
+
await signUp({ email, password });
|
|
395
|
+
} catch (error) {
|
|
396
|
+
if (error.code === 'auth/invalid-email') {
|
|
397
|
+
throw new AuthInvalidEmailError('Invalid email format');
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## Firebase Error Mapping
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
import {
|
|
406
|
+
AuthError,
|
|
407
|
+
AuthUserNotFoundError,
|
|
408
|
+
AuthWrongPasswordError,
|
|
409
|
+
AuthEmailAlreadyInUseError,
|
|
410
|
+
AuthWeakPasswordError,
|
|
411
|
+
AuthInvalidEmailError,
|
|
412
|
+
AuthNetworkError,
|
|
413
|
+
} from '@umituz/react-native-auth';
|
|
414
|
+
|
|
415
|
+
function mapFirebaseError(error: any): AuthError {
|
|
416
|
+
const code = error.code;
|
|
417
|
+
|
|
418
|
+
switch (code) {
|
|
419
|
+
case 'auth/user-not-found':
|
|
420
|
+
return new AuthUserNotFoundError('User not found');
|
|
421
|
+
|
|
422
|
+
case 'auth/wrong-password':
|
|
423
|
+
return new AuthWrongPasswordError('Incorrect password');
|
|
424
|
+
|
|
425
|
+
case 'auth/email-already-in-use':
|
|
426
|
+
return new AuthEmailAlreadyInUseError('Email already registered');
|
|
427
|
+
|
|
428
|
+
case 'auth/weak-password':
|
|
429
|
+
return new AuthWeakPasswordError('Password is too weak');
|
|
430
|
+
|
|
431
|
+
case 'auth/invalid-email':
|
|
432
|
+
return new AuthInvalidEmailError('Invalid email format');
|
|
433
|
+
|
|
434
|
+
case 'auth/network-request-failed':
|
|
435
|
+
return new AuthNetworkError('Network error');
|
|
436
|
+
|
|
437
|
+
default:
|
|
438
|
+
return new AuthError(error.message || 'Authentication failed');
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Usage
|
|
443
|
+
try {
|
|
444
|
+
await signInWithEmailAndPassword(auth, email, password);
|
|
445
|
+
} catch (error) {
|
|
446
|
+
const authError = mapFirebaseError(error);
|
|
447
|
+
throw authError;
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## Error Handling Pattern
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
async function handleSignIn(email: string, password: string) {
|
|
455
|
+
try {
|
|
456
|
+
await signIn({ email, password });
|
|
457
|
+
} catch (error) {
|
|
458
|
+
if (error instanceof AuthUserNotFoundError) {
|
|
459
|
+
Alert.alert('Error', 'No user found with this email');
|
|
460
|
+
} else if (error instanceof AuthWrongPasswordError) {
|
|
461
|
+
Alert.alert('Error', 'Incorrect password');
|
|
462
|
+
} else if (error instanceof AuthNetworkError) {
|
|
463
|
+
Alert.alert('Error', 'Check your internet connection');
|
|
464
|
+
} else if (error instanceof AuthError) {
|
|
465
|
+
Alert.alert('Error', error.message);
|
|
466
|
+
} else {
|
|
467
|
+
Alert.alert('Error', 'An unexpected error occurred');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Error Type Guards
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
function isAuthError(error: unknown): error is AuthError {
|
|
477
|
+
return error instanceof AuthError;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function isValidationError(error: unknown): error is AuthValidationError {
|
|
481
|
+
return error instanceof AuthValidationError;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Usage
|
|
485
|
+
try {
|
|
486
|
+
await signUp({ email, password });
|
|
487
|
+
} catch (error) {
|
|
488
|
+
if (isValidationError(error)) {
|
|
489
|
+
console.log('Field:', error.field);
|
|
490
|
+
console.log('Message:', error.message);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Error Localization
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
import { getAuthErrorLocalizationKey } from '@umituz/react-native-auth';
|
|
499
|
+
|
|
500
|
+
function getErrorMessage(error: AuthError): string {
|
|
501
|
+
const key = getAuthErrorLocalizationKey(error);
|
|
502
|
+
return t(key); // Translate with i18n
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// Usage
|
|
506
|
+
try {
|
|
507
|
+
await signIn({ email, password });
|
|
508
|
+
} catch (error) {
|
|
509
|
+
if (error instanceof AuthError) {
|
|
510
|
+
const message = getErrorMessage(error);
|
|
511
|
+
Alert.alert('Error', message);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Custom Errors
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
import { AuthError } from '@umituz/react-native-auth';
|
|
520
|
+
|
|
521
|
+
class AuthTooManyAttemptsError extends AuthError {
|
|
522
|
+
constructor(message = 'Too many failed attempts') {
|
|
523
|
+
super(message, 'AUTH_TOO_MANY_ATTEMPTS');
|
|
524
|
+
this.name = 'AuthTooManyAttemptsError';
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
class AuthAccountLockedError extends AuthError {
|
|
529
|
+
constructor(message = 'Account is locked') {
|
|
530
|
+
super(message, 'AUTH_ACCOUNT_LOCKED');
|
|
531
|
+
this.name = 'AuthAccountLockedError';
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Usage
|
|
536
|
+
if (failedAttempts >= 5) {
|
|
537
|
+
throw new AuthTooManyAttemptsError('Too many failed attempts. Please try again in 5 minutes.');
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
## Related Modules
|
|
542
|
+
|
|
543
|
+
- **[Domain](../README.md)** - Domain layer
|
|
544
|
+
- **[Infrastructure](../../infrastructure/README.md)** - Infrastructure implementation
|
|
545
|
+
- **[Validation Utils](../../infrastructure/utils/AuthValidation.ts)** - Validation utilities
|