reslib 1.1.0 → 2.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/README.md +9 -5
- package/build/auth/index.js +2 -2
- package/build/countries/index.js +2 -2
- package/build/currency/index.js +2 -2
- package/build/currency/session.js +2 -2
- package/build/exception/index.d.ts +1901 -0
- package/build/exception/index.js +5 -0
- package/build/i18n/index.d.ts +12 -4
- package/build/i18n/index.js +2 -2
- package/build/inputFormatter/index.js +2 -2
- package/build/logger/index.js +2 -2
- package/build/resources/ResourcePaginationHelper.js +1 -1
- package/build/resources/decorators/index.js +1 -1
- package/build/resources/fields/index.d.ts +5 -5
- package/build/resources/fields/index.js +1 -1
- package/build/resources/index.d.ts +1 -1
- package/build/resources/index.js +3 -3
- package/build/translations/index.d.ts +36 -4
- package/build/translations/index.js +2 -2
- package/build/translations/validator.en.d.ts +69 -4
- package/build/translations/validator.en.js +2 -2
- package/build/types/index.d.ts +21 -0
- package/build/utils/date/dateHelper.js +2 -2
- package/build/utils/date/index.js +2 -2
- package/build/utils/index.d.ts +2 -2
- package/build/utils/index.js +3 -3
- package/build/utils/interpolate.js +1 -1
- package/build/utils/isTime.js +1 -1
- package/build/utils/numbers.js +2 -2
- package/build/utils/object.js +1 -1
- package/build/validator/errors/index.d.ts +299 -0
- package/build/validator/errors/index.js +1 -0
- package/build/validator/index.d.ts +1 -0
- package/build/validator/index.js +3 -3
- package/build/validator/rules/array.js +2 -2
- package/build/validator/rules/boolean.js +2 -2
- package/build/validator/rules/date.js +2 -2
- package/build/validator/rules/default.js +2 -2
- package/build/validator/rules/enum.js +2 -2
- package/build/validator/rules/file.js +2 -2
- package/build/validator/rules/format.d.ts +13 -13
- package/build/validator/rules/format.js +3 -3
- package/build/validator/rules/index.js +3 -3
- package/build/validator/rules/multiRules.d.ts +10 -10
- package/build/validator/rules/multiRules.js +2 -2
- package/build/validator/rules/numeric.d.ts +8 -8
- package/build/validator/rules/numeric.js +2 -2
- package/build/validator/rules/object.js +2 -2
- package/build/validator/rules/string.d.ts +6 -6
- package/build/validator/rules/string.js +2 -2
- package/build/validator/rules/target.d.ts +8 -8
- package/build/validator/rules/target.js +2 -2
- package/build/validator/rules.types.d.ts +167 -0
- package/build/validator/rules.types.js +1 -0
- package/build/validator/types.d.ts +832 -1286
- package/build/validator/validator.d.ts +554 -867
- package/build/validator/validator.js +2 -2
- package/lib/cjs/exception.js +1 -0
- package/lib/esm/exception.mjs +2 -0
- package/package.json +6 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { I18n } from '../i18n';
|
|
2
2
|
import { InputFormatterResult } from '../inputFormatter/types';
|
|
3
|
-
import { ClassConstructor, Dictionary } from '../types';
|
|
3
|
+
import { ClassConstructor, Dictionary, MakeOptional, MakeRequired } from '../types';
|
|
4
|
+
import { ValidatorBulkError, ValidatorClassError, ValidatorError, ValidatorObjectError } from './errors';
|
|
5
|
+
import { ValidatorClassInput, ValidatorRuleName, ValidatorRuleParamTypes } from './rules.types';
|
|
6
|
+
export * from './rules.types';
|
|
4
7
|
/**
|
|
5
8
|
* ## Validator Sync Result
|
|
6
9
|
*
|
|
@@ -12,8 +15,8 @@ import { ClassConstructor, Dictionary } from '../types';
|
|
|
12
15
|
*
|
|
13
16
|
* This narrow type is intentionally small to make it easy to return a
|
|
14
17
|
* meaningful result from fast, CPU-only rule functions. If a rule needs to
|
|
15
|
-
* perform asynchronous work, it should return a {@link
|
|
16
|
-
* (i.e. a `Promise<
|
|
18
|
+
* perform asynchronous work, it should return a {@link ValidatorAsyncRuleResult}
|
|
19
|
+
* (i.e. a `Promise<ValidatorSyncRuleResult>`).
|
|
17
20
|
*
|
|
18
21
|
* @example
|
|
19
22
|
* ```ts
|
|
@@ -26,12 +29,12 @@ import { ClassConstructor, Dictionary } from '../types';
|
|
|
26
29
|
*
|
|
27
30
|
* @public
|
|
28
31
|
*/
|
|
29
|
-
export type
|
|
32
|
+
export type ValidatorSyncRuleResult = true | string;
|
|
30
33
|
/**
|
|
31
34
|
* ## Validator Async Result
|
|
32
35
|
*
|
|
33
36
|
* A convenience alias for the asynchronous validator result. Asynchronous
|
|
34
|
-
* rules return a Promise that resolves to a {@link
|
|
37
|
+
* rules return a Promise that resolves to a {@link ValidatorSyncRuleResult}.
|
|
35
38
|
*
|
|
36
39
|
* Use this type when declaring asynchronous rule implementations so that
|
|
37
40
|
* type-checking and tooling can correctly surface the expected resolved
|
|
@@ -48,7 +51,7 @@ export type ValidatorSyncResult = true | string;
|
|
|
48
51
|
*
|
|
49
52
|
* @public
|
|
50
53
|
*/
|
|
51
|
-
export type
|
|
54
|
+
export type ValidatorAsyncRuleResult = Promise<ValidatorSyncRuleResult>;
|
|
52
55
|
/**
|
|
53
56
|
* ## Validator Result
|
|
54
57
|
*
|
|
@@ -57,8 +60,8 @@ export type ValidatorAsyncResult = Promise<ValidatorSyncResult>;
|
|
|
57
60
|
* synchronous and asynchronous outcomes so rule implementations can be either
|
|
58
61
|
* sync or async without requiring the caller to have special handling logic.
|
|
59
62
|
*
|
|
60
|
-
* When consuming a `
|
|
61
|
-
* possible `Promise`, which resolves to a `
|
|
63
|
+
* When consuming a `ValidatorRuleResult` you should `await` it, or treat it as a
|
|
64
|
+
* possible `Promise`, which resolves to a `ValidatorSyncRuleResult`.
|
|
62
65
|
*
|
|
63
66
|
* @example
|
|
64
67
|
* ```ts
|
|
@@ -72,11 +75,11 @@ export type ValidatorAsyncResult = Promise<ValidatorSyncResult>;
|
|
|
72
75
|
* }
|
|
73
76
|
* ```
|
|
74
77
|
*
|
|
75
|
-
* @see {@link
|
|
76
|
-
* @see {@link
|
|
78
|
+
* @see {@link ValidatorSyncRuleResult}
|
|
79
|
+
* @see {@link ValidatorAsyncRuleResult}
|
|
77
80
|
* @public
|
|
78
81
|
*/
|
|
79
|
-
export type
|
|
82
|
+
export type ValidatorRuleResult = ValidatorSyncRuleResult | ValidatorAsyncRuleResult;
|
|
80
83
|
/**
|
|
81
84
|
* ## Validation Rule Type
|
|
82
85
|
*
|
|
@@ -86,7 +89,7 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
86
89
|
*
|
|
87
90
|
* ### Purpose
|
|
88
91
|
* Defines the complete set of valid rule specifications that can be used in validation operations.
|
|
89
|
-
* Supports
|
|
92
|
+
* Supports three different rule formats to accommodate various use cases and developer preferences.
|
|
90
93
|
*
|
|
91
94
|
* ### Union Members
|
|
92
95
|
*
|
|
@@ -98,17 +101,12 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
98
101
|
*
|
|
99
102
|
* #### 2. Named Rules (`ValidatorRuleName`)
|
|
100
103
|
* Simple string references to built-in validation rules. Most concise format.
|
|
104
|
+
* Only supports rules that don't require parameters (or have optional parameters).
|
|
101
105
|
* ```typescript
|
|
102
|
-
* "Required" | "Email" | "
|
|
106
|
+
* "Required" | "Email" | "IsNumber"
|
|
103
107
|
* ```
|
|
104
108
|
*
|
|
105
|
-
* #### 3.
|
|
106
|
-
* Built-in rules with parameters specified in string format. Readable and concise.
|
|
107
|
-
* ```typescript
|
|
108
|
-
* {MinLength:[5]}, {MaxLength:[100]} or {NumberBetween:[0,100]}
|
|
109
|
-
* ```
|
|
110
|
-
*
|
|
111
|
-
* #### 4. Object Rules (`ValidatorRuleObject`)
|
|
109
|
+
* #### 3. Object Rules (`ValidatorRuleObject`)
|
|
112
110
|
* Structured object format with type-safe parameters. Most type-safe format.
|
|
113
111
|
* ```typescript
|
|
114
112
|
* { MinLength: [5] } | { Email: [] } | { NumberBetween: [0, 100] }
|
|
@@ -124,9 +122,8 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
124
122
|
* ```typescript
|
|
125
123
|
* const rules: ValidatorRules = [
|
|
126
124
|
* "Required", // Named rule
|
|
127
|
-
*
|
|
128
|
-
* {
|
|
129
|
-
* ({ value }) => value !== "", // Function rule
|
|
125
|
+
* { MinLength: [5] }, // Object rule
|
|
126
|
+
* ({ value }) => value !== "", // Function rule
|
|
130
127
|
* ];
|
|
131
128
|
* ```
|
|
132
129
|
*
|
|
@@ -149,7 +146,7 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
149
146
|
* // Multiple rules validation
|
|
150
147
|
* const multiResult = await Validator.validate({
|
|
151
148
|
* value: "hello",
|
|
152
|
-
* rules: ["Required",
|
|
149
|
+
* rules: ["Required", { MinLength: [5] }, { MaxLength: [10] }], // ValidatorRule[]
|
|
153
150
|
* });
|
|
154
151
|
* ```
|
|
155
152
|
*
|
|
@@ -169,7 +166,6 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
169
166
|
* ### Performance Considerations
|
|
170
167
|
* - **Function rules**: Fastest (direct execution)
|
|
171
168
|
* - **Named rules**: Fast (lookup table)
|
|
172
|
-
* - **Parameterized rules**: Medium (parsing required)
|
|
173
169
|
* - **Object rules**: Medium (type mapping required)
|
|
174
170
|
*
|
|
175
171
|
* ### Best Practices
|
|
@@ -179,12 +175,9 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
179
175
|
* // ✅ Use named rules for simple cases
|
|
180
176
|
* const simpleRules = ["Required", "Email"];
|
|
181
177
|
*
|
|
182
|
-
* // ✅ Use
|
|
178
|
+
* // ✅ Use object rules for parameters or type safety
|
|
183
179
|
* const lengthRules = [{ MinLength: [5] }, { MaxLength: [100] }];
|
|
184
180
|
*
|
|
185
|
-
* // ✅ Use object rules for complex parameters or type safety
|
|
186
|
-
* const complexRules = [{ NumberBetween: [0, 100] }];
|
|
187
|
-
*
|
|
188
181
|
* // ✅ Use function rules for custom logic
|
|
189
182
|
* const customRules = [({ value }) => value % 2 === 0];
|
|
190
183
|
* ```
|
|
@@ -193,8 +186,8 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
193
186
|
* ```typescript
|
|
194
187
|
* const comprehensiveRules: ValidatorRules = [
|
|
195
188
|
* "Required", // Built-in
|
|
196
|
-
*
|
|
197
|
-
* { Email: [] },
|
|
189
|
+
* { MinLength: [5] }, // Object (parameterized)
|
|
190
|
+
* { Email: [] }, // Object (type-safe)
|
|
198
191
|
* ({ value, context }) => { // Custom function
|
|
199
192
|
* return context?.allowSpecialChars || !/[!@#$%]/.test(value);
|
|
200
193
|
* },
|
|
@@ -206,8 +199,7 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
206
199
|
* ```typescript
|
|
207
200
|
* // These will throw validation errors:
|
|
208
201
|
* const invalid1 = "UnknownRule"; // Rule doesn't exist
|
|
209
|
-
* const invalid2 =
|
|
210
|
-
* const invalid3 = { UnknownRule: [] }; // Unknown rule name
|
|
202
|
+
* const invalid2 = { UnknownRule: [] }; // Unknown rule name
|
|
211
203
|
* ```
|
|
212
204
|
*
|
|
213
205
|
* ### Relationship to Validation System
|
|
@@ -224,7 +216,7 @@ export type ValidatorResult = ValidatorSyncResult | ValidatorAsyncResult;
|
|
|
224
216
|
*
|
|
225
217
|
* const userValidationRules: UserRules = [
|
|
226
218
|
* "Required",
|
|
227
|
-
*
|
|
219
|
+
* { MinLength: [3] },
|
|
228
220
|
* { MaxLength: [50] },
|
|
229
221
|
* ({ value }) => !/\s/.test(value), // No spaces
|
|
230
222
|
* ];
|
|
@@ -359,7 +351,7 @@ export type ValidatorOptionalOrEmptyRuleNames = ExtractOptionalOrEmptyKeys<Valid
|
|
|
359
351
|
* Email: []; // No parameters needed
|
|
360
352
|
* PhoneNumber: [countryCode?: string]; // Optional parameter
|
|
361
353
|
*
|
|
362
|
-
* // ❌ Parameterized rules (must be
|
|
354
|
+
* // ❌ Parameterized rules (must be used as { RuleName: [...] })
|
|
363
355
|
* MinLength: [number]; // Required parameter
|
|
364
356
|
* MaxLength: [number]; // Required parameter
|
|
365
357
|
* Length: [number, number?]; // First parameter required
|
|
@@ -393,6 +385,90 @@ export type ValidatorTupleAllowsEmpty<T extends Array<unknown>> = T extends [] ?
|
|
|
393
385
|
type ExtractOptionalOrEmptyKeys<T> = {
|
|
394
386
|
[K in keyof T]: T[K] extends Array<unknown> ? ValidatorTupleAllowsEmpty<T[K]> extends true ? K : never : never;
|
|
395
387
|
}[keyof T];
|
|
388
|
+
/**
|
|
389
|
+
* @since 1.2.0
|
|
390
|
+
* Configuration interface for a validation rule object.
|
|
391
|
+
*
|
|
392
|
+
* This interface defines the structure for specifying rule parameters and optional customization
|
|
393
|
+
* like error messages overrides.
|
|
394
|
+
*
|
|
395
|
+
* @template TParams - The type of the rule parameters
|
|
396
|
+
*/
|
|
397
|
+
export interface ValidatorRuleConfig<TParams> {
|
|
398
|
+
/**
|
|
399
|
+
* The parameters for the validation rule.
|
|
400
|
+
*
|
|
401
|
+
* These are the arguments that are passed to the rule function.
|
|
402
|
+
* The type of these parameters is defined in `ValidatorRuleParamTypes`.
|
|
403
|
+
*/
|
|
404
|
+
params: TParams;
|
|
405
|
+
/**
|
|
406
|
+
* Custom error message that overrides the rule's default message.
|
|
407
|
+
*
|
|
408
|
+
* This property allows strict control over the error feedback. It accepts a string
|
|
409
|
+
* (static or i18n key) or a function for dynamic message generation.
|
|
410
|
+
*
|
|
411
|
+
* **Important:** If specified, this message will be used if validation fails, ignoring any
|
|
412
|
+
* message returned by the rule function itself.
|
|
413
|
+
*
|
|
414
|
+
* **Note:** If a function is provided, verify it does not throw. Exceptions are caught and ignored,
|
|
415
|
+
* causing a fallback to the default message.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* // Static message
|
|
419
|
+
* message: "This field is required"
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* // i18n key
|
|
423
|
+
* message: "errors.required"
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* // Dynamic message function
|
|
427
|
+
* message: ({ value }) => `Value ${value} is invalid`
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* // Dynamic message using i18n from options
|
|
431
|
+
* message: ({ value, i18n }) => i18n.t('validation.custom_error', { value })
|
|
432
|
+
*
|
|
433
|
+
* @see {@link ValidatorRuleConfigMessage}
|
|
434
|
+
*/
|
|
435
|
+
message?: ValidatorRuleConfigMessage;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* @since 1.2.0
|
|
439
|
+
* Defines the type for custom error messages in validation rules.
|
|
440
|
+
*
|
|
441
|
+
* This type allows for flexibility in defining error messages. It supports:
|
|
442
|
+
* 1. **Static Strings**: Direct error messages.
|
|
443
|
+
* 2. **Translation Keys**: Keys for localized messages via standard i18n system.
|
|
444
|
+
* 3. **Dynamic Functions**: Functions that generate messages based on validation context.
|
|
445
|
+
*
|
|
446
|
+
* **Important:** You must return a string. Do not throw exceptions.
|
|
447
|
+
* If an exception is thrown inside the function, it will be caught and ignored,
|
|
448
|
+
* falling back to the rule's default error message.
|
|
449
|
+
*
|
|
450
|
+
* ### Examples
|
|
451
|
+
*
|
|
452
|
+
* **Static String**
|
|
453
|
+
* ```typescript
|
|
454
|
+
* message: "This field is strictly required."
|
|
455
|
+
* ```
|
|
456
|
+
*
|
|
457
|
+
* **Translation Key**
|
|
458
|
+
* ```typescript
|
|
459
|
+
* message: "validation.errors.required"
|
|
460
|
+
* ```
|
|
461
|
+
*
|
|
462
|
+
* **Dynamic Function**
|
|
463
|
+
* ```typescript
|
|
464
|
+
* message: ({ value, fieldName }) => `The value "${value}" is not valid for ${fieldName}.`
|
|
465
|
+
* ```
|
|
466
|
+
* **Dynamic Function with i18n**
|
|
467
|
+
* ```typescript
|
|
468
|
+
* message: ({ value, i18n }) => i18n.t('the_value_is_required', { value })
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
export type ValidatorRuleConfigMessage = string | ((options: MakeRequired<Omit<ValidatorOptions, 'sanitizedRules' | 'rules' | 'rule'>, 'i18n' | 'ruleName' | 'ruleParams'>) => string);
|
|
396
472
|
/**
|
|
397
473
|
* ## Validation Rule Object Type
|
|
398
474
|
*
|
|
@@ -437,6 +513,23 @@ type ExtractOptionalOrEmptyKeys<T> = {
|
|
|
437
513
|
* };
|
|
438
514
|
* ```
|
|
439
515
|
*
|
|
516
|
+
* #### Rule Objects with Custom Messages
|
|
517
|
+
* ```typescript
|
|
518
|
+
* const customMessageRule: ValidatorRuleObject = {
|
|
519
|
+
* Required: {
|
|
520
|
+
* params: [],
|
|
521
|
+
* message: "This field is absolutely required!"
|
|
522
|
+
* }
|
|
523
|
+
* };
|
|
524
|
+
*
|
|
525
|
+
* const detailedRule: ValidatorRuleObject = {
|
|
526
|
+
* MinLength: {
|
|
527
|
+
* params: [5],
|
|
528
|
+
* message: "validation.custom.minLength" // Translation key
|
|
529
|
+
* }
|
|
530
|
+
* };
|
|
531
|
+
* ```
|
|
532
|
+
*
|
|
440
533
|
* #### In Validation Rules Array
|
|
441
534
|
* ```typescript
|
|
442
535
|
* const rules: ValidatorRules = [
|
|
@@ -466,7 +559,6 @@ type ExtractOptionalOrEmptyKeys<T> = {
|
|
|
466
559
|
* This type is one of four union members in {@link ValidatorRule}:
|
|
467
560
|
* - `ValidatorRuleFunction` - Custom validation functions
|
|
468
561
|
* - `ValidatorRuleName` - Simple rule names (strings)
|
|
469
|
-
* - `` `${ValidatorRuleName}[${string}]` `` - Parameterized rule strings
|
|
470
562
|
* - `ValidatorRuleObject` - Structured rule objects (this type)
|
|
471
563
|
*
|
|
472
564
|
* ### When to Use
|
|
@@ -476,15 +568,7 @@ type ExtractOptionalOrEmptyKeys<T> = {
|
|
|
476
568
|
* - **Complex Parameters**: Rules with multiple typed parameters
|
|
477
569
|
* - **Refactoring Safety**: Changes to rule signatures are caught by TypeScript
|
|
478
570
|
*
|
|
479
|
-
|
|
480
|
-
* | Aspect | Object Rules | String Rules |
|
|
481
|
-
* |--------|-------------|--------------|
|
|
482
|
-
* | Type Safety | ✅ Full compile-time checking | ⚠️ Runtime parameter validation |
|
|
483
|
-
* | Autocomplete | ✅ Parameter types shown | ❌ No parameter hints |
|
|
484
|
-
* | Refactoring | ✅ Breaking changes caught | ❌ May break silently |
|
|
485
|
-
* | Readability | ✅ Self-documenting | ⚠️ Requires knowledge of syntax |
|
|
486
|
-
* | Flexibility | ✅ Strongly typed | ✅ Dynamic |
|
|
487
|
-
*
|
|
571
|
+
|
|
488
572
|
* @template Context - Type of the optional validation context
|
|
489
573
|
*
|
|
490
574
|
* @example
|
|
@@ -508,11 +592,12 @@ type ExtractOptionalOrEmptyKeys<T> = {
|
|
|
508
592
|
* @see {@link ValidatorRule} - Union type that includes this
|
|
509
593
|
* @see {@link ValidatorRuleName} - Valid rule names
|
|
510
594
|
* @see {@link ValidatorRuleParamTypes} - Parameter type definitions
|
|
595
|
+
* @see {@link ValidatorRuleConfig}
|
|
511
596
|
* @see {@link ValidatorRuleFunction} - Function-based rules
|
|
512
597
|
* @public
|
|
513
598
|
*/
|
|
514
599
|
export type ValidatorRuleObject = Partial<{
|
|
515
|
-
[K in ValidatorRuleName]: ValidatorRuleParamTypes[K]
|
|
600
|
+
[K in ValidatorRuleName]: ValidatorRuleParamTypes[K] | ValidatorRuleConfig<ValidatorRuleParamTypes[K]>;
|
|
516
601
|
}>;
|
|
517
602
|
/**
|
|
518
603
|
* Represents an array of validation rules to be applied to a value.
|
|
@@ -547,7 +632,7 @@ export type ValidatorRuleObject = Partial<{
|
|
|
547
632
|
* @public
|
|
548
633
|
*
|
|
549
634
|
* @see {@link ValidatorRule} - Individual rule type
|
|
550
|
-
* @see {@link
|
|
635
|
+
* @see {@link ValidatorOptions} - Options interface that uses this type
|
|
551
636
|
* @see {@link Validator.validate} - Validation method that accepts these rules
|
|
552
637
|
*/
|
|
553
638
|
export type ValidatorRules<Context = unknown> = Array<ValidatorRule<Array<unknown>, Context>>;
|
|
@@ -589,7 +674,6 @@ export type ValidatorSanitizedRule<TParams extends ValidatorRuleParams = Validat
|
|
|
589
674
|
* - **ruleName**: The parsed rule identifier (e.g., "MinLength")
|
|
590
675
|
* - **params**: Array of parameters extracted from the rule (e.g., `[5]`)
|
|
591
676
|
* - **ruleFunction**: The actual validation function to execute
|
|
592
|
-
* - **rawRuleName**: The original unparsed rule string (e.g., {MinLength:[5]})
|
|
593
677
|
*
|
|
594
678
|
* ### Usage in Validation Pipeline
|
|
595
679
|
* ```typescript
|
|
@@ -601,7 +685,6 @@ export type ValidatorSanitizedRule<TParams extends ValidatorRuleParams = Validat
|
|
|
601
685
|
* ruleName: "MinLength",
|
|
602
686
|
* params: [8],
|
|
603
687
|
* ruleFunction: minLengthFunction,
|
|
604
|
-
* rawRuleName: "MinLength"
|
|
605
688
|
* };
|
|
606
689
|
*
|
|
607
690
|
* // During validation
|
|
@@ -667,18 +750,39 @@ export interface ValidatorSanitizedRuleObject<TParams extends ValidatorRuleParam
|
|
|
667
750
|
*/
|
|
668
751
|
ruleFunction: ValidatorRuleFunction<TParams, Context>;
|
|
669
752
|
/**
|
|
670
|
-
* The
|
|
753
|
+
* The error message associated with the validation rule.
|
|
671
754
|
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
* exactly what the user specified.
|
|
755
|
+
* Overrides the default error message generated by the `ruleFunction` if validation fails.
|
|
756
|
+
* Can be a static string, a translation key, or a function that returns a string.
|
|
675
757
|
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
*
|
|
758
|
+
* **Important:** If specified, this message will be used if validation fails, ignoring any
|
|
759
|
+
* message returned by the rule function itself.
|
|
760
|
+
*
|
|
761
|
+
* **Note:** If a function is provided, verify it does not throw. Exceptions are caught and ignored,
|
|
762
|
+
* causing a fallback to the default message.
|
|
763
|
+
*
|
|
764
|
+
* @type {ValidatorRuleConfigMessage}
|
|
765
|
+
* @since 1.2.0
|
|
766
|
+
*
|
|
767
|
+
* @example
|
|
768
|
+
* // Static string
|
|
769
|
+
* message: "This field is required."
|
|
770
|
+
*
|
|
771
|
+
* @example
|
|
772
|
+
* // Translation key
|
|
773
|
+
* message: "auth.email.required"
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* // Dynamic function
|
|
777
|
+
* message: ({ value, ruleParams }) => `Value must be between ${ruleParams[0]} and ${ruleParams[1]}`
|
|
778
|
+
*
|
|
779
|
+
* @example
|
|
780
|
+
* // Dynamic message using i18n from options
|
|
781
|
+
* message: ({ value, i18n }) => i18n.t('validation.min_length', { value, min: 5 })
|
|
782
|
+
*
|
|
783
|
+
* @see {@link ValidatorRuleConfigMessage}
|
|
680
784
|
*/
|
|
681
|
-
|
|
785
|
+
message?: ValidatorRuleConfigMessage;
|
|
682
786
|
}
|
|
683
787
|
/**
|
|
684
788
|
* @typedef ValidatorSanitizedRules
|
|
@@ -705,54 +809,55 @@ export interface ValidatorSanitizedRuleObject<TParams extends ValidatorRuleParam
|
|
|
705
809
|
*/
|
|
706
810
|
export type ValidatorSanitizedRules<Context = unknown> = ValidatorSanitizedRule<Array<unknown>, Context>[];
|
|
707
811
|
/**
|
|
708
|
-
* ## Validator
|
|
812
|
+
* ## Validator Rule Function
|
|
709
813
|
*
|
|
710
|
-
* Represents
|
|
711
|
-
* This function takes a set of options and performs validation on a given value,
|
|
712
|
-
* returning the result of the validation process.
|
|
814
|
+
* Represents the fundamental unit of logic in the validation system: a function that validates a value.
|
|
713
815
|
*
|
|
714
|
-
*
|
|
816
|
+
* This type definition abstracts both **Synchronous** and **Asynchronous** validation logic into a unified
|
|
817
|
+
* interface, allowing the validator to handle everything from simple checks (regex, length) to complex
|
|
818
|
+
* operations (database lookups, API calls) seamlessly.
|
|
715
819
|
*
|
|
716
|
-
* ###
|
|
717
|
-
*
|
|
718
|
-
*
|
|
820
|
+
* ### Core Responsibilities
|
|
821
|
+
* 1. **Receive Context**: Accepts a rich options object (`ValidatorOptions`) containing the value, rule parameters, and context.
|
|
822
|
+
* 2. **Execute Logic**: Performs the actual validation check.
|
|
823
|
+
* 3. **Report Result**: Returns `true` for success or an error message (string) for failure.
|
|
719
824
|
*
|
|
720
|
-
* ### Parameters
|
|
721
|
-
* - **
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
*
|
|
825
|
+
* ### Type Parameters
|
|
826
|
+
* - **TParams**: Tightly couples the function to a specific set of parameters (e.g., `[min: number]`).
|
|
827
|
+
* - **Context**: Allows injecting application-specific context (e.g., database connection, user session).
|
|
828
|
+
*
|
|
829
|
+
* ### Return Behavior
|
|
830
|
+
* The return type {@link ValidatorRuleResult} is a union of:
|
|
831
|
+
* - `boolean`: `true` indicates valid.
|
|
832
|
+
* - `string`: A non-empty string indicates invalid (the string is the error message/key).
|
|
833
|
+
* - `Promise<boolean | string>`: For async rules.
|
|
726
834
|
*
|
|
727
|
-
* ###
|
|
728
|
-
* - The function returns a {@link ValidatorResult}, which is either:
|
|
729
|
-
* - a `ValidatorSyncResult` (synchronous rule result) — `true` for success, or a `string` containing the error message on failure
|
|
730
|
-
* - or a `Promise<ValidatorSyncResult>` (asynchronous rule result)
|
|
835
|
+
* ### Example Usage
|
|
731
836
|
*
|
|
732
|
-
*
|
|
837
|
+
* #### Synchronous Rule
|
|
733
838
|
* ```typescript
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
738
|
-
*
|
|
739
|
-
* return true; // Valid validation
|
|
740
|
-
* }
|
|
839
|
+
* const isEven: ValidatorRuleFunction = ({ value }) => {
|
|
840
|
+
* if (typeof value !== 'number') return "Value must be a number";
|
|
841
|
+
* return value % 2 === 0 || "Value must be even";
|
|
842
|
+
* };
|
|
843
|
+
* ```
|
|
741
844
|
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
*
|
|
745
|
-
*
|
|
746
|
-
*
|
|
747
|
-
*
|
|
748
|
-
* }
|
|
845
|
+
* #### Asynchronous Rule
|
|
846
|
+
* ```typescript
|
|
847
|
+
* const isUniqueUser: ValidatorRuleFunction = async ({ value, context }) => {
|
|
848
|
+
* const user = await context.db.users.findByEmail(value);
|
|
849
|
+
* return !user || "Email already exists";
|
|
850
|
+
* };
|
|
749
851
|
* ```
|
|
750
852
|
*
|
|
751
|
-
* ###
|
|
752
|
-
*
|
|
753
|
-
*
|
|
853
|
+
* ### Interaction with Registry
|
|
854
|
+
* These functions are typically registered with the `Validator` class using names like "MinLength" or "Email",
|
|
855
|
+
* allowing them to be referenced by string later.
|
|
856
|
+
*
|
|
857
|
+
* @see {@link ValidatorOptions} - The input object received by this function.
|
|
858
|
+
* @see {@link ValidatorRuleResult} - The output produced by this function.
|
|
754
859
|
*/
|
|
755
|
-
export type ValidatorRuleFunction<TParams extends ValidatorRuleParams = ValidatorRuleParams, Context = unknown> = (options:
|
|
860
|
+
export type ValidatorRuleFunction<TParams extends ValidatorRuleParams = ValidatorRuleParams, Context = unknown> = (options: ValidatorOptions<TParams, Context>) => ValidatorRuleResult;
|
|
756
861
|
/**
|
|
757
862
|
* ## Validation Rule Parameters Type
|
|
758
863
|
*
|
|
@@ -821,31 +926,31 @@ export type ValidatorRuleParams<TParams extends Array<unknown> | ReadonlyArray<u
|
|
|
821
926
|
*
|
|
822
927
|
* Configuration interface for validating nested objects or complex data structures
|
|
823
928
|
* within the validation system. This interface is specifically designed for rule functions
|
|
824
|
-
* that need to validate
|
|
929
|
+
* that need to validate class objects (classes with decorators) rather than simple values.
|
|
825
930
|
*
|
|
826
931
|
* ### Purpose
|
|
827
932
|
* Provides a specialized options interface for validation rule functions that operate on
|
|
828
|
-
* nested or complex data structures. Unlike {@link
|
|
933
|
+
* nested or complex data structures. Unlike {@link ValidatorOptions} which handles
|
|
829
934
|
* single values, this interface is tailored for scenarios where validation rules need to
|
|
830
935
|
* work with entire class instances or nested object hierarchies.
|
|
831
936
|
*
|
|
832
|
-
* ### Key Differences from
|
|
833
|
-
* - **Extends from
|
|
937
|
+
* ### Key Differences from ValidatorOptions
|
|
938
|
+
* - **Extends from ValidatorClassOptions**: Inherits class-specific properties
|
|
834
939
|
* - **Omits "data" property**: Uses its own `data` property instead
|
|
835
|
-
* - **Optional value property**: Accepts
|
|
940
|
+
* - **Optional value property**: Accepts class data instead of single values
|
|
836
941
|
* - **Flexible data property**: Allows any record structure for nested validation
|
|
837
942
|
*
|
|
838
943
|
* ### Inheritance Structure
|
|
839
944
|
* ```
|
|
840
945
|
* ValidatorNestedRuleFunctionOptions
|
|
841
|
-
* ↳ extends Omit<
|
|
842
|
-
* ↳ extends Omit<
|
|
946
|
+
* ↳ extends Omit<ValidatorClassOptions<TClass, Context, [classInstance: TClass]>, "data">
|
|
947
|
+
* ↳ extends Omit<ValidatorOptions<TParams, Context>, "data" | "rule" | "value">
|
|
843
948
|
* ↳ extends Omit<Partial<InputFormatterResult>, "value">
|
|
844
|
-
* ↳ extends
|
|
949
|
+
* ↳ extends ValidatorBaseOptions<Context>
|
|
845
950
|
* ```
|
|
846
951
|
*
|
|
847
952
|
* ### Generic Parameters
|
|
848
|
-
* - **
|
|
953
|
+
* - **TClass**: The class constructor type being validated (extends `ClassConstructor`)
|
|
849
954
|
* - **Context**: Optional context type for validation (defaults to `unknown`)
|
|
850
955
|
*
|
|
851
956
|
* ### Properties Overview
|
|
@@ -854,7 +959,6 @@ export type ValidatorRuleParams<TParams extends Array<unknown> | ReadonlyArray<u
|
|
|
854
959
|
* - **rules**: Array of validation rules to apply
|
|
855
960
|
* - **ruleParams**: Parameters for the current rule
|
|
856
961
|
* - **ruleName**: Name of the validation rule
|
|
857
|
-
* - **rawRuleName**: Original unparsed rule name
|
|
858
962
|
* - **message**: Custom error message
|
|
859
963
|
* - **fieldName**: Form field identifier
|
|
860
964
|
* - **propertyName**: Object property name
|
|
@@ -866,7 +970,7 @@ export type ValidatorRuleParams<TParams extends Array<unknown> | ReadonlyArray<u
|
|
|
866
970
|
* - **parentData**: Parent context for nested validations
|
|
867
971
|
*
|
|
868
972
|
* #### Own Properties
|
|
869
|
-
* - **value**: Optional
|
|
973
|
+
* - **value**: Optional class data to validate
|
|
870
974
|
* - **data**: Flexible data object for nested validation context
|
|
871
975
|
*
|
|
872
976
|
* ### Usage in Nested Validation
|
|
@@ -888,7 +992,7 @@ export type ValidatorRuleParams<TParams extends Array<unknown> | ReadonlyArray<u
|
|
|
888
992
|
* // Validate the nested profile
|
|
889
993
|
* if (value && typeof value === 'object') {
|
|
890
994
|
* // Perform nested validation logic
|
|
891
|
-
* const result = await Validator.
|
|
995
|
+
* const result = await Validator.validateClass(UserProfile, value);
|
|
892
996
|
* return result.success || "Profile validation failed";
|
|
893
997
|
* }
|
|
894
998
|
*
|
|
@@ -898,8 +1002,8 @@ export type ValidatorRuleParams<TParams extends Array<unknown> | ReadonlyArray<u
|
|
|
898
1002
|
*
|
|
899
1003
|
* ### Relationship to Validation System
|
|
900
1004
|
* - **Used by**: {@link Validator.validateNestedRule} method
|
|
901
|
-
* - **Complements**: {@link
|
|
902
|
-
* - **Extends**: {@link
|
|
1005
|
+
* - **Complements**: {@link ValidatorClassOptions} for class validation
|
|
1006
|
+
* - **Extends**: {@link ValidatorOptions} with class-specific modifications
|
|
903
1007
|
* - **Supports**: Complex nested object validation scenarios
|
|
904
1008
|
*
|
|
905
1009
|
* ### Common Use Cases
|
|
@@ -934,165 +1038,33 @@ export type ValidatorRuleParams<TParams extends Array<unknown> | ReadonlyArray<u
|
|
|
934
1038
|
* ```
|
|
935
1039
|
*
|
|
936
1040
|
* ### Type Safety Benefits
|
|
937
|
-
* - **Compile-time validation** of
|
|
1041
|
+
* - **Compile-time validation** of class types
|
|
938
1042
|
* - **Type-safe property access** on nested objects
|
|
939
1043
|
* - **Context propagation** through validation hierarchy
|
|
940
1044
|
* - **Flexible data structures** for complex validation scenarios
|
|
941
1045
|
*
|
|
942
1046
|
* ### Performance Considerations
|
|
943
|
-
* - **
|
|
1047
|
+
* - **Class validation overhead**: More expensive than single-value validation
|
|
944
1048
|
* - **Parallel processing**: Multiple nested validations can run concurrently
|
|
945
1049
|
* - **Memory usage**: Larger data structures require more memory
|
|
946
1050
|
* - **Serialization**: Complex objects may need special handling
|
|
947
1051
|
*
|
|
948
|
-
* @template Target - The class constructor type being validated (must extend ClassConstructor)
|
|
949
|
-
* @template Context - Optional context type for validation (defaults to unknown)
|
|
950
|
-
*
|
|
951
|
-
* @public
|
|
952
|
-
*
|
|
953
|
-
* @see {@link ValidatorValidateTargetOptions} - Base target validation options
|
|
954
|
-
* @see {@link ValidatorValidateOptions} - Single-value validation options
|
|
955
|
-
* @see {@link Validator.validateNestedRule} - Method that uses this interface
|
|
956
|
-
* @see {@link ValidatorValidateTargetData} - Target data type
|
|
957
1052
|
* @see {@link ClassConstructor} - Class constructor constraint
|
|
958
1053
|
*/
|
|
959
|
-
export interface ValidatorNestedRuleFunctionOptions<
|
|
960
|
-
|
|
1054
|
+
export interface ValidatorNestedRuleFunctionOptions<TClass extends ClassConstructor = ClassConstructor, Context = unknown> extends Omit<ValidatorClassOptions<TClass, Context, [
|
|
1055
|
+
classInstance: TClass,
|
|
1056
|
+
options?: {
|
|
1057
|
+
/**
|
|
1058
|
+
* The custom error message to use when validation fails.
|
|
1059
|
+
* It can be either a translation key or a custom message.
|
|
1060
|
+
*/
|
|
1061
|
+
message?: string;
|
|
1062
|
+
}
|
|
1063
|
+
]>, 'data'> {
|
|
1064
|
+
value?: ValidatorClassInput<TClass>;
|
|
961
1065
|
data?: Dictionary;
|
|
962
1066
|
}
|
|
963
|
-
|
|
964
|
-
* @interface ValidatorRuleName
|
|
965
|
-
* Represents the name of a validation rule as defined in the `ValidatorRuleParamTypes`.
|
|
966
|
-
*
|
|
967
|
-
* The `ValidatorRuleName` type is a union of string literal types that correspond to the keys
|
|
968
|
-
* of the `ValidatorRuleParamTypes` interface. This allows for type-safe access to the names of
|
|
969
|
-
* validation rules, ensuring that only valid rule names can be used in contexts where a rule name
|
|
970
|
-
* is required.
|
|
971
|
-
*
|
|
972
|
-
* ### Structure:
|
|
973
|
-
* - The type is derived from the keys of the `ValidatorRuleParamTypes`, meaning it will include
|
|
974
|
-
* all the rule names defined in that map.
|
|
975
|
-
*
|
|
976
|
-
* ### Example:
|
|
977
|
-
*
|
|
978
|
-
* ```typescript
|
|
979
|
-
* const ruleName: ValidatorRuleName = "required"; // Valid
|
|
980
|
-
* const anotherRuleName: ValidatorRuleName = "minLength"; // Valid
|
|
981
|
-
*
|
|
982
|
-
* // Usage in a function that accepts a rule name
|
|
983
|
-
* function getValidationRule(ruleName: ValidatorRuleName) {
|
|
984
|
-
* return validationRules[ruleName];
|
|
985
|
-
* }
|
|
986
|
-
*
|
|
987
|
-
* const rule = getValidationRule("maxLength"); // Valid usage
|
|
988
|
-
* // const invalidRule = getValidationRule("unknownRule"); // TypeScript will throw an error
|
|
989
|
-
* ```
|
|
990
|
-
*
|
|
991
|
-
* This type enhances type safety in your code by ensuring that only valid validation rule names
|
|
992
|
-
* can be used, reducing the risk of runtime errors due to typos or invalid rule names.
|
|
993
|
-
*/
|
|
994
|
-
export type ValidatorRuleName = keyof ValidatorRuleParamTypes & string;
|
|
995
|
-
/**
|
|
996
|
-
* ## Validation Rules Parameter Map
|
|
997
|
-
*
|
|
998
|
-
* Central type definition mapping validation rule names to their parameter signatures.
|
|
999
|
-
* This interface serves as the authoritative source for all built-in validation rules,
|
|
1000
|
-
* defining the exact parameter types each rule accepts.
|
|
1001
|
-
*
|
|
1002
|
-
* ### Purpose
|
|
1003
|
-
* Provides compile-time type safety for validation rule parameters across the entire
|
|
1004
|
-
* validation system. Each property represents a built-in validation rule and its
|
|
1005
|
-
* expected parameter structure. This is a static interface with no generics.
|
|
1006
|
-
*
|
|
1007
|
-
* ### Type Structure
|
|
1008
|
-
* - **Key**: Rule name (string literal from {@link ValidatorRuleName})
|
|
1009
|
-
* - **Value**: Parameter array type (extends {@link ValidatorRuleParams})
|
|
1010
|
-
*
|
|
1011
|
-
* ### Parameter Type Patterns
|
|
1012
|
-
* - **Empty Arrays `[]`**: Rules that take no parameters (e.g., "Required", "Email")
|
|
1013
|
-
* - **Complex Parameters**: Rules with mixed required/optional parameters
|
|
1014
|
-
*
|
|
1015
|
-
* ### Usage in Type System
|
|
1016
|
-
* This interface is used throughout the validator to:
|
|
1017
|
-
* - Type-check rule parameters at compile time
|
|
1018
|
-
* - Generate {@link ValidatorRuleName} union type
|
|
1019
|
-
* - Create {@link ValidatorRuleFunctionsMap} registry type
|
|
1020
|
-
* - Validate rule definitions in rule implementation files
|
|
1021
|
-
*
|
|
1022
|
-
* ### Rule Categories
|
|
1023
|
-
*
|
|
1024
|
-
* #### Presence Validation
|
|
1025
|
-
* - **Required**: Ensures value is present and not empty
|
|
1026
|
-
* - **Nullable**: Allows null/undefined values (skips validation)
|
|
1027
|
-
* - **Optional**: Allows undefined values (skips validation)
|
|
1028
|
-
* - **Empty**: Allows empty strings (validation skipped if "")
|
|
1029
|
-
*
|
|
1030
|
-
* #### Type Validation
|
|
1031
|
-
* - **String**: Validates value is a string
|
|
1032
|
-
* - **Number**: Validates value is a number
|
|
1033
|
-
* - **NonNullString**: Validates value is a non-null string
|
|
1034
|
-
*
|
|
1035
|
-
* #### String Validation
|
|
1036
|
-
* - **MinLength**: Minimum character length requirement
|
|
1037
|
-
* - **MaxLength**: Maximum character length limit
|
|
1038
|
-
* - **Length**: Exact length or length range (min and optional max)
|
|
1039
|
-
* - **FileName**: Valid file name format
|
|
1040
|
-
*
|
|
1041
|
-
* #### Numeric Validation
|
|
1042
|
-
* - **NumberGT**: Value must be greater than specified number
|
|
1043
|
-
* - **NumberGTE**: Value must be >= specified number
|
|
1044
|
-
* - **NumberLT**: Value must be less than specified number
|
|
1045
|
-
* - **NumberLTE**: Value must be <= specified number
|
|
1046
|
-
* - **NumberEQ**: Value must equal specified number
|
|
1047
|
-
* - **NumberNE**: Value must differ from specified number
|
|
1048
|
-
*
|
|
1049
|
-
* #### Format Validation
|
|
1050
|
-
* - **Email**: Valid email address format
|
|
1051
|
-
* - **Url**: Valid URL format
|
|
1052
|
-
* - **PhoneNumber**: Valid phone number (with optional country code)
|
|
1053
|
-
* - **EmailOrPhoneNumber**: Valid email or phone number
|
|
1054
|
-
*
|
|
1055
|
-
* ### Parameter Examples
|
|
1056
|
-
* ```typescript
|
|
1057
|
-
* // Rules with no parameters
|
|
1058
|
-
* Required: ValidatorRuleParams<[]>; // "Required"
|
|
1059
|
-
* Email: ValidatorRuleParams<[]>; // "Email"
|
|
1060
|
-
*
|
|
1061
|
-
* // Rules with single parameters
|
|
1062
|
-
* MinLength: ValidatorRuleParams<[number]>; // {MinLength:[5]}
|
|
1063
|
-
* NumberEQ: ValidatorRuleParams<[number]>; // "NumberEQ[42]"
|
|
1064
|
-
*
|
|
1065
|
-
* // Rules with optional parameters
|
|
1066
|
-
* PhoneNumber: ValidatorRuleParams<[CountryCode?]>; // "PhoneNumber" or "PhoneNumber[US]"
|
|
1067
|
-
*
|
|
1068
|
-
* // Rules with multiple parameters
|
|
1069
|
-
* Length: ValidatorRuleParams<[number, number?]>; // "Length[5]" or "Length[5,10]"
|
|
1070
|
-
* ```
|
|
1071
|
-
*
|
|
1072
|
-
* ### Extending the Rules Map
|
|
1073
|
-
* When adding new validation rules:
|
|
1074
|
-
* 1. Add the rule name and parameter type to this interface
|
|
1075
|
-
* 2. Implement the rule function in the appropriate rule file
|
|
1076
|
-
* 3. Register the rule in the validator's rule registry
|
|
1077
|
-
* 4. Update rule name unions and type definitions as needed
|
|
1078
|
-
*
|
|
1079
|
-
* ### Relationship to Validation System
|
|
1080
|
-
* - **Foundation**: Base type for all rule definitions
|
|
1081
|
-
* - **Type Safety**: Ensures parameter type checking
|
|
1082
|
-
* - **Rule Discovery**: Used to generate valid rule names
|
|
1083
|
-
* - **Function Signatures**: Defines parameter types for rule functions
|
|
1084
|
-
* - **Runtime Validation**: Parameters validated against these types
|
|
1085
|
-
*
|
|
1086
|
-
* @public
|
|
1087
|
-
* @template Context - Type of the optional validation context
|
|
1088
|
-
* @see {@link ValidatorRuleName} - Union type derived from this interface's keys
|
|
1089
|
-
* @see {@link ValidatorRuleFunctionsMap} - Registry type using this interface
|
|
1090
|
-
* @see {@link ValidatorRuleParams} - Base parameter type for all rules
|
|
1091
|
-
* @see {@link Validator} - Main validator class that uses these rules
|
|
1092
|
-
*/
|
|
1093
|
-
export interface ValidatorRuleParamTypes<Context = unknown> {
|
|
1094
|
-
}
|
|
1095
|
-
export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams = ValidatorRuleParams, Context = unknown> extends Omit<Partial<InputFormatterResult>, 'value'>, BaseData<Context> {
|
|
1067
|
+
export interface ValidatorOptions<TParams extends ValidatorRuleParams = ValidatorRuleParams, Context = unknown> extends Omit<Partial<InputFormatterResult>, 'value'>, Omit<ValidatorBaseOptions<Context>, 'status' | 'name'> {
|
|
1096
1068
|
/**
|
|
1097
1069
|
* The list of validation rules to apply
|
|
1098
1070
|
*
|
|
@@ -1104,7 +1076,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1104
1076
|
*
|
|
1105
1077
|
* @example
|
|
1106
1078
|
* ```typescript
|
|
1107
|
-
* const options:
|
|
1079
|
+
* const options: ValidatorOptions = {
|
|
1108
1080
|
* value: "example@test.com",
|
|
1109
1081
|
* rules: [
|
|
1110
1082
|
* { ruleName: "Required" },
|
|
@@ -1139,7 +1111,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1139
1111
|
*
|
|
1140
1112
|
* @example
|
|
1141
1113
|
* ```typescript
|
|
1142
|
-
* const options:
|
|
1114
|
+
* const options: ValidatorOptions = {
|
|
1143
1115
|
* value: "test",
|
|
1144
1116
|
* rule: { ruleName: "Required" },
|
|
1145
1117
|
* propertyName: "username"
|
|
@@ -1162,7 +1134,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1162
1134
|
* @example
|
|
1163
1135
|
* ```typescript
|
|
1164
1136
|
* // For MinLength rule
|
|
1165
|
-
* const options:
|
|
1137
|
+
* const options: ValidatorOptions = {
|
|
1166
1138
|
* value: "password123",
|
|
1167
1139
|
* rule: { ruleName: "MinLength" },
|
|
1168
1140
|
* ruleParams: [8], // Minimum 8 characters
|
|
@@ -1170,7 +1142,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1170
1142
|
* };
|
|
1171
1143
|
*
|
|
1172
1144
|
* // For NumberBetween rule
|
|
1173
|
-
* const options2:
|
|
1145
|
+
* const options2: ValidatorOptions = {
|
|
1174
1146
|
* value: 50,
|
|
1175
1147
|
* rule: { ruleName: "NumberBetween" },
|
|
1176
1148
|
* ruleParams: [0, 100], // Between 0 and 100
|
|
@@ -1190,7 +1162,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1190
1162
|
*
|
|
1191
1163
|
* @example
|
|
1192
1164
|
* ```typescript
|
|
1193
|
-
* const options:
|
|
1165
|
+
* const options: ValidatorOptions = {
|
|
1194
1166
|
* value: "user@example.com",
|
|
1195
1167
|
* ruleName: "Email",
|
|
1196
1168
|
* propertyName: "email"
|
|
@@ -1200,58 +1172,6 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1200
1172
|
* @see {@link ValidatorRuleName}
|
|
1201
1173
|
*/
|
|
1202
1174
|
ruleName?: ValidatorRuleName;
|
|
1203
|
-
/**
|
|
1204
|
-
* The raw rule name as originally specified (before parsing)
|
|
1205
|
-
*
|
|
1206
|
-
* The unparsed rule name including any parameters in brackets.
|
|
1207
|
-
* For example, {MinLength:[5]} or {NumberGT:[0]} before the name
|
|
1208
|
-
* and parameters are extracted into `ruleName` and `ruleParams`.
|
|
1209
|
-
*
|
|
1210
|
-
* @type {string}
|
|
1211
|
-
* @optional
|
|
1212
|
-
*
|
|
1213
|
-
* @example
|
|
1214
|
-
* ```typescript
|
|
1215
|
-
* const options: ValidatorValidateOptions = {
|
|
1216
|
-
* value: "test",
|
|
1217
|
-
* rawRuleName: { MinLength: [5] }, // Raw form
|
|
1218
|
-
* ruleName: "MinLength", // Parsed name
|
|
1219
|
-
* ruleParams: [5], // Parsed params
|
|
1220
|
-
* propertyName: "username"
|
|
1221
|
-
* };
|
|
1222
|
-
* ```
|
|
1223
|
-
*/
|
|
1224
|
-
rawRuleName?: ValidatorRuleName | string;
|
|
1225
|
-
/**
|
|
1226
|
-
* Custom error message for validation failure
|
|
1227
|
-
*
|
|
1228
|
-
* Allows specifying a custom error message to display when validation fails.
|
|
1229
|
-
* If provided, this message will be used instead of the default rule-generated message.
|
|
1230
|
-
* Supports i18n translations and dynamic content.
|
|
1231
|
-
*
|
|
1232
|
-
* @type {string}
|
|
1233
|
-
* @optional
|
|
1234
|
-
*
|
|
1235
|
-
* @example
|
|
1236
|
-
* ```typescript
|
|
1237
|
-
* const options: ValidatorValidateOptions = {
|
|
1238
|
-
* value: "invalid-email",
|
|
1239
|
-
* rules: ["Email"],
|
|
1240
|
-
* message: "Please enter a valid email address (e.g., user@example.com)",
|
|
1241
|
-
* propertyName: "email"
|
|
1242
|
-
* };
|
|
1243
|
-
*
|
|
1244
|
-
* // Custom message for specific context
|
|
1245
|
-
* const options2: ValidatorValidateOptions = {
|
|
1246
|
-
* value: "short",
|
|
1247
|
-
* rule: { ruleName: "MinLength" },
|
|
1248
|
-
* ruleParams: [8],
|
|
1249
|
-
* message: "Your password must be at least 8 characters for security",
|
|
1250
|
-
* propertyName: "password"
|
|
1251
|
-
* };
|
|
1252
|
-
* ```
|
|
1253
|
-
*/
|
|
1254
|
-
message?: string;
|
|
1255
1175
|
/**
|
|
1256
1176
|
* The form field name/identifier
|
|
1257
1177
|
*
|
|
@@ -1264,7 +1184,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1264
1184
|
*
|
|
1265
1185
|
* @example
|
|
1266
1186
|
* ```typescript
|
|
1267
|
-
* const options:
|
|
1187
|
+
* const options: ValidatorOptions = {
|
|
1268
1188
|
* value: "invalid@",
|
|
1269
1189
|
* rules: ["Email"],
|
|
1270
1190
|
* fieldName: "email_input", // HTML form field ID
|
|
@@ -1304,7 +1224,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1304
1224
|
* password: string;
|
|
1305
1225
|
* }
|
|
1306
1226
|
*
|
|
1307
|
-
* const options:
|
|
1227
|
+
* const options: ValidatorOptions = {
|
|
1308
1228
|
* value: "invalid-email",
|
|
1309
1229
|
* rules: ["Email"],
|
|
1310
1230
|
* propertyName: "email", // Maps to UserData.email
|
|
@@ -1330,7 +1250,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1330
1250
|
* @example
|
|
1331
1251
|
* ```typescript
|
|
1332
1252
|
* // Before translation
|
|
1333
|
-
* const options:
|
|
1253
|
+
* const options: ValidatorOptions = {
|
|
1334
1254
|
* value: "invalid",
|
|
1335
1255
|
* rules: ["Required"],
|
|
1336
1256
|
* propertyName: "user_phone_number"
|
|
@@ -1353,7 +1273,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1353
1273
|
* ## OneOf Rule Validation Options
|
|
1354
1274
|
*
|
|
1355
1275
|
* Configuration interface for validating a value against an array of alternative validation rules
|
|
1356
|
-
* where at least one rule must pass. This interface extends {@link
|
|
1276
|
+
* where at least one rule must pass. This interface extends {@link ValidatorOptions}
|
|
1357
1277
|
* with specialized properties for OneOf rule validation.
|
|
1358
1278
|
*
|
|
1359
1279
|
* ### Purpose
|
|
@@ -1377,7 +1297,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1377
1297
|
*
|
|
1378
1298
|
* #### Basic OneOf Validation Setup
|
|
1379
1299
|
* ```typescript
|
|
1380
|
-
* const options:
|
|
1300
|
+
* const options: ValidatorMultiRuleOptions = {
|
|
1381
1301
|
* value: "user@example.com",
|
|
1382
1302
|
* ruleParams: [
|
|
1383
1303
|
* ({ value }) => value.includes("@") || "Must contain @",
|
|
@@ -1400,7 +1320,7 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1400
1320
|
* allowedDomains: string[];
|
|
1401
1321
|
* }
|
|
1402
1322
|
*
|
|
1403
|
-
* const options:
|
|
1323
|
+
* const options: ValidatorMultiRuleOptions<ValidationContext> = {
|
|
1404
1324
|
* value: "admin@company.com",
|
|
1405
1325
|
* ruleParams: [
|
|
1406
1326
|
* // Email validation
|
|
@@ -1441,11 +1361,11 @@ export interface ValidatorValidateOptions<TParams extends ValidatorRuleParams =
|
|
|
1441
1361
|
*
|
|
1442
1362
|
* @public
|
|
1443
1363
|
* @see {@link Validator.validateOneOfRule} - Method that uses this interface
|
|
1444
|
-
* @see {@link
|
|
1364
|
+
* @see {@link ValidatorOptions} - Base options interface being extended
|
|
1445
1365
|
* @see {@link ValidatorRuleFunction} - Type of functions in ruleParams array
|
|
1446
|
-
* @see {@link
|
|
1366
|
+
* @see {@link ValidatorResult} - Result type returned by validation
|
|
1447
1367
|
*/
|
|
1448
|
-
export interface
|
|
1368
|
+
export interface ValidatorMultiRuleOptions<Context = unknown, RulesFunctions extends ValidatorDefaultMultiRule<Context> = ValidatorDefaultMultiRule<Context>> extends ValidatorOptions<RulesFunctions, Context> {
|
|
1449
1369
|
startTime?: number;
|
|
1450
1370
|
}
|
|
1451
1371
|
/**
|
|
@@ -1458,7 +1378,7 @@ export interface ValidatorValidateMultiRuleOptions<Context = unknown, RulesFunct
|
|
|
1458
1378
|
* ### Purpose
|
|
1459
1379
|
* Provides a flexible type for representing collections of validation rules where each rule
|
|
1460
1380
|
* can have different parameter types. Used as a constraint for {@link ValidatorMultiRuleFunction}
|
|
1461
|
-
* and {@link
|
|
1381
|
+
* and {@link ValidatorMultiRuleOptions} to ensure type safety in multi-rule scenarios.
|
|
1462
1382
|
*
|
|
1463
1383
|
* ### Type Parameters
|
|
1464
1384
|
* - **Context**: Optional context type for validation (defaults to `unknown`)
|
|
@@ -1479,7 +1399,7 @@ export interface ValidatorValidateMultiRuleOptions<Context = unknown, RulesFunct
|
|
|
1479
1399
|
* ```
|
|
1480
1400
|
*
|
|
1481
1401
|
* ### Relationship to Validation System
|
|
1482
|
-
* - **Used by**: {@link
|
|
1402
|
+
* - **Used by**: {@link ValidatorMultiRuleOptions} as constraint
|
|
1483
1403
|
* - **Constrains**: {@link ValidatorMultiRuleFunction} parameter types
|
|
1484
1404
|
* - **Enables**: Type-safe multi-rule validation operations
|
|
1485
1405
|
*
|
|
@@ -1488,7 +1408,7 @@ export interface ValidatorValidateMultiRuleOptions<Context = unknown, RulesFunct
|
|
|
1488
1408
|
*
|
|
1489
1409
|
* @public
|
|
1490
1410
|
*
|
|
1491
|
-
* @see {@link
|
|
1411
|
+
* @see {@link ValidatorMultiRuleOptions} - Uses this as constraint
|
|
1492
1412
|
* @see {@link ValidatorMultiRuleFunction} - Function type that accepts this
|
|
1493
1413
|
* @see {@link ValidatorRule} - Individual rule type
|
|
1494
1414
|
*/
|
|
@@ -1511,7 +1431,7 @@ export type ValidatorDefaultMultiRule<Context = unknown, ParamsTypes extends Val
|
|
|
1511
1431
|
*
|
|
1512
1432
|
* ### Function Signature
|
|
1513
1433
|
* ```typescript
|
|
1514
|
-
* (options:
|
|
1434
|
+
* (options: ValidatorOptions<RulesFunctions, Context>) => ValidatorRuleResult
|
|
1515
1435
|
* ```
|
|
1516
1436
|
*
|
|
1517
1437
|
* ### Usage in Validation System
|
|
@@ -1537,7 +1457,7 @@ export type ValidatorDefaultMultiRule<Context = unknown, ParamsTypes extends Val
|
|
|
1537
1457
|
* ### Relationship to Validation System
|
|
1538
1458
|
* - **Used by**: Multi-rule validation methods in {@link Validator}
|
|
1539
1459
|
* - **Constrained by**: {@link ValidatorDefaultMultiRule} for parameter types
|
|
1540
|
-
* - **Returns**: Standard {@link
|
|
1460
|
+
* - **Returns**: Standard {@link ValidatorRuleResult} for consistency
|
|
1541
1461
|
* - **Enables**: Complex validation logic with multiple rules
|
|
1542
1462
|
*
|
|
1543
1463
|
* @template Context - Type of the optional validation context
|
|
@@ -1548,544 +1468,150 @@ export type ValidatorDefaultMultiRule<Context = unknown, ParamsTypes extends Val
|
|
|
1548
1468
|
* @see {@link ValidatorDefaultMultiRule} - Constrains the RulesFunctions parameter
|
|
1549
1469
|
* @see {@link Validator.validateOneOfRule} - Uses this function type
|
|
1550
1470
|
* @see {@link Validator.validateAllOfRule} - Uses this function type
|
|
1551
|
-
* @see {@link
|
|
1471
|
+
* @see {@link ValidatorRuleResult} - Return type
|
|
1552
1472
|
*/
|
|
1553
1473
|
export type ValidatorMultiRuleFunction<Context = unknown, RulesFunctions extends Array<ValidatorRule<Array<unknown>, Context>> = Array<ValidatorRule<Array<unknown>, Context>>> = ValidatorRuleFunction<RulesFunctions, Context>;
|
|
1554
1474
|
/**
|
|
1555
|
-
* ##
|
|
1475
|
+
* ## Validator Class Options
|
|
1476
|
+
*
|
|
1477
|
+
* Configuration options for performing class-based validation (`Validator.validateClass`).
|
|
1478
|
+
* These options control the behavior of the validation process, including context injection,
|
|
1479
|
+
* error handling, and internationalization.
|
|
1480
|
+
*
|
|
1481
|
+
* ### Inheritance
|
|
1482
|
+
* Extends `ValidatorOptions` but excludes single-value specific properties (`value`, `rule`)
|
|
1483
|
+
* in favor of class-instance specific properties (`data`).
|
|
1484
|
+
*/
|
|
1485
|
+
export interface ValidatorClassOptions<TClass extends ClassConstructor = ClassConstructor, Context = unknown, ParamsTypes extends ValidatorRuleParams = ValidatorRuleParams> extends Omit<ValidatorOptions<ParamsTypes, Context>, 'data' | 'rule' | 'value'> {
|
|
1486
|
+
data: ValidatorClassInput<TClass>;
|
|
1487
|
+
/**
|
|
1488
|
+
* The parent data/context for nested validations
|
|
1489
|
+
*
|
|
1490
|
+
* When validating nested objects, this property holds the parent
|
|
1491
|
+
*/
|
|
1492
|
+
parentData?: Dictionary;
|
|
1493
|
+
startTime?: number;
|
|
1494
|
+
errorMessageBuilder?: (translatedPropertyName: string, error: string, builderOptions: Omit<ValidatorError, 'message'> & {
|
|
1495
|
+
propertyName: keyof InstanceType<TClass> | string;
|
|
1496
|
+
translatedPropertyName: string;
|
|
1497
|
+
cause: ValidatorError;
|
|
1498
|
+
i18n: I18n;
|
|
1499
|
+
separators: {
|
|
1500
|
+
multiple: string;
|
|
1501
|
+
single: string;
|
|
1502
|
+
};
|
|
1503
|
+
data: Partial<Record<keyof InstanceType<TClass>, any>>;
|
|
1504
|
+
}) => string;
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* ## Validator Bulk Options
|
|
1508
|
+
*
|
|
1509
|
+
* Configuration for bulk validation operations (validating an array of class instances).
|
|
1510
|
+
* Extends `ValidatorClassOptions` but accepts an array of data objects instead of a single one.
|
|
1511
|
+
* @template TClass - The class constructor type to validate
|
|
1512
|
+
* @template Context - The context type for validation
|
|
1513
|
+
*/
|
|
1514
|
+
export interface ValidatorBulkOptions<TClass extends ClassConstructor = ClassConstructor, Context = unknown> extends Omit<MakeOptional<ValidatorClassOptions<TClass, Context>, 'i18n'>, 'data' | 'ruleParams'> {
|
|
1515
|
+
data: ValidatorClassInput<TClass>[];
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* ## Multi-Rule Names Union
|
|
1556
1519
|
*
|
|
1557
|
-
* A
|
|
1558
|
-
*
|
|
1559
|
-
* to their values, enabling type-safe validation of entire class instances.
|
|
1520
|
+
* A union type defining the names of validation rules that operate on multiple sub-rules.
|
|
1521
|
+
* These rules combine the results of several validation rules using logical operations.
|
|
1560
1522
|
*
|
|
1561
1523
|
* ### Purpose
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1524
|
+
* Defines the specific rule names that support multi-rule validation patterns.
|
|
1525
|
+
* These rules allow combining multiple validation conditions with logical operators
|
|
1526
|
+
* like "one of" or "all of", enabling complex validation scenarios.
|
|
1565
1527
|
*
|
|
1566
|
-
* ###
|
|
1567
|
-
*
|
|
1568
|
-
*
|
|
1569
|
-
* ```
|
|
1570
|
-
* - **Target**: Class constructor type (must extend `ClassConstructor`)
|
|
1571
|
-
* - **InstanceType<Target>**: Properties of the class instance
|
|
1572
|
-
* - **Partial**: All properties are optional (validation fills in defaults)
|
|
1573
|
-
* - **Record<..., any>**: Values can be any type (validation will check)
|
|
1528
|
+
* ### Supported Multi-Rules
|
|
1529
|
+
* - **'OneOf'**: Passes if at least one of the sub-rules passes (logical OR)
|
|
1530
|
+
* - **'AllOf'**: Passes only if all sub-rules pass (logical AND)
|
|
1574
1531
|
*
|
|
1575
|
-
* ###
|
|
1532
|
+
* ### Type Structure
|
|
1533
|
+
* Simple string literal union with two possible values:
|
|
1576
1534
|
* ```typescript
|
|
1577
|
-
*
|
|
1578
|
-
*
|
|
1579
|
-
* @IsEmail()
|
|
1580
|
-
* email: string;
|
|
1581
|
-
*
|
|
1582
|
-
* @IsRequired()
|
|
1583
|
-
* @MinLength(3)
|
|
1584
|
-
* name: string;
|
|
1535
|
+
* 'OneOf' | 'AllOf'
|
|
1536
|
+
* ```
|
|
1585
1537
|
*
|
|
1586
|
-
*
|
|
1587
|
-
*
|
|
1588
|
-
*
|
|
1538
|
+
* ### Usage in Validation
|
|
1539
|
+
* Multi-rule names are used in {@link ValidatorMultiRuleFunction} to specify
|
|
1540
|
+
* which logical operation to apply to a collection of validation rules.
|
|
1589
1541
|
*
|
|
1590
|
-
*
|
|
1591
|
-
*
|
|
1592
|
-
*
|
|
1593
|
-
*
|
|
1594
|
-
*
|
|
1542
|
+
* ```typescript
|
|
1543
|
+
* // Example: Email must be valid OR be empty (optional email field)
|
|
1544
|
+
* const rule: ValidatorMultiRuleFunction = (rules, context) => {
|
|
1545
|
+
* return rules.OneOf([
|
|
1546
|
+
* rules.Email([], context),
|
|
1547
|
+
* rules.IsEmpty([], context)
|
|
1548
|
+
* ]);
|
|
1595
1549
|
* };
|
|
1596
|
-
*
|
|
1597
|
-
* const result = await Validator.validateTarget(UserForm, data);
|
|
1598
1550
|
* ```
|
|
1599
1551
|
*
|
|
1600
|
-
* ###
|
|
1601
|
-
* - **
|
|
1602
|
-
* - **
|
|
1603
|
-
* - **
|
|
1604
|
-
* - **
|
|
1605
|
-
*
|
|
1606
|
-
* ### Comparison with Single-Value Validation
|
|
1607
|
-
* | Aspect | Target Data | Single Value |
|
|
1608
|
-
* |--------|-------------|--------------|
|
|
1609
|
-
* | Structure | Object with multiple properties | Single value |
|
|
1610
|
-
* | Validation | Multiple fields simultaneously | One value at a time |
|
|
1611
|
-
* | Type Safety | Class property mapping | Any value type |
|
|
1612
|
-
* | Use Case | Form validation | Field validation |
|
|
1552
|
+
* ### Relationship to Validation System
|
|
1553
|
+
* - **Used by**: {@link ValidatorMultiRuleFunction} as operation selector
|
|
1554
|
+
* - **Implemented in**: Rule registry as special multi-rule handlers
|
|
1555
|
+
* - **Combines with**: Regular validation rules via logical operations
|
|
1556
|
+
* - **Returns**: Single validation result from multiple rule evaluations
|
|
1613
1557
|
*
|
|
1614
|
-
* ###
|
|
1615
|
-
* - **
|
|
1616
|
-
* - **
|
|
1617
|
-
* - **Type
|
|
1558
|
+
* ### Key Characteristics
|
|
1559
|
+
* - **Logical Operations**: Supports OR ('OneOf') and AND ('AllOf') combinations
|
|
1560
|
+
* - **Rule Composition**: Enables building complex validation logic from simple rules
|
|
1561
|
+
* - **Type Safety**: Compile-time guarantees for valid multi-rule names
|
|
1562
|
+
* - **Extensible**: New logical operations can be added by extending this union
|
|
1618
1563
|
*
|
|
1619
|
-
* ###
|
|
1620
|
-
*
|
|
1621
|
-
*
|
|
1622
|
-
*
|
|
1623
|
-
*
|
|
1564
|
+
* ### Comparison with Single Rules
|
|
1565
|
+
* | Aspect | Single Rule | Multi-Rule |
|
|
1566
|
+
* |--------|-------------|------------|
|
|
1567
|
+
* | Operation | One condition | Multiple conditions |
|
|
1568
|
+
* | Logic | Direct validation | Logical combination |
|
|
1569
|
+
* | Use Case | Basic validation | Complex conditional validation |
|
|
1570
|
+
* | Example | "IsEmail" | "OneOf(IsEmail, IsEmpty())" |
|
|
1624
1571
|
*
|
|
1625
|
-
*
|
|
1572
|
+
* ### Runtime Behavior
|
|
1573
|
+
* - **OneOf**: Returns success if any sub-rule passes, failure if all fail
|
|
1574
|
+
* - **AllOf**: Returns success only if all sub-rules pass, failure if any fails
|
|
1575
|
+
* - **Short-circuiting**: May stop evaluation early based on logical operation
|
|
1576
|
+
* - **Error Aggregation**: Collects errors from all evaluated rules
|
|
1626
1577
|
*
|
|
1627
1578
|
* @public
|
|
1628
1579
|
*
|
|
1629
|
-
* @see {@link
|
|
1630
|
-
* @see {@link
|
|
1631
|
-
* @see {@link
|
|
1632
|
-
* @see {@link ClassConstructor} - Base constructor type constraint
|
|
1580
|
+
* @see {@link ValidatorMultiRuleFunction} - Function type that uses these names
|
|
1581
|
+
* @see {@link ValidatorDefaultMultiRule} - Default multi-rule configuration
|
|
1582
|
+
* @see {@link ValidatorRuleName} - General rule names (includes these)
|
|
1633
1583
|
*/
|
|
1634
|
-
export type
|
|
1584
|
+
export type ValidatorMultiRuleNames = 'OneOf' | 'AllOf';
|
|
1635
1585
|
/**
|
|
1636
|
-
* ##
|
|
1637
|
-
*
|
|
1638
|
-
* Configuration interface for validating entire class instances with decorated properties.
|
|
1639
|
-
* This interface extends {@link ValidatorValidateOptions} with target-specific properties
|
|
1640
|
-
* for complex object validation scenarios.
|
|
1586
|
+
* ## Validation Result Types (Either Pattern)
|
|
1641
1587
|
*
|
|
1642
|
-
*
|
|
1643
|
-
*
|
|
1644
|
-
|
|
1645
|
-
|
|
1588
|
+
* Uses the Either<L, R> pattern where Left represents failure and Right represents success.
|
|
1589
|
+
* This provides strong type safety and prevents accessing wrong properties based on the result state.
|
|
1590
|
+
*/
|
|
1591
|
+
/**
|
|
1592
|
+
* ## Single Value Validation Success Result
|
|
1646
1593
|
*
|
|
1647
|
-
*
|
|
1648
|
-
*
|
|
1649
|
-
* - **Omits "rule" and "value"**: Uses target-specific data structure instead
|
|
1650
|
-
* - **parentData**: Supports nested validation context
|
|
1651
|
-
* - **errorMessageBuilder**: Customizable error message formatting for target validation
|
|
1652
|
-
* - **startTime**: Performance tracking for multi-field validation
|
|
1594
|
+
* Represents a successful validation result for a single value.
|
|
1595
|
+
* This type is used as the success branch of the {@link ValidatorResult} discriminated union.
|
|
1653
1596
|
*
|
|
1654
|
-
* ###
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
*
|
|
1658
|
-
*
|
|
1659
|
-
*
|
|
1597
|
+
* ### Type Guard
|
|
1598
|
+
* Can be narrowed using {@link Validator.isSuccess}:
|
|
1599
|
+
* ```typescript
|
|
1600
|
+
* if (Validator.isSuccess(result)) {
|
|
1601
|
+
* // TypeScript knows: result satisfies ValidatorSuccess
|
|
1602
|
+
* // Can safely access result.value, result.validatedAt, result.duration
|
|
1603
|
+
* }
|
|
1660
1604
|
* ```
|
|
1661
1605
|
*
|
|
1662
|
-
* ###
|
|
1663
|
-
* - **
|
|
1664
|
-
* - **
|
|
1665
|
-
* - **
|
|
1666
|
-
*
|
|
1667
|
-
*
|
|
1668
|
-
*
|
|
1669
|
-
*
|
|
1670
|
-
* - **
|
|
1671
|
-
* - **ruleParams**: Parameters for the current rule
|
|
1672
|
-
* - **ruleName**: Name of the validation rule
|
|
1673
|
-
* - **rawRuleName**: Original unparsed rule name
|
|
1674
|
-
* - **message**: Custom error message
|
|
1675
|
-
* - **fieldName**: Form field identifier
|
|
1676
|
-
* - **propertyName**: Object property name
|
|
1677
|
-
* - **translatedPropertyName**: Localized property name
|
|
1678
|
-
* - **i18n**: Internationalization instance
|
|
1679
|
-
* - **sanitizedRules**: Preprocessed rules
|
|
1680
|
-
*
|
|
1681
|
-
* #### Target-Specific Properties
|
|
1682
|
-
* - **data**: Required target data to validate (typed as `ValidatorValidateTargetData<Target>`)
|
|
1683
|
-
* - **parentData**: Parent context for nested validations
|
|
1684
|
-
* - **startTime**: Performance tracking timestamp
|
|
1685
|
-
* - **errorMessageBuilder**: Custom error message builder function
|
|
1686
|
-
*
|
|
1687
|
-
* ### Usage in Target Validation
|
|
1688
|
-
* ```typescript
|
|
1689
|
-
* class UserProfile {
|
|
1690
|
-
* @IsRequired()
|
|
1691
|
-
* @IsEmail()
|
|
1692
|
-
* email: string;
|
|
1693
|
-
*
|
|
1694
|
-
* @IsRequired()
|
|
1695
|
-
* @MinLength(2)
|
|
1696
|
-
* name: string;
|
|
1697
|
-
*
|
|
1698
|
-
* @ValidateNested
|
|
1699
|
-
* address: Address;
|
|
1700
|
-
* }
|
|
1701
|
-
*
|
|
1702
|
-
* // Basic target validation
|
|
1703
|
-
* const options: ValidatorValidateTargetOptions<UserProfile> = {
|
|
1704
|
-
* data: {
|
|
1705
|
-
* email: "user@example.com",
|
|
1706
|
-
* name: "John",
|
|
1707
|
-
* address: { street: "123 Main St", city: "Anytown" }
|
|
1708
|
-
* },
|
|
1709
|
-
* propertyName: "userProfile",
|
|
1710
|
-
* context: validationContext,
|
|
1711
|
-
* i18n: defaultI18n,
|
|
1712
|
-
* };
|
|
1713
|
-
*
|
|
1714
|
-
* const result = await Validator.validateTarget(UserProfile, options.data);
|
|
1715
|
-
* ```
|
|
1716
|
-
*
|
|
1717
|
-
* ### Error Message Builder
|
|
1718
|
-
* The `errorMessageBuilder` allows customization of error message formatting:
|
|
1719
|
-
* ```typescript
|
|
1720
|
-
* const customErrorBuilder = (
|
|
1721
|
-
* translatedPropertyName: string,
|
|
1722
|
-
* error: string,
|
|
1723
|
-
* options: ValidatorValidationError & {
|
|
1724
|
-
* propertyName: string;
|
|
1725
|
-
* translatedPropertyName: string;
|
|
1726
|
-
* i18n: I18n;
|
|
1727
|
-
* separators: { multiple: string; single: string };
|
|
1728
|
-
* data: Partial<Record<keyof Target, any>>;
|
|
1729
|
-
* }
|
|
1730
|
-
* ) => {
|
|
1731
|
-
* return `[${translatedPropertyName}]: ${error}`;
|
|
1732
|
-
* };
|
|
1733
|
-
*
|
|
1734
|
-
* const options: ValidatorValidateTargetOptions<UserProfile> = {
|
|
1735
|
-
* data: userData,
|
|
1736
|
-
* errorMessageBuilder: customErrorBuilder,
|
|
1737
|
-
* };
|
|
1738
|
-
* ```
|
|
1739
|
-
*
|
|
1740
|
-
* ### Nested Validation Context
|
|
1741
|
-
* The `parentData` property enables context sharing in nested validations:
|
|
1742
|
-
* ```typescript
|
|
1743
|
-
* // Parent validation
|
|
1744
|
-
* const parentOptions: ValidatorValidateTargetOptions<Company> = {
|
|
1745
|
-
* data: {
|
|
1746
|
-
* name: "ACME Corp",
|
|
1747
|
-
* employees: [employeeData1, employeeData2]
|
|
1748
|
-
* },
|
|
1749
|
-
* parentData: undefined, // Root level
|
|
1750
|
-
* };
|
|
1751
|
-
*
|
|
1752
|
-
* // Nested validation (for each employee)
|
|
1753
|
-
* const nestedOptions: ValidatorValidateTargetOptions<Employee> = {
|
|
1754
|
-
* data: employeeData,
|
|
1755
|
-
* parentData: { companyName: "ACME Corp" }, // Context from parent
|
|
1756
|
-
* propertyName: "employee",
|
|
1757
|
-
* };
|
|
1758
|
-
* ```
|
|
1759
|
-
*
|
|
1760
|
-
* ### Performance Tracking
|
|
1761
|
-
* The `startTime` property enables duration measurement:
|
|
1762
|
-
* ```typescript
|
|
1763
|
-
* const startTime = Date.now();
|
|
1764
|
-
* const options: ValidatorValidateTargetOptions<UserForm> = {
|
|
1765
|
-
* data: formData,
|
|
1766
|
-
* startTime, // Track when validation began
|
|
1767
|
-
* };
|
|
1768
|
-
*
|
|
1769
|
-
* const result = await Validator.validateTarget(UserForm, formData, options);
|
|
1770
|
-
* if (result.success) {
|
|
1771
|
-
* console.log(`Validation took ${result.duration}ms`);
|
|
1772
|
-
* }
|
|
1773
|
-
* ```
|
|
1774
|
-
*
|
|
1775
|
-
* ### Type Safety Benefits
|
|
1776
|
-
* - **Compile-time validation** of target class types
|
|
1777
|
-
* - **Property type checking** for data objects
|
|
1778
|
-
* - **Context propagation** through validation hierarchy
|
|
1779
|
-
* - **Error message customization** with proper typing
|
|
1780
|
-
*
|
|
1781
|
-
* ### Common Use Cases
|
|
1782
|
-
*
|
|
1783
|
-
* #### 1. Form Validation
|
|
1784
|
-
* ```typescript
|
|
1785
|
-
* const formOptions: ValidatorValidateTargetOptions<RegistrationForm> = {
|
|
1786
|
-
* data: {
|
|
1787
|
-
* email: submittedEmail,
|
|
1788
|
-
* password: submittedPassword,
|
|
1789
|
-
* confirmPassword: submittedConfirm,
|
|
1790
|
-
* },
|
|
1791
|
-
* fieldName: "registration_form",
|
|
1792
|
-
* context: { userType: "new" },
|
|
1793
|
-
* };
|
|
1794
|
-
* ```
|
|
1795
|
-
*
|
|
1796
|
-
* #### 2. API Request Validation
|
|
1797
|
-
* ```typescript
|
|
1798
|
-
* const apiOptions: ValidatorValidateTargetOptions<CreateUserRequest> = {
|
|
1799
|
-
* data: requestBody,
|
|
1800
|
-
* propertyName: "request",
|
|
1801
|
-
* context: { requestId: req.id, userAgent: req.headers['user-agent'] },
|
|
1802
|
-
* };
|
|
1803
|
-
* ```
|
|
1804
|
-
*
|
|
1805
|
-
* #### 3. Nested Object Validation
|
|
1806
|
-
* ```typescript
|
|
1807
|
-
* const nestedOptions: ValidatorValidateTargetOptions<OrderItem> = {
|
|
1808
|
-
* data: itemData,
|
|
1809
|
-
* parentData: { orderId: "12345", customerId: "67890" },
|
|
1810
|
-
* propertyName: "item",
|
|
1811
|
-
* errorMessageBuilder: customFormatter,
|
|
1812
|
-
* };
|
|
1813
|
-
* ```
|
|
1814
|
-
*
|
|
1815
|
-
* ### Relationship to Validation System
|
|
1816
|
-
* - **Used by**: {@link Validator.validateTarget} method
|
|
1817
|
-
* - **Extends**: {@link ValidatorValidateOptions} with target-specific modifications
|
|
1818
|
-
* - **Supports**: Multi-field validation with error aggregation
|
|
1819
|
-
* - **Integrates with**: Decorator-based validation system
|
|
1820
|
-
*
|
|
1821
|
-
* @template Target - The class constructor type being validated (must extend ClassConstructor)
|
|
1822
|
-
* @template Context - Optional context type for validation (defaults to unknown)
|
|
1823
|
-
* @template ParamsTypes - Parameter types for validation rules (defaults to ValidatorRuleParams)
|
|
1824
|
-
*
|
|
1825
|
-
* @public
|
|
1826
|
-
*
|
|
1827
|
-
* @see {@link ValidatorValidateOptions} - Base options interface being extended
|
|
1828
|
-
* @see {@link ValidatorValidateTargetData} - Target data type
|
|
1829
|
-
* @see {@link Validator.validateTarget} - Method that uses this interface
|
|
1830
|
-
* @see {@link ClassConstructor} - Class constructor constraint
|
|
1831
|
-
* @see {@link ValidatorValidationError} - Error type for errorMessageBuilder
|
|
1832
|
-
*/
|
|
1833
|
-
export interface ValidatorValidateTargetOptions<Target extends ClassConstructor = ClassConstructor, Context = unknown, ParamsTypes extends ValidatorRuleParams = ValidatorRuleParams> extends Omit<ValidatorValidateOptions<ParamsTypes, Context>, 'data' | 'rule' | 'value'> {
|
|
1834
|
-
data: ValidatorValidateTargetData<Target>;
|
|
1835
|
-
/**
|
|
1836
|
-
* The parent data/context for nested validations
|
|
1837
|
-
*
|
|
1838
|
-
* When validating nested objects, this property holds the parent
|
|
1839
|
-
*/
|
|
1840
|
-
parentData?: Dictionary;
|
|
1841
|
-
startTime?: number;
|
|
1842
|
-
errorMessageBuilder?: (translatedPropertyName: string, error: string, builderOptions: ValidatorValidationError & {
|
|
1843
|
-
propertyName: keyof InstanceType<Target> | string;
|
|
1844
|
-
translatedPropertyName: string;
|
|
1845
|
-
i18n: I18n;
|
|
1846
|
-
separators: {
|
|
1847
|
-
multiple: string;
|
|
1848
|
-
single: string;
|
|
1849
|
-
};
|
|
1850
|
-
data: Partial<Record<keyof InstanceType<Target>, any>>;
|
|
1851
|
-
}) => string;
|
|
1852
|
-
}
|
|
1853
|
-
/**
|
|
1854
|
-
* ## Multi-Rule Names Union
|
|
1855
|
-
*
|
|
1856
|
-
* A union type defining the names of validation rules that operate on multiple sub-rules.
|
|
1857
|
-
* These rules combine the results of several validation rules using logical operations.
|
|
1858
|
-
*
|
|
1859
|
-
* ### Purpose
|
|
1860
|
-
* Defines the specific rule names that support multi-rule validation patterns.
|
|
1861
|
-
* These rules allow combining multiple validation conditions with logical operators
|
|
1862
|
-
* like "one of" or "all of", enabling complex validation scenarios.
|
|
1863
|
-
*
|
|
1864
|
-
* ### Supported Multi-Rules
|
|
1865
|
-
* - **'OneOf'**: Passes if at least one of the sub-rules passes (logical OR)
|
|
1866
|
-
* - **'AllOf'**: Passes only if all sub-rules pass (logical AND)
|
|
1867
|
-
*
|
|
1868
|
-
* ### Type Structure
|
|
1869
|
-
* Simple string literal union with two possible values:
|
|
1870
|
-
* ```typescript
|
|
1871
|
-
* 'OneOf' | 'AllOf'
|
|
1872
|
-
* ```
|
|
1873
|
-
*
|
|
1874
|
-
* ### Usage in Validation
|
|
1875
|
-
* Multi-rule names are used in {@link ValidatorMultiRuleFunction} to specify
|
|
1876
|
-
* which logical operation to apply to a collection of validation rules.
|
|
1877
|
-
*
|
|
1878
|
-
* ```typescript
|
|
1879
|
-
* // Example: Email must be valid OR be empty (optional email field)
|
|
1880
|
-
* const rule: ValidatorMultiRuleFunction = (rules, context) => {
|
|
1881
|
-
* return rules.OneOf([
|
|
1882
|
-
* rules.Email([], context),
|
|
1883
|
-
* rules.IsEmpty([], context)
|
|
1884
|
-
* ]);
|
|
1885
|
-
* };
|
|
1886
|
-
* ```
|
|
1887
|
-
*
|
|
1888
|
-
* ### Relationship to Validation System
|
|
1889
|
-
* - **Used by**: {@link ValidatorMultiRuleFunction} as operation selector
|
|
1890
|
-
* - **Implemented in**: Rule registry as special multi-rule handlers
|
|
1891
|
-
* - **Combines with**: Regular validation rules via logical operations
|
|
1892
|
-
* - **Returns**: Single validation result from multiple rule evaluations
|
|
1893
|
-
*
|
|
1894
|
-
* ### Key Characteristics
|
|
1895
|
-
* - **Logical Operations**: Supports OR ('OneOf') and AND ('AllOf') combinations
|
|
1896
|
-
* - **Rule Composition**: Enables building complex validation logic from simple rules
|
|
1897
|
-
* - **Type Safety**: Compile-time guarantees for valid multi-rule names
|
|
1898
|
-
* - **Extensible**: New logical operations can be added by extending this union
|
|
1899
|
-
*
|
|
1900
|
-
* ### Comparison with Single Rules
|
|
1901
|
-
* | Aspect | Single Rule | Multi-Rule |
|
|
1902
|
-
* |--------|-------------|------------|
|
|
1903
|
-
* | Operation | One condition | Multiple conditions |
|
|
1904
|
-
* | Logic | Direct validation | Logical combination |
|
|
1905
|
-
* | Use Case | Basic validation | Complex conditional validation |
|
|
1906
|
-
* | Example | "IsEmail" | "OneOf(IsEmail, IsEmpty())" |
|
|
1907
|
-
*
|
|
1908
|
-
* ### Runtime Behavior
|
|
1909
|
-
* - **OneOf**: Returns success if any sub-rule passes, failure if all fail
|
|
1910
|
-
* - **AllOf**: Returns success only if all sub-rules pass, failure if any fails
|
|
1911
|
-
* - **Short-circuiting**: May stop evaluation early based on logical operation
|
|
1912
|
-
* - **Error Aggregation**: Collects errors from all evaluated rules
|
|
1913
|
-
*
|
|
1914
|
-
* @public
|
|
1915
|
-
*
|
|
1916
|
-
* @see {@link ValidatorMultiRuleFunction} - Function type that uses these names
|
|
1917
|
-
* @see {@link ValidatorDefaultMultiRule} - Default multi-rule configuration
|
|
1918
|
-
* @see {@link ValidatorRuleName} - General rule names (includes these)
|
|
1919
|
-
*/
|
|
1920
|
-
export type ValidatorMultiRuleNames = 'OneOf' | 'AllOf';
|
|
1921
|
-
/**
|
|
1922
|
-
* ## Validation Result Types (Either Pattern)
|
|
1923
|
-
*
|
|
1924
|
-
* Uses the Either<L, R> pattern where Left represents failure and Right represents success.
|
|
1925
|
-
* This provides strong type safety and prevents accessing wrong properties based on the result state.
|
|
1926
|
-
*/
|
|
1927
|
-
/**
|
|
1928
|
-
* ## Validation Error Details
|
|
1929
|
-
*
|
|
1930
|
-
* Comprehensive error information structure for validation failures.
|
|
1931
|
-
* This interface defines the complete error object that is returned when validation rules fail,
|
|
1932
|
-
* providing detailed context about what went wrong and where.
|
|
1933
|
-
*
|
|
1934
|
-
* ### Purpose
|
|
1935
|
-
* Serves as the standardized error format across the entire validation system.
|
|
1936
|
-
* Contains all necessary information for error reporting, debugging, and user feedback.
|
|
1937
|
-
* Used by both single-value and target validation failure results.
|
|
1938
|
-
*
|
|
1939
|
-
* ### Key Properties
|
|
1940
|
-
* - **status**: Always "error" for type discrimination
|
|
1941
|
-
* - **name**: Error class name ("ValidatorValidationError")
|
|
1942
|
-
* - **message**: Human-readable error message (translated if available)
|
|
1943
|
-
* - **ruleName**: The specific validation rule that failed
|
|
1944
|
-
* - **value**: The actual value that failed validation
|
|
1945
|
-
* - **propertyName**: Object property name (for target validation)
|
|
1946
|
-
* - **fieldName**: Form field identifier
|
|
1947
|
-
*
|
|
1948
|
-
* ### Usage in Validation Results
|
|
1949
|
-
* This interface is used in failure results:
|
|
1950
|
-
* - {@link ValidatorValidateFailure.error} - Single value validation failures
|
|
1951
|
-
* - {@link ValidatorValidateTargetFailure.errors} - Array of errors in target validation
|
|
1952
|
-
*
|
|
1953
|
-
* ### Error Message Structure
|
|
1954
|
-
* Error messages follow a consistent format:
|
|
1955
|
-
* ```
|
|
1956
|
-
* "[PropertyName]: Error message from rule"
|
|
1957
|
-
* ```
|
|
1958
|
-
* For example: `"[Email]: Must be valid email format"`
|
|
1959
|
-
*
|
|
1960
|
-
* ### Internationalization Support
|
|
1961
|
-
* - **translatedPropertyName**: Localized property name for user-facing messages
|
|
1962
|
-
* - **message**: Can be translated based on i18n configuration
|
|
1963
|
-
* - **timestamp**: When the error occurred (for logging/debugging)
|
|
1964
|
-
*
|
|
1965
|
-
* ### Metadata and Extensibility
|
|
1966
|
-
* - **code**: Programmatic error code for conditional handling
|
|
1967
|
-
* - **severity**: Error level ("error", "warning", "info")
|
|
1968
|
-
* - **metadata**: Additional error context as key-value pairs
|
|
1969
|
-
*
|
|
1970
|
-
* ### Example Error Object
|
|
1971
|
-
* ```typescript
|
|
1972
|
-
* const error: ValidatorValidationError = {
|
|
1973
|
-
* status: "error",
|
|
1974
|
-
* name: "ValidatorValidationError",
|
|
1975
|
-
* message: "[Email]: Must be valid email format",
|
|
1976
|
-
* ruleName: "Email",
|
|
1977
|
-
* ruleParams: [],
|
|
1978
|
-
* rawRuleName: "Email",
|
|
1979
|
-
* propertyName: "email",
|
|
1980
|
-
* fieldName: "email_input",
|
|
1981
|
-
* translatedPropertyName: "Email Address",
|
|
1982
|
-
* value: "invalid-email",
|
|
1983
|
-
* code: "INVALID_EMAIL",
|
|
1984
|
-
* severity: "error",
|
|
1985
|
-
* timestamp: new Date(),
|
|
1986
|
-
* metadata: {
|
|
1987
|
-
* suggestion: "Please use format: user@example.com",
|
|
1988
|
-
* domain: "example.com"
|
|
1989
|
-
* }
|
|
1990
|
-
* };
|
|
1991
|
-
* ```
|
|
1992
|
-
*
|
|
1993
|
-
* ### Relationship to Validation System
|
|
1994
|
-
* - **Created by**: Validation rule functions when they return failure strings
|
|
1995
|
-
* - **Processed by**: {@link Validator.validate} and {@link Validator.validateTarget}
|
|
1996
|
-
* - **Used in**: Error aggregation and reporting throughout the system
|
|
1997
|
-
* - **Compatible with**: Standard error handling patterns and logging systems
|
|
1998
|
-
*
|
|
1999
|
-
* ### Best Practices
|
|
2000
|
-
*
|
|
2001
|
-
* #### Error Message Guidelines
|
|
2002
|
-
* ```typescript
|
|
2003
|
-
* // ✅ Good: Specific, actionable messages
|
|
2004
|
-
* message: "[Password]: Must contain at least one uppercase letter"
|
|
2005
|
-
*
|
|
2006
|
-
* // ❌ Avoid: Generic or unhelpful messages
|
|
2007
|
-
* message: "Invalid input"
|
|
2008
|
-
* ```
|
|
2009
|
-
*
|
|
2010
|
-
* #### Using Error Codes
|
|
2011
|
-
* ```typescript
|
|
2012
|
-
* // Enable programmatic error handling
|
|
2013
|
-
* if (error.code === "EMAIL_INVALID_FORMAT") {
|
|
2014
|
-
* highlightEmailField();
|
|
2015
|
-
* showEmailFormatHint();
|
|
2016
|
-
* }
|
|
2017
|
-
* ```
|
|
2018
|
-
*
|
|
2019
|
-
* #### Metadata for Rich Errors
|
|
2020
|
-
* ```typescript
|
|
2021
|
-
* // Provide additional context
|
|
2022
|
-
* error.metadata = {
|
|
2023
|
-
* minLength: 8,
|
|
2024
|
-
* actualLength: 5,
|
|
2025
|
-
* missingChars: ["uppercase", "number"]
|
|
2026
|
-
* };
|
|
2027
|
-
* ```
|
|
2028
|
-
*
|
|
2029
|
-
* @public
|
|
2030
|
-
*
|
|
2031
|
-
* @see {@link ValidatorValidateFailure} - Single validation failure result
|
|
2032
|
-
* @see {@link ValidatorValidateTargetFailure} - Target validation failure result
|
|
2033
|
-
* @see {@link Validator.validate} - Method that creates these errors
|
|
2034
|
-
* @see {@link Validator.validateTarget} - Method that creates these errors
|
|
2035
|
-
*/
|
|
2036
|
-
export interface ValidatorValidationError {
|
|
2037
|
-
/** Always 'error' for failures */
|
|
2038
|
-
status: 'error';
|
|
2039
|
-
name: 'ValidatorValidationError';
|
|
2040
|
-
/** The property name that failed validation (required) */
|
|
2041
|
-
fieldName?: string;
|
|
2042
|
-
/** Alias for fieldName (required) */
|
|
2043
|
-
propertyName?: string;
|
|
2044
|
-
/** The validation error message (required) */
|
|
2045
|
-
message: string;
|
|
2046
|
-
/** Localized field name for user-facing messages */
|
|
2047
|
-
translatedPropertyName?: string;
|
|
2048
|
-
/** The specific rule that failed */
|
|
2049
|
-
ruleName?: ValidatorRuleName;
|
|
2050
|
-
/** Parameters passed to the failing rule */
|
|
2051
|
-
ruleParams: any[];
|
|
2052
|
-
/** The value that failed validation */
|
|
2053
|
-
value: any;
|
|
2054
|
-
/** Raw rule name with parameters (e.g., "minLength[5]") */
|
|
2055
|
-
rawRuleName?: ValidatorRuleName | string;
|
|
2056
|
-
/** Error code for programmatic handling */
|
|
2057
|
-
code?: string;
|
|
2058
|
-
/** Error severity level */
|
|
2059
|
-
severity?: 'error' | 'warning' | 'info';
|
|
2060
|
-
/** When the validation failed */
|
|
2061
|
-
timestamp?: Date;
|
|
2062
|
-
/** Additional error metadata */
|
|
2063
|
-
metadata?: Dictionary;
|
|
2064
|
-
}
|
|
2065
|
-
/**
|
|
2066
|
-
* ## Single Value Validation Success Result
|
|
2067
|
-
*
|
|
2068
|
-
* Represents a successful validation result for a single value.
|
|
2069
|
-
* This type is used as the success branch of the {@link ValidatorValidateResult} discriminated union.
|
|
2070
|
-
*
|
|
2071
|
-
* ### Type Guard
|
|
2072
|
-
* Can be narrowed using {@link Validator.isSuccess}:
|
|
2073
|
-
* ```typescript
|
|
2074
|
-
* if (Validator.isSuccess(result)) {
|
|
2075
|
-
* // TypeScript knows: result satisfies ValidatorValidateSuccess
|
|
2076
|
-
* // Can safely access result.value, result.validatedAt, result.duration
|
|
2077
|
-
* }
|
|
2078
|
-
* ```
|
|
2079
|
-
*
|
|
2080
|
-
* ### Properties
|
|
2081
|
-
* - **success**: Literal `true` for type discrimination
|
|
2082
|
-
* - **value**: The original value that passed validation
|
|
2083
|
-
* - **validatedAt**: ISO timestamp indicating when validation completed
|
|
2084
|
-
* - **duration**: Duration in milliseconds from validation start to completion
|
|
2085
|
-
* - **error**: Explicitly `undefined` for success (aids type narrowing)
|
|
2086
|
-
* - **failedAt**: Explicitly `undefined` for success (aids type narrowing)
|
|
2087
|
-
* - **data**: Optional context data (inherited from BaseData)
|
|
2088
|
-
* - **context**: Optional validation context (inherited from BaseData)
|
|
1606
|
+
* ### Properties
|
|
1607
|
+
* - **success**: Literal `true` for type discrimination
|
|
1608
|
+
* - **value**: The original value that passed validation
|
|
1609
|
+
* - **validatedAt**: ISO timestamp indicating when validation completed
|
|
1610
|
+
* - **duration**: Duration in milliseconds from validation start to completion
|
|
1611
|
+
* - **error**: Explicitly `undefined` for success (aids type narrowing)
|
|
1612
|
+
* - **failedAt**: Explicitly `undefined` for success (aids type narrowing)
|
|
1613
|
+
* - **data**: Optional context data (inherited from ValidatorBaseOptions)
|
|
1614
|
+
* - **context**: Optional validation context (inherited from ValidatorBaseOptions)
|
|
2089
1615
|
*
|
|
2090
1616
|
* ### Example
|
|
2091
1617
|
* ```typescript
|
|
@@ -2095,7 +1621,7 @@ export interface ValidatorValidationError {
|
|
|
2095
1621
|
* });
|
|
2096
1622
|
*
|
|
2097
1623
|
* if (result.success) {
|
|
2098
|
-
* // result is
|
|
1624
|
+
* // result is ValidatorSuccess
|
|
2099
1625
|
* console.log("Validated:", result.value);
|
|
2100
1626
|
* console.log("Took:", result.duration, "ms");
|
|
2101
1627
|
* console.log("Completed at:", result.validatedAt.toISOString());
|
|
@@ -2106,12 +1632,12 @@ export interface ValidatorValidationError {
|
|
|
2106
1632
|
*
|
|
2107
1633
|
* @public
|
|
2108
1634
|
*
|
|
2109
|
-
* @see {@link
|
|
2110
|
-
* @see {@link
|
|
1635
|
+
* @see {@link ValidatorResult}
|
|
1636
|
+
* @see {@link ValidatorError}
|
|
2111
1637
|
* @see {@link Validator.validate}
|
|
2112
1638
|
* @see {@link Validator.isSuccess}
|
|
2113
1639
|
*/
|
|
2114
|
-
export interface
|
|
1640
|
+
export interface ValidatorSuccess<Context = unknown> extends ValidatorBaseOptions<Context> {
|
|
2115
1641
|
/** Discriminant for type narrowing - always `true` for success */
|
|
2116
1642
|
success: true;
|
|
2117
1643
|
/**
|
|
@@ -2128,234 +1654,7 @@ export interface ValidatorValidateSuccess<Context = unknown> extends BaseData<Co
|
|
|
2128
1654
|
error?: undefined;
|
|
2129
1655
|
/** Always undefined for success results (type narrowing aid) */
|
|
2130
1656
|
failedAt?: undefined;
|
|
2131
|
-
|
|
2132
|
-
/**
|
|
2133
|
-
* ## Base Data Structure
|
|
2134
|
-
*
|
|
2135
|
-
* Shared data structure for both validation success and failure results.
|
|
2136
|
-
* Contains the core properties that exist in all validation outcomes.
|
|
2137
|
-
*
|
|
2138
|
-
* ### Purpose
|
|
2139
|
-
* Provides a common interface for passing data through the validation pipeline
|
|
2140
|
-
* and in the result objects. Used by both {@link ValidatorValidateSuccess}
|
|
2141
|
-
* and {@link ValidatorValidateFailure}.
|
|
2142
|
-
*
|
|
2143
|
-
* ### Properties
|
|
2144
|
-
* - **value**: The actual value being validated (required)
|
|
2145
|
-
* - **data**: Optional contextual data available to validation rules
|
|
2146
|
-
* - **context**: Optional typed context object for advanced validations
|
|
2147
|
-
*
|
|
2148
|
-
* ### Usage in Validation Results
|
|
2149
|
-
* ```typescript
|
|
2150
|
-
* // In ValidatorValidateSuccess
|
|
2151
|
-
* const successResult: ValidatorValidateSuccess = {
|
|
2152
|
-
* success: true,
|
|
2153
|
-
* value: "user@example.com", // Original validated value
|
|
2154
|
-
* data: { userId: 123 }, // Additional context
|
|
2155
|
-
* context: { ... }, // Typed context object
|
|
2156
|
-
* validatedAt: new Date(),
|
|
2157
|
-
* duration: 5,
|
|
2158
|
-
* };
|
|
2159
|
-
*
|
|
2160
|
-
* // In ValidatorValidateFailure
|
|
2161
|
-
* const failureResult: ValidatorValidateFailure = {
|
|
2162
|
-
* success: false,
|
|
2163
|
-
* value: "invalid-email", // Value that failed
|
|
2164
|
-
* data: { userId: 123 }, // Available during failure too
|
|
2165
|
-
* context: { ... }, // Context from validation request
|
|
2166
|
-
* error: { ... },
|
|
2167
|
-
* failedAt: new Date(),
|
|
2168
|
-
* duration: 2,
|
|
2169
|
-
* };
|
|
2170
|
-
* ```
|
|
2171
|
-
*
|
|
2172
|
-
* @template Context - Type parameter for optional typed context object
|
|
2173
|
-
*
|
|
2174
|
-
* @public
|
|
2175
|
-
*
|
|
2176
|
-
* @see {@link ValidatorValidateOptions} - Options passed to validation
|
|
2177
|
-
* @see {@link ValidatorValidateSuccess} - Success result type
|
|
2178
|
-
* @see {@link ValidatorValidateFailure} - Failure result type
|
|
2179
|
-
*/
|
|
2180
|
-
interface BaseData<Context = unknown> {
|
|
2181
|
-
/**
|
|
2182
|
-
* The value to use for performing the validation.
|
|
2183
|
-
* This is the actual data that will be validated against the specified rules.
|
|
2184
|
-
*
|
|
2185
|
-
* @type {any}
|
|
2186
|
-
*
|
|
2187
|
-
* @example
|
|
2188
|
-
* ```typescript
|
|
2189
|
-
* const result = await Validator.validate({
|
|
2190
|
-
* value: "user@example.com", // This is the value being validated
|
|
2191
|
-
* rules: ["Required", "Email"],
|
|
2192
|
-
* });
|
|
2193
|
-
* ```
|
|
2194
|
-
*
|
|
2195
|
-
* @remarks
|
|
2196
|
-
* - This is the core data being validated
|
|
2197
|
-
* - Type can be any JavaScript value: string, number, object, array, etc.
|
|
2198
|
-
* - Available in both success and failure results
|
|
2199
|
-
*/
|
|
2200
|
-
value: any;
|
|
2201
|
-
/**
|
|
2202
|
-
* Optional data object providing contextual information for validation rules.
|
|
2203
|
-
*
|
|
2204
|
-
* This property is used to provide additional context for the validation rule.
|
|
2205
|
-
* It can be used to pass any additional data that might be needed for validation,
|
|
2206
|
-
* such as form data, related field values, or other contextual information.
|
|
2207
|
-
*
|
|
2208
|
-
* @type {Dictionary | undefined}
|
|
2209
|
-
*
|
|
2210
|
-
* @example
|
|
2211
|
-
* ```typescript
|
|
2212
|
-
* const result = await Validator.validate({
|
|
2213
|
-
* value: "test@example.com",
|
|
2214
|
-
* rules: ["Required", "Email"],
|
|
2215
|
-
* data: {
|
|
2216
|
-
* userId: 123,
|
|
2217
|
-
* formId: "user_form",
|
|
2218
|
-
* },
|
|
2219
|
-
* });
|
|
2220
|
-
* ```
|
|
2221
|
-
*
|
|
2222
|
-
* @remarks
|
|
2223
|
-
* - Optional property (not required)
|
|
2224
|
-
* - Passed to validation rule functions via options.data
|
|
2225
|
-
* - Useful for multi-field validation scenarios
|
|
2226
|
-
* - Commonly used for form data context in validateTarget
|
|
2227
|
-
*/
|
|
2228
|
-
data?: Dictionary;
|
|
2229
|
-
/**
|
|
2230
|
-
* Optional typed context object for validation.
|
|
2231
|
-
*
|
|
2232
|
-
* Provides a typed context that can be passed to validation rules for
|
|
2233
|
-
* advanced validation scenarios requiring external data or permissions.
|
|
2234
|
-
*
|
|
2235
|
-
* @template Context - Type of the context object
|
|
2236
|
-
*
|
|
2237
|
-
* @example
|
|
2238
|
-
* ```typescript
|
|
2239
|
-
* interface UserContext {
|
|
2240
|
-
* userId: number;
|
|
2241
|
-
* permissions: string[];
|
|
2242
|
-
* isAdmin: boolean;
|
|
2243
|
-
* }
|
|
2244
|
-
*
|
|
2245
|
-
* const result = await Validator.validate<UserContext>({
|
|
2246
|
-
* value: "admin_action",
|
|
2247
|
-
* rules: ["Required"],
|
|
2248
|
-
* context: {
|
|
2249
|
-
* userId: 123,
|
|
2250
|
-
* permissions: ["read", "write", "admin"],
|
|
2251
|
-
* isAdmin: true,
|
|
2252
|
-
* },
|
|
2253
|
-
* });
|
|
2254
|
-
* ```
|
|
2255
|
-
*
|
|
2256
|
-
* @remarks
|
|
2257
|
-
* - Optional property (not required)
|
|
2258
|
-
* - Type is defined by the Context generic parameter
|
|
2259
|
-
* - Passed to all validation rule functions
|
|
2260
|
-
* - Enables context-aware validation rules
|
|
2261
|
-
* - Commonly used for permission-based or user-specific validations
|
|
2262
|
-
*/
|
|
2263
|
-
context?: Context;
|
|
2264
|
-
}
|
|
2265
|
-
/**
|
|
2266
|
-
* ## Single Value Validation Failure Result
|
|
2267
|
-
*
|
|
2268
|
-
* Represents a failed validation result for a single value.
|
|
2269
|
-
* This type is used as the failure branch of the {@link ValidatorValidateResult} discriminated union.
|
|
2270
|
-
*
|
|
2271
|
-
* ### Type Guard
|
|
2272
|
-
* Can be narrowed using {@link Validator.isFailure}:
|
|
2273
|
-
* ```typescript
|
|
2274
|
-
* if (Validator.isFailure(result)) {
|
|
2275
|
-
* // TypeScript knows: result satisfies ValidatorValidateFailure
|
|
2276
|
-
* // Can safely access result.error, result.failedAt, result.duration
|
|
2277
|
-
* }
|
|
2278
|
-
* ```
|
|
2279
|
-
*
|
|
2280
|
-
* ### Properties
|
|
2281
|
-
* - **success**: Literal `false` for type discrimination
|
|
2282
|
-
* - **error**: Validation error details (name, message, rule info)
|
|
2283
|
-
* - **failedAt**: ISO timestamp indicating when validation failed
|
|
2284
|
-
* - **duration**: Duration in milliseconds until failure
|
|
2285
|
-
* - **validatedAt**: Explicitly `undefined` for failure (aids type narrowing)
|
|
2286
|
-
* - **value**: The original value that failed validation
|
|
2287
|
-
* - **data**: Optional context data (inherited from BaseData)
|
|
2288
|
-
* - **context**: Optional validation context (inherited from BaseData)
|
|
2289
|
-
*
|
|
2290
|
-
* ### Error Object Structure
|
|
2291
|
-
* The `error` property contains:
|
|
2292
|
-
* ```typescript
|
|
2293
|
-
* {
|
|
2294
|
-
* name: "ValidatorValidationError",
|
|
2295
|
-
* message: "Error message (translated if available)",
|
|
2296
|
-
* ruleName: "Email", // Name of failing rule
|
|
2297
|
-
* ruleParams: [], // Parameters passed to rule
|
|
2298
|
-
* rawRuleName: "Email", // Original rule specification
|
|
2299
|
-
* fieldName: "email_field", // Optional field identifier
|
|
2300
|
-
* propertyName: "email", // Optional property name
|
|
2301
|
-
* translatedPropertyName?: "Email Address", // Translated name
|
|
2302
|
-
* value: "invalid@", // Value that failed
|
|
2303
|
-
* }
|
|
2304
|
-
* ```
|
|
2305
|
-
*
|
|
2306
|
-
* ### Example
|
|
2307
|
-
* ```typescript
|
|
2308
|
-
* const result = await Validator.validate({
|
|
2309
|
-
* value: "not-an-email",
|
|
2310
|
-
* rules: ["Required", "Email"],
|
|
2311
|
-
* });
|
|
2312
|
-
*
|
|
2313
|
-
* if (!result.success) {
|
|
2314
|
-
* // result is ValidatorValidateFailure
|
|
2315
|
-
* console.error("Validation failed:");
|
|
2316
|
-
* console.error(" Value:", result.value);
|
|
2317
|
-
* console.error(" Error:", result.error.message);
|
|
2318
|
-
* console.error(" Rule:", result.error.ruleName);
|
|
2319
|
-
* console.error(" Failed at:", result.failedAt.toISOString());
|
|
2320
|
-
* console.error(" Duration:", result.duration, "ms");
|
|
2321
|
-
* }
|
|
2322
|
-
* ```
|
|
2323
|
-
*
|
|
2324
|
-
* @template Context - Type of the optional validation context
|
|
2325
|
-
*
|
|
2326
|
-
* @public
|
|
2327
|
-
*
|
|
2328
|
-
* @see {@link ValidatorValidateResult}
|
|
2329
|
-
* @see {@link ValidatorValidateSuccess}
|
|
2330
|
-
* @see {@link ValidatorValidationError}
|
|
2331
|
-
* @see {@link Validator.validate}
|
|
2332
|
-
* @see {@link Validator.isFailure}
|
|
2333
|
-
*/
|
|
2334
|
-
export interface ValidatorValidateFailure<Context = unknown> extends BaseData<Context> {
|
|
2335
|
-
/** Discriminant for type narrowing - always `false` for failure */
|
|
2336
|
-
success: false;
|
|
2337
|
-
/**
|
|
2338
|
-
* The validation error details
|
|
2339
|
-
*
|
|
2340
|
-
* Contains complete information about what validation rule failed
|
|
2341
|
-
* and why, including the rule name, parameters, and error message.
|
|
2342
|
-
*
|
|
2343
|
-
* @type {ValidatorValidationError}
|
|
2344
|
-
* @see {@link ValidatorValidationError}
|
|
2345
|
-
*/
|
|
2346
|
-
error: ValidatorValidationError;
|
|
2347
|
-
/**
|
|
2348
|
-
* ISO timestamp indicating when validation failed
|
|
2349
|
-
* @example "2024-11-08T10:30:45.118Z"
|
|
2350
|
-
*/
|
|
2351
|
-
failedAt?: Date;
|
|
2352
|
-
/**
|
|
2353
|
-
* Duration of validation before failure in milliseconds
|
|
2354
|
-
* @example 2 (milliseconds - failed quickly on first rule)
|
|
2355
|
-
*/
|
|
2356
|
-
duration?: number;
|
|
2357
|
-
/** Always undefined for failure results (type narrowing aid) */
|
|
2358
|
-
validatedAt?: undefined;
|
|
1657
|
+
message?: string | undefined;
|
|
2359
1658
|
}
|
|
2360
1659
|
/**
|
|
2361
1660
|
* ## Validation Result Type (Discriminated Union)
|
|
@@ -2370,12 +1669,12 @@ export interface ValidatorValidateFailure<Context = unknown> extends BaseData<Co
|
|
|
2370
1669
|
* const result = await Validator.validate({ value: "...", rules: [...] });
|
|
2371
1670
|
*
|
|
2372
1671
|
* if (result.success) {
|
|
2373
|
-
* // TypeScript knows:
|
|
1672
|
+
* // TypeScript knows: ValidatorSuccess
|
|
2374
1673
|
* console.log(result.value); // ✓ Available
|
|
2375
1674
|
* console.log(result.validatedAt); // ✓ Available
|
|
2376
1675
|
* console.log(result.error); // ✗ Type error (undefined for success)
|
|
2377
1676
|
* } else {
|
|
2378
|
-
* // TypeScript knows:
|
|
1677
|
+
* // TypeScript knows: ValidatorError
|
|
2379
1678
|
* console.log(result.value); // ✓ Available
|
|
2380
1679
|
* console.log(result.error); // ✓ Available
|
|
2381
1680
|
* console.log(result.validatedAt); // ✗ Type error (undefined for failure)
|
|
@@ -2387,11 +1686,11 @@ export interface ValidatorValidateFailure<Context = unknown> extends BaseData<Co
|
|
|
2387
1686
|
* const result = await Validator.validate({ value: "...", rules: [...] });
|
|
2388
1687
|
*
|
|
2389
1688
|
* if (Validator.isSuccess(result)) {
|
|
2390
|
-
* // result is
|
|
1689
|
+
* // result is ValidatorSuccess<Context>
|
|
2391
1690
|
* console.log(result.value);
|
|
2392
1691
|
* console.log(result.validatedAt);
|
|
2393
|
-
* } else if (Validator.
|
|
2394
|
-
* // result is
|
|
1692
|
+
* } else if (Validator.isValidatorError(result)) {
|
|
1693
|
+
* // result is ValidatorError
|
|
2395
1694
|
* console.log(result.error.message);
|
|
2396
1695
|
* console.log(result.error.ruleName);
|
|
2397
1696
|
* }
|
|
@@ -2412,8 +1711,8 @@ export interface ValidatorValidateFailure<Context = unknown> extends BaseData<Co
|
|
|
2412
1711
|
* ```
|
|
2413
1712
|
*
|
|
2414
1713
|
* ### Union Members
|
|
2415
|
-
* - {@link
|
|
2416
|
-
* - {@link
|
|
1714
|
+
* - {@link ValidatorSuccess} - When validation passes (success: true)
|
|
1715
|
+
* - {@link ValidatorError} - When validation fails (success: false)
|
|
2417
1716
|
*
|
|
2418
1717
|
* @template Context - Type of the optional validation context
|
|
2419
1718
|
*
|
|
@@ -2423,199 +1722,42 @@ export interface ValidatorValidateFailure<Context = unknown> extends BaseData<Co
|
|
|
2423
1722
|
* userId: number;
|
|
2424
1723
|
* }
|
|
2425
1724
|
*
|
|
2426
|
-
* const result:
|
|
1725
|
+
* const result: ValidatorResult<MyContext> = await Validator.validate({
|
|
2427
1726
|
* value: "test@example.com",
|
|
2428
1727
|
* rules: ["Required", "Email"],
|
|
2429
1728
|
* context: { userId: 123 },
|
|
2430
1729
|
* });
|
|
2431
1730
|
* ```
|
|
2432
|
-
*
|
|
2433
|
-
* @public
|
|
2434
|
-
*
|
|
2435
|
-
* @see {@link
|
|
2436
|
-
* @see {@link
|
|
2437
|
-
* @see {@link Validator.validate} - Main validation method
|
|
2438
|
-
* @see {@link Validator.isSuccess} - Type guard for success
|
|
2439
|
-
* @see {@link Validator.isFailure} - Type guard for failure
|
|
2440
|
-
*/
|
|
2441
|
-
export type
|
|
2442
|
-
/**
|
|
2443
|
-
* ## Validate Target Result Types
|
|
2444
|
-
*
|
|
2445
|
-
* Types for class-based validation using decorators.
|
|
2446
|
-
* Supports accumulation of multiple field errors across all decorated properties.
|
|
2447
|
-
*
|
|
2448
|
-
* ### Key Differences from Single-Value Validation
|
|
2449
|
-
* - **Multiple Errors**: Collects errors from all fields that fail validation
|
|
2450
|
-
* - **Parallel Validation**: All fields are validated concurrently
|
|
2451
|
-
* - **Error Aggregation**: Returns array of errors with field-level details
|
|
2452
|
-
* - **Class-Based**: Works with decorated class properties rather than single values
|
|
2453
|
-
* - **FieldMeta Mapping**: Maps validated data back to class structure with proper typing
|
|
2454
|
-
*/
|
|
2455
|
-
/**
|
|
2456
|
-
* ## Class Validation Failure Result
|
|
2457
|
-
*
|
|
2458
|
-
* Represents a failed multi-field validation result when using {@link Validator.validateTarget}.
|
|
2459
|
-
* Unlike single-value validation, this accumulates errors from all fields that fail.
|
|
2460
|
-
*
|
|
2461
|
-
* ### Type Guard
|
|
2462
|
-
* Can be narrowed by checking the `success` property:
|
|
2463
|
-
* ```typescript
|
|
2464
|
-
* const result = await Validator.validateTarget(UserForm, data);
|
|
2465
|
-
*
|
|
2466
|
-
* if (!result.success) {
|
|
2467
|
-
* // result is ValidatorValidateTargetFailure
|
|
2468
|
-
* console.log(result.errors); // Array of field errors
|
|
2469
|
-
* console.log(result.failureCount); // Number of failed fields
|
|
2470
|
-
* console.log(result.message); // Summary message
|
|
2471
|
-
* }
|
|
2472
|
-
* ```
|
|
2473
|
-
*
|
|
2474
|
-
* ### Properties
|
|
2475
|
-
* - **success**: Literal `false` for type discrimination
|
|
2476
|
-
* - **errors**: Array of ValidatorValidationError, one per failed field
|
|
2477
|
-
* - **failureCount**: Number of fields that failed validation
|
|
2478
|
-
* - **message**: Summary message (e.g., "Validation failed for 3 fields")
|
|
2479
|
-
* - **status**: Always "error" for consistency
|
|
2480
|
-
* - **failedAt**: ISO timestamp of when validation failed
|
|
2481
|
-
* - **duration**: Milliseconds elapsed during validation
|
|
2482
|
-
* - **data**: Always `undefined` for target failures
|
|
2483
|
-
* - **value**: Always `undefined` for target (use `errors` instead)
|
|
2484
|
-
* - **context**: Optional validation context provided
|
|
2485
|
-
*
|
|
2486
|
-
* ### Error Array Structure
|
|
2487
|
-
* Each error in the `errors` array contains:
|
|
2488
|
-
* ```typescript
|
|
2489
|
-
* {
|
|
2490
|
-
* name: "ValidatorValidationError",
|
|
2491
|
-
* status: "error",
|
|
2492
|
-
* fieldName: "email_field", // Form field identifier
|
|
2493
|
-
* propertyName: "email", // Class property name
|
|
2494
|
-
* message: "[Email]: Must be valid email", // Formatted error message
|
|
2495
|
-
* ruleName: "Email", // Name of failing rule
|
|
2496
|
-
* ruleParams: [], // Rule parameters
|
|
2497
|
-
* value: "invalid@", // Value that failed
|
|
2498
|
-
* }
|
|
2499
|
-
* ```
|
|
2500
|
-
*
|
|
2501
|
-
* ### Example
|
|
2502
|
-
* ```typescript
|
|
2503
|
-
* class UserForm {
|
|
2504
|
-
* @IsRequired()
|
|
2505
|
-
* @IsEmail()
|
|
2506
|
-
* email: string;
|
|
2507
|
-
*
|
|
2508
|
-
* @IsRequired()
|
|
2509
|
-
* @MinLength(3)
|
|
2510
|
-
* name: string;
|
|
2511
|
-
* }
|
|
2512
|
-
*
|
|
2513
|
-
* const result = await Validator.validateTarget(UserForm, {
|
|
2514
|
-
* email: "invalid-email",
|
|
2515
|
-
* name: "ab", // Too short
|
|
2516
|
-
* });
|
|
2517
|
-
*
|
|
2518
|
-
* if (!result.success) {
|
|
2519
|
-
* // result.failureCount === 2
|
|
2520
|
-
* // result.errors.length === 2
|
|
2521
|
-
* result.errors.forEach(error => {
|
|
2522
|
-
* console.error(`${error.propertyName}: ${error.message}`);
|
|
2523
|
-
* });
|
|
2524
|
-
* }
|
|
2525
|
-
* ```
|
|
2526
|
-
* @template Context - Type of the optional validation context
|
|
2527
|
-
*
|
|
2528
|
-
* @public
|
|
2529
|
-
*
|
|
2530
|
-
* @see {@link ValidatorValidateTargetResult}
|
|
2531
|
-
* @see {@link ValidatorValidationError}
|
|
2532
|
-
* @see {@link Validator.validateTarget}
|
|
2533
|
-
*/
|
|
2534
|
-
export interface ValidatorValidateTargetFailure<Context = unknown> extends Omit<BaseData<Context>, 'value' | 'data'> {
|
|
2535
|
-
/** Discriminant for type narrowing - always `false` for failures */
|
|
2536
|
-
success: false;
|
|
2537
|
-
/**
|
|
2538
|
-
* Summary message describing the failure
|
|
2539
|
-
*
|
|
2540
|
-
* Typically formatted as "Validation failed for N fields" where N is the number of failures.
|
|
2541
|
-
* Can be customized via i18n translations.
|
|
2542
|
-
*
|
|
2543
|
-
* @type {string}
|
|
2544
|
-
* @example "Validation failed for 3 fields"
|
|
2545
|
-
*/
|
|
2546
|
-
message: string;
|
|
2547
|
-
/**
|
|
2548
|
-
* Array of validation errors for each field that failed
|
|
2549
|
-
*
|
|
2550
|
-
* Contains one error object per field that failed validation.
|
|
2551
|
-
* Each error includes the field name, error message, rule name, and value.
|
|
2552
|
-
*
|
|
2553
|
-
* @type {ValidatorValidationError[]}
|
|
2554
|
-
* @see {@link ValidatorValidationError}
|
|
2555
|
-
*/
|
|
2556
|
-
errors: ValidatorValidationError[];
|
|
2557
|
-
/**
|
|
2558
|
-
* Number of fields that failed validation
|
|
2559
|
-
*
|
|
2560
|
-
* Equal to errors.length. Provided for convenience.
|
|
2561
|
-
*
|
|
2562
|
-
* @type {number}
|
|
2563
|
-
* @example 3
|
|
2564
|
-
*/
|
|
2565
|
-
failureCount: number;
|
|
2566
|
-
/**
|
|
2567
|
-
* Status indicator for this result
|
|
2568
|
-
*
|
|
2569
|
-
* Always "error" for failures. Provided for consistency with HTTP and API conventions.
|
|
2570
|
-
*
|
|
2571
|
-
* @type {"error"}
|
|
2572
|
-
*/
|
|
2573
|
-
status: 'error';
|
|
2574
|
-
/**
|
|
2575
|
-
* ISO timestamp of when validation failed
|
|
2576
|
-
*
|
|
2577
|
-
* Indicates the exact time validation completed with failures.
|
|
2578
|
-
*
|
|
2579
|
-
* @type {Date | undefined}
|
|
2580
|
-
* @example new Date("2024-11-08T10:30:45.523Z")
|
|
2581
|
-
*/
|
|
2582
|
-
failedAt?: Date;
|
|
2583
|
-
/**
|
|
2584
|
-
* Duration of validation in milliseconds
|
|
2585
|
-
*
|
|
2586
|
-
* Measures time from validation start until failures were detected.
|
|
2587
|
-
* Note: All fields are validated in parallel, so this is not the sum of individual field times.
|
|
2588
|
-
*
|
|
2589
|
-
* @type {number | undefined}
|
|
2590
|
-
* @example 45 (milliseconds)
|
|
2591
|
-
*/
|
|
2592
|
-
duration?: number;
|
|
2593
|
-
/** Validation context (if provided) */
|
|
2594
|
-
context?: Context;
|
|
2595
|
-
/** Always `undefined` for target failures (type narrowing aid) */
|
|
2596
|
-
validatedAt?: undefined;
|
|
2597
|
-
data: Dictionary;
|
|
2598
|
-
}
|
|
1731
|
+
*
|
|
1732
|
+
* @public
|
|
1733
|
+
*
|
|
1734
|
+
* @see {@link ValidatorSuccess} - Success variant
|
|
1735
|
+
* @see {@link ValidatorError} - Failure variant
|
|
1736
|
+
* @see {@link Validator.validate} - Main validation method
|
|
1737
|
+
* @see {@link Validator.isSuccess} - Type guard for success
|
|
1738
|
+
* @see {@link Validator.isFailure} - Type guard for failure
|
|
1739
|
+
*/
|
|
1740
|
+
export type ValidatorResult<Context = unknown> = ValidatorSuccess<Context> | ValidatorError;
|
|
2599
1741
|
/**
|
|
2600
1742
|
* ## Class Validation Success Result
|
|
2601
1743
|
*
|
|
2602
|
-
* Represents a successful multi-field validation result when using {@link Validator.
|
|
1744
|
+
* Represents a successful multi-field validation result when using {@link Validator.validateClass}.
|
|
2603
1745
|
* All decorated fields passed their respective validation rules.
|
|
2604
1746
|
*
|
|
2605
1747
|
* ### Type Guard
|
|
2606
1748
|
* Can be narrowed by checking the `success` property:
|
|
2607
1749
|
* ```typescript
|
|
2608
|
-
* const result = await Validator.
|
|
1750
|
+
* const result = await Validator.validateClass(UserForm, data);
|
|
2609
1751
|
*
|
|
2610
1752
|
* if (result.success) {
|
|
2611
|
-
* // result is
|
|
1753
|
+
* // result is ValidatorClassSuccess
|
|
2612
1754
|
* console.log(result.data); // Validated instance of T
|
|
2613
1755
|
* console.log(result.validatedAt); // Timestamp of validation
|
|
2614
1756
|
* }
|
|
2615
1757
|
* ```
|
|
2616
1758
|
*
|
|
2617
1759
|
* ### Properties vs Single-Value Success
|
|
2618
|
-
* Unlike {@link
|
|
1760
|
+
* Unlike {@link ValidatorSuccess}, class validation success uses:
|
|
2619
1761
|
* - **data**: The validated class instance (not `value`)
|
|
2620
1762
|
* - **value**: Always `undefined` (type narrowing aid)
|
|
2621
1763
|
* - **errors**: Always `undefined` (type narrowing aid)
|
|
@@ -2635,7 +1777,7 @@ export interface ValidatorValidateTargetFailure<Context = unknown> extends Omit<
|
|
|
2635
1777
|
* name: string;
|
|
2636
1778
|
* }
|
|
2637
1779
|
*
|
|
2638
|
-
* const result = await Validator.
|
|
1780
|
+
* const result = await Validator.validateClass(UserForm, {
|
|
2639
1781
|
* email: "user@example.com",
|
|
2640
1782
|
* name: "John",
|
|
2641
1783
|
* });
|
|
@@ -2652,7 +1794,7 @@ export interface ValidatorValidateTargetFailure<Context = unknown> extends Omit<
|
|
|
2652
1794
|
* ```
|
|
2653
1795
|
*
|
|
2654
1796
|
* ### Comparison with Single-Value Success
|
|
2655
|
-
* | Aspect | Single-Value |
|
|
1797
|
+
* | Aspect | Single-Value | TClass |
|
|
2656
1798
|
* |--------|-------------|--------|
|
|
2657
1799
|
* | Property | `value` | `data` |
|
|
2658
1800
|
* | Validates | One value | Multiple fields |
|
|
@@ -2666,7 +1808,7 @@ export interface ValidatorValidateTargetFailure<Context = unknown> extends Omit<
|
|
|
2666
1808
|
* form.email = "user@example.com";
|
|
2667
1809
|
* form.name = "John";
|
|
2668
1810
|
*
|
|
2669
|
-
* const result = await Validator.
|
|
1811
|
+
* const result = await Validator.validateClass(UserForm, form);
|
|
2670
1812
|
*
|
|
2671
1813
|
* if (result.success) {
|
|
2672
1814
|
* // Safe to use result.data
|
|
@@ -2679,23 +1821,13 @@ export interface ValidatorValidateTargetFailure<Context = unknown> extends Omit<
|
|
|
2679
1821
|
*
|
|
2680
1822
|
* @public
|
|
2681
1823
|
*
|
|
2682
|
-
* @see {@link
|
|
2683
|
-
* @see {@link
|
|
2684
|
-
* @see {@link Validator.validateTarget}
|
|
1824
|
+
* @see {@link ValidatorClassResult}
|
|
1825
|
+
* @see {@link ValidatorSuccess} - Single-value equivalent
|
|
2685
1826
|
*/
|
|
2686
|
-
export interface
|
|
1827
|
+
export interface ValidatorClassSuccess<TClass extends ClassConstructor = ClassConstructor, Context = unknown> extends Omit<ValidatorBaseOptions<Context>, 'data' | 'value'> {
|
|
2687
1828
|
/** Discriminant for type narrowing - always `true` for success */
|
|
2688
1829
|
success: true;
|
|
2689
1830
|
message?: undefined;
|
|
2690
|
-
/**
|
|
2691
|
-
* Status indicator for this result
|
|
2692
|
-
*
|
|
2693
|
-
* Always "success" for successful validations. Provided for consistency with HTTP
|
|
2694
|
-
* and API conventions.
|
|
2695
|
-
*
|
|
2696
|
-
* @type {"success"}
|
|
2697
|
-
*/
|
|
2698
|
-
status: 'success';
|
|
2699
1831
|
/**
|
|
2700
1832
|
* ISO timestamp of when validation succeeded
|
|
2701
1833
|
*
|
|
@@ -2715,26 +1847,41 @@ export interface ValidatorValidateTargetSuccess<Context = unknown> extends Omit<
|
|
|
2715
1847
|
* @example 23 (milliseconds)
|
|
2716
1848
|
*/
|
|
2717
1849
|
duration?: number;
|
|
2718
|
-
data:
|
|
1850
|
+
data: ValidatorClassInput<TClass>;
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* ## Validator Object Success
|
|
1854
|
+
*
|
|
1855
|
+
* Represents a successful validation result for a plain object.
|
|
1856
|
+
* This is the success variant of the discriminated union {@link ValidatorObjectResult}.
|
|
1857
|
+
*
|
|
1858
|
+
* It contains the original data object and metadata about the validation.
|
|
1859
|
+
*
|
|
1860
|
+
* @template TObject - The type of the validated object
|
|
1861
|
+
* @template Context - Optional validation context type
|
|
1862
|
+
* @public
|
|
1863
|
+
*/
|
|
1864
|
+
export interface ValidatorObjectSuccess<TObject extends object, Context = unknown> extends Omit<ValidatorClassSuccess<ClassConstructor, Context>, 'data'> {
|
|
1865
|
+
data: TObject;
|
|
2719
1866
|
}
|
|
2720
1867
|
/**
|
|
2721
1868
|
* ## Class Validation Result Type (Discriminated Union)
|
|
2722
1869
|
*
|
|
2723
|
-
* Discriminated union type representing the result of a {@link Validator.
|
|
2724
|
-
* Can be either {@link
|
|
1870
|
+
* Discriminated union type representing the result of a {@link Validator.validateClass} operation.
|
|
1871
|
+
* Can be either {@link ValidatorClassSuccess} or {@link ValidatorClassError}.
|
|
2725
1872
|
*
|
|
2726
1873
|
* ### Type Narrowing Strategies
|
|
2727
1874
|
*
|
|
2728
1875
|
* **Strategy 1: Check `success` property**
|
|
2729
1876
|
* ```typescript
|
|
2730
|
-
* const result = await Validator.
|
|
1877
|
+
* const result = await Validator.validateClass(UserForm, data);
|
|
2731
1878
|
*
|
|
2732
1879
|
* if (result.success) {
|
|
2733
|
-
* // result is
|
|
1880
|
+
* // result is ValidatorClassSuccess<T>
|
|
2734
1881
|
* console.log(result.data); // Class instance with all fields valid
|
|
2735
1882
|
* console.log(result.validatedAt); // Validation timestamp
|
|
2736
1883
|
* } else {
|
|
2737
|
-
* // result is
|
|
1884
|
+
* // result is ValidatorClassError
|
|
2738
1885
|
* console.log(result.errors); // Array of field-level errors
|
|
2739
1886
|
* console.log(result.failureCount); // Number of failed fields
|
|
2740
1887
|
* }
|
|
@@ -2744,11 +1891,11 @@ export interface ValidatorValidateTargetSuccess<Context = unknown> extends Omit<
|
|
|
2744
1891
|
* ```typescript
|
|
2745
1892
|
* switch (result.status) {
|
|
2746
1893
|
* case "success":
|
|
2747
|
-
* // result is
|
|
1894
|
+
* // result is ValidatorClassSuccess
|
|
2748
1895
|
* await saveToDatabase(result.data);
|
|
2749
1896
|
* break;
|
|
2750
1897
|
* case "error":
|
|
2751
|
-
* // result is
|
|
1898
|
+
* // result is ValidatorClassError
|
|
2752
1899
|
* logErrors(result.errors);
|
|
2753
1900
|
* break;
|
|
2754
1901
|
* }
|
|
@@ -2757,15 +1904,15 @@ export interface ValidatorValidateTargetSuccess<Context = unknown> extends Omit<
|
|
|
2757
1904
|
* **Strategy 3: Use type guard helper**
|
|
2758
1905
|
* ```typescript
|
|
2759
1906
|
* if (Validator.isSuccess(result)) {
|
|
2760
|
-
* // result is
|
|
1907
|
+
* // result is ValidatorClassSuccess
|
|
2761
1908
|
* return result.data;
|
|
2762
1909
|
* }
|
|
2763
|
-
* // result is
|
|
1910
|
+
* // result is ValidatorClassError
|
|
2764
1911
|
* throw new Error(result.message);
|
|
2765
1912
|
* ```
|
|
2766
1913
|
*
|
|
2767
1914
|
* ### Comparison with Single-Value Result
|
|
2768
|
-
* | Aspect | Single-Value |
|
|
1915
|
+
* | Aspect | Single-Value | TClass |
|
|
2769
1916
|
* |--------|-------------|--------|
|
|
2770
1917
|
* | Success Property | `value` | `data` |
|
|
2771
1918
|
* | On Failure | Single error | Array of errors |
|
|
@@ -2788,7 +1935,7 @@ export interface ValidatorValidateTargetSuccess<Context = unknown> extends Omit<
|
|
|
2788
1935
|
* confirmPassword: string;
|
|
2789
1936
|
* }
|
|
2790
1937
|
*
|
|
2791
|
-
* const result = await Validator.
|
|
1938
|
+
* const result = await Validator.validateClass(RegistrationForm, {
|
|
2792
1939
|
* email: "user@example.com",
|
|
2793
1940
|
* password: "SecurePass123",
|
|
2794
1941
|
* confirmPassword: "SecurePass123",
|
|
@@ -2806,21 +1953,243 @@ export interface ValidatorValidateTargetSuccess<Context = unknown> extends Omit<
|
|
|
2806
1953
|
* ```
|
|
2807
1954
|
*
|
|
2808
1955
|
* ### Union Members
|
|
2809
|
-
* - {@link
|
|
2810
|
-
* - {@link
|
|
1956
|
+
* - {@link ValidatorClassSuccess} - When all fields pass (success: true)
|
|
1957
|
+
* - {@link ValidatorClassError} - When one or more fields fail (success: false)
|
|
2811
1958
|
*
|
|
2812
1959
|
* @template Context - Type of the optional validation context
|
|
2813
1960
|
*
|
|
2814
1961
|
* @public
|
|
2815
1962
|
*
|
|
2816
|
-
* @see {@link
|
|
2817
|
-
* @see {@link
|
|
2818
|
-
* @see {@link Validator.
|
|
1963
|
+
* @see {@link ValidatorClassSuccess} - Success variant
|
|
1964
|
+
* @see {@link ValidatorClassError} - Failure variant
|
|
1965
|
+
* @see {@link Validator.validateClass} - Main class validation method
|
|
1966
|
+
* @see {@link Validator.isSuccess} - Type guard for success
|
|
1967
|
+
* @see {@link Validator.isFailure} - Type guard for failure
|
|
1968
|
+
* @see {@link ValidatorResult} - Single-value equivalent
|
|
1969
|
+
*/
|
|
1970
|
+
export type ValidatorClassResult<TClass extends ClassConstructor = ClassConstructor, Context = unknown> = ValidatorClassSuccess<TClass, Context> | ValidatorClassError<TClass>;
|
|
1971
|
+
/**
|
|
1972
|
+
* ## Validator Bulk Success
|
|
1973
|
+
*
|
|
1974
|
+
* Represents a successful bulk validation result when validating an array of class instances.
|
|
1975
|
+
* This interface extends the single-item success structure but operates on arrays of data.
|
|
1976
|
+
*
|
|
1977
|
+
* ### Purpose
|
|
1978
|
+
* Provides a structured success response for batch validation operations, indicating that
|
|
1979
|
+
* all items in the input array passed validation successfully. This is the success variant
|
|
1980
|
+
* of the discriminated union {@link ValidatorBulkResult}.
|
|
1981
|
+
*
|
|
1982
|
+
* ### Key Characteristics
|
|
1983
|
+
* - **success**: Always `true` for this type
|
|
1984
|
+
* - **data**: Contains the validated array of items (all items passed validation)
|
|
1985
|
+
* - **Inherits**: All properties from {@link ValidatorClassSuccess} except `data`
|
|
1986
|
+
*
|
|
1987
|
+
* ### Usage Scenarios
|
|
1988
|
+
* - Batch user registration validation
|
|
1989
|
+
* - Bulk data import validation
|
|
1990
|
+
* - CSV/Excel file validation
|
|
1991
|
+
* - API batch endpoint validation
|
|
1992
|
+
* - Mass data migration validation
|
|
1993
|
+
*
|
|
1994
|
+
* @template TClass - The class constructor type being validated
|
|
1995
|
+
* @template Context - Optional context type for validation
|
|
1996
|
+
*
|
|
1997
|
+
* @example
|
|
1998
|
+
* ```typescript
|
|
1999
|
+
* class User {
|
|
2000
|
+
* @IsRequired()
|
|
2001
|
+
* @IsEmail()
|
|
2002
|
+
* email: string;
|
|
2003
|
+
*
|
|
2004
|
+
* @IsRequired()
|
|
2005
|
+
* @MinLength(3)
|
|
2006
|
+
* name: string;
|
|
2007
|
+
* }
|
|
2008
|
+
*
|
|
2009
|
+
* const users = [
|
|
2010
|
+
* { email: 'user1@example.com', name: 'Alice' },
|
|
2011
|
+
* { email: 'user2@example.com', name: 'Bob' }
|
|
2012
|
+
* ];
|
|
2013
|
+
*
|
|
2014
|
+
* const result = await Validator.validateBulk(User, { data: users });
|
|
2015
|
+
*
|
|
2016
|
+
* if (result.success) {
|
|
2017
|
+
* // Type: ValidatorBulkSuccess<typeof User>
|
|
2018
|
+
* console.log(`All ${result.data.length} users are valid`);
|
|
2019
|
+
* result.data.forEach(user => {
|
|
2020
|
+
* // Process validated user data
|
|
2021
|
+
* });
|
|
2022
|
+
* }
|
|
2023
|
+
* ```
|
|
2024
|
+
*
|
|
2025
|
+
* @example
|
|
2026
|
+
* ```typescript
|
|
2027
|
+
* // With context
|
|
2028
|
+
* interface ValidationContext {
|
|
2029
|
+
* organizationId: string;
|
|
2030
|
+
* }
|
|
2031
|
+
*
|
|
2032
|
+
* const result = await Validator.validateBulk<typeof User, ValidationContext>(
|
|
2033
|
+
* User,
|
|
2034
|
+
* {
|
|
2035
|
+
* data: users,
|
|
2036
|
+
* context: { organizationId: '123' }
|
|
2037
|
+
* }
|
|
2038
|
+
* );
|
|
2039
|
+
*
|
|
2040
|
+
* if (result.success) {
|
|
2041
|
+
* // All items validated successfully
|
|
2042
|
+
* console.log('Validation duration:', result.duration);
|
|
2043
|
+
* }
|
|
2044
|
+
* ```
|
|
2045
|
+
*
|
|
2046
|
+
* @see {@link ValidatorBulkResult} - The discriminated union type
|
|
2047
|
+
* @see {@link ValidatorBulkError} - The failure variant
|
|
2048
|
+
* @see {@link ValidatorClassSuccess} - Single-item success type
|
|
2049
|
+
* @see {@link Validator.validateBulk} - Method that returns this type
|
|
2050
|
+
* @public
|
|
2051
|
+
*/
|
|
2052
|
+
export interface ValidatorBulkSuccess<TClass extends ClassConstructor = ClassConstructor, Context = unknown> extends Omit<ValidatorClassSuccess<TClass, Context>, 'data'> {
|
|
2053
|
+
/**
|
|
2054
|
+
* The validated array of data items.
|
|
2055
|
+
* All items in this array have passed validation successfully.
|
|
2056
|
+
*/
|
|
2057
|
+
data: ValidatorClassInput<TClass>[];
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* ## Validator Bulk Result
|
|
2061
|
+
*
|
|
2062
|
+
* Discriminated union type representing the outcome of a bulk validation operation.
|
|
2063
|
+
* This type can be either a success (all items valid) or an error (one or more items failed).
|
|
2064
|
+
*
|
|
2065
|
+
* ### Purpose
|
|
2066
|
+
* Provides type-safe handling of bulk validation results through TypeScript's discriminated
|
|
2067
|
+
* union pattern. The `success` property acts as the discriminant, allowing TypeScript to
|
|
2068
|
+
* narrow the type automatically in conditional branches.
|
|
2069
|
+
*
|
|
2070
|
+
* ### Type Structure
|
|
2071
|
+
* - **Success case**: {@link ValidatorBulkSuccess} - All items passed validation
|
|
2072
|
+
* - **Failure case**: {@link ValidatorBulkError} - One or more items failed validation
|
|
2073
|
+
*
|
|
2074
|
+
* ### Discriminant Property
|
|
2075
|
+
* The `success` boolean property serves as the type discriminant:
|
|
2076
|
+
* - `success: true` → Type narrows to `ValidatorBulkSuccess`
|
|
2077
|
+
* - `success: false` → Type narrows to `ValidatorBulkError`
|
|
2078
|
+
*
|
|
2079
|
+
* ### Usage Patterns
|
|
2080
|
+
*
|
|
2081
|
+
* **Type Narrowing with if/else:**
|
|
2082
|
+
* ```typescript
|
|
2083
|
+
* const result = await Validator.validateBulk(User, { data: users });
|
|
2084
|
+
*
|
|
2085
|
+
* if (result.success) {
|
|
2086
|
+
* // TypeScript knows: result is ValidatorBulkSuccess
|
|
2087
|
+
* result.data.forEach(user => processUser(user));
|
|
2088
|
+
* } else {
|
|
2089
|
+
* // TypeScript knows: result is ValidatorBulkError
|
|
2090
|
+
* console.error(`${result.failureCount} items failed`);
|
|
2091
|
+
* result.failures.forEach(failure => {
|
|
2092
|
+
* console.log(`Item ${failure.index}: ${failure.message}`);
|
|
2093
|
+
* });
|
|
2094
|
+
* }
|
|
2095
|
+
* ```
|
|
2096
|
+
*
|
|
2097
|
+
* **Type Guards:**
|
|
2098
|
+
* ```typescript
|
|
2099
|
+
* if (Validator.isSuccess(result)) {
|
|
2100
|
+
* // result is ValidatorBulkSuccess
|
|
2101
|
+
* return result.data;
|
|
2102
|
+
* }
|
|
2103
|
+
*
|
|
2104
|
+
* if (Validator.isFailure(result)) {
|
|
2105
|
+
* // result is ValidatorBulkError
|
|
2106
|
+
* throw new Error(result.message);
|
|
2107
|
+
* }
|
|
2108
|
+
* ```
|
|
2109
|
+
*
|
|
2110
|
+
* **Exhaustive Handling:**
|
|
2111
|
+
* ```typescript
|
|
2112
|
+
* const result = await Validator.validateBulk(User, { data: users });
|
|
2113
|
+
*
|
|
2114
|
+
* switch (result.success) {
|
|
2115
|
+
* case true:
|
|
2116
|
+
* // Handle success
|
|
2117
|
+
* return { validated: result.data };
|
|
2118
|
+
* case false:
|
|
2119
|
+
* // Handle failure
|
|
2120
|
+
* return { errors: result.failures };
|
|
2121
|
+
* }
|
|
2122
|
+
* ```
|
|
2123
|
+
*
|
|
2124
|
+
* @template TClass - The class constructor type being validated
|
|
2125
|
+
* @template Context - Optional context type for validation
|
|
2126
|
+
*
|
|
2127
|
+
* @example
|
|
2128
|
+
* ```typescript
|
|
2129
|
+
* class Product {
|
|
2130
|
+
* @IsRequired()
|
|
2131
|
+
* name: string;
|
|
2132
|
+
*
|
|
2133
|
+
* @IsNumber()
|
|
2134
|
+
* @NumberGTE(0)
|
|
2135
|
+
* price: number;
|
|
2136
|
+
* }
|
|
2137
|
+
*
|
|
2138
|
+
* async function importProducts(
|
|
2139
|
+
* products: Array<{ name: string; price: number }>
|
|
2140
|
+
* ): Promise<ValidatorBulkResult<typeof Product>> {
|
|
2141
|
+
* return Validator.validateBulk(Product, { data: products });
|
|
2142
|
+
* }
|
|
2143
|
+
*
|
|
2144
|
+
* // Usage
|
|
2145
|
+
* const result = await importProducts([
|
|
2146
|
+
* { name: 'Widget', price: 10 },
|
|
2147
|
+
* { name: 'Gadget', price: -5 }, // Invalid: negative price
|
|
2148
|
+
* ]);
|
|
2149
|
+
*
|
|
2150
|
+
* if (result.success) {
|
|
2151
|
+
* console.log('All products valid');
|
|
2152
|
+
* } else {
|
|
2153
|
+
* console.log(`${result.failureCount} products failed validation`);
|
|
2154
|
+
* }
|
|
2155
|
+
* ```
|
|
2156
|
+
*
|
|
2157
|
+
* @example
|
|
2158
|
+
* ```typescript
|
|
2159
|
+
* // API endpoint example
|
|
2160
|
+
* async function bulkCreateUsers(
|
|
2161
|
+
* req: Request,
|
|
2162
|
+
* res: Response
|
|
2163
|
+
* ): Promise<void> {
|
|
2164
|
+
* const result = await Validator.validateBulk(User, {
|
|
2165
|
+
* data: req.body.users
|
|
2166
|
+
* });
|
|
2167
|
+
*
|
|
2168
|
+
* if (result.success) {
|
|
2169
|
+
* const created = await db.users.insertMany(result.data);
|
|
2170
|
+
* res.json({ success: true, count: created.length });
|
|
2171
|
+
* } else {
|
|
2172
|
+
* res.status(400).json({
|
|
2173
|
+
* success: false,
|
|
2174
|
+
* message: result.message,
|
|
2175
|
+
* failures: result.failures.map(f => ({
|
|
2176
|
+
* index: f.index,
|
|
2177
|
+
* errors: f.errors
|
|
2178
|
+
* }))
|
|
2179
|
+
* });
|
|
2180
|
+
* }
|
|
2181
|
+
* }
|
|
2182
|
+
* ```
|
|
2183
|
+
*
|
|
2184
|
+
* @see {@link ValidatorBulkSuccess} - Success variant
|
|
2185
|
+
* @see {@link ValidatorBulkError} - Failure variant
|
|
2186
|
+
* @see {@link ValidatorClassResult} - Single-item equivalent
|
|
2187
|
+
* @see {@link Validator.validateBulk} - Method that returns this type
|
|
2819
2188
|
* @see {@link Validator.isSuccess} - Type guard for success
|
|
2820
2189
|
* @see {@link Validator.isFailure} - Type guard for failure
|
|
2821
|
-
* @
|
|
2190
|
+
* @public
|
|
2822
2191
|
*/
|
|
2823
|
-
export type
|
|
2192
|
+
export type ValidatorBulkResult<TClass extends ClassConstructor = ClassConstructor, Context = unknown> = ValidatorBulkSuccess<TClass, Context> | ValidatorBulkError<TClass>;
|
|
2824
2193
|
/**
|
|
2825
2194
|
* ## Validator Rule Functions Map
|
|
2826
2195
|
*
|
|
@@ -2847,7 +2216,7 @@ export type ValidatorValidateTargetResult<Context = unknown> = ValidatorValidate
|
|
|
2847
2216
|
* ### Usage in Validator Class
|
|
2848
2217
|
* This type is primarily used internally by the {@link Validator} class:
|
|
2849
2218
|
* - {@link Validator.getRules} returns an instance of this mapped type
|
|
2850
|
-
* - {@link Validator.
|
|
2219
|
+
* - {@link Validator.validateClass} uses it to retrieve rule functions by name
|
|
2851
2220
|
* - Rule execution methods access functions through this type-safe lookup table
|
|
2852
2221
|
*
|
|
2853
2222
|
* ### Example Structure
|
|
@@ -2893,9 +2262,186 @@ export type ValidatorValidateTargetResult<Context = unknown> = ValidatorValidate
|
|
|
2893
2262
|
* @see {@link ValidatorRuleParamTypes} - Rule parameter definitions
|
|
2894
2263
|
* @see {@link ValidatorRuleFunction} - Validation function signature
|
|
2895
2264
|
* @see {@link Validator.getRules} - Method that returns this map
|
|
2896
|
-
* @see {@link Validator.
|
|
2265
|
+
* @see {@link Validator.validateClass} - Method that uses this map
|
|
2897
2266
|
*/
|
|
2898
2267
|
export type ValidatorRuleFunctionsMap<Context = unknown> = {
|
|
2899
2268
|
[K in ValidatorRuleName]: ValidatorRuleFunction<ValidatorRuleParamTypes<Context>[K], Context>;
|
|
2900
2269
|
};
|
|
2901
|
-
|
|
2270
|
+
/**
|
|
2271
|
+
* ## Validator Base Options
|
|
2272
|
+
*
|
|
2273
|
+
* The foundational type that defines the core data properties involved in any validation operation.
|
|
2274
|
+
* It serves as the base for both:
|
|
2275
|
+
* 1. **Validation Options**: The input configurations passed to validation methods (e.g., {@link ValidatorOptions}).
|
|
2276
|
+
* 2. **Validation Results**: The successful output of validation containing the validated data (e.g., {@link ValidatorSuccess}).
|
|
2277
|
+
*
|
|
2278
|
+
* ### Purpose
|
|
2279
|
+
* This interface identifies the three key pieces of data in the validation lifecycle:
|
|
2280
|
+
* - **value**: The primary data being validated.
|
|
2281
|
+
* - **data**: Auxiliary data (e.g., the full form object) for cross-field validation.
|
|
2282
|
+
* - **context**: Application-specific context (e.g., database connections, user session) injected into rules.
|
|
2283
|
+
*
|
|
2284
|
+
* ### Usage
|
|
2285
|
+
* You typically don't use this type directly. Instead, you use one of its specialized extensions:
|
|
2286
|
+
* - Use {@link ValidatorOptions} for calling `Validator.validate()`
|
|
2287
|
+
* - Use {@link ValidatorClassResult} or {@link ValidatorSuccess} when handling return values
|
|
2288
|
+
*
|
|
2289
|
+
* @template Context - Type of the optional application context
|
|
2290
|
+
* @public
|
|
2291
|
+
*/
|
|
2292
|
+
export interface ValidatorBaseOptions<Context = unknown> {
|
|
2293
|
+
/**
|
|
2294
|
+
* The value to use for performing the validation.
|
|
2295
|
+
* This is the actual data that will be validated against the specified rules.
|
|
2296
|
+
*
|
|
2297
|
+
* @type {any}
|
|
2298
|
+
*
|
|
2299
|
+
* @example
|
|
2300
|
+
* ```typescript
|
|
2301
|
+
* const result = await Validator.validate({
|
|
2302
|
+
* value: "user@example.com", // This is the value being validated
|
|
2303
|
+
* rules: ["Required", "Email"],
|
|
2304
|
+
* });
|
|
2305
|
+
* ```
|
|
2306
|
+
*
|
|
2307
|
+
* @remarks
|
|
2308
|
+
* - This is the core data being validated
|
|
2309
|
+
* - Type can be any JavaScript value: string, number, object, array, etc.
|
|
2310
|
+
* - Available in both success and failure results
|
|
2311
|
+
*/
|
|
2312
|
+
value: any;
|
|
2313
|
+
/**
|
|
2314
|
+
* Optional data object providing contextual information for validation rules.
|
|
2315
|
+
*
|
|
2316
|
+
* This property is used to provide additional context for the validation rule.
|
|
2317
|
+
* It can be used to pass any additional data that might be needed for validation,
|
|
2318
|
+
* such as form data, related field values, or other contextual information.
|
|
2319
|
+
*
|
|
2320
|
+
* @type {Dictionary | undefined}
|
|
2321
|
+
*
|
|
2322
|
+
* @example
|
|
2323
|
+
* ```typescript
|
|
2324
|
+
* const result = await Validator.validate({
|
|
2325
|
+
* value: "test@example.com",
|
|
2326
|
+
* rules: ["Required", "Email"],
|
|
2327
|
+
* data: {
|
|
2328
|
+
* userId: 123,
|
|
2329
|
+
* formId: "user_form",
|
|
2330
|
+
* },
|
|
2331
|
+
* });
|
|
2332
|
+
* ```
|
|
2333
|
+
*
|
|
2334
|
+
* @remarks
|
|
2335
|
+
* - Optional property (not required)
|
|
2336
|
+
* - Passed to validation rule functions via options.data
|
|
2337
|
+
* - Useful for multi-field validation scenarios
|
|
2338
|
+
* - Commonly used for form data context in validateClass
|
|
2339
|
+
*/
|
|
2340
|
+
data?: Dictionary;
|
|
2341
|
+
/**
|
|
2342
|
+
* Optional typed context object for validation.
|
|
2343
|
+
*
|
|
2344
|
+
* Provides a typed context that can be passed to validation rules for
|
|
2345
|
+
* advanced validation scenarios requiring external data or permissions.
|
|
2346
|
+
*
|
|
2347
|
+
* @template Context - Type of the context object
|
|
2348
|
+
*
|
|
2349
|
+
* @example
|
|
2350
|
+
* ```typescript
|
|
2351
|
+
* interface UserContext {
|
|
2352
|
+
* userId: number;
|
|
2353
|
+
* permissions: string[];
|
|
2354
|
+
* isAdmin: boolean;
|
|
2355
|
+
* }
|
|
2356
|
+
*
|
|
2357
|
+
* const result = await Validator.validate<UserContext>({
|
|
2358
|
+
* value: "admin_action",
|
|
2359
|
+
* rules: ["Required"],
|
|
2360
|
+
* context: {
|
|
2361
|
+
* userId: 123,
|
|
2362
|
+
* permissions: ["read", "write", "admin"],
|
|
2363
|
+
* isAdmin: true,
|
|
2364
|
+
* },
|
|
2365
|
+
* });
|
|
2366
|
+
* ```
|
|
2367
|
+
*
|
|
2368
|
+
* @remarks
|
|
2369
|
+
* - Optional property (not required)
|
|
2370
|
+
* - Type is defined by the Context generic parameter
|
|
2371
|
+
* - Passed to all validation rule functions
|
|
2372
|
+
* - Enables context-aware validation rules
|
|
2373
|
+
* - Commonly used for permission-based or user-specific validations
|
|
2374
|
+
*/
|
|
2375
|
+
context?: Context;
|
|
2376
|
+
/**
|
|
2377
|
+
* Status indicator for this result
|
|
2378
|
+
*
|
|
2379
|
+
* Always "success" for successful validations. Provided for consistency with HTTP
|
|
2380
|
+
* and API conventions.
|
|
2381
|
+
*
|
|
2382
|
+
* @type {"success"}
|
|
2383
|
+
*/
|
|
2384
|
+
status: 'success';
|
|
2385
|
+
name: 'ValidatorSuccessResult';
|
|
2386
|
+
}
|
|
2387
|
+
/**
|
|
2388
|
+
* ## Validator Object Schema Interface
|
|
2389
|
+
*
|
|
2390
|
+
* Defines the structure for object-based validation schemas created with `Validator.object()`.
|
|
2391
|
+
* This enables a functional, Zod-like validation pattern where rules are defined
|
|
2392
|
+
* outside of classes.
|
|
2393
|
+
*
|
|
2394
|
+
* @template T - The type of data to validate
|
|
2395
|
+
* @template Context - Optional validation context type
|
|
2396
|
+
*
|
|
2397
|
+
* @public
|
|
2398
|
+
*/
|
|
2399
|
+
export interface ValidatorObjectSchema<T extends object, Context = unknown> {
|
|
2400
|
+
/** The internal schema target object containing metadata */
|
|
2401
|
+
readonly schema: object;
|
|
2402
|
+
/**
|
|
2403
|
+
* Validates a data object against this schema.
|
|
2404
|
+
*
|
|
2405
|
+
* @template Context - The custom validation context
|
|
2406
|
+
* @param data - The data to validate
|
|
2407
|
+
* @param options - Optional validation configuration
|
|
2408
|
+
* @returns Promise resolving to a structured validation result
|
|
2409
|
+
*/
|
|
2410
|
+
validate(data: T, options?: Omit<ValidatorObjectOptions<T, Context>, 'data' | 'rules'>): Promise<ValidatorObjectResult<T, Context>>;
|
|
2411
|
+
}
|
|
2412
|
+
/**
|
|
2413
|
+
* ## Validator Object Rules
|
|
2414
|
+
*
|
|
2415
|
+
* A type representing the validation rules for a plain object.
|
|
2416
|
+
* Maps property names to their respective validation rules.
|
|
2417
|
+
*
|
|
2418
|
+
* @template T - The type of the object being validated
|
|
2419
|
+
* @public
|
|
2420
|
+
*/
|
|
2421
|
+
export type ValidatorObjectRules<T extends object> = {
|
|
2422
|
+
[K in keyof T | string]: ValidatorRules;
|
|
2423
|
+
};
|
|
2424
|
+
/**
|
|
2425
|
+
* ## Validator Object Options
|
|
2426
|
+
*
|
|
2427
|
+
* Configuration options for object-based validation (`Validator.validateObject`).
|
|
2428
|
+
* Extends class validation options but focuses on plain object data.
|
|
2429
|
+
*
|
|
2430
|
+
* @template T - The type of data to validate
|
|
2431
|
+
* @template Context - Optional validation context type
|
|
2432
|
+
* @public
|
|
2433
|
+
*/
|
|
2434
|
+
export interface ValidatorObjectOptions<T extends object, Context = unknown> extends Omit<MakeOptional<ValidatorClassOptions<ClassConstructor, Context>, 'i18n'>, 'data' | 'rules' | 'ruleParams'> {
|
|
2435
|
+
data: T;
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* ## Validator Object Result
|
|
2439
|
+
*
|
|
2440
|
+
* Discriminated union type representing the result of a {@link Validator.validateObject} operation.
|
|
2441
|
+
* Can be either {@link ValidatorObjectSuccess} or {@link ValidatorObjectError}.
|
|
2442
|
+
*
|
|
2443
|
+
* @template T - The type of data being validated
|
|
2444
|
+
* @template Context - Optional validation context type
|
|
2445
|
+
* @public
|
|
2446
|
+
*/
|
|
2447
|
+
export type ValidatorObjectResult<T extends object, Context = unknown> = ValidatorObjectSuccess<T, Context> | ValidatorObjectError<T>;
|