@umituz/react-native-validation 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Ümit UZ
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # @umituz/react-native-validation
2
+
3
+ Comprehensive validation utilities for React Native forms. Provides reusable validation functions for common input types.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @umituz/react-native-validation
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ - `react` >= 18.2.0
14
+ - `react-native` >= 0.74.0
15
+
16
+ ## Features
17
+
18
+ - ✅ Email validation
19
+ - ✅ Password validation (with strength requirements)
20
+ - ✅ Phone number validation (E.164 format)
21
+ - ✅ Required field validation
22
+ - ✅ Name validation
23
+ - ✅ Number range validation
24
+ - ✅ Min/Max length validation
25
+ - ✅ Pattern (regex) validation
26
+ - ✅ Date of birth validation
27
+ - ✅ Health & fitness validators (weight, height, age, calories, macros, etc.)
28
+ - ✅ Batch validation
29
+ - ✅ TypeScript type safety
30
+
31
+ ## Usage
32
+
33
+ ### Basic Example
34
+
35
+ ```typescript
36
+ import { validateEmail, validatePassword, validateRequired } from '@umituz/react-native-validation';
37
+
38
+ // Validate email
39
+ const emailResult = validateEmail('user@example.com');
40
+ if (!emailResult.isValid) {
41
+ console.error(emailResult.error);
42
+ }
43
+
44
+ // Validate password
45
+ const passwordResult = validatePassword('MySecure123', {
46
+ minLength: 8,
47
+ requireUppercase: true,
48
+ requireLowercase: true,
49
+ requireNumber: true,
50
+ });
51
+
52
+ // Validate required field
53
+ const requiredResult = validateRequired('value', 'Field Name');
54
+ ```
55
+
56
+ ### Form Validation Example
57
+
58
+ ```typescript
59
+ import {
60
+ validateEmail,
61
+ validatePassword,
62
+ validatePasswordConfirmation,
63
+ validateRequired,
64
+ batchValidate,
65
+ } from '@umituz/react-native-validation';
66
+
67
+ const validateForm = (email: string, password: string, confirmPassword: string) => {
68
+ return batchValidate([
69
+ { field: 'email', validator: () => validateEmail(email) },
70
+ { field: 'password', validator: () => validatePassword(password) },
71
+ {
72
+ field: 'confirmPassword',
73
+ validator: () => validatePasswordConfirmation(password, confirmPassword),
74
+ },
75
+ ]);
76
+ };
77
+
78
+ const result = validateForm('user@example.com', 'MySecure123', 'MySecure123');
79
+ if (!result.isValid) {
80
+ console.log('Validation errors:', result.errors);
81
+ }
82
+ ```
83
+
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
+ ### Custom Validation
103
+
104
+ ```typescript
105
+ import { validatePattern, validateNumberRange } from '@umituz/react-native-validation';
106
+
107
+ // Validate with custom pattern
108
+ const patternResult = validatePattern(
109
+ 'ABC123',
110
+ /^[A-Z]{3}\d{3}$/,
111
+ 'Code',
112
+ 'Code must be 3 uppercase letters followed by 3 numbers'
113
+ );
114
+
115
+ // Validate number range
116
+ const rangeResult = validateNumberRange(50, 0, 100, 'Percentage');
117
+ ```
118
+
119
+ ## API Reference
120
+
121
+ ### Core Validators
122
+
123
+ - `validateEmail(email: string): ValidationResult`
124
+ - `validatePassword(password: string, options?: PasswordOptions): ValidationResult`
125
+ - `validatePasswordConfirmation(password: string, confirmPassword: string): ValidationResult`
126
+ - `validateRequired(value: string, fieldName?: string): ValidationResult`
127
+ - `validateName(name: string, fieldName?: string, minLength?: number): ValidationResult`
128
+ - `validatePhone(phone: string): ValidationResult`
129
+
130
+ ### Number Validators
131
+
132
+ - `validateNumberRange(value: number, min: number, max: number, fieldName?: string): ValidationResult`
133
+ - `validatePositiveNumber(value: number, fieldName?: string): ValidationResult`
134
+
135
+ ### String Validators
136
+
137
+ - `validateMinLength(value: string, minLength: number, fieldName?: string): ValidationResult`
138
+ - `validateMaxLength(value: string, maxLength: number, fieldName?: string): ValidationResult`
139
+ - `validatePattern(value: string, pattern: RegExp, fieldName?: string, errorMessage?: string): ValidationResult`
140
+
141
+ ### Date Validators
142
+
143
+ - `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)
157
+
158
+ ### Batch Validation
159
+
160
+ - `batchValidate(validations: Array<{ field: string; validator: () => ValidationResult }>): { isValid: boolean; errors: Record<string, string> }`
161
+
162
+ ## Types
163
+
164
+ ```typescript
165
+ interface ValidationResult {
166
+ isValid: boolean;
167
+ error?: string;
168
+ }
169
+
170
+ interface PasswordOptions {
171
+ minLength?: number;
172
+ requireUppercase?: boolean;
173
+ requireLowercase?: boolean;
174
+ requireNumber?: boolean;
175
+ }
176
+ ```
177
+
178
+ ## License
179
+
180
+ MIT
181
+
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Validation Result Entity
3
+ * Standard return type for all validation functions
4
+ */
5
+ export interface ValidationResult {
6
+ isValid: boolean;
7
+ error?: string;
8
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Validation Result Entity
4
+ * Standard return type for all validation functions
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @umituz/react-native-validation
3
+ *
4
+ * Comprehensive validation utilities for React Native forms.
5
+ * Provides reusable validation functions for common input types.
6
+ *
7
+ * @package react-native-validation
8
+ */
9
+ export type { ValidationResult } from './domain/entities/ValidationResult';
10
+ export { validateEmail, validatePassword, validatePasswordConfirmation, validateRequired, validateName, validatePhone, validateNumberRange, validatePositiveNumber, validateMinLength, validateMaxLength, validatePattern, validateDateOfBirth, validateAge, validateWeight, validateHeight, validateCalories, validateMacros, validateWaterIntake, validateWorkoutDuration, validateReps, validateSets, validateExerciseWeight, batchValidate, } from './infrastructure/utils/validators';
package/lib/index.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * @umituz/react-native-validation
4
+ *
5
+ * Comprehensive validation utilities for React Native forms.
6
+ * Provides reusable validation functions for common input types.
7
+ *
8
+ * @package react-native-validation
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.batchValidate = exports.validateExerciseWeight = exports.validateSets = exports.validateReps = exports.validateWorkoutDuration = exports.validateWaterIntake = exports.validateMacros = exports.validateCalories = exports.validateHeight = exports.validateWeight = 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
+ // Infrastructure Layer - Validators
13
+ var validators_1 = require("./infrastructure/utils/validators");
14
+ Object.defineProperty(exports, "validateEmail", { enumerable: true, get: function () { return validators_1.validateEmail; } });
15
+ Object.defineProperty(exports, "validatePassword", { enumerable: true, get: function () { return validators_1.validatePassword; } });
16
+ Object.defineProperty(exports, "validatePasswordConfirmation", { enumerable: true, get: function () { return validators_1.validatePasswordConfirmation; } });
17
+ Object.defineProperty(exports, "validateRequired", { enumerable: true, get: function () { return validators_1.validateRequired; } });
18
+ Object.defineProperty(exports, "validateName", { enumerable: true, get: function () { return validators_1.validateName; } });
19
+ Object.defineProperty(exports, "validatePhone", { enumerable: true, get: function () { return validators_1.validatePhone; } });
20
+ Object.defineProperty(exports, "validateNumberRange", { enumerable: true, get: function () { return validators_1.validateNumberRange; } });
21
+ Object.defineProperty(exports, "validatePositiveNumber", { enumerable: true, get: function () { return validators_1.validatePositiveNumber; } });
22
+ Object.defineProperty(exports, "validateMinLength", { enumerable: true, get: function () { return validators_1.validateMinLength; } });
23
+ Object.defineProperty(exports, "validateMaxLength", { enumerable: true, get: function () { return validators_1.validateMaxLength; } });
24
+ Object.defineProperty(exports, "validatePattern", { enumerable: true, get: function () { return validators_1.validatePattern; } });
25
+ Object.defineProperty(exports, "validateDateOfBirth", { enumerable: true, get: function () { return validators_1.validateDateOfBirth; } });
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
+ Object.defineProperty(exports, "batchValidate", { enumerable: true, get: function () { return validators_1.batchValidate; } });
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Validation Utilities
3
+ * Comprehensive validation functions for React Native forms
4
+ */
5
+ import type { ValidationResult } from '../../domain/entities/ValidationResult';
6
+ /**
7
+ * Validate email format
8
+ */
9
+ export declare const validateEmail: (email: string) => ValidationResult;
10
+ /**
11
+ * Validate password strength
12
+ * @param password - Password to validate
13
+ * @param minLength - Minimum password length (default: 8)
14
+ * @param requireUppercase - Require uppercase letter (default: true)
15
+ * @param requireLowercase - Require lowercase letter (default: true)
16
+ * @param requireNumber - Require number (default: true)
17
+ */
18
+ export declare const validatePassword: (password: string, options?: {
19
+ minLength?: number;
20
+ requireUppercase?: boolean;
21
+ requireLowercase?: boolean;
22
+ requireNumber?: boolean;
23
+ }) => ValidationResult;
24
+ /**
25
+ * Validate password confirmation
26
+ */
27
+ export declare const validatePasswordConfirmation: (password: string, confirmPassword: string) => ValidationResult;
28
+ /**
29
+ * Validate required field
30
+ */
31
+ export declare const validateRequired: (value: string, fieldName?: string) => ValidationResult;
32
+ /**
33
+ * Validate name
34
+ */
35
+ export declare const validateName: (name: string, fieldName?: string, minLength?: number) => ValidationResult;
36
+ /**
37
+ * Validate phone number (E.164 format)
38
+ */
39
+ export declare const validatePhone: (phone: string) => ValidationResult;
40
+ /**
41
+ * Validate number range
42
+ */
43
+ export declare const validateNumberRange: (value: number, min: number, max: number, fieldName?: string) => ValidationResult;
44
+ /**
45
+ * Validate positive number
46
+ */
47
+ export declare const validatePositiveNumber: (value: number, fieldName?: string) => ValidationResult;
48
+ /**
49
+ * Validate min length
50
+ */
51
+ export declare const validateMinLength: (value: string, minLength: number, fieldName?: string) => ValidationResult;
52
+ /**
53
+ * Validate max length
54
+ */
55
+ export declare const validateMaxLength: (value: string, maxLength: number, fieldName?: string) => ValidationResult;
56
+ /**
57
+ * Validate pattern (regex)
58
+ */
59
+ export declare const validatePattern: (value: string, pattern: RegExp, fieldName?: string, errorMessage?: string) => ValidationResult;
60
+ /**
61
+ * Validate date of birth
62
+ */
63
+ export declare const validateDateOfBirth: (date: Date) => ValidationResult;
64
+ /**
65
+ * Validate age
66
+ */
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
+ /**
105
+ * Batch validation
106
+ * Validates multiple fields and returns all errors
107
+ */
108
+ export declare const batchValidate: (validations: Array<{
109
+ field: string;
110
+ validator: () => ValidationResult;
111
+ }>) => {
112
+ isValid: boolean;
113
+ errors: Record<string, string>;
114
+ };
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ /**
3
+ * Validation Utilities
4
+ * Comprehensive validation functions for React Native forms
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.batchValidate = exports.validateExerciseWeight = exports.validateSets = exports.validateReps = exports.validateWorkoutDuration = exports.validateWaterIntake = exports.validateMacros = exports.validateCalories = exports.validateHeight = exports.validateWeight = 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
+ /**
9
+ * Validate email format
10
+ */
11
+ const validateEmail = (email) => {
12
+ if (!email || email.trim() === '') {
13
+ return { isValid: false, error: 'Email is required' };
14
+ }
15
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
16
+ if (!emailRegex.test(email)) {
17
+ return { isValid: false, error: 'Please enter a valid email address' };
18
+ }
19
+ return { isValid: true };
20
+ };
21
+ exports.validateEmail = validateEmail;
22
+ /**
23
+ * Validate password strength
24
+ * @param password - Password to validate
25
+ * @param minLength - Minimum password length (default: 8)
26
+ * @param requireUppercase - Require uppercase letter (default: true)
27
+ * @param requireLowercase - Require lowercase letter (default: true)
28
+ * @param requireNumber - Require number (default: true)
29
+ */
30
+ const validatePassword = (password, options) => {
31
+ const { minLength = 8, requireUppercase = true, requireLowercase = true, requireNumber = true, } = options || {};
32
+ if (!password || password.trim() === '') {
33
+ return { isValid: false, error: 'Password is required' };
34
+ }
35
+ if (password.length < minLength) {
36
+ return {
37
+ isValid: false,
38
+ error: `Password must be at least ${minLength} characters`,
39
+ };
40
+ }
41
+ if (requireUppercase && !/[A-Z]/.test(password)) {
42
+ return {
43
+ isValid: false,
44
+ error: 'Password must contain at least one uppercase letter',
45
+ };
46
+ }
47
+ if (requireLowercase && !/[a-z]/.test(password)) {
48
+ return {
49
+ isValid: false,
50
+ error: 'Password must contain at least one lowercase letter',
51
+ };
52
+ }
53
+ if (requireNumber && !/[0-9]/.test(password)) {
54
+ return {
55
+ isValid: false,
56
+ error: 'Password must contain at least one number',
57
+ };
58
+ }
59
+ return { isValid: true };
60
+ };
61
+ exports.validatePassword = validatePassword;
62
+ /**
63
+ * Validate password confirmation
64
+ */
65
+ const validatePasswordConfirmation = (password, confirmPassword) => {
66
+ if (!confirmPassword) {
67
+ return { isValid: false, error: 'Please confirm your password' };
68
+ }
69
+ if (password !== confirmPassword) {
70
+ return { isValid: false, error: 'Passwords do not match' };
71
+ }
72
+ return { isValid: true };
73
+ };
74
+ exports.validatePasswordConfirmation = validatePasswordConfirmation;
75
+ /**
76
+ * Validate required field
77
+ */
78
+ const validateRequired = (value, fieldName = 'This field') => {
79
+ if (!value || value.trim() === '') {
80
+ return { isValid: false, error: `${fieldName} is required` };
81
+ }
82
+ return { isValid: true };
83
+ };
84
+ exports.validateRequired = validateRequired;
85
+ /**
86
+ * Validate name
87
+ */
88
+ const validateName = (name, fieldName = 'Name', minLength = 2) => {
89
+ if (!name || name.trim() === '') {
90
+ return { isValid: false, error: `${fieldName} is required` };
91
+ }
92
+ if (name.trim().length < minLength) {
93
+ return {
94
+ isValid: false,
95
+ error: `${fieldName} must be at least ${minLength} characters`,
96
+ };
97
+ }
98
+ return { isValid: true };
99
+ };
100
+ exports.validateName = validateName;
101
+ /**
102
+ * Validate phone number (E.164 format)
103
+ */
104
+ const validatePhone = (phone) => {
105
+ if (!phone || phone.trim() === '') {
106
+ return { isValid: false, error: 'Phone number is required' };
107
+ }
108
+ const phoneRegex = /^\+[1-9]\d{1,14}$/;
109
+ if (!phoneRegex.test(phone)) {
110
+ return { isValid: false, error: 'Please enter a valid phone number' };
111
+ }
112
+ return { isValid: true };
113
+ };
114
+ exports.validatePhone = validatePhone;
115
+ /**
116
+ * Validate number range
117
+ */
118
+ const validateNumberRange = (value, min, max, fieldName = 'Value') => {
119
+ if (isNaN(value)) {
120
+ return { isValid: false, error: `${fieldName} must be a number` };
121
+ }
122
+ if (value < min || value > max) {
123
+ return {
124
+ isValid: false,
125
+ error: `${fieldName} must be between ${min} and ${max}`,
126
+ };
127
+ }
128
+ return { isValid: true };
129
+ };
130
+ exports.validateNumberRange = validateNumberRange;
131
+ /**
132
+ * Validate positive number
133
+ */
134
+ const validatePositiveNumber = (value, fieldName = 'Value') => {
135
+ if (isNaN(value)) {
136
+ return { isValid: false, error: `${fieldName} must be a number` };
137
+ }
138
+ if (value <= 0) {
139
+ return { isValid: false, error: `${fieldName} must be greater than 0` };
140
+ }
141
+ return { isValid: true };
142
+ };
143
+ exports.validatePositiveNumber = validatePositiveNumber;
144
+ /**
145
+ * Validate min length
146
+ */
147
+ const validateMinLength = (value, minLength, fieldName = 'Field') => {
148
+ if (!value || value.trim().length < minLength) {
149
+ return {
150
+ isValid: false,
151
+ error: `${fieldName} must be at least ${minLength} characters`,
152
+ };
153
+ }
154
+ return { isValid: true };
155
+ };
156
+ exports.validateMinLength = validateMinLength;
157
+ /**
158
+ * Validate max length
159
+ */
160
+ const validateMaxLength = (value, maxLength, fieldName = 'Field') => {
161
+ if (value && value.trim().length > maxLength) {
162
+ return {
163
+ isValid: false,
164
+ error: `${fieldName} must be at most ${maxLength} characters`,
165
+ };
166
+ }
167
+ return { isValid: true };
168
+ };
169
+ exports.validateMaxLength = validateMaxLength;
170
+ /**
171
+ * Validate pattern (regex)
172
+ */
173
+ const validatePattern = (value, pattern, fieldName = 'Field', errorMessage) => {
174
+ if (!value) {
175
+ return { isValid: false, error: `${fieldName} is required` };
176
+ }
177
+ if (!pattern.test(value)) {
178
+ return {
179
+ isValid: false,
180
+ error: errorMessage || `${fieldName} format is invalid`,
181
+ };
182
+ }
183
+ return { isValid: true };
184
+ };
185
+ exports.validatePattern = validatePattern;
186
+ /**
187
+ * Validate date of birth
188
+ */
189
+ const validateDateOfBirth = (date) => {
190
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
191
+ return { isValid: false, error: 'Please enter a valid date' };
192
+ }
193
+ const today = new Date();
194
+ const age = today.getFullYear() - date.getFullYear();
195
+ if (age < 13) {
196
+ return { isValid: false, error: 'You must be at least 13 years old' };
197
+ }
198
+ if (age > 120) {
199
+ return { isValid: false, error: 'Please enter a valid date of birth' };
200
+ }
201
+ return { isValid: true };
202
+ };
203
+ exports.validateDateOfBirth = validateDateOfBirth;
204
+ /**
205
+ * Validate age
206
+ */
207
+ const validateAge = (age) => {
208
+ return (0, exports.validateNumberRange)(age, 13, 120, 'Age');
209
+ };
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
+ /**
275
+ * Batch validation
276
+ * Validates multiple fields and returns all errors
277
+ */
278
+ const batchValidate = (validations) => {
279
+ const errors = {};
280
+ let isValid = true;
281
+ validations.forEach(({ field, validator }) => {
282
+ const result = validator();
283
+ if (!result.isValid && result.error) {
284
+ errors[field] = result.error;
285
+ isValid = false;
286
+ }
287
+ });
288
+ return { isValid, errors };
289
+ };
290
+ exports.batchValidate = batchValidate;
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@umituz/react-native-validation",
3
+ "version": "1.0.0",
4
+ "description": "Comprehensive validation utilities for React Native forms",
5
+ "main": "./lib/index.js",
6
+ "types": "./lib/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "typecheck": "tsc --noEmit",
10
+ "lint": "tsc --noEmit",
11
+ "clean": "rm -rf lib",
12
+ "prebuild": "npm run clean",
13
+ "prepublishOnly": "npm run build",
14
+ "version:patch": "npm version patch -m 'chore: release v%s'",
15
+ "version:minor": "npm version minor -m 'chore: release v%s'",
16
+ "version:major": "npm version major -m 'chore: release v%s'"
17
+ },
18
+ "keywords": [
19
+ "react-native",
20
+ "validation",
21
+ "forms",
22
+ "validators",
23
+ "form-validation"
24
+ ],
25
+ "author": "Ümit UZ <umit@umituz.com>",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/umituz/react-native-validation"
30
+ },
31
+ "peerDependencies": {
32
+ "react": ">=18.2.0",
33
+ "react-native": ">=0.74.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/react": "^18.2.45",
37
+ "@types/react-native": "^0.73.0",
38
+ "react": "^18.2.0",
39
+ "react-native": "^0.74.0",
40
+ "typescript": "^5.3.3"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "files": [
46
+ "lib",
47
+ "src",
48
+ "README.md",
49
+ "LICENSE"
50
+ ]
51
+ }
52
+
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Validation Result Entity
3
+ * Standard return type for all validation functions
4
+ */
5
+
6
+ export interface ValidationResult {
7
+ isValid: boolean;
8
+ error?: string;
9
+ }
10
+
package/src/index.ts ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @umituz/react-native-validation
3
+ *
4
+ * Comprehensive validation utilities for React Native forms.
5
+ * Provides reusable validation functions for common input types.
6
+ *
7
+ * @package react-native-validation
8
+ */
9
+
10
+ // Domain Layer - Entities
11
+ export type { ValidationResult } from './domain/entities/ValidationResult';
12
+
13
+ // Infrastructure Layer - Validators
14
+ export {
15
+ validateEmail,
16
+ validatePassword,
17
+ validatePasswordConfirmation,
18
+ validateRequired,
19
+ validateName,
20
+ validatePhone,
21
+ validateNumberRange,
22
+ validatePositiveNumber,
23
+ validateMinLength,
24
+ validateMaxLength,
25
+ validatePattern,
26
+ validateDateOfBirth,
27
+ validateAge,
28
+ validateWeight,
29
+ validateHeight,
30
+ validateCalories,
31
+ validateMacros,
32
+ validateWaterIntake,
33
+ validateWorkoutDuration,
34
+ validateReps,
35
+ validateSets,
36
+ validateExerciseWeight,
37
+ batchValidate,
38
+ } from './infrastructure/utils/validators';
39
+
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Validation Utilities
3
+ * Comprehensive validation functions for React Native forms
4
+ */
5
+
6
+ import type { ValidationResult } from '../../domain/entities/ValidationResult';
7
+
8
+ /**
9
+ * Validate email format
10
+ */
11
+ export const validateEmail = (email: string): ValidationResult => {
12
+ if (!email || email.trim() === '') {
13
+ return { isValid: false, error: 'Email is required' };
14
+ }
15
+
16
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17
+ if (!emailRegex.test(email)) {
18
+ return { isValid: false, error: 'Please enter a valid email address' };
19
+ }
20
+
21
+ return { isValid: true };
22
+ };
23
+
24
+ /**
25
+ * Validate password strength
26
+ * @param password - Password to validate
27
+ * @param minLength - Minimum password length (default: 8)
28
+ * @param requireUppercase - Require uppercase letter (default: true)
29
+ * @param requireLowercase - Require lowercase letter (default: true)
30
+ * @param requireNumber - Require number (default: true)
31
+ */
32
+ export const validatePassword = (
33
+ password: string,
34
+ options?: {
35
+ minLength?: number;
36
+ requireUppercase?: boolean;
37
+ requireLowercase?: boolean;
38
+ requireNumber?: boolean;
39
+ }
40
+ ): ValidationResult => {
41
+ const {
42
+ minLength = 8,
43
+ requireUppercase = true,
44
+ requireLowercase = true,
45
+ requireNumber = true,
46
+ } = options || {};
47
+
48
+ if (!password || password.trim() === '') {
49
+ return { isValid: false, error: 'Password is required' };
50
+ }
51
+
52
+ if (password.length < minLength) {
53
+ return {
54
+ isValid: false,
55
+ error: `Password must be at least ${minLength} characters`,
56
+ };
57
+ }
58
+
59
+ if (requireUppercase && !/[A-Z]/.test(password)) {
60
+ return {
61
+ isValid: false,
62
+ error: 'Password must contain at least one uppercase letter',
63
+ };
64
+ }
65
+
66
+ if (requireLowercase && !/[a-z]/.test(password)) {
67
+ return {
68
+ isValid: false,
69
+ error: 'Password must contain at least one lowercase letter',
70
+ };
71
+ }
72
+
73
+ if (requireNumber && !/[0-9]/.test(password)) {
74
+ return {
75
+ isValid: false,
76
+ error: 'Password must contain at least one number',
77
+ };
78
+ }
79
+
80
+ return { isValid: true };
81
+ };
82
+
83
+ /**
84
+ * Validate password confirmation
85
+ */
86
+ export const validatePasswordConfirmation = (
87
+ password: string,
88
+ confirmPassword: string
89
+ ): ValidationResult => {
90
+ if (!confirmPassword) {
91
+ return { isValid: false, error: 'Please confirm your password' };
92
+ }
93
+
94
+ if (password !== confirmPassword) {
95
+ return { isValid: false, error: 'Passwords do not match' };
96
+ }
97
+
98
+ return { isValid: true };
99
+ };
100
+
101
+ /**
102
+ * Validate required field
103
+ */
104
+ export const validateRequired = (
105
+ value: string,
106
+ fieldName: string = 'This field'
107
+ ): ValidationResult => {
108
+ if (!value || value.trim() === '') {
109
+ return { isValid: false, error: `${fieldName} is required` };
110
+ }
111
+
112
+ return { isValid: true };
113
+ };
114
+
115
+ /**
116
+ * Validate name
117
+ */
118
+ export const validateName = (
119
+ name: string,
120
+ fieldName: string = 'Name',
121
+ minLength: number = 2
122
+ ): ValidationResult => {
123
+ if (!name || name.trim() === '') {
124
+ return { isValid: false, error: `${fieldName} is required` };
125
+ }
126
+
127
+ if (name.trim().length < minLength) {
128
+ return {
129
+ isValid: false,
130
+ error: `${fieldName} must be at least ${minLength} characters`,
131
+ };
132
+ }
133
+
134
+ return { isValid: true };
135
+ };
136
+
137
+ /**
138
+ * Validate phone number (E.164 format)
139
+ */
140
+ export const validatePhone = (phone: string): ValidationResult => {
141
+ if (!phone || phone.trim() === '') {
142
+ return { isValid: false, error: 'Phone number is required' };
143
+ }
144
+
145
+ const phoneRegex = /^\+[1-9]\d{1,14}$/;
146
+ if (!phoneRegex.test(phone)) {
147
+ return { isValid: false, error: 'Please enter a valid phone number' };
148
+ }
149
+
150
+ return { isValid: true };
151
+ };
152
+
153
+ /**
154
+ * Validate number range
155
+ */
156
+ export const validateNumberRange = (
157
+ value: number,
158
+ min: number,
159
+ max: number,
160
+ fieldName: string = 'Value'
161
+ ): ValidationResult => {
162
+ if (isNaN(value)) {
163
+ return { isValid: false, error: `${fieldName} must be a number` };
164
+ }
165
+
166
+ if (value < min || value > max) {
167
+ return {
168
+ isValid: false,
169
+ error: `${fieldName} must be between ${min} and ${max}`,
170
+ };
171
+ }
172
+
173
+ return { isValid: true };
174
+ };
175
+
176
+ /**
177
+ * Validate positive number
178
+ */
179
+ export const validatePositiveNumber = (
180
+ value: number,
181
+ fieldName: string = 'Value'
182
+ ): ValidationResult => {
183
+ if (isNaN(value)) {
184
+ return { isValid: false, error: `${fieldName} must be a number` };
185
+ }
186
+
187
+ if (value <= 0) {
188
+ return { isValid: false, error: `${fieldName} must be greater than 0` };
189
+ }
190
+
191
+ return { isValid: true };
192
+ };
193
+
194
+ /**
195
+ * Validate min length
196
+ */
197
+ export const validateMinLength = (
198
+ value: string,
199
+ minLength: number,
200
+ fieldName: string = 'Field'
201
+ ): ValidationResult => {
202
+ if (!value || value.trim().length < minLength) {
203
+ return {
204
+ isValid: false,
205
+ error: `${fieldName} must be at least ${minLength} characters`,
206
+ };
207
+ }
208
+
209
+ return { isValid: true };
210
+ };
211
+
212
+ /**
213
+ * Validate max length
214
+ */
215
+ export const validateMaxLength = (
216
+ value: string,
217
+ maxLength: number,
218
+ fieldName: string = 'Field'
219
+ ): ValidationResult => {
220
+ if (value && value.trim().length > maxLength) {
221
+ return {
222
+ isValid: false,
223
+ error: `${fieldName} must be at most ${maxLength} characters`,
224
+ };
225
+ }
226
+
227
+ return { isValid: true };
228
+ };
229
+
230
+ /**
231
+ * Validate pattern (regex)
232
+ */
233
+ export const validatePattern = (
234
+ value: string,
235
+ pattern: RegExp,
236
+ fieldName: string = 'Field',
237
+ errorMessage?: string
238
+ ): ValidationResult => {
239
+ if (!value) {
240
+ return { isValid: false, error: `${fieldName} is required` };
241
+ }
242
+
243
+ if (!pattern.test(value)) {
244
+ return {
245
+ isValid: false,
246
+ error: errorMessage || `${fieldName} format is invalid`,
247
+ };
248
+ }
249
+
250
+ return { isValid: true };
251
+ };
252
+
253
+ /**
254
+ * Validate date of birth
255
+ */
256
+ export const validateDateOfBirth = (date: Date): ValidationResult => {
257
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
258
+ return { isValid: false, error: 'Please enter a valid date' };
259
+ }
260
+
261
+ const today = new Date();
262
+ const age = today.getFullYear() - date.getFullYear();
263
+
264
+ if (age < 13) {
265
+ return { isValid: false, error: 'You must be at least 13 years old' };
266
+ }
267
+
268
+ if (age > 120) {
269
+ return { isValid: false, error: 'Please enter a valid date of birth' };
270
+ }
271
+
272
+ return { isValid: true };
273
+ };
274
+
275
+ /**
276
+ * Validate age
277
+ */
278
+ export const validateAge = (age: number): ValidationResult => {
279
+ return validateNumberRange(age, 13, 120, 'Age');
280
+ };
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
+ /**
349
+ * Batch validation
350
+ * Validates multiple fields and returns all errors
351
+ */
352
+ export const batchValidate = (
353
+ validations: Array<{ field: string; validator: () => ValidationResult }>
354
+ ): { isValid: boolean; errors: Record<string, string> } => {
355
+ const errors: Record<string, string> = {};
356
+ let isValid = true;
357
+
358
+ validations.forEach(({ field, validator }) => {
359
+ const result = validator();
360
+ if (!result.isValid && result.error) {
361
+ errors[field] = result.error;
362
+ isValid = false;
363
+ }
364
+ });
365
+
366
+ return { isValid, errors };
367
+ };
368
+