@resk/core
Version:
An innovative TypeScript framework that empowers developers to build applications with a fully decorator-based architecture for efficient resource management. By combining the power of decorators with a resource-oriented design, DecorRes enhances code cla
1,068 lines • 108 kB
TypeScript
import { IClassConstructor, IMakeOptional } from "../types";
import { I18n } from "../i18n";
import { IValidatorDefaultMultiRule, IValidatorMultiRuleFunction, IValidatorMultiRuleNames, IValidatorNestedRuleFunctionOptions, IValidatorRegisteredRules, IValidatorResult, IValidatorRule, IValidatorRuleFunction, IValidatorRuleName, IValidatorRuleParams, IValidatorRules, IValidatorSanitizedRules, IValidatorValidateFailure, IValidatorValidateMultiRuleOptions, IValidatorValidateOptions, IValidatorValidateResult, IValidatorValidateSuccess, IValidatorValidateTargetOptions, IValidatorValidateTargetResult } from "./types";
/**
* # Validator Class
*
* A comprehensive validation system that provides flexible and powerful validation capabilities
* for TypeScript/JavaScript applications. This class supports both synchronous and asynchronous
* validation, decorator-based validation for classes, and a rich ecosystem of validation rules.
*
* ## Key Features
* - **Type-Safe Validation**: Full TypeScript support with generic types
* - **Decorator Support**: Class property validation using decorators
* - **Async Validation**: Support for asynchronous validation rules
* - **Internationalization**: Built-in i18n support for error messages
* - **Extensible**: Easy to register custom validation rules
* - **Rule Composition**: Combine multiple validation rules
*
* ## Basic Usage
* ```typescript
* // Register a custom validation rule
* Validator.registerRule('CustomRule', ({ value }) => {
* return value > 10 || 'Value must be greater than 10';
* });
*
* // Validate a single value
* const result = await Validator.validate({
* value: 15,
* rules: ['Required', 'CustomRule']
* });
*
* // Use with decorators
* class User {
* @IsRequired
* @IsEmail
* email: string;
*
* @IsRequired
* @MinLength([3])
* name: string;
* }
*
* const userData = { email: 'user@example.com', name: 'John' };
* const validated = await Validator.validateTarget(User, userData);
* ```
*
* ## Advanced Usage
* ```typescript
* // Complex validation with context
* const validationOptions = {
* value: userData,
* rules: [
* 'required',
* { minLength: [5] },
* async ({ value, context }) => {
* const exists = await checkIfUserExists(value);
* return !exists || 'User already exists';
* }
* ],
* context: { userId: 123 }
* };
*
* try {
* const result = await Validator.validate(validationOptions);
* console.log('Validation passed!', result);
* } catch (error) {
* console.error('Validation failed:', error.message);
* }
* ```
*
* @author Resk Framework Team
* @since 1.0.0
* @version 2.1.0
* @see {@link https://docs.resk.dev/validation | Validation Documentation}
* @public
*/
export declare class Validator {
/**
* ## Metadata Storage Key
*
* Private symbol used to store validation rules in metadata. This ensures
* that the validation rules don't conflict with other metadata keys.
*
* @private
* @readonly
* @since 1.0.0
*/
private static readonly RULES_METADATA_KEY;
/**
* ## Mark Rule With Symbol
*
* Marks a rule function with a specific marker symbol. Used internally to mark
* decorators (OneOf, AllOf, ArrayOf, ValidateNested) for reliable identification
* even in minified code. Symbols survive minification while function names do not.
*
* @param ruleFunc - The rule function to mark
* @param marker - The marker symbol to apply
* @internal
*/
static markRuleWithSymbol(ruleFunc: any, marker: symbol): void;
/**
* ## Register Validation Rule
*
* Registers a new custom validation rule that can be used throughout the application.
* This method provides type-safe registration of validation functions with proper
* error handling and validation of input parameters.
*
* ### Type Parameters
* - `ParamType` - Array type defining the parameters the rule function accepts
* - `Context` - Type of the validation context object passed to the rule
*
* ### Rule Function Signature
* ```typescript
* type RuleFunction<ParamType, Context> = (options: {
* value: any;
* ruleParams: ParamType;
* context?: Context;
* fieldName?: string;
* translatedPropertyName?: string;
* }) => boolean | string | Promise<boolean | string>;
* ```
*
* ### Rule Return Values
* - `true` - Validation passed
* - `false` - Validation failed (uses default error message)
* - `string` - Validation failed with custom error message
* - `Promise<boolean|string>` - Async validation
*
* @example
* ```typescript
* // Simple synchronous rule
* Validator.registerRule('MinValue', ({ value, ruleParams }) => {
* const [minValue] = ruleParams;
* return value >= minValue || `Value must be at least ${minValue}`;
* });
*
* // Async rule with database check
* Validator.registerRule('UniqueEmail', async ({ value, context }) => {
* const exists = await database.user.findByEmail(value);
* return !exists || 'Email address is already taken';
* });
*
* // Rule with multiple parameters
* Validator.registerRule('Between', ({ value, ruleParams }) => {
* const [min, max] = ruleParams;
* return (value >= min && value <= max) ||
* `Value must be between ${min} and ${max}`;
* });
*
* // Rule with context
* Validator.registerRule('DifferentFrom', ({ value, ruleParams, context }) => {
* const [fieldName] = ruleParams;
* const otherValue = context?.data?.[fieldName];
* return value !== otherValue ||
* `Must be different from ${fieldName}`;
* });
* ```
*
* @template ParamType - Array type for rule parameters
* @template Context - Type for validation context
*
* @param ruleName - Unique identifier for the validation rule (must be non-empty string)
* @param ruleHandler - Function that performs the validation logic
*
* @throws {Error} When ruleName is not a non-empty string
* @throws {Error} When ruleHandler is not a function
*
* @since 1.0.0
* @see {@link findRegisteredRule} - Find a registered rule
* @see {@link getRules} - Get all registered rules
* @public
*/
static registerRule<ParamType extends Array<any> = Array<any>, Context = unknown>(ruleName: IValidatorRuleName, ruleHandler: IValidatorRuleFunction<ParamType, Context>): void;
/**
* ## Get All Registered Rules
*
* Retrieves an immutable copy of all currently registered validation rules.
* This method returns a shallow copy to prevent external modification of
* the internal rules registry while allowing inspection of available rules.
*
* ### Use Cases
* - Debugging: Check what rules are available
* - Rule Discovery: List all registered rules for documentation
* - Testing: Verify rule registration in unit tests
* - Introspection: Build dynamic validation UIs
*
* @example
* ```typescript
* // Get all registered rules
* const allRules = Validator.getRules();
* console.log('Available rules:', Object.keys(allRules));
*
* // Check if a specific rule exists
* const hasEmailRule = 'Email' in Validator.getRules();
*
* // Get rule function directly (not recommended, use findRegisteredRule instead)
* const emailRule = Validator.getRules()['Email'];
* ```
*
* @returns An immutable copy of all registered validation rules
*
* @since 1.0.0
* @see {@link registerRule} - Register a new rule
* @see {@link findRegisteredRule} - Find a specific rule
* @public
*/
static getRules<Context = unknown>(): IValidatorRegisteredRules<Context>;
/**
* ## Get Registered Rule
*
* Retrieves a specific validation rule function by its registered name. This method
* provides direct access to the underlying validation functions that have been
* registered with the Validator system.
*
* ### Rule Retrieval
* This method looks up rules in the internal rules registry that was populated
* through the `registerRule` method. It returns the actual validation function
* that can be used for custom validation logic or inspection.
*
* ### Return Value
* - Returns the validation rule function if found
* - Returns `undefined` if no rule with the given name exists
* - The returned function has the signature `IValidatorRuleFunction`
*
* @example
* ```typescript
* // Get a registered rule function
* const emailRule = Validator.getRule('Email');
* if (emailRule) {
* // Use the rule directly
* const result = await emailRule({
* value: 'test@example.com',
* ruleParams: []
* });
* console.log('Email validation result:', result);
* }
*
* // Check if a rule exists before using it
* const customRule = Validator.getRule('CustomRule');
* if (customRule) {
* // Rule exists, safe to use
* } else {
* console.log('CustomRule is not registered');
* }
*
* // Get rule for programmatic validation
* const minLengthRule = Validator.getRule('MinLength');
* if (minLengthRule) {
* const isValid = await minLengthRule({
* value: 'hello',
ruleParams: [3] // Minimum length of 3
* });
* }
* ```
*
* @param ruleName - The name of the validation rule to retrieve
*
* @returns The validation rule function if found, undefined otherwise
*
* @since 1.0.0
* @see {@link registerRule} - Register a new validation rule
* @see {@link getRules} - Get all registered rules
* @see {@link hasRule} - Check if a rule exists (type guard)
* @public
*/
static getRule<Context = unknown>(ruleName: IValidatorRuleName): IValidatorRuleFunction<[], Context> | IValidatorRuleFunction<[number], Context> | IValidatorRuleFunction<[lengthOrMinLength: number, maxLength?: number | undefined], Context> | IValidatorRuleFunction<[minLength: number], Context> | IValidatorRuleFunction<[maxLength: number], Context> | IValidatorRuleFunction<[countryCode?: "AF" | "AL" | "DZ" | "AS" | "AD" | "AO" | "AI" | "AG" | "AR" | "AM" | "AW" | "AU" | "AT" | "AZ" | "BS" | "BH" | "BD" | "BB" | "BY" | "BE" | "BZ" | "BJ" | "BM" | "BT" | "BO" | "BA" | "BW" | "BR" | "IO" | "VG" | "BN" | "BG" | "BF" | "BI" | "KH" | "CM" | "CA" | "CV" | "BQ" | "KY" | "CF" | "TD" | "CL" | "CN" | "CX" | "CC" | "CO" | "KM" | "CD" | "CG" | "CK" | "CR" | "CI" | "HR" | "CU" | "CW" | "CY" | "CZ" | "DK" | "DJ" | "DM" | "DO" | "EC" | "EG" | "SV" | "GQ" | "ER" | "EE" | "ET" | "FK" | "FO" | "FJ" | "FI" | "FR" | "GF" | "PF" | "GA" | "GM" | "GE" | "DE" | "GH" | "GI" | "GR" | "GL" | "GD" | "GP" | "GU" | "GT" | "GG" | "GN" | "GW" | "GY" | "HT" | "HN" | "HK" | "HU" | "IS" | "IN" | "ID" | "IR" | "IQ" | "IE" | "IM" | "IL" | "IT" | "JM" | "JP" | "JE" | "JO" | "KZ" | "KE" | "KI" | "KW" | "KG" | "LA" | "LV" | "LB" | "LS" | "LR" | "LY" | "LI" | "LT" | "LU" | "MO" | "MK" | "MG" | "MW" | "MY" | "MV" | "ML" | "MT" | "MH" | "MQ" | "MR" | "MU" | "YT" | "MX" | "FM" | "MD" | "MC" | "MN" | "ME" | "MS" | "MA" | "MZ" | "MM" | "NA" | "NR" | "NP" | "NL" | "NC" | "NZ" | "NI" | "NE" | "NG" | "NU" | "NF" | "KP" | "MP" | "NO" | "OM" | "PK" | "PW" | "PS" | "PA" | "PG" | "PY" | "PE" | "PH" | "PL" | "PT" | "PR" | "QA" | "RE" | "RO" | "RU" | "RW" | "BL" | "SH" | "KN" | "LC" | "MF" | "PM" | "VC" | "WS" | "SM" | "ST" | "SA" | "SN" | "RS" | "SC" | "SL" | "SG" | "SX" | "SK" | "SI" | "SB" | "SO" | "ZA" | "KR" | "SS" | "ES" | "LK" | "SD" | "SR" | "SJ" | "SZ" | "SE" | "CH" | "SY" | "TW" | "TJ" | "TZ" | "TH" | "TL" | "TG" | "TK" | "TO" | "TT" | "TN" | "TR" | "TM" | "TC" | "TV" | "VI" | "UG" | "UA" | "AE" | "GB" | "US" | "UY" | "UZ" | "VU" | "VA" | "VE" | "VN" | "WF" | "EH" | "YE" | "ZM" | "ZW" | "AX" | undefined], Context> | IValidatorRuleFunction<[minLength: number], Context> | IValidatorRuleFunction<[maxLength: number], Context> | IValidatorRuleFunction<[length: number], Context> | IValidatorRuleFunction<any[], Context> | IValidatorRuleFunction<[date: string | Date], Context> | IValidatorRuleFunction<[date: string | Date], Context> | IValidatorRuleFunction<[minDate: string | Date, maxDate: string | Date], Context> | IValidatorRuleFunction<[date: string | Date], Context> | IValidatorRuleFunction<import("../types").IPrimitive[], Context> | IValidatorRuleFunction<[size: number], Context> | IValidatorRuleFunction<string[], Context> | IValidatorRuleFunction<[minSize: number], Context> | IValidatorRuleFunction<[min: number, max: number], Context> | IValidatorRuleFunction<[minDecimalPlaces: number, maxDecimalPlaces?: number | undefined], Context>;
/**
* ## Check Rule Existence (Type Guard)
*
* Type guard method that checks whether a validation rule with the given name
* is registered in the Validator system. This method provides both existence
* checking and TypeScript type narrowing for rule names.
*
* ### Type Guard Behavior
* - **Input Validation**: First checks if the input is a non-null string
* - **Rule Lookup**: Uses `getRule` to check if the rule exists in the registry
* - **Type Narrowing**: Narrows `ruleName` to `IValidatorRuleName` if it returns true
*
* ### Use Cases
* - **Safe Rule Access**: Verify rule existence before using `getRule`
* - **Dynamic Validation**: Check rules at runtime before applying them
* - **Type Safety**: Enable TypeScript to narrow types based on rule existence
* - **Error Prevention**: Avoid undefined access when working with rule names
*
* @example
* ```typescript
* // Basic existence check
* if (Validator.hasRule('Email')) {
* console.log('Email rule is available');
* }
*
* // Type narrowing with type guard
* function processRule(ruleName: string) {
* if (Validator.hasRule(ruleName)) {
* // TypeScript now knows ruleName is IValidatorRuleName
* const rule = Validator.getRule(ruleName); // Type safe
return rule;
* } else {
* console.log(`${ruleName} is not a valid rule`);
return null;
* }
* }
*
* // Safe rule processing
* const ruleNames = ['Email', 'Required', 'InvalidRule'];
* const validRules = ruleNames.filter(Validator.hasRule);
* console.log('Valid rules:', validRules); // ['Email', 'Required']
*
* // Dynamic rule application
* function applyRuleIfExists(value: any, ruleName: string) {
* if (Validator.hasRule(ruleName)) {
* const rule = Validator.getRule(ruleName);
* return rule?.({ value, ruleParams: [] });
* }
* return 'Rule not found';
* }
* ```
*
* @param ruleName - The name to check for rule existence (any type, validated internally)
*
* @returns `true` if the rule exists and ruleName is a valid IValidatorRuleName, `false` otherwise
*
* @since 1.0.0
* @see {@link getRule} - Get the actual rule function
* @see {@link getRules} - Get all registered rules
* @see {@link registerRule} - Register a new validation rule
* @public
*/
static hasRule(ruleName: any): ruleName is IValidatorRuleName;
private static getI18n;
/**
* ## Get Error Message Separators
*
* Retrieves the configured separators used for formatting validation error messages.
* These separators are internationalized and can be customized through the i18n system.
* This method provides a centralized way to get consistent error message formatting.
*
* ### Separator Types
* - `multiple` - Used when joining multiple error messages
* - `single` - Used for single error message formatting
*
* ### Internationalization
* The separators are loaded from the i18n translation system under the key
* `validator.separators`. This allows different languages to use appropriate
* punctuation and formatting conventions.
*
* @param customI18n - Optional custom I18n instance to use for translations
* @example
* ```typescript
* // Get current separators
* const separators = Validator.getErrorMessageSeparators();
* console.log(separators); // { multiple: ", ", single: ", " }
*
* // Use separators for custom error formatting
* const errors = ['Field is required', 'Must be an email', 'Too short'];
* const errorMessage = errors.join(separators.multiple);
* console.log(errorMessage); // "Field is required, Must be an email, Too short"
*
* // Custom error message builder
* function buildErrorMessage(fieldName: string, errors: string[]) {
* const seps = Validator.getErrorMessageSeparators();
* return `${fieldName}: ${errors.join(seps.multiple)}`;
* }
* ```
*
* @returns Object containing separator strings for error message formatting
* @returns returns.multiple - Separator for joining multiple error messages
* @returns returns.single - Separator for single error message formatting
*
* @since 1.0.0
* @see {@link validate} - Uses these separators for error formatting
* @see {@link validateTarget} - Also uses these separators
* @public
*/
static getErrorMessageSeparators(customI18n?: I18n): {
multiple: string;
single: string;
};
/**
* ## Find Registered Rule
*
* Locates and returns a specific validation rule by its name. This method provides
* type-safe access to registered validation rules with proper error handling for
* invalid rule names. Returns undefined if the rule doesn't exist.
*
* ### Type Safety
* This method is fully type-safe and will return the correctly typed rule function
* based on the generic parameters provided. The rule function signature will match
* the expected parameter and context types.
*
* @example
* ```typescript
* // Find a simple rule
* const emailRule = Validator.findRegisteredRule('Email');
* if (emailRule) {
* const result = await emailRule({
* value: 'test@example.com',
* ruleParams: []
* });
* }
*
* // Find a rule with specific parameter types
* const minLengthRule = Validator.findRegisteredRule<[number]>('MinLength');
* if (minLengthRule) {
* const result = await minLengthRule({
* value: 'hello',
* ruleParams: [5]
* });
* }
*
* // Find a rule with context
* interface UserContext {
* userId: number;
* permissions: string[];
* }
*
* const permissionRule = Validator.findRegisteredRule<string[], UserContext>('HasPermission');
* if (permissionRule) {
* const result = await permissionRule({
* value: 'admin',
* ruleParams: ['admin', 'moderator'],
* context: { userId: 123, permissions: ['user', 'admin'] }
* });
* }
*
* // Safe rule checking
* const unknownRule = Validator.findRegisteredRule('NonExistentRule');
* console.log(unknownRule); // undefined
* ```
*
* @template ParamType - Array type specifying the rule parameter types
* @template Context - Type of the validation context object
*
* @param ruleName - The name of the rule to find
*
* @returns The validation rule function if found, undefined otherwise
*
* @since 1.0.0
* @see {@link registerRule} - Register a new rule
* @see {@link getRules} - Get all rules
* @public
*/
static findRegisteredRule<ParamType extends Array<any> = Array<any>, Context = unknown>(ruleName: IValidatorRuleName): IValidatorRuleFunction<ParamType, Context> | undefined;
/**
* ## Parse and Validate Rules
*
* Converts various input rule formats into a standardized, executable format while
* identifying and reporting any invalid rules. This method handles the complex task
* of normalizing different rule input formats into a consistent internal representation.
*
* ### Supported Input Formats
*
* #### 1. Function Rules
* ```typescript
* const functionRule = ({ value }) => value > 0 || 'Must be positive';
* ```
*
* #### 2. String Rules
* ```typescript
* 'Required' // Simple rule
* 'MinLength[5]' // Rule with single parameter
* 'Between[10,20]' // Rule with multiple parameters
* ```
*
* #### 3. Object Rules
* ```typescript
* { Required: [] } // Rule without parameters
* { MinLength: [5] } // Rule with parameters
* { Between: [10, 20] } // Rule with multiple parameters
* ```
*
* ### Processing Logic
* 1. **Function Detection**: Direct function rules are passed through unchanged
* 2. **String Parsing**: Extracts rule names and parameters from bracketed syntax
* 3. **Object Processing**: Converts object notation to standardized format
* 4. **Validation**: Verifies that all referenced rules are registered
* 5. **Error Tracking**: Collects invalid rules for reporting
*
* @example
* ```typescript
* // Mixed rule formats
* const mixedRules = [
* 'Required',
* 'MinLength[3]',
* { MaxLength: [50] },
* ({ value }) => value.includes('@') || 'Must contain @',
* 'InvalidRule' // This will be reported as invalid
* ];
*
* const { sanitizedRules, invalidRules } = Validator.parseAndValidateRules(mixedRules);
*
* console.log('Valid rules:', sanitizedRules.length); // 4
* console.log('Invalid rules:', invalidRules); // ['InvalidRule']
*
* // Empty or undefined input
* const { sanitizedRules: empty } = Validator.parseAndValidateRules();
* console.log(empty.length); // 0
*
* // Complex rule with parameters
* const complexRules = [
* 'Between[1,100]',
* { CustomRule: ['param1', 'param2'] }
* ];
*
* const result = Validator.parseAndValidateRules(complexRules);
* // Each sanitized rule will have: ruleName, params, ruleFunction, rawRuleName
* ```
*
* @param inputRules - Array of validation rules in various formats, or undefined
*
* @returns Object containing processed results
* @returns returns.sanitizedRules - Array of standardized, executable rule objects
* @returns returns.invalidRules - Array of rules that couldn't be processed (unregistered)
*
* @since 1.22.0
* @see {@link parseStringRule} - Internal string rule parser
* @see {@link parseObjectRule} - Internal object rule parser
* @see {@link validate} - Uses this method for rule processing
* @public
*/
static parseAndValidateRules<Context = unknown>(inputRules?: IValidatorValidateOptions<Array<any>, Context>["rules"]): {
sanitizedRules: IValidatorSanitizedRules<Context>;
invalidRules: IValidatorRules<Context>[];
};
/**
* ## Parse String-Based Validation Rules
*
* Internal helper method that parses string-format validation rules into standardized
* rule objects. Handles both simple rule names and rules with parameters using
* bracket notation syntax.
*
* ### Supported String Formats
* - `"ruleName"` - Simple rule without parameters
* - `"ruleName[param]"` - Rule with single parameter
* - `"ruleName[param1,param2,param3]"` - Rule with multiple parameters
*
* ### Parameter Parsing
* - Parameters are extracted from content within square brackets
* - Multiple parameters are separated by commas
* - Leading/trailing whitespace is automatically trimmed
* - All parameters are treated as strings (conversion happens in rule functions)
*
* @example
* ```typescript
* // These calls demonstrate the parsing logic (internal method)
* // Simple rule
* parseStringRule("Required", registeredRules)
* // Returns: { ruleName: "Required", params: [], ruleFunction: fn, rawRuleName: "Required" }
*
* // Rule with single parameter
* parseStringRule("MinLength[5]", registeredRules)
* // Returns: { ruleName: "MinLength", params: ["5"], ruleFunction: fn, rawRuleName: "MinLength[5]" }
*
* // Rule with multiple parameters
* parseStringRule("Between[10, 20]", registeredRules)
* // Returns: { ruleName: "Between", params: ["10", "20"], ruleFunction: fn, rawRuleName: "Between[10, 20]" }
* ```
*
* @internal
* @param ruleString - The string representation of the rule to parse
* @param registeredRules - Map of all currently registered validation rules
*
* @returns Parsed rule object with standardized structure, or null if rule not found
* @returns returns.ruleName - The extracted rule name
* @returns returns.params - Array of string parameters
* @returns returns.ruleFunction - The actual validation function
* @returns returns.rawRuleName - The original unparsed rule string
*
* @since 1.22.0
* @see {@link parseAndValidateRules} - Public method that uses this parser
* @private
*/
private static parseStringRule;
private static parseObjectRule;
/**
* ## Validate a Single Value
*
* Performs validation on a single value using a set of specified validation rules.
* This is the main validation method for validating individual values outside of
* class-based validation contexts.
*
* ### Key Features
* - **Synchronous Rule Support**: Handles both synchronous and asynchronous validation rules
* - **Multiple Rules**: Supports validation with multiple rules applied sequentially
* - **Error Handling**: Never throws errors; returns a result object with success/failure status
* - **Type Safe**: Full TypeScript support with generic typing for context
* - **Nullable Handling**: Supports Empty, Nullable, and Optional rules for conditional validation
* - **Performance**: Tracks validation duration and timestamps
*
* ### Return Type: IValidatorValidateResult
* The method returns a discriminated union that can be narrowed:
* ```typescript
* type IValidatorValidateResult<Context> =
* | IValidatorValidateSuccess<Context> // success: true
* | IValidatorValidateFailure<Context> // success: false
* ```
*
* #### Success Result (success: true)
* - `success`: true
* - `value`: The original value that was validated
* - `validatedAt`: ISO timestamp when validation completed
* - `duration`: Milliseconds elapsed during validation
* - `data`: Optional context data passed to rules
* - `context`: Optional validation context of type Context
*
* #### Failure Result (success: false)
* - `success`: false
* - `value`: The original value that failed validation
* - `error`: IValidatorValidationError containing:
* - `message`: Error message (translated if i18n available)
* - `ruleName`: Name of the rule that failed
* - `ruleParams`: Parameters passed to the rule
* - `fieldName`: Optionally provided field identifier
* - `failedAt`: ISO timestamp when validation failed
* - `duration`: Milliseconds elapsed before failure
*
* ### Nullable Rules
* Special handling for conditional validation rules:
* - **Empty**: Skips validation if value is empty string ""
* - **Nullable**: Skips validation if value is null or undefined
* - **Optional**: Skips validation if value is undefined only
*
* Priority order: Empty > Nullable > Optional
*
* ### Examples
*
* #### Basic Single Rule Validation
* ```typescript
* const result = await Validator.validate({
* value: "user@example.com",
* rules: ["Required", "Email"],
* });
*
* if (result.success) {
* console.log("Email is valid:", result.value);
* } else {
* console.error("Validation failed:", result.error.message);
* }
* ```
*
* #### Validation with Parameters
* ```typescript
* const result = await Validator.validate({
* value: "hello",
* rules: [
* "Required",
* "MinLength[5]", // Validates length >= 5
* "MaxLength[20]", // Validates length <= 20
* ],
* });
* ```
*
* #### Custom Error Messages with i18n
* ```typescript
* const result = await Validator.validate({
* value: "",
* rules: ["Required"],
* fieldName: "email", // For context in error messages
* });
*
* if (!result.success) {
* // Error message can include field name if i18n is configured
* console.error(result.error.message);
* }
* ```
*
* #### Async Rule with Context
* ```typescript
* interface MyContext {
* userId: number;
* permissions: string[];
* }
*
* const result = await Validator.validate<MyContext>({
* value: "admin_action",
* rules: ["Required", "UniqueAction"],
* context: {
* userId: 123,
* permissions: ["admin"],
* },
* });
* ```
*
* #### Nullable Rule Examples
* ```typescript
* // Null is valid with Nullable rule
* const result1 = await Validator.validate({
* value: null,
* rules: ["Nullable", "Required"],
* });
* // result1.success === true (skips Required check)
*
* // Empty string is valid with Empty rule
* const result2 = await Validator.validate({
* value: "",
* rules: ["Empty", "Email"],
* });
* // result2.success === true (skips Email check)
*
* // Undefined is valid with Optional rule
* const result3 = await Validator.validate({
* value: undefined,
* rules: ["Optional", "MinLength[5]"],
* });
* // result3.success === true (skips MinLength check)
* ```
*
* #### Type Guards for Result Narrowing
* ```typescript
* const result = await Validator.validate({
* value: "test",
* rules: ["Required"],
* });
*
* // Using type guards
* if (Validator.isSuccess(result)) {
* // TypeScript knows result.success === true
* console.log("Valid value:", result.value);
* } else if (Validator.isFailure(result)) {
* // TypeScript knows result.success === false
* console.error("Error:", result.error.message);
* }
* ```
*
* @template Context - Optional type for the validation context object
*
* @param options - Validation options (IMakeOptional<
IValidatorValidateOptions<Array<any>, Context>,
"i18n"
>)
* @param options.value - The value to validate (required)
* @param options.rules - Array of validation rules to apply
* @param options.context - Optional context object passed to rule functions
* @param options.data - Optional data object for rule context
* @param options.fieldName - Optional field identifier for error messages
* @param options.propertyName - Optional property identifier for error messages
* @param options.translatedPropertyName - Optional translated property name
* @param options.message - Optional custom error message prefix
*
* @returns Promise resolving to IValidatorValidateResult<Context>
* - Success: object with success=true, value, validatedAt, duration
* - Failure: object with success=false, error, failedAt, duration
*
* @throws {Never} This method never throws. All errors are returned in the result object.
*
* @since 1.0.0
* @see {@link validateTarget} - For class-based validation using decorators
* @see {@link registerRule} - To register custom validation rules
* @see {@link IValidatorValidateResult} - Result type documentation
* @see {@link IValidatorValidationError} - Error details type
*
* @public
* @async
*/
static validate<Context = unknown>({ rules, ...extra }: IMakeOptional<IValidatorValidateOptions<Array<any>, Context>, "i18n">): Promise<IValidatorValidateResult<Context>>;
/**
* ## Should Skip Validation
*
* Determines whether validation should be skipped based on the presence of nullable rules
* and the current value. This method checks if the value meets the conditions for
* skipping validation when nullable rules like Empty, Nullable, or Optional are present
* in the rules array.
*
* ### Nullable Rules and Conditions
* - **Empty**: Skips validation if value is an empty string ""
* - **Nullable**: Skips validation if value is null or undefined
* - **Optional**: Skips validation if value is undefined
*
* ### Logic
* 1. Only checks when the value is considered "empty" (using isEmpty utility)
* 2. Iterates through the rules array to find matching nullable rule names
* 3. Supports both string rules ("Empty") and object rules ({ Empty: [] })
* 4. Returns true if any matching nullable rule condition is met
* 5. Function rules are ignored in this check
*
* @param options - The options object containing value and rules
* @param options.value - The value to check for nullable conditions
* @param options.rules - The array of validation rules to inspect for nullable rules
*
* @returns `true` if validation should be skipped due to nullable conditions, `false` otherwise
*
* @since 1.0.0
* @see {@link validate} - Uses this method to conditionally skip validation
* @see {@link validateTarget} - Also uses this method for class-based validation
* @public
*/
static shouldSkipValidation({ value, rules }: {
rules: Array<IValidatorRuleName> | IValidatorSanitizedRules<any>;
value: any;
}): boolean;
/**
* ## Validate OneOf Rule
*
* Wrapper that applies OR logic across multiple sub-rules. Delegates to
* {@link validateMultiRule} with `"OneOf"`. Succeeds on the first passing
* sub-rule (early exit). If all sub-rules fail, returns a single error string
* aggregating each sub-rule’s message joined by `; `.
*
* @template Context - Optional type for validation context
* @template RulesFunctions - Array of sub-rules to evaluate
* @param options - Multi-rule validation options
* @returns `IValidatorResult` (`Promise<boolean|string>`)
* @example
* const res = await Validator.validateOneOfRule({
* value: "user@example.com",
* ruleParams: ["Email", "PhoneNumber"],
* });
* // res === true when any sub-rule succeeds
* @since 1.35.0
* @see {@link validateMultiRule}
*/
static validateOneOfRule<Context = unknown, RulesFunctions extends IValidatorDefaultMultiRule<Context> = IValidatorDefaultMultiRule<Context>>(options: IValidatorValidateMultiRuleOptions<Context, RulesFunctions>): IValidatorResult;
/**
* ## Validate AllOf Rule
*
* Wrapper that applies AND logic across multiple sub-rules. Delegates to
* {@link validateMultiRule} with `"AllOf"`. Succeeds only if all sub-rules
* pass. When any sub-rule fails, returns a single aggregated error string
* joining messages with `; `.
*
* @template Context - Optional type for validation context
* @template RulesFunctions - Array of sub-rules to evaluate
* @param options - Multi-rule validation options
* @returns `IValidatorResult` (`Promise<boolean|string>`)
* @example
* const res = await Validator.validateAllOfRule({
* value: "hello",
* ruleParams: ["String", { MinLength: [5] }],
* });
* // res === true only if all sub-rules succeed
* @since 1.35.0
* @see {@link validateMultiRule}
*/
static validateAllOfRule<Context = unknown, RulesFunctions extends IValidatorDefaultMultiRule<Context> = IValidatorDefaultMultiRule<Context>>(options: IValidatorValidateMultiRuleOptions<Context, RulesFunctions>): IValidatorResult;
/**
* ## Validate ArrayOf Rule
*
* Validates that a value is an array and that each item in the array
* satisfies all of the provided sub-rules (AND logic per item).
*
* - Ensures `value` is an array; otherwise returns the localized `array` error.
* - Applies {@link validateMultiRule} with `"AllOf"` to each item using the provided `ruleParams`.
* - Aggregates failing item messages; returns `true` when all items pass.
* - When any items fail, returns a localized summary using `failedForNItems`
* followed by concatenated item error messages.
*
* @template Context - Optional type for validation context
* @template RulesFunctions - Array of sub-rules applied to each item
* @param options - Multi-rule validation options
* @returns `IValidatorResult` (`Promise<boolean|string>`) - `true` if all items pass; otherwise an aggregated error string
* @example
* const res = await Validator.validateArrayOfRule({
* value: ["user@example.com", "admin@example.com"],
* ruleParams: ["Email"],
* });
* // res === true when every item is a valid email
* @since 1.36.0
*/
static validateArrayOfRule<Context = unknown, RulesFunctions extends IValidatorDefaultMultiRule<Context> = IValidatorDefaultMultiRule<Context>>(options: IValidatorValidateMultiRuleOptions<Context, RulesFunctions>): Promise<boolean | string>;
static getI18nTranslateOptions({ fieldName, propertyName, fieldLabel, translatedPropertyName, context, data, ...rest }: Partial<IValidatorValidateOptions<Array<any>, any>>): Partial<IValidatorValidateOptions<any[], any>>;
/**
* ## Validate Nested Rule (Core Nested Validation Executor)
*
* Internal rule function that validates a nested object against a class constructor with
* validation decorators. This method is the workhorse for nested class validation, delegating
* to {@link validateTarget} for the actual multi-field validation logic.
*
* ### Purpose
* This method implements the core logic for the `ValidateNested` rule, enabling validation of
* complex hierarchical object structures where a property value must itself be validated against
* a decorated class schema. It acts as the bridge between single-value rule validation and
* multi-field class-based validation.
*
* ### Validation Flow
* 1. **Parameter Extraction**: Extracts the target class constructor from `ruleParams[0]`
* 2. **Validation**: Calls `validateTarget()` to validate the nested object against the class
* 3. **Error Aggregation**: Collects nested validation errors with property path information
* 4. **Result Formatting**: Returns either `true` (success) or error message string (failure)
*
* ### Error Handling Strategy
* - **Missing Class Constructor**: Returns invalidRule error if no target class provided
* - **Invalid Data Type**: Returns validateNested error if data is not an object
* - **Nested Validation Failures**: Aggregates all nested field errors with property names in format:
* `"[propertyName]: error message; [propertyName]: error message"`
* - **Successful Validation**: Returns `true` without modification
*
* ### Type Parameters
* - `Target` - Class constructor extending IClassConstructor with validation decorators
* - `Context` - Optional validation context type passed through nested validations
*
* ### Return Values
* - `true` - Nested object validation succeeded
* - `string` - Validation failed; returns i18n-formatted error message with nested error details
*
* ### Usage Context
* This method is primarily used as:
* - The internal handler for the `validateNested` factory function
* - A sub-rule within multi-rule validators (OneOf, AllOf)
* - Direct validator for nested object properties in class-based validation
*
* ### Example
* ```typescript
* class Address {
* @IsRequired
* @MinLength([5])
* street: string;
*
* @IsRequired
* @IsPostalCode
* postalCode: string;
* }
*
* class User {
* @IsRequired
* name: string;
*
* @ValidateNested([Address])
* address: Address;
* }
*
* // When validating a User instance with an Address property,
* // validateNestedRule is called to validate the address against the Address class
* const result = await Validator.validateTarget(User, {
* data : {
* name: "John",
* address: { street: "123 Main St", postalCode: "12345" }
* }});
* ```
*
* ### Key Features
* - **DRY Principle**: Reuses existing `validateTarget` logic to avoid code duplication
* - **Error Context**: Preserves field hierarchy information in error messages
* - **i18n Integration**: Uses translation system for localized error messages
* - **Context Propagation**: Passes validation context through to nested validators
* - **Timing Tracking**: Maintains duration tracking across nested validations
*
* @template Target - Class constructor type (must extend IClassConstructor)
* @template Context - Optional validation context type
*
* @param options - Validation rule function options (IValidatorNestedRuleFunctionOptions<Target, Context>)
* @param options.ruleParams - Array containing the nested class constructor at index [0]
* @param options.value - The nested object value to validate (extracted to data property)
* @param options.data - The nested object data to validate against the target class
* @param options.context - Optional validation context passed to all validation rules
* @param options.fieldName - Optional field identifier for error messages
* @param options.propertyName - Optional property identifier for error messages
* @param options.translatedPropertyName - Optional i18n property name for error messages
* @param options.startTime - Optional timestamp for duration tracking
* @param options.i18n - Optional i18n instance for error message translation
*
* @returns Promise<boolean | string>
* - Resolves to `true` if nested object validation succeeds
* - Resolves to error message string if validation fails
* - Never rejects; all errors are returned as resolution values
* - Error messages include nested field paths: `"[fieldName]: error; [fieldName]: error"`
*
* @throws {Never} This method never throws errors; all failures are returned as strings
*
* @remarks
* - This is an internal method primarily used by the `validateNested` factory
* - Accepts IValidatorNestedRuleFunctionOptions which omits validateTarget's i18n parameter
* - Delegates directly to validateTarget(target, options) maintaining all context
* - Nested validation errors include property names for clear error tracing
* - The method integrates seamlessly with the multi-rule validation system
* - Supports recursive nesting of arbitrarily deep object structures
* - Performance: Delegates to validateTarget which validates fields in parallel
* - Error aggregation uses nested field paths for hierarchical clarity
*
* @since 1.36.0
* @see {@link validateNested} - Factory function that creates rule functions using this method
* @see {@link validateTarget} - The underlying class-based validation method (accepts options with data)
* @see {@link ValidateNested} - Decorator that uses this method via the factory
* @see {@link IValidatorNestedRuleFunctionOptions} - Options interface for this method
* @see {@link buildMultiRuleDecorator} - Decorator builder for complex multi-rule scenarios
* @internal
* @async
*/
static validateNestedRule<Target extends IClassConstructor = IClassConstructor, Context = unknown>({ ruleParams, ...options }: IValidatorNestedRuleFunctionOptions<Target, Context>): Promise<boolean | string>;
/**
* ## Validate Multi-Rule (OneOf / AllOf)
*
* Evaluates multiple sub-rules against a single value using either OR logic (`OneOf`) or
* AND logic (`AllOf`). Each sub-rule is validated in sequence via {@link Validator.validate},
* with early exit on success for `OneOf` and full aggregation of errors for `AllOf`.
*
* ### Behavior
* - `OneOf`: Returns `true` as soon as any sub-rule succeeds (early exit). If all sub-rules fail,
* returns a concatenated error message string summarizing each failure.
* - `AllOf`: Requires every sub-rule to succeed. If any sub-rule fails, returns a concatenated
* error message string summarizing all failures; otherwise returns `true`.
* - Empty `ruleParams`: If no sub-rules are provided, returns `true`.
*
* ### Execution Notes
* - Sub-rules are evaluated sequentially (not in parallel) to allow early exit optimization for `OneOf`.
* - Error messages from failed sub-rules are collected and joined using `; ` as a separator.
* - Internationalization: Uses `i18n` (if provided) to prefix the aggregated error message
* with the localized rule label (`validator.OneOf` or `validator.AllOf`).
* - Timing: Initializes `startTime` when absent to enable duration tracking downstream.
*
* @template Context - Optional type for the validation context object
* @template RulesFunctions - Array type of sub-rules; each sub-rule can be a named rule,
* parameterized rule object, or a rule function
*
* @param ruleName - Multi-rule mode to apply: `"OneOf"` or `"AllOf"`
* @param options - Validation options extending {@link IValidatorValidateMultiRuleOptions}
* @param options.value - The value to validate against the sub-rules
* @param options.ruleParams - Array of sub-rules to evaluate (functions or named/object rules)
* @param options.context - Optional context passed through to each sub-rule
* @param options.data - Optional auxiliary data passed through to each sub-rule
* @param options.startTime - Optional start timestamp used for duration tracking
* @param options.fieldName - Optional field identifier used in error construction
* @param options.propertyName - Optional property identifier used in error construction
* @param options.translatedPropertyName - Optional localized property name for error messages
* @param options.i18n - Optional i18n instance used to localize the error label
*
* @returns IValidatorResult
* - `true` when validation succeeds (any sub-rule for `OneOf`, all sub-rules for `AllOf`)
* - `string` containing aggregated error messages when validation fails
*
* @example
* // OneOf: either email or phone must be valid
* const resultOneOf = await Validator.validateOneOfRule({
* value: "user@example.com",
* ruleParams: ["Email", "PhoneNumber"],
* });
* // resultOneOf === true
*
* @example
* // AllOf: must be a string and minimum length 5
* const resultAllOf = await Validator.validateAllOfRule({
* value: "hello",
* ruleParams: ["String", { MinLength: [5] }],
* });
* // resultAllOf === true
*
* @since 1.35.0
* @see {@link validateOneOfRule} - Convenience wrapper applying `OneOf` logic
* @see {@link validateAllOfRule} - Convenience wrapper applying `AllOf` logic
* @see {@link oneOf} - Factory to build a reusable `OneOf` rule function
* @see {@link allOf} - Factory to build a reusable `AllOf` rule function
* @see {@link validate} - Underlying validator used for each sub-rule
* @public
* @async
*/
static validateMultiRule<Context = unknown, RulesFunctions extends IValidatorDefaultMultiRule<Context> = IValidatorDefaultMultiRule<Context>>(ruleName: IValidatorMultiRuleNames, { value, ruleParams, startTime, ...extra }: IValidatorValidateMultiRuleOptions<Context, RulesFunctions>): Promise<string | true>;
/**
* ## Create OneOf Validation Rule
*
* Factory method that creates a OneOf validation rule function. This method provides
* a programmatic way to create validation rules that implement OR logic, where
* validation succeeds if at least one of the specified sub-rules passes.
*
* ### OneOf Validation Concept
* OneOf validation allows flexible validation scenarios where multiple validation
* paths are acceptable. Instead of requiring all rules to pass (AND logic),
* OneOf requires only one rule to pass (OR logic), making it ideal for:
* - Alternative input formats (email OR phone number)
* - Flexible validation requirements
* - Multiple acceptable validation criteria
*
* ### Method Behavior
* This factory method returns a validation rule function that can be used directly
* in validation calls or registered as a named rule. The returned function delegates
* to `validateOneOfRule` for the actual validation logic.
*
* ### Parallel Execution
* When the returned rule function is executed, all sub-rules are validated in parallel
* usi