import { Entity } from "./EntityManager" ; import { getEm , Loaded , LoadHint , RelationsIn } from "./index" ; import { AbstractRelationImpl } from "./relations/AbstractRelationImpl" ; import { MaybePromise , ValidationRule } from "./rules" ; export type EntityHook = "beforeFlush" | "beforeCreate" | "beforeUpdate" | "beforeDelete" | "afterValidation" | "afterCommit" ; type HookFn < T extends Entity , C > = ( entity : T , ctx : C ) => MaybePromise < void > ; /** The public API to configure an Entity's hooks & validation rules. */ export class ConfigApi < T extends Entity , C > { __data = new ConfigData < T , C > ( ) ; addRule < H extends LoadHint < T > > ( populate , rule ) ; addRule ( rule ) ; addRule ( ruleOrHint , maybeRule ? ) { if ( typeof ruleOrHint === "function" ) { this . __data . rules . push ( ruleOrHint ) ; } else { const fn = async ( entity ) => { const em = getEm ( entity ) ; const loaded = await em . populate ( entity , ruleOrHint ) ; return maybeRule ! ( loaded ) ; } ; ( fn as any ) . hint = ruleOrHint ; this . __data . rules . push ( fn ) ; } } cascadeDelete ( relationship ) { this . __data . cascadeDeleteFields . push ( relationship ) ; this . beforeDelete ( relationship , ( entity ) => { const relation = entity [ relationship ] as any as AbstractRelationImpl < any > ; relation . maybeCascadeDelete ( ) ; } ) ; } /** Registers `fn` as the lambda to provide the async value for `key`. */ setAsyncDerivedField < P extends keyof T , H extends LoadHint < T > > ( key , populate , fn ) { this . __data . asyncDerivedFields [ key ] = [ populate , fn as any ] ; } private addHook ( hook , ruleOrHint , maybeFn ? ) { if ( typeof ruleOrHint === "function" ) { this . __data . hooks [ hook ] . push ( ruleOrHint ) ; } else { const fn = async ( entity , ctx ) => { const em = getEm ( entity ) ; const loaded = await em . populate ( entity , ruleOrHint ) ; return maybeFn ! ( loaded , ctx ) ; } ; ( fn as any ) . hint = ruleOrHint ; this . __data . hooks [ hook ] . push ( fn ) ; } } beforeDelete < H extends LoadHint < T > > ( populate , fn ) ; beforeDelete ( fn ) ; beforeDelete ( ruleOrHint , maybeFn ? ) { this . addHook ( "beforeDelete" , ruleOrHint , maybeFn ) ; } beforeFlush < H extends LoadHint < T > > ( populate , fn ) ; beforeFlush ( fn ) ; beforeFlush ( ruleOrHint , maybeFn ? ) { this . addHook ( "beforeFlush" , ruleOrHint , maybeFn ) ; } beforeCreate < H extends LoadHint < T > > ( populate , fn ) ; beforeCreate ( fn ) ; beforeCreate ( ruleOrHint , maybeFn ? ) { this . addHook ( "beforeCreate" , ruleOrHint , maybeFn ) ; } beforeUpdate < H extends LoadHint < T > > ( populate , fn ) ; beforeUpdate ( fn ) ; beforeUpdate ( ruleOrHint , maybeFn ? ) { this . addHook ( "beforeUpdate" , ruleOrHint , maybeFn ) ; } afterValidation < H extends LoadHint < T > > ( populate , fn ) ; afterValidation ( fn ) ; afterValidation ( ruleOrHint , maybeFn ? ) { this . addHook ( "afterValidation" , ruleOrHint , maybeFn ) ; } afterCommit ( fn ) { this . addHook ( "afterCommit" , fn ) ; } } /** The internal state of an entity's configuration data, i.e. validation rules/hooks. */ export class ConfigData < T extends Entity , C > { /** The validation rules for this entity type. */ rules : ValidationRule < T > [ ] = [ ] ; /** The async derived fields for this entity type. */ asyncDerivedFields : Partial < Record < keyof T , [ LoadHint < T > , ( entity : T ) => any ] > > = { } ; /** The hooks for this instance. */ hooks : Record < EntityHook , HookFn < T , C > [ ] > = { beforeDelete : [ ] , beforeFlush : [ ] , beforeCreate : [ ] , beforeUpdate : [ ] , afterCommit : [ ] , afterValidation : [ ] , } ; reactiveRules : string [ ] [ ] = [ ] ; reactiveDerivedValues : string [ ] [ ] = [ ] ; cascadeDeleteFields : Array < keyof RelationsIn < T > > = [ ] ; }