@umituz/react-native-validation 1.4.7 → 1.4.8

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.7",
3
+ "version": "1.4.8",
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
@@ -23,20 +23,15 @@ export {
23
23
  validatePattern,
24
24
  validateDateOfBirth,
25
25
  validateAge,
26
- batchValidate,
27
26
  } from "./infrastructure/utils/validators";
28
27
 
29
- // Dream-specific validators
28
+ // Infrastructure Layer - Advanced Validators
30
29
  export {
31
- validateDreamTitle,
32
- validateDreamDescription,
33
- validateDreamMood,
34
- validateDreamCategory,
35
- validateDreamDate,
36
- validateDreamTags,
37
- validateDreamPrivacy,
38
- validateDreamForm,
39
- } from "./infrastructure/utils/validators";
30
+ validateEnum,
31
+ validateTags,
32
+ validateDateRange,
33
+ batchValidate,
34
+ } from "./infrastructure/utils/advanced-validators";
40
35
 
41
36
  // Infrastructure Layer - Sanitization
42
37
  export {
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Advanced Validation Utilities
3
+ * Complex validation functions for React Native forms
4
+ */
5
+
6
+ import type { ValidationResult } from "../../domain/entities/ValidationResult";
7
+
8
+ /**
9
+ * Custom enum validation
10
+ * Generic validator for enum-like values with custom options
11
+ */
12
+ export const validateEnum = (
13
+ value: string,
14
+ validOptions: readonly string[],
15
+ fieldName: string = "Field",
16
+ ): ValidationResult => {
17
+ if (!value || value.trim() === "") {
18
+ return { isValid: false, error: `${fieldName} is required` };
19
+ }
20
+
21
+ if (!validOptions.includes(value.toLowerCase())) {
22
+ return {
23
+ isValid: false,
24
+ error: `Please select a valid ${fieldName.toLowerCase()}`,
25
+ };
26
+ }
27
+
28
+ return { isValid: true };
29
+ };
30
+
31
+ /**
32
+ * Tags validation
33
+ * Generic validator for array of strings with constraints
34
+ */
35
+ export const validateTags = (
36
+ tags: string[],
37
+ maxTags: number = 10,
38
+ maxTagLength: number = 20,
39
+ ): ValidationResult => {
40
+ if (!Array.isArray(tags)) {
41
+ return { isValid: false, error: "Tags must be an array" };
42
+ }
43
+
44
+ if (tags.length > maxTags) {
45
+ return { isValid: false, error: `Maximum ${maxTags} tags allowed` };
46
+ }
47
+
48
+ for (const tag of tags) {
49
+ if (typeof tag !== "string" || tag.trim().length === 0) {
50
+ return { isValid: false, error: "All tags must be non-empty strings" };
51
+ }
52
+
53
+ if (tag.trim().length > maxTagLength) {
54
+ return {
55
+ isValid: false,
56
+ error: `Each tag must be at most ${maxTagLength} characters`,
57
+ };
58
+ }
59
+ }
60
+
61
+ return { isValid: true };
62
+ };
63
+
64
+ /**
65
+ * Date range validation
66
+ * Validates date is within a specific range
67
+ */
68
+ export const validateDateRange = (
69
+ date: Date,
70
+ minDate?: Date,
71
+ maxDate?: Date,
72
+ fieldName: string = "Date",
73
+ ): ValidationResult => {
74
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
75
+ return { isValid: false, error: `Please enter a valid ${fieldName.toLowerCase()}` };
76
+ }
77
+
78
+ if (minDate && date < minDate) {
79
+ return {
80
+ isValid: false,
81
+ error: `${fieldName} cannot be before ${minDate.toLocaleDateString()}`,
82
+ };
83
+ }
84
+
85
+ if (maxDate && date > maxDate) {
86
+ return {
87
+ isValid: false,
88
+ error: `${fieldName} cannot be after ${maxDate.toLocaleDateString()}`,
89
+ };
90
+ }
91
+
92
+ return { isValid: true };
93
+ };
94
+
95
+ /**
96
+ * Batch validation
97
+ * Validates multiple fields and returns all errors
98
+ */
99
+ export const batchValidate = (
100
+ validations: Array<{ field: string; validator: () => ValidationResult }>,
101
+ ): { isValid: boolean; errors: Record<string, string> } => {
102
+ const errors: Record<string, string> = {};
103
+ let isValid = true;
104
+
105
+ validations.forEach(({ field, validator }) => {
106
+ const result = validator();
107
+ if (!result.isValid && result.error) {
108
+ errors[field] = result.error;
109
+ isValid = false;
110
+ }
111
+ });
112
+
113
+ return { isValid, errors };
114
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Date Validation Utilities
3
+ * Validation functions for date fields
4
+ */
5
+
6
+ import type { ValidationResult } from "../../../domain/entities/ValidationResult";
7
+
8
+ /**
9
+ * Validate date of birth
10
+ */
11
+ export const validateDateOfBirth = (date: Date): ValidationResult => {
12
+ if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
13
+ return { isValid: false, error: "Please enter a valid date" };
14
+ }
15
+
16
+ const today = new Date();
17
+ const age = today.getFullYear() - date.getFullYear();
18
+
19
+ if (age < 13) {
20
+ return { isValid: false, error: "You must be at least 13 years old" };
21
+ }
22
+
23
+ if (age > 120) {
24
+ return { isValid: false, error: "Please enter a valid date of birth" };
25
+ }
26
+
27
+ return { isValid: true };
28
+ };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Numeric Validation Utilities
3
+ * Validation functions for numeric values
4
+ */
5
+
6
+ import type { ValidationResult } from "../../../domain/entities/ValidationResult";
7
+
8
+ /**
9
+ * Validate number range
10
+ */
11
+ export const validateNumberRange = (
12
+ value: number,
13
+ min: number,
14
+ max: number,
15
+ fieldName: string = "Value",
16
+ ): ValidationResult => {
17
+ if (isNaN(value)) {
18
+ return { isValid: false, error: `${fieldName} must be a number` };
19
+ }
20
+
21
+ if (value < min || value > max) {
22
+ return {
23
+ isValid: false,
24
+ error: `${fieldName} must be between ${min} and ${max}`,
25
+ };
26
+ }
27
+
28
+ return { isValid: true };
29
+ };
30
+
31
+ /**
32
+ * Validate positive number
33
+ */
34
+ export const validatePositiveNumber = (
35
+ value: number,
36
+ fieldName: string = "Value",
37
+ ): ValidationResult => {
38
+ if (isNaN(value)) {
39
+ return { isValid: false, error: `${fieldName} must be a number` };
40
+ }
41
+
42
+ if (value <= 0) {
43
+ return { isValid: false, error: `${fieldName} must be greater than 0` };
44
+ }
45
+
46
+ return { isValid: true };
47
+ };
48
+
49
+ /**
50
+ * Validate age
51
+ */
52
+ export const validateAge = (age: number): ValidationResult => {
53
+ return validateNumberRange(age, 13, 120, "Age");
54
+ };
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Text Validation Utilities
3
+ * Validation functions for text-based fields
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 required field
26
+ */
27
+ export const validateRequired = (
28
+ value: string,
29
+ fieldName: string = "This field",
30
+ ): ValidationResult => {
31
+ if (!value || value.trim() === "") {
32
+ return { isValid: false, error: `${fieldName} is required` };
33
+ }
34
+
35
+ return { isValid: true };
36
+ };
37
+
38
+ /**
39
+ * Validate name
40
+ */
41
+ export const validateName = (
42
+ name: string,
43
+ fieldName: string = "Name",
44
+ minLength: number = 2,
45
+ ): ValidationResult => {
46
+ if (!name || name.trim() === "") {
47
+ return { isValid: false, error: `${fieldName} is required` };
48
+ }
49
+
50
+ if (name.trim().length < minLength) {
51
+ return {
52
+ isValid: false,
53
+ error: `${fieldName} must be at least ${minLength} characters`,
54
+ };
55
+ }
56
+
57
+ return { isValid: true };
58
+ };
59
+
60
+ /**
61
+ * Validate phone number (E.164 format)
62
+ */
63
+ export const validatePhone = (phone: string): ValidationResult => {
64
+ if (!phone || phone.trim() === "") {
65
+ return { isValid: false, error: "Phone number is required" };
66
+ }
67
+
68
+ const phoneRegex = /^\+[1-9]\d{1,14}$/;
69
+ if (!phoneRegex.test(phone)) {
70
+ return { isValid: false, error: "Please enter a valid phone number" };
71
+ }
72
+
73
+ return { isValid: true };
74
+ };
75
+
76
+ /**
77
+ * Validate min length
78
+ */
79
+ export const validateMinLength = (
80
+ value: string,
81
+ minLength: number,
82
+ fieldName: string = "Field",
83
+ ): ValidationResult => {
84
+ if (!value || value.trim().length < minLength) {
85
+ return {
86
+ isValid: false,
87
+ error: `${fieldName} must be at least ${minLength} characters`,
88
+ };
89
+ }
90
+
91
+ return { isValid: true };
92
+ };
93
+
94
+ /**
95
+ * Validate max length
96
+ */
97
+ export const validateMaxLength = (
98
+ value: string,
99
+ maxLength: number,
100
+ fieldName: string = "Field",
101
+ ): ValidationResult => {
102
+ if (value && value.trim().length > maxLength) {
103
+ return {
104
+ isValid: false,
105
+ error: `${fieldName} must be at most ${maxLength} characters`,
106
+ };
107
+ }
108
+
109
+ return { isValid: true };
110
+ };
111
+
112
+ /**
113
+ * Validate pattern (regex)
114
+ */
115
+ export const validatePattern = (
116
+ value: string,
117
+ pattern: RegExp,
118
+ fieldName: string = "Field",
119
+ errorMessage?: string,
120
+ ): ValidationResult => {
121
+ if (!value) {
122
+ return { isValid: false, error: `${fieldName} is required` };
123
+ }
124
+
125
+ if (!pattern.test(value)) {
126
+ return {
127
+ isValid: false,
128
+ error: errorMessage || `${fieldName} format is invalid`,
129
+ };
130
+ }
131
+
132
+ return { isValid: true };
133
+ };
@@ -3,464 +3,25 @@
3
3
  * Comprehensive validation functions for React Native forms
