UNPKG

@decaf-ts/decorator-validation

Version:
125 lines 5.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseValidator = void 0; const constants_1 = require("./constants.cjs"); const strings_1 = require("./../../utils/strings.cjs"); const utils_1 = require("./utils.cjs"); /** * @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 */ class BaseValidator { constructor(async, message = constants_1.DEFAULT_ERROR_MESSAGES.DEFAULT, ...acceptedTypes) { this.async = async; this.message = message; if (acceptedTypes.length) this.acceptedTypes = acceptedTypes; if (this.acceptedTypes) this.hasErrors = this.checkTypeAndHasErrors(this.hasErrors.bind(this)); } /** * @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 */ getMessage(message, ...args) { return (0, strings_1.sf)(message, ...args); } /** * @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 */ checkTypeAndHasErrors(unbound) { return function (value, options, proxy, ...args) { if (value === undefined || !this.acceptedTypes) return unbound(value, options, proxy, ...args); if (!(0, utils_1.checkTypes)(value, this.acceptedTypes)) return this.getMessage(constants_1.DEFAULT_ERROR_MESSAGES.TYPE, this.acceptedTypes.join(", "), typeof value !== "number" ? typeof value : isNaN(value) ? "NaN" : typeof value); return unbound(value, options, proxy, ...args); }.bind(this); } /** * @summary Duck typing for Validators * @param val */ static isValidator(val) { return val.constructor && !!val["hasErrors"]; } } exports.BaseValidator = BaseValidator; //# sourceMappingURL=BaseValidator.js.map