@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.
Files changed (30) hide show
  1. package/README.md +347 -348
  2. package/package.json +2 -3
  3. package/src/application/README.md +323 -442
  4. package/src/domain/ConfigAndErrors.md +296 -431
  5. package/src/domain/README.md +361 -210
  6. package/src/domain/entities/AuthUser.md +231 -372
  7. package/src/domain/entities/UserProfile.md +271 -441
  8. package/src/index.ts +35 -0
  9. package/src/infrastructure/README.md +388 -444
  10. package/src/infrastructure/services/README.md +386 -312
  11. package/src/infrastructure/utils/validation/BaseValidators.ts +35 -0
  12. package/src/infrastructure/utils/validation/CollectionValidators.ts +56 -0
  13. package/src/infrastructure/utils/validation/DateValidators.ts +63 -0
  14. package/src/infrastructure/utils/validation/FormValidators.ts +22 -0
  15. package/src/infrastructure/utils/validation/NumberValidators.ts +55 -0
  16. package/src/infrastructure/utils/validation/StringValidators.ts +55 -0
  17. package/src/infrastructure/utils/validation/sanitization.ts +98 -0
  18. package/src/infrastructure/utils/validation/types.ts +15 -0
  19. package/src/presentation/README.md +631 -563
  20. package/src/presentation/components/ProfileComponents.md +307 -504
  21. package/src/presentation/components/README.md +254 -92
  22. package/src/presentation/hooks/README.md +247 -83
  23. package/src/presentation/hooks/useAccountManagement.md +295 -344
  24. package/src/presentation/hooks/useAuth.md +271 -227
  25. package/src/presentation/hooks/useAuthBottomSheet.md +417 -367
  26. package/src/presentation/hooks/useAuthRequired.md +308 -194
  27. package/src/presentation/hooks/useProfileUpdate.md +251 -279
  28. package/src/presentation/hooks/useSocialLogin.md +312 -287
  29. package/src/presentation/hooks/useUserProfile.md +259 -192
  30. package/src/presentation/screens/README.md +151 -153
