reslib 2.0.1 → 2.0.3
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/build/exception/index.d.ts +325 -12
- package/build/exception/index.js +2 -2
- package/build/validator/errors/index.d.ts +9 -3
- package/build/validator/index.js +1 -1
- package/build/validator/rules/array.js +2 -2
- package/build/validator/rules/boolean.js +2 -2
- package/build/validator/rules/date.js +1 -1
- 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.js +1 -1
- package/build/validator/rules/index.js +1 -1
- package/build/validator/rules/multiRules.js +2 -2
- package/build/validator/rules/numeric.js +1 -1
- package/build/validator/rules/object.js +2 -2
- package/build/validator/rules/string.js +2 -2
- package/build/validator/rules/target.js +2 -2
- package/build/validator/validator.d.ts +689 -15
- package/build/validator/validator.js +2 -2
- package/package.json +1 -1
|
@@ -2484,35 +2484,709 @@ export declare class Validator {
|
|
|
2484
2484
|
*/
|
|
2485
2485
|
static createBulkError<TClass extends ClassConstructor = ClassConstructor>(message: string, details: ValidatorCreateBulkErrorPayload): ValidatorBulkError<TClass>;
|
|
2486
2486
|
/**
|
|
2487
|
-
* ## Check for Single Validation Error
|
|
2487
|
+
* ## Check for Single Field Validation Error
|
|
2488
2488
|
*
|
|
2489
|
-
* Type guard
|
|
2490
|
-
*
|
|
2489
|
+
* Type guard that determines if a value is specifically a `ValidatorError`,
|
|
2490
|
+
* representing a validation failure for a **single field or value**.
|
|
2491
2491
|
*
|
|
2492
|
-
*
|
|
2493
|
-
*
|
|
2492
|
+
* ### Purpose
|
|
2493
|
+
* - **Type Discrimination**: Distinguish single field errors from class/bulk errors
|
|
2494
|
+
* - **Type Safety**: Enables TypeScript to narrow the type to `ValidatorError`
|
|
2495
|
+
* - **Specific Handling**: Access field-specific error properties
|
|
2496
|
+
* - **Error Classification**: Categorize validation errors by granularity
|
|
2497
|
+
*
|
|
2498
|
+
* ### When to Use
|
|
2499
|
+
* - **Single Field Validation**: When validating individual values
|
|
2500
|
+
* - **Field-Level Errors**: To access specific field, rule, and value information
|
|
2501
|
+
* - **Granular Error Handling**: When you need different logic for single vs. multiple errors
|
|
2502
|
+
* - **Error Reporting**: To format single field errors differently
|
|
2503
|
+
*
|
|
2504
|
+
* ### When NOT to Use
|
|
2505
|
+
* - **Generic Handling**: Use `isAnyError()` to handle all validator errors the same way
|
|
2506
|
+
* - **Class Validation**: Use `isClassError()` for object/class validation errors
|
|
2507
|
+
* - **Bulk Validation**: Use `isBulkError()` for array validation errors
|
|
2508
|
+
*
|
|
2509
|
+
* @param result - The value to check for ValidatorError type
|
|
2510
|
+
* @returns `true` if the value is a ValidatorError, `false` otherwise
|
|
2511
|
+
*
|
|
2512
|
+
* @example
|
|
2513
|
+
* ```typescript
|
|
2514
|
+
* // Basic single field validation
|
|
2515
|
+
* const emailResult = await Validator.validate({
|
|
2516
|
+
* value: 'invalid-email',
|
|
2517
|
+
* rules: ['Email']
|
|
2518
|
+
* });
|
|
2519
|
+
*
|
|
2520
|
+
* if (!emailResult.success && Validator.isError(emailResult)) {
|
|
2521
|
+
* // TypeScript knows emailResult is ValidatorError
|
|
2522
|
+
* console.log('Field:', emailResult.field); // undefined (single value)
|
|
2523
|
+
* console.log('Rule:', emailResult.rule); // 'Email'
|
|
2524
|
+
* console.log('Value:', emailResult.value); // 'invalid-email'
|
|
2525
|
+
* console.log('Message:', emailResult.message); // 'Must be a valid email'
|
|
2526
|
+
* }
|
|
2527
|
+
* ```
|
|
2528
|
+
*
|
|
2529
|
+
* @example
|
|
2530
|
+
* ```typescript
|
|
2531
|
+
* // Conditional error handling based on error type
|
|
2532
|
+
* async function validateInput(value: unknown, rules: string[]) {
|
|
2533
|
+
* const result = await Validator.validate({ value, rules });
|
|
2534
|
+
*
|
|
2535
|
+
* if (!result.success) {
|
|
2536
|
+
* if (Validator.isError(result)) {
|
|
2537
|
+
* // Handle single field error
|
|
2538
|
+
* return {
|
|
2539
|
+
* type: 'field',
|
|
2540
|
+
* field: result.field || 'value',
|
|
2541
|
+
* rule: result.rule,
|
|
2542
|
+
* message: result.message
|
|
2543
|
+
* };
|
|
2544
|
+
* } else if (Validator.isClassError(result)) {
|
|
2545
|
+
* // Handle class validation error
|
|
2546
|
+
* return {
|
|
2547
|
+
* type: 'class',
|
|
2548
|
+
* errors: result.fieldErrors
|
|
2549
|
+
* };
|
|
2550
|
+
* }
|
|
2551
|
+
* }
|
|
2552
|
+
*
|
|
2553
|
+
* return { type: 'success', value };
|
|
2554
|
+
* }
|
|
2555
|
+
* ```
|
|
2556
|
+
*
|
|
2557
|
+
* @example
|
|
2558
|
+
* ```typescript
|
|
2559
|
+
* // Error logging with field information
|
|
2560
|
+
* function logValidationError(error: unknown) {
|
|
2561
|
+
* if (Validator.isError(error)) {
|
|
2562
|
+
* logger.error({
|
|
2563
|
+
* type: 'SINGLE_FIELD_VALIDATION',
|
|
2564
|
+
* field: error.field,
|
|
2565
|
+
* rule: error.rule,
|
|
2566
|
+
* value: error.value,
|
|
2567
|
+
* message: error.message,
|
|
2568
|
+
* timestamp: error.failedAt,
|
|
2569
|
+
* duration: error.duration
|
|
2570
|
+
* });
|
|
2571
|
+
* }
|
|
2572
|
+
* }
|
|
2573
|
+
* ```
|
|
2574
|
+
*
|
|
2575
|
+
* @example
|
|
2576
|
+
* ```typescript
|
|
2577
|
+
* // Custom error formatting for single fields
|
|
2578
|
+
* function formatValidationError(error: unknown): string {
|
|
2579
|
+
* if (Validator.isError(error)) {
|
|
2580
|
+
* const fieldName = error.field || 'Value';
|
|
2581
|
+
* return `${fieldName} validation failed: ${error.message} (Rule: ${error.rule})`;
|
|
2582
|
+
* }
|
|
2583
|
+
* return 'Unknown validation error';
|
|
2584
|
+
* }
|
|
2585
|
+
* ```
|
|
2586
|
+
*
|
|
2587
|
+
* @remarks
|
|
2588
|
+
* **ValidatorError Properties**:
|
|
2589
|
+
* - `name: 'ValidatorError'` - Error type identifier
|
|
2590
|
+
* - `field?: string` - Field name (may be undefined for standalone validation)
|
|
2591
|
+
* - `rule: string` - The validation rule that failed
|
|
2592
|
+
* - `value: unknown` - The value that failed validation
|
|
2593
|
+
* - `message: string` - Human-readable error message
|
|
2594
|
+
* - `errorCode: 'ERR_VALIDATION_FAILED'` - Standard error code
|
|
2595
|
+
* - `statusCode: 400` - HTTP status code
|
|
2596
|
+
* - `failedAt: Date` - Timestamp of failure
|
|
2597
|
+
* - `duration: number` - Validation duration in milliseconds
|
|
2598
|
+
*
|
|
2599
|
+
* **Type Narrowing**:
|
|
2600
|
+
* - After this check, TypeScript narrows the type to `ValidatorError`
|
|
2601
|
+
* - Enables safe access to field-specific properties
|
|
2602
|
+
* - No need for additional type assertions
|
|
2603
|
+
*
|
|
2604
|
+
* **Performance**:
|
|
2605
|
+
* - O(1) complexity - two property checks
|
|
2606
|
+
* - Very fast, suitable for high-frequency validation
|
|
2607
|
+
* - No object creation or memory allocation
|
|
2608
|
+
*
|
|
2609
|
+
* @see {@link isClassError} - Check for class/object validation errors
|
|
2610
|
+
* @see {@link isBulkError} - Check for bulk/array validation errors
|
|
2611
|
+
* @see {@link isAnyError} - Check for any validator error type
|
|
2612
|
+
* @see {@link ValidatorError} - Single field validation error type
|
|
2613
|
+
* @see {@link validate} - Method that returns ValidatorError on failure
|
|
2614
|
+
*
|
|
2615
|
+
* @public
|
|
2616
|
+
* @category Type Guards
|
|
2494
2617
|
*/
|
|
2495
2618
|
static isError(result: unknown): result is ValidatorError;
|
|
2496
2619
|
/**
|
|
2497
|
-
* ## Check for
|
|
2620
|
+
* ## Check for Class/Object Validation Error
|
|
2621
|
+
*
|
|
2622
|
+
* Type guard that determines if a value is specifically a `ValidatorClassError`,
|
|
2623
|
+
* representing validation failures for **class or object validation** with
|
|
2624
|
+
* multiple field-level errors.
|
|
2625
|
+
*
|
|
2626
|
+
* ### Purpose
|
|
2627
|
+
* - **Type Discrimination**: Distinguish class validation errors from single/bulk errors
|
|
2628
|
+
* - **Type Safety**: Enables TypeScript to narrow the type to `ValidatorClassError`
|
|
2629
|
+
* - **Field Access**: Access detailed field-level error information
|
|
2630
|
+
* - **Error Aggregation**: Handle multiple field errors together
|
|
2631
|
+
*
|
|
2632
|
+
* ### When to Use
|
|
2633
|
+
* - **Class Validation**: When validating decorated class instances
|
|
2634
|
+
* - **Object Validation**: When validating complex objects with multiple fields
|
|
2635
|
+
* - **Field-Level Errors**: To access individual field error details
|
|
2636
|
+
* - **Form Validation**: To map errors to form fields
|
|
2498
2637
|
*
|
|
2499
|
-
*
|
|
2500
|
-
*
|
|
2638
|
+
* ### When NOT to Use
|
|
2639
|
+
* - **Generic Handling**: Use `isAnyError()` to handle all validator errors the same way
|
|
2640
|
+
* - **Single Field**: Use `isError()` for single field validation errors
|
|
2641
|
+
* - **Array Validation**: Use `isBulkError()` for bulk array validation errors
|
|
2642
|
+
*
|
|
2643
|
+
* @param result - The value to check for ValidatorClassError type
|
|
2644
|
+
* @returns `true` if the value is a ValidatorClassError, `false` otherwise
|
|
2645
|
+
*
|
|
2646
|
+
* @example
|
|
2647
|
+
* ```typescript
|
|
2648
|
+
* // Basic class validation
|
|
2649
|
+
* class User {
|
|
2650
|
+
* @IsRequired()
|
|
2651
|
+
* @IsEmail()
|
|
2652
|
+
* email: string;
|
|
2653
|
+
*
|
|
2654
|
+
* @IsRequired()
|
|
2655
|
+
* @MinLength(8)
|
|
2656
|
+
* password: string;
|
|
2657
|
+
* }
|
|
2501
2658
|
*
|
|
2502
|
-
*
|
|
2503
|
-
*
|
|
2659
|
+
* const result = await Validator.validateClass(User, {
|
|
2660
|
+
* data: { email: 'invalid', password: '123' }
|
|
2661
|
+
* });
|
|
2662
|
+
*
|
|
2663
|
+
* if (!result.success && Validator.isClassError(result)) {
|
|
2664
|
+
* // TypeScript knows result is ValidatorClassError
|
|
2665
|
+
* console.log('Failed fields:', result.fieldCount); // 2
|
|
2666
|
+
* console.log('Target class:', result.targetClass); // User
|
|
2667
|
+
*
|
|
2668
|
+
* result.fieldErrors.forEach(fieldError => {
|
|
2669
|
+
* console.log(`${fieldError.field}: ${fieldError.message}`);
|
|
2670
|
+
* // Output:
|
|
2671
|
+
* // email: Must be a valid email address
|
|
2672
|
+
* // password: Minimum length is 8 characters
|
|
2673
|
+
* });
|
|
2674
|
+
* }
|
|
2675
|
+
* ```
|
|
2676
|
+
*
|
|
2677
|
+
* @example
|
|
2678
|
+
* ```typescript
|
|
2679
|
+
* // Form validation with field mapping
|
|
2680
|
+
* async function validateForm(formData: FormData) {
|
|
2681
|
+
* const result = await Validator.validateClass(FormSchema, {
|
|
2682
|
+
* data: Object.fromEntries(formData)
|
|
2683
|
+
* });
|
|
2684
|
+
*
|
|
2685
|
+
* if (!result.success && Validator.isClassError(result)) {
|
|
2686
|
+
* // Map errors to form fields
|
|
2687
|
+
* const fieldErrors: Record<string, string> = {};
|
|
2688
|
+
*
|
|
2689
|
+
* result.fieldErrors.forEach(error => {
|
|
2690
|
+
* fieldErrors[error.field] = error.message;
|
|
2691
|
+
* });
|
|
2692
|
+
*
|
|
2693
|
+
* return {
|
|
2694
|
+
* success: false,
|
|
2695
|
+
* errors: fieldErrors,
|
|
2696
|
+
* message: result.message
|
|
2697
|
+
* };
|
|
2698
|
+
* }
|
|
2699
|
+
*
|
|
2700
|
+
* return { success: true };
|
|
2701
|
+
* }
|
|
2702
|
+
* ```
|
|
2703
|
+
*
|
|
2704
|
+
* @example
|
|
2705
|
+
* ```typescript
|
|
2706
|
+
* // Error logging with field details
|
|
2707
|
+
* function logClassValidationError(error: unknown) {
|
|
2708
|
+
* if (Validator.isClassError(error)) {
|
|
2709
|
+
* logger.error({
|
|
2710
|
+
* type: 'CLASS_VALIDATION',
|
|
2711
|
+
* targetClass: error.targetClass?.name,
|
|
2712
|
+
* fieldCount: error.fieldCount,
|
|
2713
|
+
* fields: error.fieldErrors.map(e => e.field),
|
|
2714
|
+
* message: error.message,
|
|
2715
|
+
* timestamp: error.failedAt,
|
|
2716
|
+
* duration: error.duration
|
|
2717
|
+
* });
|
|
2718
|
+
*
|
|
2719
|
+
* // Log individual field errors
|
|
2720
|
+
* error.fieldErrors.forEach(fieldError => {
|
|
2721
|
+
* logger.debug({
|
|
2722
|
+
* field: fieldError.field,
|
|
2723
|
+
* rule: fieldError.rule,
|
|
2724
|
+
* message: fieldError.message,
|
|
2725
|
+
* value: fieldError.value
|
|
2726
|
+
* });
|
|
2727
|
+
* });
|
|
2728
|
+
* }
|
|
2729
|
+
* }
|
|
2730
|
+
* ```
|
|
2731
|
+
*
|
|
2732
|
+
* @example
|
|
2733
|
+
* ```typescript
|
|
2734
|
+
* // Conditional error handling
|
|
2735
|
+
* function handleValidationResult(result: unknown) {
|
|
2736
|
+
* if (Validator.isClassError(result)) {
|
|
2737
|
+
* // Handle class validation errors
|
|
2738
|
+
* return {
|
|
2739
|
+
* type: 'class',
|
|
2740
|
+
* summary: `${result.fieldCount} field(s) failed validation`,
|
|
2741
|
+
* fields: result.fieldErrors.reduce((acc, error) => {
|
|
2742
|
+
* acc[error.field] = {
|
|
2743
|
+
* message: error.message,
|
|
2744
|
+
* rule: error.rule,
|
|
2745
|
+
* value: error.value
|
|
2746
|
+
* };
|
|
2747
|
+
* return acc;
|
|
2748
|
+
* }, {} as Record<string, any>)
|
|
2749
|
+
* };
|
|
2750
|
+
* } else if (Validator.isError(result)) {
|
|
2751
|
+
* // Handle single field error
|
|
2752
|
+
* return {
|
|
2753
|
+
* type: 'field',
|
|
2754
|
+
* message: result.message
|
|
2755
|
+
* };
|
|
2756
|
+
* }
|
|
2757
|
+
*
|
|
2758
|
+
* return { type: 'unknown' };
|
|
2759
|
+
* }
|
|
2760
|
+
* ```
|
|
2761
|
+
*
|
|
2762
|
+
* @remarks
|
|
2763
|
+
* **ValidatorClassError Properties**:
|
|
2764
|
+
* - `name: 'ValidatorClassError'` - Error type identifier
|
|
2765
|
+
* - `targetClass: ClassConstructor` - The class that was validated
|
|
2766
|
+
* - `fieldErrors: FieldError[]` - Array of individual field errors
|
|
2767
|
+
* - `fieldCount: number` - Number of fields that failed validation
|
|
2768
|
+
* - `message: string` - Summary message (e.g., "Validation failed for 2 fields")
|
|
2769
|
+
* - `errorCode: 'ERR_VALIDATION_FAILED'` - Standard error code
|
|
2770
|
+
* - `statusCode: 400` - HTTP status code
|
|
2771
|
+
* - `failedAt: Date` - Timestamp of failure
|
|
2772
|
+
* - `duration: number` - Validation duration in milliseconds
|
|
2773
|
+
*
|
|
2774
|
+
* **FieldError Structure**:
|
|
2775
|
+
* - `field: string` - Property name that failed
|
|
2776
|
+
* - `message: string` - Error message for this field
|
|
2777
|
+
* - `rule: string` - The validation rule that failed
|
|
2778
|
+
* - `value: unknown` - The value that failed validation
|
|
2779
|
+
* - `translatedPropertyName?: string` - Localized field name
|
|
2780
|
+
*
|
|
2781
|
+
* **Type Narrowing**:
|
|
2782
|
+
* - After this check, TypeScript narrows the type to `ValidatorClassError`
|
|
2783
|
+
* - Enables safe access to `fieldErrors`, `targetClass`, etc.
|
|
2784
|
+
* - No need for additional type assertions
|
|
2785
|
+
*
|
|
2786
|
+
* **Performance**:
|
|
2787
|
+
* - O(1) complexity - two property checks
|
|
2788
|
+
* - Very fast, suitable for high-frequency validation
|
|
2789
|
+
* - No object creation or memory allocation
|
|
2790
|
+
*
|
|
2791
|
+
* @see {@link isError} - Check for single field validation errors
|
|
2792
|
+
* @see {@link isBulkError} - Check for bulk/array validation errors
|
|
2793
|
+
* @see {@link isAnyError} - Check for any validator error type
|
|
2794
|
+
* @see {@link ValidatorClassError} - Class validation error type
|
|
2795
|
+
* @see {@link validateClass} - Method that returns ValidatorClassError on failure
|
|
2796
|
+
*
|
|
2797
|
+
* @public
|
|
2798
|
+
* @category Type Guards
|
|
2504
2799
|
*/
|
|
2505
2800
|
static isClassError(result: unknown): result is ValidatorClassError;
|
|
2506
2801
|
/**
|
|
2507
|
-
* ## Check for Bulk Validation Error
|
|
2802
|
+
* ## Check for Bulk/Array Validation Error
|
|
2803
|
+
*
|
|
2804
|
+
* Type guard that determines if a value is specifically a `ValidatorBulkError`,
|
|
2805
|
+
* representing validation failures for **bulk array validation** with
|
|
2806
|
+
* multiple item-level errors.
|
|
2807
|
+
*
|
|
2808
|
+
* ### Purpose
|
|
2809
|
+
* - **Type Discrimination**: Distinguish bulk validation errors from single/class errors
|
|
2810
|
+
* - **Type Safety**: Enables TypeScript to narrow the type to `ValidatorBulkError`
|
|
2811
|
+
* - **Item Access**: Access detailed item-level error information with indices
|
|
2812
|
+
* - **Error Aggregation**: Handle multiple item errors together
|
|
2813
|
+
*
|
|
2814
|
+
* ### When to Use
|
|
2815
|
+
* - **Array Validation**: When validating arrays of items
|
|
2816
|
+
* - **Bulk Operations**: When processing multiple records/items
|
|
2817
|
+
* - **Item-Level Errors**: To access individual item error details with indices
|
|
2818
|
+
* - **Batch Processing**: To identify which items failed in a batch
|
|
2819
|
+
*
|
|
2820
|
+
* ### When NOT to Use
|
|
2821
|
+
* - **Generic Handling**: Use `isAnyError()` to handle all validator errors the same way
|
|
2822
|
+
* - **Single Field**: Use `isError()` for single field validation errors
|
|
2823
|
+
* - **Object Validation**: Use `isClassError()` for class/object validation errors
|
|
2824
|
+
*
|
|
2825
|
+
* @param result - The value to check for ValidatorBulkError type
|
|
2826
|
+
* @returns `true` if the value is a ValidatorBulkError, `false` otherwise
|
|
2508
2827
|
*
|
|
2509
|
-
*
|
|
2510
|
-
*
|
|
2828
|
+
* @example
|
|
2829
|
+
* ```typescript
|
|
2830
|
+
* // Basic bulk validation
|
|
2831
|
+
* class User {
|
|
2832
|
+
* @IsRequired()
|
|
2833
|
+
* @IsEmail()
|
|
2834
|
+
* email: string;
|
|
2511
2835
|
*
|
|
2512
|
-
*
|
|
2513
|
-
*
|
|
2836
|
+
* @IsRequired()
|
|
2837
|
+
* name: string;
|
|
2838
|
+
* }
|
|
2839
|
+
*
|
|
2840
|
+
* const users = [
|
|
2841
|
+
* { email: 'valid@example.com', name: 'John' },
|
|
2842
|
+
* { email: 'invalid', name: '' }, // Invalid
|
|
2843
|
+
* { email: 'test@example.com', name: 'Jane' },
|
|
2844
|
+
* { email: 'bad-email', name: 'Bob' } // Invalid
|
|
2845
|
+
* ];
|
|
2846
|
+
*
|
|
2847
|
+
* const result = await Validator.validateBulk(User, {
|
|
2848
|
+
* data: users
|
|
2849
|
+
* });
|
|
2850
|
+
*
|
|
2851
|
+
* if (!result.success && Validator.isBulkError(result)) {
|
|
2852
|
+
* // TypeScript knows result is ValidatorBulkError
|
|
2853
|
+
* console.log('Total items:', result.totalCount); // 4
|
|
2854
|
+
* console.log('Failed items:', result.failureCount); // 2
|
|
2855
|
+
* console.log('Success rate:',
|
|
2856
|
+
* `${((result.totalCount - result.failureCount) / result.totalCount * 100).toFixed(1)}%`
|
|
2857
|
+
* ); // 50.0%
|
|
2858
|
+
*
|
|
2859
|
+
* result.itemErrors.forEach(itemError => {
|
|
2860
|
+
* console.log(`Item[${itemError.index}]: ${itemError.message}`);
|
|
2861
|
+
* // Output:
|
|
2862
|
+
* // Item[1]: Validation failed for 2 fields: email, name
|
|
2863
|
+
* // Item[3]: Validation failed for field: email
|
|
2864
|
+
* });
|
|
2865
|
+
* }
|
|
2866
|
+
* ```
|
|
2867
|
+
*
|
|
2868
|
+
* @example
|
|
2869
|
+
* ```typescript
|
|
2870
|
+
* // Bulk import with error reporting
|
|
2871
|
+
* async function importUsers(csvData: string[][]) {
|
|
2872
|
+
* const result = await Validator.validateBulk(User, {
|
|
2873
|
+
* data: csvData.map(row => ({
|
|
2874
|
+
* email: row[0],
|
|
2875
|
+
* name: row[1]
|
|
2876
|
+
* }))
|
|
2877
|
+
* });
|
|
2878
|
+
*
|
|
2879
|
+
* if (!result.success && Validator.isBulkError(result)) {
|
|
2880
|
+
* // Generate error report
|
|
2881
|
+
* const errorReport = {
|
|
2882
|
+
* totalRecords: result.totalCount,
|
|
2883
|
+
* failedRecords: result.failureCount,
|
|
2884
|
+
* successRecords: result.totalCount - result.failureCount,
|
|
2885
|
+
* errors: result.itemErrors.map(error => ({
|
|
2886
|
+
* row: error.index + 2, // +2 for 1-based + header row
|
|
2887
|
+
* message: error.message,
|
|
2888
|
+
* data: csvData[error.index]
|
|
2889
|
+
* }))
|
|
2890
|
+
* };
|
|
2891
|
+
*
|
|
2892
|
+
* return {
|
|
2893
|
+
* success: false,
|
|
2894
|
+
* report: errorReport
|
|
2895
|
+
* };
|
|
2896
|
+
* }
|
|
2897
|
+
*
|
|
2898
|
+
* return { success: true };
|
|
2899
|
+
* }
|
|
2900
|
+
* ```
|
|
2901
|
+
*
|
|
2902
|
+
* @example
|
|
2903
|
+
* ```typescript
|
|
2904
|
+
* // Error logging with item details
|
|
2905
|
+
* function logBulkValidationError(error: unknown) {
|
|
2906
|
+
* if (Validator.isBulkError(error)) {
|
|
2907
|
+
* logger.error({
|
|
2908
|
+
* type: 'BULK_VALIDATION',
|
|
2909
|
+
* targetClass: error.targetClass?.name,
|
|
2910
|
+
* totalCount: error.totalCount,
|
|
2911
|
+
* failureCount: error.failureCount,
|
|
2912
|
+
* successRate: ((error.totalCount - error.failureCount) / error.totalCount * 100).toFixed(2) + '%',
|
|
2913
|
+
* message: error.message,
|
|
2914
|
+
* timestamp: error.failedAt,
|
|
2915
|
+
* duration: error.duration
|
|
2916
|
+
* });
|
|
2917
|
+
*
|
|
2918
|
+
* // Log individual item errors
|
|
2919
|
+
* error.itemErrors.forEach(itemError => {
|
|
2920
|
+
* logger.debug({
|
|
2921
|
+
* index: itemError.index,
|
|
2922
|
+
* message: itemError.message,
|
|
2923
|
+
* error: itemError.error
|
|
2924
|
+
* });
|
|
2925
|
+
* });
|
|
2926
|
+
* }
|
|
2927
|
+
* }
|
|
2928
|
+
* ```
|
|
2929
|
+
*
|
|
2930
|
+
* @example
|
|
2931
|
+
* ```typescript
|
|
2932
|
+
* // Retry failed items
|
|
2933
|
+
* async function processBatchWithRetry(items: any[]) {
|
|
2934
|
+
* const result = await Validator.validateBulk(ItemClass, { data: items });
|
|
2935
|
+
*
|
|
2936
|
+
* if (!result.success && Validator.isBulkError(result)) {
|
|
2937
|
+
* // Extract failed item indices
|
|
2938
|
+
* const failedIndices = new Set(
|
|
2939
|
+
* result.itemErrors.map(error => error.index)
|
|
2940
|
+
* );
|
|
2941
|
+
*
|
|
2942
|
+
* // Retry only failed items
|
|
2943
|
+
* const failedItems = items.filter((_, index) =>
|
|
2944
|
+
* failedIndices.has(index)
|
|
2945
|
+
* );
|
|
2946
|
+
*
|
|
2947
|
+
* console.log(`Retrying ${failedItems.length} failed items...`);
|
|
2948
|
+
* return await retryValidation(failedItems);
|
|
2949
|
+
* }
|
|
2950
|
+
*
|
|
2951
|
+
* return { success: true };
|
|
2952
|
+
* }
|
|
2953
|
+
* ```
|
|
2954
|
+
*
|
|
2955
|
+
* @remarks
|
|
2956
|
+
* **ValidatorBulkError Properties**:
|
|
2957
|
+
* - `name: 'ValidatorBulkError'` - Error type identifier
|
|
2958
|
+
* - `targetClass: ClassConstructor` - The class used for validation
|
|
2959
|
+
* - `itemErrors: ItemError[]` - Array of individual item errors with indices
|
|
2960
|
+
* - `failures: ValidatorClassError[]` - Detailed class errors for each failed item
|
|
2961
|
+
* - `failureCount: number` - Number of items that failed validation
|
|
2962
|
+
* - `totalCount: number` - Total number of items validated
|
|
2963
|
+
* - `message: string` - Summary message (e.g., "2 of 5 items failed validation")
|
|
2964
|
+
* - `errorCode: 'ERR_VALIDATION_FAILED'` - Standard error code
|
|
2965
|
+
* - `statusCode: 400` - HTTP status code
|
|
2966
|
+
* - `failedAt: Date` - Timestamp of failure
|
|
2967
|
+
* - `duration: number` - Validation duration in milliseconds
|
|
2968
|
+
*
|
|
2969
|
+
* **ItemError Structure**:
|
|
2970
|
+
* - `index: number` - Zero-based index of the failed item
|
|
2971
|
+
* - `message: string` - Error message for this item
|
|
2972
|
+
* - `error: ValidatorClassError` - Detailed validation error for the item
|
|
2973
|
+
*
|
|
2974
|
+
* **Type Narrowing**:
|
|
2975
|
+
* - After this check, TypeScript narrows the type to `ValidatorBulkError`
|
|
2976
|
+
* - Enables safe access to `itemErrors`, `failures`, `totalCount`, etc.
|
|
2977
|
+
* - No need for additional type assertions
|
|
2978
|
+
*
|
|
2979
|
+
* **Performance**:
|
|
2980
|
+
* - O(1) complexity - two property checks
|
|
2981
|
+
* - Very fast, suitable for high-frequency validation
|
|
2982
|
+
* - No object creation or memory allocation
|
|
2983
|
+
*
|
|
2984
|
+
* @see {@link isError} - Check for single field validation errors
|
|
2985
|
+
* @see {@link isClassError} - Check for class/object validation errors
|
|
2986
|
+
* @see {@link isAnyError} - Check for any validator error type
|
|
2987
|
+
* @see {@link ValidatorBulkError} - Bulk validation error type
|
|
2988
|
+
* @see {@link validateBulk} - Method that returns ValidatorBulkError on failure
|
|
2989
|
+
*
|
|
2990
|
+
* @public
|
|
2991
|
+
* @category Type Guards
|
|
2514
2992
|
*/
|
|
2515
2993
|
static isBulkError(result: unknown): result is ValidatorBulkError;
|
|
2994
|
+
/**
|
|
2995
|
+
* ## Check for Any Validator Error Type
|
|
2996
|
+
*
|
|
2997
|
+
* Universal type guard that checks if a value is **any type** of validator error.
|
|
2998
|
+
* This method returns `true` if the value is a `ValidatorError`, `ValidatorClassError`,
|
|
2999
|
+
* or `ValidatorBulkError`, providing a convenient way to detect validation failures
|
|
3000
|
+
* without needing to check each error type individually.
|
|
3001
|
+
*
|
|
3002
|
+
* ### Purpose
|
|
3003
|
+
* - **Unified Error Detection**: Single method to detect all validation error types
|
|
3004
|
+
* - **Type Safety**: Narrows TypeScript type to union of all validator errors
|
|
3005
|
+
* - **Convenience**: Eliminates need for multiple type checks
|
|
3006
|
+
* - **Error Handling**: Simplifies error handling logic in catch blocks
|
|
3007
|
+
*
|
|
3008
|
+
* ### When to Use
|
|
3009
|
+
* - **Generic Error Handling**: When you want to handle all validation errors the same way
|
|
3010
|
+
* - **Error Classification**: To distinguish validation errors from other error types
|
|
3011
|
+
* - **API Responses**: To check if a response contains validation errors
|
|
3012
|
+
* - **Logging**: To categorize errors by type for monitoring
|
|
3013
|
+
*
|
|
3014
|
+
* ### When NOT to Use
|
|
3015
|
+
* - **Type-Specific Handling**: When you need different logic for each error type
|
|
3016
|
+
* → Use `isError()`, `isClassError()`, or `isBulkError()` instead
|
|
3017
|
+
* - **Field-Level Access**: When you need to access specific error properties
|
|
3018
|
+
* → Check specific type first, then access properties
|
|
3019
|
+
*
|
|
3020
|
+
* @param result - The value to check for validator error types
|
|
3021
|
+
* @returns `true` if the value is any validator error type, `false` otherwise
|
|
3022
|
+
*
|
|
3023
|
+
* @example
|
|
3024
|
+
* ```typescript
|
|
3025
|
+
* // Basic usage - generic validation error handling
|
|
3026
|
+
* try {
|
|
3027
|
+
* const result = await Validator.validateClass(UserClass, { data: userData });
|
|
3028
|
+
* if (!result.success) {
|
|
3029
|
+
* // Handle validation failure
|
|
3030
|
+
* }
|
|
3031
|
+
* } catch (error) {
|
|
3032
|
+
* if (Validator.isAnyError(error)) {
|
|
3033
|
+
* // TypeScript knows error is ValidatorError | ValidatorClassError | ValidatorBulkError
|
|
3034
|
+
* console.log('Validation failed:', error.message);
|
|
3035
|
+
* console.log('Error code:', error.errorCode);
|
|
3036
|
+
* console.log('Status code:', error.statusCode);
|
|
3037
|
+
* } else {
|
|
3038
|
+
* // Handle other error types
|
|
3039
|
+
* console.error('Unexpected error:', error);
|
|
3040
|
+
* }
|
|
3041
|
+
* }
|
|
3042
|
+
* ```
|
|
3043
|
+
*
|
|
3044
|
+
* @example
|
|
3045
|
+
* ```typescript
|
|
3046
|
+
* // API response validation
|
|
3047
|
+
* async function submitForm(formData: FormData) {
|
|
3048
|
+
* const response = await fetch('/api/submit', {
|
|
3049
|
+
* method: 'POST',
|
|
3050
|
+
* body: formData
|
|
3051
|
+
* });
|
|
3052
|
+
*
|
|
3053
|
+
* const result = await response.json();
|
|
3054
|
+
*
|
|
3055
|
+
* if (Validator.isAnyError(result)) {
|
|
3056
|
+
* // Server returned validation errors
|
|
3057
|
+
* return {
|
|
3058
|
+
* success: false,
|
|
3059
|
+
* type: 'validation',
|
|
3060
|
+
* message: result.message,
|
|
3061
|
+
* errors: result
|
|
3062
|
+
* };
|
|
3063
|
+
* }
|
|
3064
|
+
*
|
|
3065
|
+
* return { success: true, data: result };
|
|
3066
|
+
* }
|
|
3067
|
+
* ```
|
|
3068
|
+
*
|
|
3069
|
+
* @example
|
|
3070
|
+
* ```typescript
|
|
3071
|
+
* // Error classification for logging
|
|
3072
|
+
* function logError(error: unknown) {
|
|
3073
|
+
* const errorType = Validator.isAnyError(error)
|
|
3074
|
+
* ? 'VALIDATION_ERROR'
|
|
3075
|
+
* : error instanceof Error
|
|
3076
|
+
* ? 'RUNTIME_ERROR'
|
|
3077
|
+
* : 'UNKNOWN_ERROR';
|
|
3078
|
+
*
|
|
3079
|
+
* logger.error({
|
|
3080
|
+
* type: errorType,
|
|
3081
|
+
* message: error instanceof Error ? error.message : String(error),
|
|
3082
|
+
* timestamp: new Date().toISOString(),
|
|
3083
|
+
* details: Validator.isAnyError(error) ? {
|
|
3084
|
+
* errorCode: error.errorCode,
|
|
3085
|
+
* statusCode: error.statusCode,
|
|
3086
|
+
* duration: error.duration
|
|
3087
|
+
* } : undefined
|
|
3088
|
+
* });
|
|
3089
|
+
* }
|
|
3090
|
+
* ```
|
|
3091
|
+
*
|
|
3092
|
+
* @example
|
|
3093
|
+
* ```typescript
|
|
3094
|
+
* // Conditional error handling with type narrowing
|
|
3095
|
+
* function handleValidationResult(result: unknown) {
|
|
3096
|
+
* if (Validator.isAnyError(result)) {
|
|
3097
|
+
* // Now TypeScript knows the exact union type
|
|
3098
|
+
*
|
|
3099
|
+
* // Further narrow to specific types if needed
|
|
3100
|
+
* if (Validator.isClassError(result)) {
|
|
3101
|
+
* // Handle class validation errors
|
|
3102
|
+
* result.fieldErrors.forEach(fieldError => {
|
|
3103
|
+
* console.log(`${fieldError.field}: ${fieldError.message}`);
|
|
3104
|
+
* });
|
|
3105
|
+
* } else if (Validator.isBulkError(result)) {
|
|
3106
|
+
* // Handle bulk validation errors
|
|
3107
|
+
* console.log(`${result.failureCount} items failed validation`);
|
|
3108
|
+
* } else if (Validator.isError(result)) {
|
|
3109
|
+
* // Handle single field errors
|
|
3110
|
+
* console.log(`Field ${result.field} failed: ${result.message}`);
|
|
3111
|
+
* }
|
|
3112
|
+
* }
|
|
3113
|
+
* }
|
|
3114
|
+
* ```
|
|
3115
|
+
*
|
|
3116
|
+
* @example
|
|
3117
|
+
* ```typescript
|
|
3118
|
+
* // Integration with exception handling
|
|
3119
|
+
* class ValidationException extends Error {
|
|
3120
|
+
* constructor(public validatorError: ValidatorError | ValidatorClassError | ValidatorBulkError) {
|
|
3121
|
+
* super(validatorError.message);
|
|
3122
|
+
* this.name = 'ValidationException';
|
|
3123
|
+
* }
|
|
3124
|
+
*
|
|
3125
|
+
* static from(error: unknown): ValidationException | null {
|
|
3126
|
+
* if (Validator.isAnyError(error)) {
|
|
3127
|
+
* return new ValidationException(error);
|
|
3128
|
+
* }
|
|
3129
|
+
* return null;
|
|
3130
|
+
* }
|
|
3131
|
+
* }
|
|
3132
|
+
*
|
|
3133
|
+
* try {
|
|
3134
|
+
* await validateUserInput(data);
|
|
3135
|
+
* } catch (error) {
|
|
3136
|
+
* const validationException = ValidationException.from(error);
|
|
3137
|
+
* if (validationException) {
|
|
3138
|
+
* throw validationException;
|
|
3139
|
+
* }
|
|
3140
|
+
* throw error;
|
|
3141
|
+
* }
|
|
3142
|
+
* ```
|
|
3143
|
+
*
|
|
3144
|
+
* @remarks
|
|
3145
|
+
* **Implementation Details**:
|
|
3146
|
+
* - Checks `isError()`, `isClassError()`, and `isBulkError()` in sequence
|
|
3147
|
+
* - Short-circuits on first match for performance
|
|
3148
|
+
* - All checks delegate to `isBaseError()` for consistency
|
|
3149
|
+
* - No additional overhead beyond individual type checks
|
|
3150
|
+
*
|
|
3151
|
+
* **Type Narrowing**:
|
|
3152
|
+
* - TypeScript narrows to: `ValidatorError | ValidatorClassError | ValidatorBulkError`
|
|
3153
|
+
* - Use specific type guards for further narrowing
|
|
3154
|
+
* - Enables safe access to common properties (message, errorCode, statusCode, etc.)
|
|
3155
|
+
*
|
|
3156
|
+
* **Performance**:
|
|
3157
|
+
* - O(1) complexity - maximum 3 checks
|
|
3158
|
+
* - Short-circuits on first match (typically 1 check)
|
|
3159
|
+
* - No object creation or memory allocation
|
|
3160
|
+
* - Safe for high-frequency error checking
|
|
3161
|
+
*
|
|
3162
|
+
* **Common Properties** (available on all validator errors):
|
|
3163
|
+
* - `message: string` - Human-readable error message
|
|
3164
|
+
* - `errorCode: 'ERR_VALIDATION_FAILED'` - Standard error code
|
|
3165
|
+
* - `statusCode: 400` - HTTP status code
|
|
3166
|
+
* - `success: false` - Always false for errors
|
|
3167
|
+
* - `status: 'error'` - Status indicator
|
|
3168
|
+
* - `failedAt: Date` - Timestamp of failure
|
|
3169
|
+
* - `duration: number` - Validation duration in milliseconds
|
|
3170
|
+
*
|
|
3171
|
+
* **Type-Specific Properties**:
|
|
3172
|
+
* - `ValidatorError`: `field`, `rule`, `value`
|
|
3173
|
+
* - `ValidatorClassError`: `fieldErrors`, `fieldCount`, `targetClass`
|
|
3174
|
+
* - `ValidatorBulkError`: `failures`, `failureCount`, `totalCount`, `itemErrors`
|
|
3175
|
+
*
|
|
3176
|
+
* @see {@link isError} - Check for single field validation errors only
|
|
3177
|
+
* @see {@link isClassError} - Check for class/object validation errors only
|
|
3178
|
+
* @see {@link isBulkError} - Check for bulk/array validation errors only
|
|
3179
|
+
* @see {@link isBaseError} - Internal base error structure check
|
|
3180
|
+
* @see {@link ValidatorError} - Single field validation error type
|
|
3181
|
+
* @see {@link ValidatorClassError} - Class validation error type
|
|
3182
|
+
* @see {@link ValidatorBulkError} - Bulk validation error type
|
|
3183
|
+
* @see {@link ValidatorBaseError} - Base error interface
|
|
3184
|
+
*
|
|
3185
|
+
* @public
|
|
3186
|
+
* @since 2.0.2
|
|
3187
|
+
* @category Type Guards
|
|
3188
|
+
*/
|
|
3189
|
+
static isAnyError(result: unknown): result is ValidatorError | ValidatorClassError | ValidatorBulkError;
|
|
2516
3190
|
private static _prepareRuleDecorator;
|
|
2517
3191
|
private static _buildRuleDecorator;
|
|
2518
3192
|
/**
|