octonom
Version:
Object Document Mapper for any database
81 lines (66 loc) • 2.42 kB
text/typescript
import { ValidationError } from '../errors';
export interface ISanitizeOptions {
/** Set undefined values to defaults (if configured). Default is false. */
defaults?: boolean;
/** Unset all properties that are not provided in the data. Default is false. */
replace?: boolean;
/** Parent schema node */
parent?: ISchemaParent;
}
export interface ISchema<
T,
TSchemaInstance extends ISchemaInstance<T>,
TToObject = any,
> {
options: ISchemaOptions<TSchemaInstance>;
create(value: any, sanitizeOptions?: ISanitizeOptions): TSchemaInstance;
populate?(instance: TSchemaInstance, populateReference: PopulateReference): Promise<T>;
toObject(instance: TSchemaInstance, toObjectOptions?: IToObjectOptions): TToObject;
validate(instance: TSchemaInstance): Promise<void>;
}
export interface ISchemaInstance<T = any> {
parent?: ISchemaParent;
schema: ISchema<T, ISchemaInstance<T>>;
value: T;
}
export interface ISchemaOptions<TSchemaInstance extends ISchemaInstance<any>> {
required?: boolean;
validate?(instance: TSchemaInstance): Promise<void>;
}
export interface ISchemaParent<T = any> {
instance: ISchemaParentInstance<T>;
path: string | number;
}
export interface ISchemaParentInstance<T = any> extends ISchemaInstance<T> {
beforeChange(path: Path, rawValue: any, oldInstance: ISchemaInstance<T>);
afterChange(path: Path, rawValue: any, newInstance: ISchemaInstance<T>);
}
export interface IToObjectOptions {
/** Turn populated references into references */
unpopulate?: boolean;
}
export type Path = Array<string | number>;
export type PopulateMap<T extends object = object> = {
[key in keyof T]?: PopulateReference;
};
export type PopulateReference<T extends object = object> = PopulateMap<T> | true;
export type SchemaInstanceMap<T extends object = object> = {[key in keyof T]?: ISchemaInstance};
export type SchemaMap<T extends object = object> = {[key in keyof T]: ISchema<any, any>};
export async function validate<TSchemaInstance extends ISchemaInstance>(
schemaOptions: ISchemaOptions<TSchemaInstance>,
instance: TSchemaInstance,
): Promise<void> {
if (!schemaOptions.validate) {
return;
}
try {
await schemaOptions.validate(instance);
} catch (error) {
if (error instanceof ValidationError) {
error.reason = error.reason || 'custom';
error.parent = instance.parent;
throw error;
}
throw error;
}
}