@umituz/react-native-auth 3.4.29 → 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.
@@ -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