@umituz/react-native-validation 1.4.5 → 1.4.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-validation",
3
- "version": "1.4.5",
3
+ "version": "1.4.6",
4
4
  "description": "Comprehensive validation and sanitization utilities for React Native forms",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  // Domain Layer - Entities
11
- export type { ValidationResult } from './domain/entities/ValidationResult';
11
+ export type { ValidationResult } from "./domain/entities/ValidationResult";
12
12
 
13
13
  // Infrastructure Layer - Validators
14
14
  export {
@@ -24,7 +24,19 @@ export {
24
24
  validateDateOfBirth,
25
25
  validateAge,
26
26
  batchValidate,
27
- } from './infrastructure/utils/validators';
27
+ } from "./infrastructure/utils/validators";
28
+
29
+ // Dream-specific validators
30
+ export {
31
+ validateDreamTitle,
32
+ validateDreamDescription,
33
+ validateDreamMood,
34
+ validateDreamCategory,
35
+ validateDreamDate,
36
+ validateDreamTags,
37
+ validateDreamPrivacy,
38
+ validateDreamForm,
39
+ } from "./infrastructure/utils/validators";
28
40
 
29
41
  // Infrastructure Layer - Sanitization
30
42
  export {
@@ -36,7 +48,7 @@ export {
36
48
  sanitizeText,
37
49
  containsDangerousChars,
38
50
  isWithinLengthLimit,
39
- } from './infrastructure/utils/sanitization';
51
+ } from "./infrastructure/utils/sanitization";
40
52
 
41
53
  // Infrastructure Layer - MIME Type Validation
42
54
  export {
@@ -44,7 +56,7 @@ export {
44
56
  SUPPORTED_IMAGE_MIME_TYPES,
45
57
  EXTENSION_TO_MIME_TYPE,
46
58
  MIME_TYPE_TO_EXTENSION,
47
- } from './infrastructure/utils/mime-types.constants';
59
+ } from "./infrastructure/utils/mime-types.constants";
48
60
 
49
61
  export {
50
62
  getFileExtension,
@@ -53,8 +65,10 @@ export {
53
65
  validateImageMimeType,
54
66
  validateImageExtension,
55
67
  validateImageDataUrl,
56
- } from './infrastructure/utils/mime-type-validator';
68
+ } from "./infrastructure/utils/mime-type-validator";
57
69
 
58
70
  // Infrastructure Layer - Image Validation
59
- export { validateImageUri, getImageMimeType } from './infrastructure/utils/image-validator';
60
-
71
+ export {
72
+ validateImageUri,
73
+ getImageMimeType,
74
+ } from "./infrastructure/utils/image-validator";
@@ -3,19 +3,19 @@
3
3
  * Comprehensive validation functions for React Native forms
4
4
  */
5
5
 
6
- import type { ValidationResult } from '../../domain/entities/ValidationResult';
6
+ import type { ValidationResult } from "../../domain/entities/ValidationResult";
7
7
 
8
8
  /**
9
9
  * Validate email format
10
10
  */
