import { NEST_EVENT_ON , NEST_EVENT_EMITTER , NEST_EVENT_FROM } from './constants' ; import { EventEmitter } from 'events' ; import { DiscoveryService , DiscoveredClassWithMeta , DiscoveredMethodWithMeta , DiscoveredClass } from '@nestjs-plus/discovery' ; import { Injectable } from '@nestjs/common' ; @ Injectable ( ) export class NestEvent { private emitters : Map < string , EventEmitter > ; constructor ( private readonly discovery ) { } public async configure ( ) { this . emitters = await this . findEmitters ( ) ; await this . setEventListeners ( ) ; } public getEmitters ( ) { return this . emitters ; } private async findEmitters ( ) { const discoveredEmitters = await this . discovery . providersWithMetaAtKey < string > ( NEST_EVENT_EMITTER ) ; const defaultEmitter = discoveredEmitters . find ( ( item ) => item . meta === 'default' ) ; const emitters = new Map < string , EventEmitter > ( discoveredEmitters . map ( ( item ) => [ item . meta , item . discoveredClass . instance as EventEmitter ] ) ) ; if ( ! defaultEmitter ) { emitters . set ( 'default' , new EventEmitter ( ) ) ; } return emitters ; } private async getMethodEmitters ( ) { const methodEmitters = await this . findFromControllersAndProviders ( NEST_EVENT_FROM ) ; return new Map < string , EventEmitter > ( methodEmitters . map ( ( m ) => [ `${ m . discoveredMethod . parentClass . name }.${ m . discoveredMethod . methodName }` , this . emitters . get ( m . meta ) , ] ) ) ; } private async setEventListeners ( ) { const methodEmitters = await this . getMethodEmitters ( ) ; const methods = await this . findFromControllersAndProviders ( NEST_EVENT_ON ) ; methods . forEach ( ( m ) => { const eventName = m . meta ; const discoveredClass = m . discoveredMethod . parentClass ; const methodName = m . discoveredMethod . methodName ; const methodKey = `${ discoveredClass . name }.${ methodName }` ; const method = discoveredClass . instance [ methodName ] . bind ( discoveredClass . instance ) ; if ( methodEmitters . has ( methodKey ) ) { const emiterInstance = methodEmitters . get ( methodKey ) ; if ( emiterInstance ) { emiterInstance . on ( eventName , method ) ; } return ; } const emitter = this . emitters . get ( 'default' ) ; if ( emitter ) { emitter . on ( eventName , method ) ; } } ) ; } private async findFromControllersAndProviders ( metaKey ) { const methodsFromControllers = await this . discovery . controllerMethodsWithMetaAtKey < string > ( metaKey ) ; const methodsFromProviders = await this . discovery . providerMethodsWithMetaAtKey < string > ( metaKey ) ; return [ ... methodsFromControllers , ... methodsFromProviders ] ; } }