@decaf-ts/decorator-validation
Version:
simple decorator based validation engine
119 lines (118 loc) • 5.2 kB
TypeScript
import { ValidatorOptions } from "../types";
import type { PathProxy } from "../../utils";
import type { ConditionalAsync } from "../../types";
/**
* @description Abstract base class for all validators in the validation framework.
* @summary The BaseValidator class provides the foundation for all synchronous and asynchronous validator implementations.
* It handles type checking, error message formatting, and defines the interface that all validators must implement.
* This class is designed to be extended by specific validator classes that define their own validation logic.
*
* @template V - Validator options type
* @template IsAsync - Whether the validator is async (true) or sync (false). Default `false`.
*
* @param {boolean} async - Defines if the validator is async (must match the subclass signature)
* @param {string} message - Default error message to display when validation fails (defaults to {@link DEFAULT_ERROR_MESSAGES#DEFAULT})
* @param {string[]} acceptedTypes - Type names that this validator accepts (used for runtime type checking)
*
* @class BaseValidator
* @abstract
*
* @example
* // Example of a synchronous validator
* class SyncValidator extends BaseValidator<SomeOptions, false> {
* constructor() {
* super(false, "Sync validation failed", String.name);
* }
*
* public hasErrors(value: any, options?: SomeOptions): string | undefined {
* if (typeof value !== "string") return this.getMessage(this.message);
* return undefined;
* }
* }
*
* @example
* // Example of an asynchronous custom validator
* class AsyncValidator extends BaseValidator<SomeOptions, true> {
* constructor() {
* super(true, "Async validation failed", String.name);
* }
*
* public async hasErrors(value: any, options?: SomeOptions): Promise<string | undefined> {
* const result = await someAsyncCheck(value);
* if (!result) return this.getMessage(this.message);
* return undefined;
* }
* }
*
* @mermaid
* sequenceDiagram
* participant C as Client
* participant V as Validator Subclass
* participant B as BaseValidator
*
* C->>V: new CustomValidator(async, message)
* V->>B: super(async, message, acceptedTypes)
* B->>B: Store message, async flag, and accepted types
* B->>B: Optionally wrap hasErrors with type checking
* C->>V: hasErrors(value, options)
* alt value type not in acceptedTypes
* B-->>C: Type error message
* else value type is accepted
* V->>V: Custom validation logic
* V-->>C: Validation result
* end
*
* @category Validators
*/
export declare abstract class BaseValidator<V extends ValidatorOptions = ValidatorOptions, Async extends boolean = false> {
readonly message: string;
readonly acceptedTypes?: string[];
readonly async?: Async;
protected constructor(async: Async, message?: string, ...acceptedTypes: string[]);
/**
* @description Formats an error message with optional arguments
* @summary Creates a formatted error message by replacing placeholders with provided arguments.
* This method uses the string formatting utility to generate consistent error messages
* across all validators.
*
* @param {string} message - The message template with placeholders
* @param {...any} args - Values to insert into the message template
* @return {string} The formatted error message
* @protected
*/
protected getMessage(message: string, ...args: any[]): string;
/**
* @description Creates a type-checking wrapper around the hasErrors method
* @summary Wraps the hasErrors method with type validation logic to ensure that
* the value being validated is of an accepted type before performing specific validation.
* This method is called during construction if acceptedTypes are provided.
*
* @param {Function} unbound - The original hasErrors method to be wrapped
* @return {Function} A new function that performs type checking before calling the original method
* @private
*/
private checkTypeAndHasErrors;
/**
* @description Validates a value against specific validation rules
* @summary Abstract method that must be implemented by all validator subclasses.
* This method contains the core validation logic that determines whether a value
* is valid according to the specific rules of the validator. If the value is valid,
* the method returns undefined; otherwise, it returns an error message.
*
* @template V - Type of the options object that can be passed to the validator
* @param {any} value - The value to validate
* @param {V} [options] - Optional configuration options for customizing validation behavior
* @param {PathProxy<any>} proxy -
* @return {string | undefined} Error message if validation fails, undefined if validation passes
*
* @abstract
*
* @see Model#validate
*/
abstract hasErrors(value: any, options?: V, proxy?: PathProxy<any>): ConditionalAsync<Async, string | undefined>;
/**
* @summary Duck typing for Validators
* @param val
*/
static isValidator(val: any): boolean;
}