@@ -0,0 +1,35 @@
1
+ import { ValidationResult } from './types';
2
+
3
+ /**
4
+ * Validate required field (not null, undefined, or empty string)
5
+ */
6
+ export const validateRequired = (
7
+ value: any,
8
+ fieldName: string = "Field",
9
+ errorKey?: string
10
+ ): ValidationResult => {
11
+ const isValid = value !== undefined && value !== null && (typeof value === 'string' ? value.trim() !== "" : true);
12
+
13
+ return {
14
+ isValid,
15
+ error: isValid ? undefined : (errorKey || `${fieldName} is required`)
16
+ };
17
+ };
18
+
19
+ /**
20
+ * Validate pattern (regex)
21
+ */
22
+ export const validatePattern = (
23
+ value: string,
24
+ pattern: RegExp,
25
+ fieldName: string = "Field",
26
+ errorKey?: string
27
+ ): ValidationResult => {
28
+ if (!value) return { isValid: true }; // Use validateRequired for mandatory check
29
+
30
+ const isValid = pattern.test(value);
31
+ return {
32
+ isValid,
33
+ error: isValid ? undefined : (errorKey || `${fieldName} format is invalid`)
34
+ };
35
+ };
@@ -0,0 +1,56 @@
1
+ import { ValidationResult } from './types';
2
+
3
+ /**
4
+ * Custom enum validation
5
+ * Generic validator for enum-like values with custom options
6
+ */
7
+ export const validateEnum = (
8
+ value: string,
9
+ validOptions: readonly string[],
10
+ fieldName: string = "Field",
11
+ errorKey?: string
12
+ ): ValidationResult => {
13
+ if (!value || value.trim() === "") {
14
+ return { isValid: false, error: `${fieldName} is required` };
15
+ }
16
+
17
+ const isValid = validOptions.includes(value.toLowerCase());
18
+ return {
19
+ isValid,
20
+ error: isValid ? undefined : (errorKey || `Please select a valid ${fieldName.toLowerCase()}`)
21
+ };
22
+ };
23
+
24
+ /**
25
+ * Tags validation
26
+ * Generic validator for array of strings with constraints
27
+ */
28
+ export const validateTags = (
29
+ tags: string[],
30
+ maxTags: number = 10,
31
+ maxTagLength: number = 20,
32
+ errorKey?: string
33
+ ): ValidationResult => {
34
+ if (!Array.isArray(tags)) {
35
+ return { isValid: false, error: errorKey || "Tags must be an array" };
36
+ }
37
+
38
+ if (tags.length > maxTags) {
39
+ return { isValid: false, error: errorKey || `Maximum ${maxTags} tags allowed` };
40
+ }
41
+
42
+ for (const tag of tags) {
43
+ if (typeof tag !== "string" || tag.trim().length === 0) {
44
+ return { isValid: false, error: errorKey || "All tags must be non-empty strings" };
45
+ }
46
+
47
+ if (tag.trim().length > maxTagLength) {
48
+ return {
49
+ isValid: false,
50
+ error: errorKey || `Each tag must be at most ${maxTagLength} characters`,
51
+ };
52
+ }
53
+ }
54
+
55
+ return { isValid: true };
56
+ };
@@ -0,0 +1,63 @@
1
+ import { ValidationResult } from './types';
2
+
3
+ /**
4
+ * Validate date of birth
5
+ */
6
+ export const validateDateOfBirth = (
7
+ date: Date,
8
+ minAge: number = 13,
9
+ errorKey?: string
10
+ ): ValidationResult => {
11
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
12
+ return { isValid: false, error: "Please enter a valid date" };
13
+ }
14
+
15
+ const today = new Date();
16
+ let age = today.getFullYear() - date.getFullYear();
17
+ const m = today.getMonth() - date.getMonth();
18
+ if (m < 0 || (m === 0 && today.getDate() < date.getDate())) {
19
+ age--;
20
+ }
21
+
22
+ if (age < minAge) {
23
+ return { isValid: false, error: errorKey || `You must be at least ${minAge} years old` };
24
+ }
25
+
26
+ if (age > 120) {
27
+ return { isValid: false, error: "Please enter a valid date of birth" };
28
+ }
29
+
30
+ return { isValid: true };
31
+ };
32
+
33
+ /**
34
+ * Date range validation
35
+ * Validates date is within a specific range
36
+ */
37
+ export const validateDateRange = (
38
+ date: Date,
39
+ minDate?: Date,
40
+ maxDate?: Date,
41
+ fieldName: string = "Date",
42
+ errorKey?: string
43
+ ): ValidationResult => {
44
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
45
+ return { isValid: false, error: errorKey || `Please enter a valid ${fieldName.toLowerCase()}` };
46
+ }
47
+
48
+ if (minDate && date < minDate) {
49
+ return {
50
+ isValid: false,
51
+ error: errorKey || `${fieldName} cannot be before ${minDate.toLocaleDateString()}`,
52
+ };
53
+ }
54
+
55
+ if (maxDate && date > maxDate) {
56
+ return {
57
+ isValid: false,
58
+ error: errorKey || `${fieldName} cannot be after ${maxDate.toLocaleDateString()}`,
59
+ };
60
+ }
61
+
62
+ return { isValid: true };
63
+ };
@@ -0,0 +1,22 @@
1
+ import { ValidationResult } from './types';
2
+
3
+ /**
4
+ * Batch validation helper
5
+ * Validates multiple fields and returns all errors in a record
6
+ */
7
+ export const batchValidate = (
8
+ validations: Array<{ field: string; validator: () => ValidationResult }>,
9
+ ): { isValid: boolean; errors: Record<string, string> } => {
10
+ const errors: Record<string, string> = {};
11
+ let isValid = true;
12
+
13
+ validations.forEach(({ field, validator }) => {
14
+ const result = validator();
15
+ if (!result.isValid && result.error) {
16
+ errors[field] = result.error;
17
+ isValid = false;
18
+ }
19
+ });
20
+
21
+ return { isValid, errors };
22
+ };
@@ -0,0 +1,55 @@
1
+ import { ValidationResult } from './types';
2
+
3
+ /**
4
+ * Validate numeric range
5
+ */
6
+ export const validateNumberRange = (
7
+ value: number,
8
+ min: number,
9
+ max: number,
10
+ fieldName: string = "Number",
11
+ errorKey?: string
12
+ ): ValidationResult => {
13
+ const isValid = value >= min && value <= max;
14
+ return {
15
+ isValid,
16
+ error: isValid ? undefined : (errorKey || `${fieldName} must be between ${min} and ${max}`)
17
+ };
18
+ };
19
+
20
+ /**
21
+ * Validate positive number
22
+ */
23
+ export const validatePositiveNumber = (
24
+ value: number,
25
+ fieldName: string = "Number",
26
+ errorKey?: string
27
+ ): ValidationResult => {
28
+ const isValid = value > 0;
29
+ return {
30
+ isValid,
31
+ error: isValid ? undefined : (errorKey || `${fieldName} must be a positive number`)
32
+ };
33
+ };
34
+
35
+ /**
36
+ * Validate age based on birth date
37
+ */
38
+ export const validateAge = (
39
+ birthDate: Date,
40
+ minAge: number,
41
+ errorKey?: string
42
+ ): ValidationResult => {
43
+ const today = new Date();
44
+ let age = today.getFullYear() - birthDate.getFullYear();
45
+ const m = today.getMonth() - birthDate.getMonth();
46
+ if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
47
+ age--;
48
+ }
49
+
50
+ const isValid = age >= minAge;
51
+ return {
52
+ isValid,
53
+ error: isValid ? undefined : (errorKey || `You must be at least ${minAge} years old`)
54
+ };
55
+ };
@@ -0,0 +1,55 @@
1
+ import { ValidationResult } from './types';
2
+
3
+ /**
4
+ * Validate min length of a string
5
+ */
6
+ export const validateMinLength = (
7
+ value: string,
8
+ minLength: number,
9
+ fieldName: string = "Field",
10
+ errorKey?: string
11
+ ): ValidationResult => {
12
+ if (!value) return { isValid: false, error: `${fieldName} is required` };
13
+
14
+ const isValid = value.trim().length >= minLength;
15
+ return {
16
+ isValid,
17
+ error: isValid ? undefined : (errorKey || `${fieldName} must be at least ${minLength} characters`)
18
+ };
19
+ };
20
+
21
+ /**
22
+ * Validate max length of a string
23
+ */
24
+ export const validateMaxLength = (
25
+ value: string,
26
+ maxLength: number,
27
+ fieldName: string = "Field",
28
+ errorKey?: string
29
+ ): ValidationResult => {
30
+ if (!value) return { isValid: true };
31
+
32
+ const isValid = value.trim().length <= maxLength;
33
+ return {
34
+ isValid,
35
+ error: isValid ? undefined : (errorKey || `${fieldName} must be at most ${maxLength} characters`)
36
+ };
37
+ };
38
+
39
+ /**
40
+ * Validate phone number (E.164 format)
41
+ */
42
+ export const validatePhone = (
43
+ phone: string,
44
+ errorKey?: string
45
+ ): ValidationResult => {
46
+ if (!phone) return { isValid: true };
47
+
48
+ const phoneRegex = /^\+[1-9]\d{1,14}$/;
49
+ const isValid = phoneRegex.test(phone);
50
+
51
+ return {
52
+ isValid,
53
+ error: isValid ? undefined : (errorKey || "Please enter a valid phone number")
54
+ };
55
+ };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Sanitization Utilities
3
+ * Secure input cleaning for user data
4
+ */
5
+
6
+ /**
7
+ * Security constants for input validation
8
+ */
9
+ export const SECURITY_LIMITS = {
10
+ EMAIL_MAX_LENGTH: 254, // RFC 5321
11
+ PASSWORD_MIN_LENGTH: 6,
12
+ PASSWORD_MAX_LENGTH: 128,
13
+ NAME_MAX_LENGTH: 100,
14
+ GENERAL_TEXT_MAX_LENGTH: 500,
15
+ } as const;
16
+
17
+ /**
18
+ * Trim and normalize whitespace
19
+ */
20
+ export const sanitizeWhitespace = (input: string): string => {
21
+ return input.trim().replace(/\s+/g, ' ');
22
+ };
23
+
24
+ /**
25
+ * Sanitize email address
26
+ * - Trim whitespace
27
+ * - Convert to lowercase
28
+ * - Limit length
29
+ */
30
+ export const sanitizeEmail = (email: string): string => {
31
+ const trimmed = email.trim().toLowerCase();
32
+ return trimmed.substring(0, SECURITY_LIMITS.EMAIL_MAX_LENGTH);
33
+ };
34
+
35
+ /**
36
+ * Sanitize password
37
+ * - Only trim (preserve case and special chars)
38
+ * - Limit length to prevent DoS
39
+ */
40
+ export const sanitizePassword = (password: string): string => {
41
+ // Don't trim password to preserve intentional spaces
42
+ // Only limit length
43
+ return password.substring(0, SECURITY_LIMITS.PASSWORD_MAX_LENGTH);
44
+ };
45
+
46
+ /**
47
+ * Sanitize display name
48
+ * - Trim whitespace
49
+ * - Normalize multiple spaces
50
+ * - Remove potential XSS characters
51
+ * - Limit length
52
+ */
53
+ export const sanitizeName = (name: string): string => {
54
+ const trimmed = sanitizeWhitespace(name);
55
+ // Remove HTML tags and script content
56
+ const noTags = trimmed.replace(/<[^>]*>/g, '');
57
+ return noTags.substring(0, SECURITY_LIMITS.NAME_MAX_LENGTH);
58
+ };
59
+
60
+ /**
61
+ * Sanitize general text input
62
+ * - Trim whitespace
63
+ * - Remove HTML/script tags
64
+ * - Limit length
65
+ */
66
+ export const sanitizeText = (text: string): string => {
67
+ const trimmed = sanitizeWhitespace(text);
68
+ const noTags = trimmed.replace(/<[^>]*>/g, '');
69
+ return noTags.substring(0, SECURITY_LIMITS.GENERAL_TEXT_MAX_LENGTH);
70
+ };
71
+
72
+ /**
73
+ * Check if string contains potentially dangerous characters
74
+ */
75
+ export const containsDangerousChars = (input: string): boolean => {
76
+ // Check for common XSS patterns
77
+ const dangerousPatterns = [
78
+ /<script/i,
79
+ /javascript:/i,
80
+ /on\w+\s*=/i, // onclick, onload, etc.
81
+ /<iframe/i,
82
+ /eval\(/i,
83
+ ];
84
+
85
+ return dangerousPatterns.some(pattern => pattern.test(input));
86
+ };
87
+
88
+ /**
89
+ * Validate string length is within bounds
90
+ */
91
+ export const isWithinLengthLimit = (
92
+ input: string,
93
+ maxLength: number,
94
+ minLength = 0
95
+ ): boolean => {
96
+ const length = input.trim().length;
97
+ return length >= minLength && length <= maxLength;
98
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Validation Result Interface
3
+ * Represents the outcome of a validation operation
4
+ */
5
+ export interface ValidationResult {
6
+ /**
7
+ * Whether the validation passed
8
+ */
9
+ isValid: boolean;
10
+
11
+ /**
12
+ * Error message or translation key if validation failed
13
+ */
14
+ error?: string;
15
+ }