import type { AnyEntity , EntityMetadata } from '../typings' ; import type { EventArgs , EventSubscriber , FlushEventArgs , TransactionEventArgs } from './EventSubscriber' ; import { Utils } from '../utils' ; import type { TransactionEventType } from '../enums' ; import { EventType } from '../enums' ; export class EventManager { private readonly listeners : Partial < Record < EventType , EventSubscriber [ ] > > = { } ; private readonly entities : Map < EventSubscriber , string [ ] > = new Map ( ) ; constructor ( subscribers ) { subscribers . forEach ( subscriber => this . registerSubscriber ( subscriber ) ) ; } registerSubscriber ( subscriber ) { this . entities . set ( subscriber , this . getSubscribedEntities ( subscriber ) ) ; Object . keys ( EventType ) . filter ( event => event in subscriber ) . forEach ( event => { this . listeners [ event ] = this . listeners [ event ] || [ ] ; this . listeners [ event ] . push ( subscriber ) ; } ) ; } dispatchEvent < T extends AnyEntity < T > > ( event , args ) ; dispatchEvent < T extends AnyEntity < T > > ( event , args ) ; dispatchEvent < T extends AnyEntity < T > > ( event , args ) ; dispatchEvent < T extends AnyEntity < T > > ( event , args ) { const listeners = [ ] ; const entity = ( args as EventArgs < T > ) . entity ; const hooks = ( entity && entity . __meta ! . hooks [ event ] ) || [ ] ; listeners . push ( ... hooks . map ( hook => [ hook , entity ] as [ EventType , EventSubscriber < T > ] ) ) ; for ( const listener of this . listeners [ event ] || [ ] ) { const entities = this . entities . get ( listener ) ! ; if ( entities . length === 0 || ! entity || entities . includes ( entity . constructor . name ) ) { listeners . push ( [ event , listener ] ) ; } } if ( event === EventType . onInit ) { return listeners . forEach ( listener => listener [ 1 ] [ listener [ 0 ] ] ! ( args as ( EventArgs < T > & FlushEventArgs & TransactionEventArgs ) ) ) ; } return Utils . runSerial ( listeners , listener => listener [ 1 ] [ listener [ 0 ] ] ! ( args as ( EventArgs < T > & FlushEventArgs & TransactionEventArgs ) ) as Promise < void > ) ; } hasListeners < T extends AnyEntity < T > > ( event , meta ) { const hasHooks = meta . hooks [ event ] ?. length ; if ( hasHooks ) { return true ; } for ( const listener of this . listeners [ event ] ?? [ ] ) { const entities = this . entities . get ( listener ) ! ; if ( entities . length === 0 || entities . includes ( meta . className ) ) { return true ; } } return false ; } private getSubscribedEntities ( listener ) { if ( ! listener . getSubscribedEntities ) { return [ ] ; } return listener . getSubscribedEntities ( ) . map ( name => Utils . className ( name ) ) ; } }