octonom
Version:
Object Document Mapper for any database
58 lines (47 loc) • 1.83 kB
text/typescript
import { Model } from './model';
import { ISchemaInstance, Path } from './schema/schema';
/* Hook handlers are always called with instance set to the *unproxied*
* instance where the hook is registered
**/
export interface IChangeHookOptions<TModel extends Model> {
path: Path;
value: any;
modelInstance: TModel;
schemaInstance: ISchemaInstance;
}
export interface IChangeHooks<TModel extends Model = Model> {
beforeChange?(options: IChangeHookOptions<TModel>);
afterChange?(options: IChangeHookOptions<TModel>);
}
// union of all hook interfaces
export type IHooks<TModel extends Model = Model> = IChangeHooks<TModel>;
export interface IHookOptionsMap<TModel extends Model> {
beforeChange: IChangeHookOptions<TModel>;
afterChange: IChangeHookOptions<TModel>;
}
export type hookHandlers<TOptions> = Array<(options: TOptions) => void>;
export type HookHandlersMap<TModel extends Model> = {
[k in keyof IHookOptionsMap<TModel>]: hookHandlers<IHookOptionsMap<TModel>[k]>;
};
export class Hooks<TModel extends Model> {
private handlers: HookHandlersMap<TModel> = {
beforeChange: [],
afterChange: [],
};
constructor(hooks?: Hooks<TModel>) {
// copy hooks from passed Hooks instance
if (hooks) {
Object.keys(this.handlers).forEach(key => {
this.handlers[key] = hooks.handlers[key].slice();
});
}
}
public register<K extends keyof HookHandlersMap<TModel>>(name: K, handler: HookHandlersMap<TModel>[K][0]) {
const handlers = this.handlers[name] as Array<HookHandlersMap<TModel>[K][0]>;
handlers.push(handler);
}
public run<K extends keyof IHookOptionsMap<TModel>>(name: K, options: IHookOptionsMap<TModel>[K]) {
const handlers = this.handlers[name] as Array<HookHandlersMap<TModel>[K][0]>;
handlers.forEach(handler => handler(options));
}
}