@travetto/schema
Version:
Data type registry for runtime validation, reflection and binding.
65 lines (59 loc) • 2.09 kB
text/typescript
import { Any, castTo, Class, ClassInstance, DeepPartial } from '@travetto/runtime';
import { BindUtil } from '../bind-util';
import { SchemaRegistry } from '../service/registry';
import { ClassConfig, ViewFieldsConfig } from '../service/types';
import { MethodValidatorFn, ValidatorFn } from '../validate/types';
/**
* Register a class as a Schema
*
*
* @augments `@travetto/schema:Schema`
*/
export function Schema(cfg?: Partial<Pick<ClassConfig, 'subTypeName' | 'subTypeField' | 'baseType'>>) { // Auto is used during compilation
return <T, U extends Class<T>>(target: U): U => {
target.from ??= function <V>(this: Class<V>, data: DeepPartial<V>, view?: string): V {
return BindUtil.bindSchema(this, data, { view });
};
SchemaRegistry.register(target, cfg);
return target;
};
}
/**
* Add a custom validator, can be at the class level
*
* @param fn The validator function
*/
export const Validator = <T>(fn: ValidatorFn<T, string>) =>
(target: Class<T>, k?: string): void => {
SchemaRegistry.getOrCreatePending(target).validators!.push(castTo(fn));
};
/**
* Add a custom validator for a given method
*
* @param fn The validator function
*/
export function MethodValidator<T extends (...args: Any[]) => Any>(fn: MethodValidatorFn<Parameters<T>>) {
return (target: ClassInstance, k: string, prop: TypedPropertyDescriptor<T>): void => {
SchemaRegistry.registerPendingMethod(target.constructor, k).validators!.push(castTo(fn));
};
}
/**
* Register a specific view for a class
* @param name The name of the view
* @param fields The specific fields to add as part of a view
*/
export function View<T>(name: string, fields: ViewFieldsConfig<Partial<T>>) {
return (target: Class<Partial<T>>): void => {
SchemaRegistry.registerPendingView(target, name, fields);
};
}
/**
* Register a class as a subtype, with a specific discriminator
* @param name
* @returns
*/
export function SubType<T>(name: string) {
return (target: Class<Partial<T>>): void => {
SchemaRegistry.register(target, { subTypeName: name });
};
}