import { Validator } from "./Validators/Validator";
import { IValidatorRegistry, ValidatorDefinition } from "./types";
import { ValidatorRegistry } from "./Validators/ValidatorRegistry";
import { ValidationKeys } from "./Validators/constants";
import { ModelKeys } from "../utils/index";
import { Metadata } from "@decaf-ts/decoration";
/**
* @summary Static class acting as a namespace for the Validation
*
* @class Validation
* @static
*
* @category Validation
*/
export class Validation {
private static actingValidatorRegistry?: IValidatorRegistry<Validator> =
undefined;
private constructor() {}
/**
* @summary Defines the acting ValidatorRegistry
*
* @param {IValidatorRegistry} validatorRegistry the new implementation of the validator Registry
* @param {function(Validator): Validator} [migrationHandler] the method to map the validator if required;
*/
static setRegistry(
validatorRegistry: IValidatorRegistry<Validator>,
migrationHandler?: (validator: Validator) => Validator
) {
if (migrationHandler && Validation.actingValidatorRegistry)
Validation.actingValidatorRegistry.getKeys().forEach((k: string) => {
const validator = validatorRegistry.get(k);
if (validator) validatorRegistry.register(migrationHandler(validator));
});
Validation.actingValidatorRegistry = validatorRegistry;
}
/**
* @summary Returns the current ValidatorRegistry
*
* @return IValidatorRegistry, defaults to {@link ValidatorRegistry}
*/
private static getRegistry() {
if (!Validation.actingValidatorRegistry)
Validation.actingValidatorRegistry = new ValidatorRegistry();
return Validation.actingValidatorRegistry;
}
/**
* @summary Retrieves a validator
*
* @param {string} validatorKey one of the {@link ValidationKeys}
* @return {Validator | undefined} the registered Validator or undefined if there is nono matching the provided key
*/
static get<T extends Validator>(validatorKey: string): T | undefined {
return Validation.getRegistry().get(validatorKey);
}
/**
* @summary Registers the provided validators onto the registry
*
* @param {T[] | ValidatorDefinition[]} validator
*/
static register<T extends Validator>(
...validator: (ValidatorDefinition | T)[]
): void {
return Validation.getRegistry().register(...validator);
}
/**
* @summary Builds the key to store as Metadata under Reflections
* @description concatenates {@link ValidationKeys#REFLECT} with the provided key
*
* @param {string} key
*/
static key(key: string) {
return ValidationKeys.REFLECT + key;
}
/**
* @summary Returns all registered validation keys
*/
static keys() {
return this.getRegistry().getKeys();
}
static registerDecorator(
key: string,
decorator: (...args: any[]) => PropertyDecorator
) {
const meta = Metadata["innerGet"](
Symbol.for(ModelKeys.DECORATORS),
Metadata.key(ValidationKeys.REFLECT, key)
) as Record<string, PropertyDecorator> | undefined;
if (meta?.[key]) return;
Metadata.set(
ModelKeys.DECORATORS,
Metadata.key(ValidationKeys.REFLECT, key),
decorator
);
}
static decoratorFromKey(key: string) {
try {
return Metadata["innerGet"](
Symbol.for(ModelKeys.DECORATORS),
Metadata.key(ValidationKeys.REFLECT, key)
);
} catch (e: unknown) {
throw new Error(`No decorator registered under ${key}: ${e}`);
}
}
}
Source