@umituz/react-native-validation 1.0.0 → 1.0.1
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 +46 -33
- package/lib/index.d.ts +2 -1
- package/lib/index.js +11 -10
- package/lib/infrastructure/utils/sanitization.d.ts +54 -0
- package/lib/infrastructure/utils/sanitization.js +95 -0
- package/lib/infrastructure/utils/validators.d.ts +0 -36
- package/lib/infrastructure/utils/validators.js +1 -64
- package/package.json +2 -3
- package/src/index.ts +12 -9
- package/src/infrastructure/utils/sanitization.ts +99 -0
- package/src/infrastructure/utils/validators.ts +0 -66
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @umituz/react-native-validation
|
|
2
2
|
|
|
3
|
-
Comprehensive validation utilities for React Native forms. Provides reusable validation functions for common input types.
|
|
3
|
+
Comprehensive validation and sanitization utilities for React Native forms. Provides reusable validation and sanitization functions for common input types.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,6 +15,7 @@ npm install @umituz/react-native-validation
|
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
|
+
### Validation
|
|
18
19
|
- ✅ Email validation
|
|
19
20
|
- ✅ Password validation (with strength requirements)
|
|
20
21
|
- ✅ Phone number validation (E.164 format)
|
|
@@ -24,8 +25,19 @@ npm install @umituz/react-native-validation
|
|
|
24
25
|
- ✅ Min/Max length validation
|
|
25
26
|
- ✅ Pattern (regex) validation
|
|
26
27
|
- ✅ Date of birth validation
|
|
27
|
-
- ✅
|
|
28
|
+
- ✅ Age validation
|
|
28
29
|
- ✅ Batch validation
|
|
30
|
+
|
|
31
|
+
### Sanitization
|
|
32
|
+
- ✅ Email sanitization
|
|
33
|
+
- ✅ Password sanitization
|
|
34
|
+
- ✅ Name sanitization
|
|
35
|
+
- ✅ Text sanitization
|
|
36
|
+
- ✅ XSS protection
|
|
37
|
+
- ✅ Length limit validation
|
|
38
|
+
- ✅ Whitespace normalization
|
|
39
|
+
|
|
40
|
+
### General
|
|
29
41
|
- ✅ TypeScript type safety
|
|
30
42
|
|
|
31
43
|
## Usage
|
|
@@ -81,24 +93,6 @@ if (!result.isValid) {
|
|
|
81
93
|
}
|
|
82
94
|
```
|
|
83
95
|
|
|
84
|
-
### Health & Fitness Validators
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
import {
|
|
88
|
-
validateWeight,
|
|
89
|
-
validateHeight,
|
|
90
|
-
validateAge,
|
|
91
|
-
validateCalories,
|
|
92
|
-
validateWorkoutDuration,
|
|
93
|
-
} from '@umituz/react-native-validation';
|
|
94
|
-
|
|
95
|
-
const weightResult = validateWeight(75); // kg
|
|
96
|
-
const heightResult = validateHeight(175); // cm
|
|
97
|
-
const ageResult = validateAge(25);
|
|
98
|
-
const caloriesResult = validateCalories(2000);
|
|
99
|
-
const durationResult = validateWorkoutDuration(45); // minutes
|
|
100
|
-
```
|
|
101
|
-
|
|
102
96
|
### Custom Validation
|
|
103
97
|
|
|
104
98
|
```typescript
|
|
@@ -116,6 +110,37 @@ const patternResult = validatePattern(
|
|
|
116
110
|
const rangeResult = validateNumberRange(50, 0, 100, 'Percentage');
|
|
117
111
|
```
|
|
118
112
|
|
|
113
|
+
### Sanitization Example
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import {
|
|
117
|
+
sanitizeEmail,
|
|
118
|
+
sanitizeName,
|
|
119
|
+
sanitizeText,
|
|
120
|
+
containsDangerousChars,
|
|
121
|
+
SECURITY_LIMITS,
|
|
122
|
+
} from '@umituz/react-native-validation';
|
|
123
|
+
|
|
124
|
+
// Sanitize email
|
|
125
|
+
const cleanEmail = sanitizeEmail(' User@Example.COM ');
|
|
126
|
+
// Result: 'user@example.com'
|
|
127
|
+
|
|
128
|
+
// Sanitize name
|
|
129
|
+
const cleanName = sanitizeName(' John Doe ');
|
|
130
|
+
// Result: 'John Doe'
|
|
131
|
+
|
|
132
|
+
// Sanitize text (removes HTML tags)
|
|
133
|
+
const cleanText = sanitizeText('<script>alert("xss")</script>Hello');
|
|
134
|
+
// Result: 'Hello'
|
|
135
|
+
|
|
136
|
+
// Check for dangerous characters
|
|
137
|
+
const isDangerous = containsDangerousChars('<script>alert("xss")</script>');
|
|
138
|
+
// Result: true
|
|
139
|
+
|
|
140
|
+
// Check length limits
|
|
141
|
+
const isValidLength = isWithinLengthLimit('text', SECURITY_LIMITS.NAME_MAX_LENGTH);
|
|
142
|
+
```
|
|
143
|
+
|
|
119
144
|
## API Reference
|
|
120
145
|
|
|
121
146
|
### Core Validators
|
|
@@ -141,19 +166,7 @@ const rangeResult = validateNumberRange(50, 0, 100, 'Percentage');
|
|
|
141
166
|
### Date Validators
|
|
142
167
|
|
|
143
168
|
- `validateDateOfBirth(date: Date): ValidationResult`
|
|
144
|
-
- `validateAge(age: number): ValidationResult`
|
|
145
|
-
|
|
146
|
-
### Health & Fitness Validators
|
|
147
|
-
|
|
148
|
-
- `validateWeight(weight: number): ValidationResult` (20-300 kg)
|
|
149
|
-
- `validateHeight(height: number): ValidationResult` (50-250 cm)
|
|
150
|
-
- `validateCalories(calories: number): ValidationResult` (0-10000)
|
|
151
|
-
- `validateMacros(grams: number, macroType: string): ValidationResult` (0-1000 g)
|
|
152
|
-
- `validateWaterIntake(glasses: number): ValidationResult` (0-50)
|
|
153
|
-
- `validateWorkoutDuration(minutes: number): ValidationResult` (1-600 min)
|
|
154
|
-
- `validateReps(reps: number): ValidationResult` (1-1000)
|
|
155
|
-
- `validateSets(sets: number): ValidationResult` (1-100)
|
|
156
|
-
- `validateExerciseWeight(weight: number): ValidationResult` (0-1000 kg)
|
|
169
|
+
- `validateAge(age: number): ValidationResult` (13-120 years)
|
|
157
170
|
|
|
158
171
|
### Batch Validation
|
|
159
172
|
|
package/lib/index.d.ts
CHANGED
|
@@ -7,4 +7,5 @@
|
|
|
7
7
|
* @package react-native-validation
|
|
8
8
|
*/
|
|
9
9
|
export type { ValidationResult } from './domain/entities/ValidationResult';
|
|
10
|
-
export { validateEmail, validatePassword, validatePasswordConfirmation, validateRequired, validateName, validatePhone, validateNumberRange, validatePositiveNumber, validateMinLength, validateMaxLength, validatePattern, validateDateOfBirth, validateAge,
|
|
10
|
+
export { validateEmail, validatePassword, validatePasswordConfirmation, validateRequired, validateName, validatePhone, validateNumberRange, validatePositiveNumber, validateMinLength, validateMaxLength, validatePattern, validateDateOfBirth, validateAge, batchValidate, } from './infrastructure/utils/validators';
|
|
11
|
+
export { SECURITY_LIMITS, sanitizeWhitespace, sanitizeEmail, sanitizePassword, sanitizeName, sanitizeText, containsDangerousChars, isWithinLengthLimit, } from './infrastructure/utils/sanitization';
|
package/lib/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @package react-native-validation
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.
|
|
11
|
+
exports.isWithinLengthLimit = exports.containsDangerousChars = exports.sanitizeText = exports.sanitizeName = exports.sanitizePassword = exports.sanitizeEmail = exports.sanitizeWhitespace = exports.SECURITY_LIMITS = exports.batchValidate = exports.validateAge = exports.validateDateOfBirth = exports.validatePattern = exports.validateMaxLength = exports.validateMinLength = exports.validatePositiveNumber = exports.validateNumberRange = exports.validatePhone = exports.validateName = exports.validateRequired = exports.validatePasswordConfirmation = exports.validatePassword = exports.validateEmail = void 0;
|
|
12
12
|
// Infrastructure Layer - Validators
|
|
13
13
|
var validators_1 = require("./infrastructure/utils/validators");
|
|
14
14
|
Object.defineProperty(exports, "validateEmail", { enumerable: true, get: function () { return validators_1.validateEmail; } });
|
|
@@ -24,13 +24,14 @@ Object.defineProperty(exports, "validateMaxLength", { enumerable: true, get: fun
|
|
|
24
24
|
Object.defineProperty(exports, "validatePattern", { enumerable: true, get: function () { return validators_1.validatePattern; } });
|
|
25
25
|
Object.defineProperty(exports, "validateDateOfBirth", { enumerable: true, get: function () { return validators_1.validateDateOfBirth; } });
|
|
26
26
|
Object.defineProperty(exports, "validateAge", { enumerable: true, get: function () { return validators_1.validateAge; } });
|
|
27
|
-
Object.defineProperty(exports, "validateWeight", { enumerable: true, get: function () { return validators_1.validateWeight; } });
|
|
28
|
-
Object.defineProperty(exports, "validateHeight", { enumerable: true, get: function () { return validators_1.validateHeight; } });
|
|
29
|
-
Object.defineProperty(exports, "validateCalories", { enumerable: true, get: function () { return validators_1.validateCalories; } });
|
|
30
|
-
Object.defineProperty(exports, "validateMacros", { enumerable: true, get: function () { return validators_1.validateMacros; } });
|
|
31
|
-
Object.defineProperty(exports, "validateWaterIntake", { enumerable: true, get: function () { return validators_1.validateWaterIntake; } });
|
|
32
|
-
Object.defineProperty(exports, "validateWorkoutDuration", { enumerable: true, get: function () { return validators_1.validateWorkoutDuration; } });
|
|
33
|
-
Object.defineProperty(exports, "validateReps", { enumerable: true, get: function () { return validators_1.validateReps; } });
|
|
34
|
-
Object.defineProperty(exports, "validateSets", { enumerable: true, get: function () { return validators_1.validateSets; } });
|
|
35
|
-
Object.defineProperty(exports, "validateExerciseWeight", { enumerable: true, get: function () { return validators_1.validateExerciseWeight; } });
|
|
36
27
|
Object.defineProperty(exports, "batchValidate", { enumerable: true, get: function () { return validators_1.batchValidate; } });
|
|
28
|
+
// Infrastructure Layer - Sanitization
|
|
29
|
+
var sanitization_1 = require("./infrastructure/utils/sanitization");
|
|
30
|
+
Object.defineProperty(exports, "SECURITY_LIMITS", { enumerable: true, get: function () { return sanitization_1.SECURITY_LIMITS; } });
|
|
31
|
+
Object.defineProperty(exports, "sanitizeWhitespace", { enumerable: true, get: function () { return sanitization_1.sanitizeWhitespace; } });
|
|
32
|
+
Object.defineProperty(exports, "sanitizeEmail", { enumerable: true, get: function () { return sanitization_1.sanitizeEmail; } });
|
|
33
|
+
Object.defineProperty(exports, "sanitizePassword", { enumerable: true, get: function () { return sanitization_1.sanitizePassword; } });
|
|
34
|
+
Object.defineProperty(exports, "sanitizeName", { enumerable: true, get: function () { return sanitization_1.sanitizeName; } });
|
|
35
|
+
Object.defineProperty(exports, "sanitizeText", { enumerable: true, get: function () { return sanitization_1.sanitizeText; } });
|
|
36
|
+
Object.defineProperty(exports, "containsDangerousChars", { enumerable: true, get: function () { return sanitization_1.containsDangerousChars; } });
|
|
37
|
+
Object.defineProperty(exports, "isWithinLengthLimit", { enumerable: true, get: function () { return sanitization_1.isWithinLengthLimit; } });
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitization Utilities
|
|
3
|
+
* Secure input cleaning for user data
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Security constants for input validation
|
|
7
|
+
*/
|
|
8
|
+
export declare const SECURITY_LIMITS: {
|
|
9
|
+
readonly EMAIL_MAX_LENGTH: 254;
|
|
10
|
+
readonly PASSWORD_MIN_LENGTH: 6;
|
|
11
|
+
readonly PASSWORD_MAX_LENGTH: 128;
|
|
12
|
+
readonly NAME_MAX_LENGTH: 100;
|
|
13
|
+
readonly GENERAL_TEXT_MAX_LENGTH: 500;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Trim and normalize whitespace
|
|
17
|
+
*/
|
|
18
|
+
export declare const sanitizeWhitespace: (input: string) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Sanitize email address
|
|
21
|
+
* - Trim whitespace
|
|
22
|
+
* - Convert to lowercase
|
|
23
|
+
* - Limit length
|
|
24
|
+
*/
|
|
25
|
+
export declare const sanitizeEmail: (email: string) => string;
|
|
26
|
+
/**
|
|
27
|
+
* Sanitize password
|
|
28
|
+
* - Only trim (preserve case and special chars)
|
|
29
|
+
* - Limit length to prevent DoS
|
|
30
|
+
*/
|
|
31
|
+
export declare const sanitizePassword: (password: string) => string;
|
|
32
|
+
/**
|
|
33
|
+
* Sanitize display name
|
|
34
|
+
* - Trim whitespace
|
|
35
|
+
* - Normalize multiple spaces
|
|
36
|
+
* - Remove potential XSS characters
|
|
37
|
+
* - Limit length
|
|
38
|
+
*/
|
|
39
|
+
export declare const sanitizeName: (name: string) => string;
|
|
40
|
+
/**
|
|
41
|
+
* Sanitize general text input
|
|
42
|
+
* - Trim whitespace
|
|
43
|
+
* - Remove HTML/script tags
|
|
44
|
+
* - Limit length
|
|
45
|
+
*/
|
|
46
|
+
export declare const sanitizeText: (text: string) => string;
|
|
47
|
+
/**
|
|
48
|
+
* Check if string contains potentially dangerous characters
|
|
49
|
+
*/
|
|
50
|
+
export declare const containsDangerousChars: (input: string) => boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Validate string length is within bounds
|
|
53
|
+
*/
|
|
54
|
+
export declare const isWithinLengthLimit: (input: string, maxLength: number, minLength?: number) => boolean;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sanitization Utilities
|
|
4
|
+
* Secure input cleaning for user data
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isWithinLengthLimit = exports.containsDangerousChars = exports.sanitizeText = exports.sanitizeName = exports.sanitizePassword = exports.sanitizeEmail = exports.sanitizeWhitespace = exports.SECURITY_LIMITS = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Security constants for input validation
|
|
10
|
+
*/
|
|
11
|
+
exports.SECURITY_LIMITS = {
|
|
12
|
+
EMAIL_MAX_LENGTH: 254, // RFC 5321
|
|
13
|
+
PASSWORD_MIN_LENGTH: 6,
|
|
14
|
+
PASSWORD_MAX_LENGTH: 128,
|
|
15
|
+
NAME_MAX_LENGTH: 100,
|
|
16
|
+
GENERAL_TEXT_MAX_LENGTH: 500,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Trim and normalize whitespace
|
|
20
|
+
*/
|
|
21
|
+
const sanitizeWhitespace = (input) => {
|
|
22
|
+
return input.trim().replace(/\s+/g, ' ');
|
|
23
|
+
};
|
|
24
|
+
exports.sanitizeWhitespace = sanitizeWhitespace;
|
|
25
|
+
/**
|
|
26
|
+
* Sanitize email address
|
|
27
|
+
* - Trim whitespace
|
|
28
|
+
* - Convert to lowercase
|
|
29
|
+
* - Limit length
|
|
30
|
+
*/
|
|
31
|
+
const sanitizeEmail = (email) => {
|
|
32
|
+
const trimmed = email.trim().toLowerCase();
|
|
33
|
+
return trimmed.substring(0, exports.SECURITY_LIMITS.EMAIL_MAX_LENGTH);
|
|
34
|
+
};
|
|
35
|
+
exports.sanitizeEmail = sanitizeEmail;
|
|
36
|
+
/**
|
|
37
|
+
* Sanitize password
|
|
38
|
+
* - Only trim (preserve case and special chars)
|
|
39
|
+
* - Limit length to prevent DoS
|
|
40
|
+
*/
|
|
41
|
+
const sanitizePassword = (password) => {
|
|
42
|
+
// Don't trim password to preserve intentional spaces
|
|
43
|
+
// Only limit length
|
|
44
|
+
return password.substring(0, exports.SECURITY_LIMITS.PASSWORD_MAX_LENGTH);
|
|
45
|
+
};
|
|
46
|
+
exports.sanitizePassword = sanitizePassword;
|
|
47
|
+
/**
|
|
48
|
+
* Sanitize display name
|
|
49
|
+
* - Trim whitespace
|
|
50
|
+
* - Normalize multiple spaces
|
|
51
|
+
* - Remove potential XSS characters
|
|
52
|
+
* - Limit length
|
|
53
|
+
*/
|
|
54
|
+
const sanitizeName = (name) => {
|
|
55
|
+
const trimmed = (0, exports.sanitizeWhitespace)(name);
|
|
56
|
+
// Remove HTML tags and script content
|
|
57
|
+
const noTags = trimmed.replace(/<[^>]*>/g, '');
|
|
58
|
+
return noTags.substring(0, exports.SECURITY_LIMITS.NAME_MAX_LENGTH);
|
|
59
|
+
};
|
|
60
|
+
exports.sanitizeName = sanitizeName;
|
|
61
|
+
/**
|
|
62
|
+
* Sanitize general text input
|
|
63
|
+
* - Trim whitespace
|
|
64
|
+
* - Remove HTML/script tags
|
|
65
|
+
* - Limit length
|
|
66
|
+
*/
|
|
67
|
+
const sanitizeText = (text) => {
|
|
68
|
+
const trimmed = (0, exports.sanitizeWhitespace)(text);
|
|
69
|
+
const noTags = trimmed.replace(/<[^>]*>/g, '');
|
|
70
|
+
return noTags.substring(0, exports.SECURITY_LIMITS.GENERAL_TEXT_MAX_LENGTH);
|
|
71
|
+
};
|
|
72
|
+
exports.sanitizeText = sanitizeText;
|
|
73
|
+
/**
|
|
74
|
+
* Check if string contains potentially dangerous characters
|
|
75
|
+
*/
|
|
76
|
+
const containsDangerousChars = (input) => {
|
|
77
|
+
// Check for common XSS patterns
|
|
78
|
+
const dangerousPatterns = [
|
|
79
|
+
/<script/i,
|
|
80
|
+
/javascript:/i,
|
|
81
|
+
/on\w+\s*=/i, // onclick, onload, etc.
|
|
82
|
+
/<iframe/i,
|
|
83
|
+
/eval\(/i,
|
|
84
|
+
];
|
|
85
|
+
return dangerousPatterns.some(pattern => pattern.test(input));
|
|
86
|
+
};
|
|
87
|
+
exports.containsDangerousChars = containsDangerousChars;
|
|
88
|
+
/**
|
|
89
|
+
* Validate string length is within bounds
|
|
90
|
+
*/
|
|
91
|
+
const isWithinLengthLimit = (input, maxLength, minLength = 0) => {
|
|
92
|
+
const length = input.trim().length;
|
|
93
|
+
return length >= minLength && length <= maxLength;
|
|
94
|
+
};
|
|
95
|
+
exports.isWithinLengthLimit = isWithinLengthLimit;
|
|
@@ -65,42 +65,6 @@ export declare const validateDateOfBirth: (date: Date) => ValidationResult;
|
|
|
65
65
|
* Validate age
|
|
66
66
|
*/
|
|
67
67
|
export declare const validateAge: (age: number) => ValidationResult;
|
|
68
|
-
/**
|
|
69
|
-
* Validate weight (kg)
|
|
70
|
-
*/
|
|
71
|
-
export declare const validateWeight: (weight: number) => ValidationResult;
|
|
72
|
-
/**
|
|
73
|
-
* Validate height (cm)
|
|
74
|
-
*/
|
|
75
|
-
export declare const validateHeight: (height: number) => ValidationResult;
|
|
76
|
-
/**
|
|
77
|
-
* Validate calories
|
|
78
|
-
*/
|
|
79
|
-
export declare const validateCalories: (calories: number) => ValidationResult;
|
|
80
|
-
/**
|
|
81
|
-
* Validate macros (protein, carbs, fat in grams)
|
|
82
|
-
*/
|
|
83
|
-
export declare const validateMacros: (grams: number, macroType: string) => ValidationResult;
|
|
84
|
-
/**
|
|
85
|
-
* Validate water intake (glasses)
|
|
86
|
-
*/
|
|
87
|
-
export declare const validateWaterIntake: (glasses: number) => ValidationResult;
|
|
88
|
-
/**
|
|
89
|
-
* Validate workout duration (minutes)
|
|
90
|
-
*/
|
|
91
|
-
export declare const validateWorkoutDuration: (minutes: number) => ValidationResult;
|
|
92
|
-
/**
|
|
93
|
-
* Validate reps
|
|
94
|
-
*/
|
|
95
|
-
export declare const validateReps: (reps: number) => ValidationResult;
|
|
96
|
-
/**
|
|
97
|
-
* Validate sets
|
|
98
|
-
*/
|
|
99
|
-
export declare const validateSets: (sets: number) => ValidationResult;
|
|
100
|
-
/**
|
|
101
|
-
* Validate exercise weight (kg)
|
|
102
|
-
*/
|
|
103
|
-
export declare const validateExerciseWeight: (weight: number) => ValidationResult;
|
|
104
68
|
/**
|
|
105
69
|
* Batch validation
|
|
106
70
|
* Validates multiple fields and returns all errors
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Comprehensive validation functions for React Native forms
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.batchValidate = exports.
|
|
7
|
+
exports.batchValidate = exports.validateAge = exports.validateDateOfBirth = exports.validatePattern = exports.validateMaxLength = exports.validateMinLength = exports.validatePositiveNumber = exports.validateNumberRange = exports.validatePhone = exports.validateName = exports.validateRequired = exports.validatePasswordConfirmation = exports.validatePassword = exports.validateEmail = void 0;
|
|
8
8
|
/**
|
|
9
9
|
* Validate email format
|
|
10
10
|
*/
|
|
@@ -208,69 +208,6 @@ const validateAge = (age) => {
|
|
|
208
208
|
return (0, exports.validateNumberRange)(age, 13, 120, 'Age');
|
|
209
209
|
};
|
|
210
210
|
exports.validateAge = validateAge;
|
|
211
|
-
/**
|
|
212
|
-
* Validate weight (kg)
|
|
213
|
-
*/
|
|
214
|
-
const validateWeight = (weight) => {
|
|
215
|
-
return (0, exports.validateNumberRange)(weight, 20, 300, 'Weight');
|
|
216
|
-
};
|
|
217
|
-
exports.validateWeight = validateWeight;
|
|
218
|
-
/**
|
|
219
|
-
* Validate height (cm)
|
|
220
|
-
*/
|
|
221
|
-
const validateHeight = (height) => {
|
|
222
|
-
return (0, exports.validateNumberRange)(height, 50, 250, 'Height');
|
|
223
|
-
};
|
|
224
|
-
exports.validateHeight = validateHeight;
|
|
225
|
-
/**
|
|
226
|
-
* Validate calories
|
|
227
|
-
*/
|
|
228
|
-
const validateCalories = (calories) => {
|
|
229
|
-
return (0, exports.validateNumberRange)(calories, 0, 10000, 'Calories');
|
|
230
|
-
};
|
|
231
|
-
exports.validateCalories = validateCalories;
|
|
232
|
-
/**
|
|
233
|
-
* Validate macros (protein, carbs, fat in grams)
|
|
234
|
-
*/
|
|
235
|
-
const validateMacros = (grams, macroType) => {
|
|
236
|
-
return (0, exports.validateNumberRange)(grams, 0, 1000, macroType);
|
|
237
|
-
};
|
|
238
|
-
exports.validateMacros = validateMacros;
|
|
239
|
-
/**
|
|
240
|
-
* Validate water intake (glasses)
|
|
241
|
-
*/
|
|
242
|
-
const validateWaterIntake = (glasses) => {
|
|
243
|
-
return (0, exports.validateNumberRange)(glasses, 0, 50, 'Water intake');
|
|
244
|
-
};
|
|
245
|
-
exports.validateWaterIntake = validateWaterIntake;
|
|
246
|
-
/**
|
|
247
|
-
* Validate workout duration (minutes)
|
|
248
|
-
*/
|
|
249
|
-
const validateWorkoutDuration = (minutes) => {
|
|
250
|
-
return (0, exports.validateNumberRange)(minutes, 1, 600, 'Workout duration');
|
|
251
|
-
};
|
|
252
|
-
exports.validateWorkoutDuration = validateWorkoutDuration;
|
|
253
|
-
/**
|
|
254
|
-
* Validate reps
|
|
255
|
-
*/
|
|
256
|
-
const validateReps = (reps) => {
|
|
257
|
-
return (0, exports.validateNumberRange)(reps, 1, 1000, 'Reps');
|
|
258
|
-
};
|
|
259
|
-
exports.validateReps = validateReps;
|
|
260
|
-
/**
|
|
261
|
-
* Validate sets
|
|
262
|
-
*/
|
|
263
|
-
const validateSets = (sets) => {
|
|
264
|
-
return (0, exports.validateNumberRange)(sets, 1, 100, 'Sets');
|
|
265
|
-
};
|
|
266
|
-
exports.validateSets = validateSets;
|
|
267
|
-
/**
|
|
268
|
-
* Validate exercise weight (kg)
|
|
269
|
-
*/
|
|
270
|
-
const validateExerciseWeight = (weight) => {
|
|
271
|
-
return (0, exports.validateNumberRange)(weight, 0, 1000, 'Weight');
|
|
272
|
-
};
|
|
273
|
-
exports.validateExerciseWeight = validateExerciseWeight;
|
|
274
211
|
/**
|
|
275
212
|
* Batch validation
|
|
276
213
|
* Validates multiple fields and returns all errors
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-validation",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Comprehensive validation utilities for React Native forms",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Comprehensive validation and sanitization utilities for React Native forms",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -49,4 +49,3 @@
|
|
|
49
49
|
"LICENSE"
|
|
50
50
|
]
|
|
51
51
|
}
|
|
52
|
-
|
package/src/index.ts
CHANGED
|
@@ -25,15 +25,18 @@ export {
|
|
|
25
25
|
validatePattern,
|
|
26
26
|
validateDateOfBirth,
|
|
27
27
|
validateAge,
|
|
28
|
-
validateWeight,
|
|
29
|
-
validateHeight,
|
|
30
|
-
validateCalories,
|
|
31
|
-
validateMacros,
|
|
32
|
-
validateWaterIntake,
|
|
33
|
-
validateWorkoutDuration,
|
|
34
|
-
validateReps,
|
|
35
|
-
validateSets,
|
|
36
|
-
validateExerciseWeight,
|
|
37
28
|
batchValidate,
|
|
38
29
|
} from './infrastructure/utils/validators';
|
|
39
30
|
|
|
31
|
+
// Infrastructure Layer - Sanitization
|
|
32
|
+
export {
|
|
33
|
+
SECURITY_LIMITS,
|
|
34
|
+
sanitizeWhitespace,
|
|
35
|
+
sanitizeEmail,
|
|
36
|
+
sanitizePassword,
|
|
37
|
+
sanitizeName,
|
|
38
|
+
sanitizeText,
|
|
39
|
+
containsDangerousChars,
|
|
40
|
+
isWithinLengthLimit,
|
|
41
|
+
} from './infrastructure/utils/sanitization';
|
|
42
|
+
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
};
|
|
99
|
+
|
|
@@ -279,72 +279,6 @@ export const validateAge = (age: number): ValidationResult => {
|
|
|
279
279
|
return validateNumberRange(age, 13, 120, 'Age');
|
|
280
280
|
};
|
|
281
281
|
|
|
282
|
-
/**
|
|
283
|
-
* Validate weight (kg)
|
|
284
|
-
*/
|
|
285
|
-
export const validateWeight = (weight: number): ValidationResult => {
|
|
286
|
-
return validateNumberRange(weight, 20, 300, 'Weight');
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Validate height (cm)
|
|
291
|
-
*/
|
|
292
|
-
export const validateHeight = (height: number): ValidationResult => {
|
|
293
|
-
return validateNumberRange(height, 50, 250, 'Height');
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Validate calories
|
|
298
|
-
*/
|
|
299
|
-
export const validateCalories = (calories: number): ValidationResult => {
|
|
300
|
-
return validateNumberRange(calories, 0, 10000, 'Calories');
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Validate macros (protein, carbs, fat in grams)
|
|
305
|
-
*/
|
|
306
|
-
export const validateMacros = (
|
|
307
|
-
grams: number,
|
|
308
|
-
macroType: string
|
|
309
|
-
): ValidationResult => {
|
|
310
|
-
return validateNumberRange(grams, 0, 1000, macroType);
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Validate water intake (glasses)
|
|
315
|
-
*/
|
|
316
|
-
export const validateWaterIntake = (glasses: number): ValidationResult => {
|
|
317
|
-
return validateNumberRange(glasses, 0, 50, 'Water intake');
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Validate workout duration (minutes)
|
|
322
|
-
*/
|
|
323
|
-
export const validateWorkoutDuration = (minutes: number): ValidationResult => {
|
|
324
|
-
return validateNumberRange(minutes, 1, 600, 'Workout duration');
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Validate reps
|
|
329
|
-
*/
|
|
330
|
-
export const validateReps = (reps: number): ValidationResult => {
|
|
331
|
-
return validateNumberRange(reps, 1, 1000, 'Reps');
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Validate sets
|
|
336
|
-
*/
|
|
337
|
-
export const validateSets = (sets: number): ValidationResult => {
|
|
338
|
-
return validateNumberRange(sets, 1, 100, 'Sets');
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Validate exercise weight (kg)
|
|
343
|
-
*/
|
|
344
|
-
export const validateExerciseWeight = (weight: number): ValidationResult => {
|
|
345
|
-
return validateNumberRange(weight, 0, 1000, 'Weight');
|
|
346
|
-
};
|
|
347
|
-
|
|
348
282
|
/**
|
|
349
283
|
* Batch validation
|
|
350
284
|
* Validates multiple fields and returns all errors
|