4
4
  */
5
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 required field
26
- */
27
- export const validateRequired = (
28
- value: string,
29
- fieldName: string = "This field",
30
- ): ValidationResult => {
31
- if (!value || value.trim() === "") {
32
- return { isValid: false, error: `${fieldName} is required` };
33
- }
34
-
35
- return { isValid: true };
36
- };
37
-
38
- /**
39
- * Validate name
40
- */
41
- export const validateName = (
42
- name: string,
43
- fieldName: string = "Name",
44
- minLength: number = 2,
45
- ): ValidationResult => {
46
- if (!name || name.trim() === "") {
47
- return { isValid: false, error: `${fieldName} is required` };
48
- }
49
-
50
- if (name.trim().length < minLength) {
51
- return {
52
- isValid: false,
53
- error: `${fieldName} must be at least ${minLength} characters`,
54
- };
55
- }
56
-
57
- return { isValid: true };
58
- };
59
-
60
- /**
61
- * Validate phone number (E.164 format)
62
- */
63
- export const validatePhone = (phone: string): ValidationResult => {
64
- if (!phone || phone.trim() === "") {
65
- return { isValid: false, error: "Phone number is required" };
66
- }
67
-
68
- const phoneRegex = /^\+[1-9]\d{1,14}$/;
69
- if (!phoneRegex.test(phone)) {
70
- return { isValid: false, error: "Please enter a valid phone number" };
71
- }
72
-
73
- return { isValid: true };
74
- };
75
-
76
- /**
77
- * Validate number range
78
- */
79
- export const validateNumberRange = (
80
- value: number,
81
- min: number,
82
- max: number,
83
- fieldName: string = "Value",
84
- ): ValidationResult => {
85
- if (isNaN(value)) {
86
- return { isValid: false, error: `${fieldName} must be a number` };
87
- }
88
-
89
- if (value < min || value > max) {
90
- return {
91
- isValid: false,
92
- error: `${fieldName} must be between ${min} and ${max}`,
93
- };
94
- }
95
-
96
- return { isValid: true };
97
- };
98
-
99
- /**
100
- * Validate positive number
101
- */
102
- export const validatePositiveNumber = (
103
- value: number,
104
- fieldName: string = "Value",
105
- ): ValidationResult => {
106
- if (isNaN(value)) {
107
- return { isValid: false, error: `${fieldName} must be a number` };
108
- }
109
-
110
- if (value <= 0) {
111
- return { isValid: false, error: `${fieldName} must be greater than 0` };
112
- }
113
-
114
- return { isValid: true };
115
- };
116
-
117
- /**
118
- * Validate min length
119
- */
120
- export const validateMinLength = (
121
- value: string,
122
- minLength: number,
123
- fieldName: string = "Field",
124
- ): ValidationResult => {
125
- if (!value || value.trim().length < minLength) {
126
- return {
127
- isValid: false,
128
- error: `${fieldName} must be at least ${minLength} characters`,
129
- };
130
- }
131
-
132
- return { isValid: true };
133
- };
134
-
135
- /**
136
- * Validate max length
137
- */
138
- export const validateMaxLength = (
139
- value: string,
140
- maxLength: number,
141
- fieldName: string = "Field",
142
- ): ValidationResult => {
143
- if (value && value.trim().length > maxLength) {
144
- return {
145
- isValid: false,
146
- error: `${fieldName} must be at most ${maxLength} characters`,
147
- };
148
- }
149
-
150
- return { isValid: true };
151
- };
152
-
153
- /**
154
- * Validate pattern (regex)
155
- */
156
- export const validatePattern = (
157
- value: string,
158
- pattern: RegExp,
159
- fieldName: string = "Field",
160
- errorMessage?: string,
161
- ): ValidationResult => {
162
- if (!value) {
163
- return { isValid: false, error: `${fieldName} is required` };
164
- }
165
-
166
- if (!pattern.test(value)) {
167
- return {
168
- isValid: false,
169
- error: errorMessage || `${fieldName} format is invalid`,
170
- };
171
- }
172
-
173
- return { isValid: true };
174
- };
175
-
176
- /**
177
- * Validate date of birth
178
- */
179
- export const validateDateOfBirth = (date: Date): ValidationResult => {
180
- if (!date || !(date instanceof Date) || isNaN(date.getTime())) {
181
- return { isValid: false, error: "Please enter a valid date" };
182
- }
183
-
184
- const today = new Date();
185
- const age = today.getFullYear() - date.getFullYear();
186
-
187
- if (age < 13) {
188
- return { isValid: false, error: "You must be at least 13 years old" };
189
- }
190
-
191
- if (age > 120) {
192
- return { isValid: false, error: "Please enter a valid date of birth" };
193
- }
194
-
195
- return { isValid: true };
196
- };
197
-
198
- /**
199
- * Validate age
200
- */
201
- export const validateAge = (age: number): ValidationResult => {
202
- return validateNumberRange(age, 13, 120, "Age");
203
- };
204
-
205
- /**
206
- * Batch validation
207
- * Validates multiple fields and returns all errors
208
- */
209
- export const batchValidate = (
210
- validations: Array<{ field: string; validator: () => ValidationResult }>,
211
- ): { isValid: boolean; errors: Record<string, string> } => {
212
- const errors: Record<string, string> = {};
213
- let isValid = true;
214
-
215
- validations.forEach(({ field, validator }) => {
216
- const result = validator();
217
- if (!result.isValid && result.error) {
218
- errors[field] = result.error;
219
- isValid = false;
220
- }
221
- });
222
-
223
- return { isValid, errors };
224
- };
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
- };
6
+ // Text validators
7
+ export {
8
+ validateEmail,
9
+ validateRequired,
10
+ validateName,
11
+ validatePhone,
12
+ validateMinLength,
13
+ validateMaxLength,
14
+ validatePattern,
15
+ } from "./text-validators";
16
+
17
+ // Numeric validators
18
+ export {
19
+ validateNumberRange,
20
+ validatePositiveNumber,
21
+ validateAge,
22
+ } from "./numeric-validators";
23
+
24
+ // Date validators
25
+ export {
26
+ validateDateOfBirth,
27
+ } from "./date-validators";