11
11
  export const validateEmail = (email: string): ValidationResult => {
12
- if (!email || email.trim() === '') {
13
- return { isValid: false, error: 'Email is required' };
12
+ if (!email || email.trim() === "") {
13
+ return { isValid: false, error: "Email is required" };
14
14
  }
15
15
 
16
16
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17
17
  if (!emailRegex.test(email)) {
18
- return { isValid: false, error: 'Please enter a valid email address' };
18
+ return { isValid: false, error: "Please enter a valid email address" };
19
19
  }
20
20
 
21
21
  return { isValid: true };
@@ -26,9 +26,9 @@ export const validateEmail = (email: string): ValidationResult => {
26
26
  */
27
27
  export const validateRequired = (
28
28
  value: string,
29
- fieldName: string = 'This field'
29
+ fieldName: string = "This field",
30
30
  ): ValidationResult => {
31
- if (!value || value.trim() === '') {
31
+ if (!value || value.trim() === "") {
32
32
  return { isValid: false, error: `${fieldName} is required` };
33
33
  }
34
34
 
@@ -40,10 +40,10 @@ export const validateRequired = (
40
40
  */
41
41
  export const validateName = (
42
42
  name: string,
43
- fieldName: string = 'Name',
44
- minLength: number = 2
43
+ fieldName: string = "Name",
44
+ minLength: number = 2,
45
45
  ): ValidationResult => {
46
- if (!name || name.trim() === '') {
46
+ if (!name || name.trim() === "") {
47
47
  return { isValid: false, error: `${fieldName} is required` };
48
48
  }
49
49
 
@@ -61,13 +61,13 @@ export const validateName = (
61
61
  * Validate phone number (E.164 format)
62
62
  */
63
63
  export const validatePhone = (phone: string): ValidationResult => {
64
- if (!phone || phone.trim() === '') {
65
- return { isValid: false, error: 'Phone number is required' };
64
+ if (!phone || phone.trim() === "") {
65
+ return { isValid: false, error: "Phone number is required" };
66
66
  }
67
67
 
68
68
  const phoneRegex = /^\+[1-9]\d{1,14}$/;
69
69
  if (!phoneRegex.test(phone)) {
70
- return { isValid: false, error: 'Please enter a valid phone number' };
70
+ return { isValid: false, error: "Please enter a valid phone number" };
71
71
  }
72
72
 
73
73
  return { isValid: true };
@@ -80,7 +80,7 @@ export const validateNumberRange = (
80
80
  value: number,
81
81
  min: number,
82
82
  max: number,
83
- fieldName: string = 'Value'
83
+ fieldName: string = "Value",
84
84
  ): ValidationResult => {
85
85
  if (isNaN(value)) {
86
86
  return { isValid: false, error: `${fieldName} must be a number` };
@@ -101,7 +101,7 @@ export const validateNumberRange = (
101
101
  */
102
102
  export const validatePositiveNumber = (
103
103
  value: number,
104
- fieldName: string = 'Value'
104
+ fieldName: string = "Value",
105
105
  ): ValidationResult => {
106
106
  if (isNaN(value)) {
107
107
  return { isValid: false, error: `${fieldName} must be a number` };
@@ -120,7 +120,7 @@ export const validatePositiveNumber = (
120
120
  export const validateMinLength = (
121
121
  value: string,
122
122
  minLength: number,
123
- fieldName: string = 'Field'
123
+ fieldName: string = "Field",
124
124
  ): ValidationResult => {
125
125
  if (!value || value.trim().length < minLength) {
126
126
  return {
@@ -138,7 +138,7 @@ export const validateMinLength = (
138
138
  export const validateMaxLength = (
139
139
  value: string,
140
140
  maxLength: number,
141
- fieldName: string = 'Field'
141
+ fieldName: string = "Field",
142
142
  ): ValidationResult => {
143
143
  if (value && value.trim().length > maxLength) {
144
144
  return {
@@ -156,8 +156,8 @@ export const validateMaxLength = (
156
156
  export const validatePattern = (
157
157
  value: string,
158
158
  pattern: RegExp,
159
- fieldName: string = 'Field',
160
- errorMessage?: string
159
+ fieldName: string = "Field",
160
+ errorMessage?: string,
161
161
  ): ValidationResult => {
162
162
  if (!value) {
163
163
  return { isValid: false, error: `${fieldName} is required` };
@@ -178,18 +178,18 @@ export const validatePattern = (
178
178
  */
179
179
  export const validateDateOfBirth = (date: Date): ValidationResult => {
180
180
  if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
181
- return { isValid: false, error: 'Please enter a valid date' };
181
+ return { isValid: false, error: "Please enter a valid date" };
182
182
  }
183
183
 
184
184
  const today = new Date();
185
185
  const age = today.getFullYear() - date.getFullYear();
186
186
 
187
187
  if (age < 13) {
188
- return { isValid: false, error: 'You must be at least 13 years old' };
188
+ return { isValid: false, error: "You must be at least 13 years old" };
189
189
  }
190
190
 
191
191
  if (age > 120) {
192
- return { isValid: false, error: 'Please enter a valid date of birth' };
192
+ return { isValid: false, error: "Please enter a valid date of birth" };
193
193
  }
194
194
 
195
195
  return { isValid: true };
@@ -199,7 +199,7 @@ export const validateDateOfBirth = (date: Date): ValidationResult => {
199
199
  * Validate age
200
200
  */
201
201
  export const validateAge = (age: number): ValidationResult => {
202
- return validateNumberRange(age, 13, 120, 'Age');
202
+ return validateNumberRange(age, 13, 120, "Age");
203
203
  };
204
204
 
205
205
  /**
@@ -207,7 +207,7 @@ export const validateAge = (age: number): ValidationResult => {
207
207
  * Validates multiple fields and returns all errors
208
208
  */
209
209
  export const batchValidate = (
210
- validations: Array<{ field: string; validator: () => ValidationResult }>
210
+ validations: Array<{ field: string; validator: () => ValidationResult }>,
211
211
  ): { isValid: boolean; errors: Record<string, string> } => {
212
212
  const errors: Record<string, string> = {};
213
213
  let isValid = true;
@@ -223,3 +223,244 @@ export const batchValidate = (
223
223
  return { isValid, errors };
224
224
  };
225
225
 
226
+ /**
227
+ * Dream-specific validation functions
228
+ */
229
+
230
+ /**
231
+ * Validate dream title
232
+ */
233
+ export const validateDreamTitle = (
234
+ title: string,
235
+ minLength: number = 3,
236
+ maxLength: number = 100,
237
+ ): ValidationResult => {
238
+ if (!title || title.trim() === "") {
239
+ return { isValid: false, error: "Dream title is required" };
240
+ }
241
+
242
+ if (title.trim().length < minLength) {
243
+ return {
244
+ isValid: false,
245
+ error: `Dream title must be at least ${minLength} characters`,
246
+ };
247
+ }
248
+
249
+ if (title.trim().length > maxLength) {
250
+ return {
251
+ isValid: false,
252
+ error: `Dream title must be at most ${maxLength} characters`,
253
+ };
254
+ }
255
+
256
+ return { isValid: true };
257
+ };
258
+
259
+ /**
260
+ * Validate dream description
261
+ */
262
+ export const validateDreamDescription = (
263
+ description: string,
264
+ minLength: number = 10,
265
+ maxLength: number = 2000,
266
+ ): ValidationResult => {
267
+ if (!description || description.trim() === "") {
268
+ return { isValid: false, error: "Dream description is required" };
269
+ }
270
+
271
+ if (description.trim().length < minLength) {
272
+ return {
273
+ isValid: false,
274
+ error: `Dream description must be at least ${minLength} characters`,
275
+ };
276
+ }
277
+
278
+ if (description.trim().length > maxLength) {
279
+ return {
280
+ isValid: false,
281
+ error: `Dream description must be at most ${maxLength} characters`,
282
+ };
283
+ }
284
+
285
+ return { isValid: true };
286
+ };
287
+
288
+ /**
289
+ * Validate dream mood
290
+ */
291
+ export const validateDreamMood = (mood: string): ValidationResult => {
292
+ if (!mood || mood.trim() === "") {
293
+ return { isValid: false, error: "Dream mood is required" };
294
+ }
295
+
296
+ const validMoods = [
297
+ "happy",
298
+ "sad",
299
+ "scared",
300
+ "excited",
301
+ "peaceful",
302
+ "anxious",
303
+ "confused",
304
+ "angry",
305
+ "surprised",
306
+ "neutral",
307
+ ];
308
+ if (!validMoods.includes(mood.toLowerCase())) {
309
+ return {
310
+ isValid: false,
311
+ error: "Please select a valid mood",
312
+ };
313
+ }
314
+
315
+ return { isValid: true };
316
+ };
317
+
318
+ /**
319
+ * Validate dream category
320
+ */
321
+ export const validateDreamCategory = (category: string): ValidationResult => {
322
+ if (!category || category.trim() === "") {
323
+ return { isValid: false, error: "Dream category is required" };
324
+ }
325
+
326
+ const validCategories = [
327
+ "lucid",
328
+ "nightmare",
329
+ "recurring",
330
+ "prophetic",
331
+ "healing",
332
+ "creative",
333
+ "adventure",
334
+ "relationship",
335
+ "work",
336
+ "childhood",
337
+ "flying",
338
+ "falling",
339
+ "chase",
340
+ "exam",
341
+ "tooth",
342
+ "other",
343
+ ];
344
+ if (!validCategories.includes(category.toLowerCase())) {
345
+ return {
346
+ isValid: false,
347
+ error: "Please select a valid category",
348
+ };
349
+ }
350
+
351
+ return { isValid: true };
352
+ };
353
+
354
+ /**
355
+ * Validate dream date
356
+ */
357
+ export const validateDreamDate = (date: Date): ValidationResult => {
358
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
359
+ return { isValid: false, error: "Please enter a valid dream date" };
360
+ }
361
+
362
+ const today = new Date();
363
+ if (date > today) {
364
+ return { isValid: false, error: "Dream date cannot be in the future" };
365
+ }
366
+
367
+ // Don't allow dreams older than 1 year
368
+ const oneYearAgo = new Date();
369
+ oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
370
+ if (date < oneYearAgo) {
371
+ return {
372
+ isValid: false,
373
+ error: "Dream date cannot be more than 1 year old",
374
+ };
375
+ }
376
+
377
+ return { isValid: true };
378
+ };
379
+
380
+ /**
381
+ * Validate dream tags
382
+ */
383
+ export const validateDreamTags = (tags: string[]): ValidationResult => {
384
+ if (!Array.isArray(tags)) {
385
+ return { isValid: false, error: "Dream tags must be an array" };
386
+ }
387
+
388
+ if (tags.length > 10) {
389
+ return { isValid: false, error: "Maximum 10 tags allowed" };
390
+ }
391
+
392
+ for (const tag of tags) {
393
+ if (typeof tag !== "string" || tag.trim().length === 0) {
394
+ return { isValid: false, error: "All tags must be non-empty strings" };
395
+ }
396
+
397
+ if (tag.trim().length > 20) {
398
+ return {
399
+ isValid: false,
400
+ error: "Each tag must be at most 20 characters",
401
+ };
402
+ }
403
+ }
404
+
405
+ return { isValid: true };
406
+ };
407
+
408
+ /**
409
+ * Validate dream privacy setting
410
+ */
411
+ export const validateDreamPrivacy = (privacy: string): ValidationResult => {
412
+ if (!privacy || privacy.trim() === "") {
413
+ return { isValid: false, error: "Privacy setting is required" };
414
+ }
415
+
416
+ const validPrivacyOptions = ["private", "friends", "public"];
417
+ if (!validPrivacyOptions.includes(privacy.toLowerCase())) {
418
+ return {
419
+ isValid: false,
420
+ error: "Please select a valid privacy setting",
421
+ };
422
+ }
423
+
424
+ return { isValid: true };
425
+ };
426
+
427
+ /**
428
+ * Complete dream form validation
429
+ * Validates all dream fields at once
430
+ */
431
+ export const validateDreamForm = (formData: {
432
+ title?: string;
433
+ description?: string;
434
+ mood?: string;
435
+ category?: string;
436
+ date?: Date;
437
+ tags?: string[];
438
+ privacy?: string;
439
+ }): { isValid: boolean; errors: Record<string, string> } => {
440
+ const validations = [
441
+ {
442
+ field: "title",
443
+ validator: () => validateDreamTitle(formData.title || ""),
444
+ },
445
+ {
446
+ field: "description",
447
+ validator: () => validateDreamDescription(formData.description || ""),
448
+ },
449
+ { field: "mood", validator: () => validateDreamMood(formData.mood || "") },
450
+ {
451
+ field: "category",
452
+ validator: () => validateDreamCategory(formData.category || ""),
453
+ },
454
+ {
455
+ field: "date",
456
+ validator: () => validateDreamDate(formData.date || new Date()),
457
+ },
458
+ { field: "tags", validator: () => validateDreamTags(formData.tags || []) },
459
+ {
460
+ field: "privacy",
461
+ validator: () => validateDreamPrivacy(formData.privacy || ""),
462
+ },
463
+ ];
464
+
465
+ return batchValidate(validations);
466
+ };