import { CustomResolver , HandlerRegistrations , HandlerRegistry , HandlerResolver , MessageName } from './handler-registry' ; import { HandlerAlreadyRegistered , SystemMessageMissingResolver } from './error' ; import { Handler , HandlerDefinition , isClassHandler , MessageBase } from './handler' ; import { ClassConstructor } from '../util' ; import { Message } from '@node-ts/bus-messages' ; import { LoggerFactory } from '../logger' ; export class DefaultHandlerRegistry implements HandlerRegistry { private registry : HandlerRegistrations = { } ; private unhandledMessages : MessageName [ ] = [ ] ; private handlerResolvers : HandlerResolver [ ] = [ ] ; registerCustom < TMessage extends MessageBase > ( handler , customResolver ) { this . handlerResolvers . push ( { handler , messageType : undefined , resolver : customResolver . resolveWith , topicIdentifier : customResolver . topicIdentifier } ) ; } register < TMessage extends MessageBase > ( messageType , handler ) { const message = new messageType ( ) ; if ( ! ( '$name' in message ) ) { throw new SystemMessageMissingResolver ( messageType ) ; } const messageName = message . $name ; if ( ! this . registry [ messageName ] ) { this . registry [ messageName ] = { messageType , handlers : [ ] } ; } const handlerNameAlreadyRegistered = this . registry [ messageName ] . handlers . some ( registeredHandler => registeredHandler === handler ) ; if ( handlerNameAlreadyRegistered ) { throw new HandlerAlreadyRegistered ( handler . name ) ; } this . registry [ messageName ] . handlers . push ( handler ) ; } get < MessageType extends MessageBase > ( loggerFactory , message ) { const logger = loggerFactory ( '@node-ts/bus-core:handler-registry' ) ; logger . debug ( 'Getting handlers for message' , { msg : message } ) ; const customHandlers = this . resolveCustomHandlers ( message ) ; const messageName = '$name' in message ? message . $name : undefined ; const noHandlersForMessage = ! customHandlers . length && ( ! messageName || ! ( messageName in this . registry ) ) ; if ( noHandlersForMessage ) { const warnNoHandlersForMessageType = messageName && ! this . unhandledMessages . some ( m => m === messageName ) ; if ( warnNoHandlersForMessageType ) { this . unhandledMessages . push ( messageName ! ) ; logger . error ( `No handlers were registered for message` , { messageName , help : `This could mean that either the handlers haven't been registered with bootstrap.registerHandler(),` + ` or that the underlying transport is subscribed to messages that aren't handled and should be removed.` } ) ; } logger . debug ( 'No handlers found for message' , { msg : message } ) ; return [ ] ; } const messageHandlers = messageName && this . registry [ messageName ] ? this . registry [ messageName ] . handlers : [ ] ; logger . debug ( 'Found handlers for message' , { msg : message , numMessageHandlers : messageHandlers . length , numCustomHandlers : customHandlers . length } ) ; const result = [ ... messageHandlers , ... customHandlers ] ; return result as HandlerDefinition < MessageType > [ ] ; } getMessageNames ( ) { return Object . keys ( this . registry ) ; } getMessageConstructor < T extends Message > ( messageName ) { if ( ! ( messageName in this . registry ) ) { return undefined ; } return this . registry [ messageName ] . messageType as ClassConstructor < T > ; } getExternallyManagedTopicIdentifiers ( ) { return this . handlerResolvers . map ( resolver => resolver . topicIdentifier ) . filter ( topicArn => ! ! topicArn ) as string [ ] ; } getResolvers ( ) { return this . handlerResolvers ; } reset ( ) { this . registry = { } ; } getClassHandlers ( ) { const customHandlers = this . handlerResolvers . map ( handlerResolver => handlerResolver . handler ) . filter ( isClassHandler ) as unknown as Handler [ ] ; const regularHandlers = Object . values ( this . registry ) . map ( h => h . handlers ) . flat ( ) . filter ( isClassHandler ) as unknown as Handler [ ] ; return [ ... customHandlers , ... regularHandlers ] ; } param message node-ts private resolveCustomHandlers < MessageType extends MessageBase > ( message ) { return this . handlerResolvers . filter ( handlerResolver => handlerResolver . resolver ( message ) ) . map ( handlerResolver => handlerResolver . handler ) as HandlerDefinition < MessageType > [ ] ; } }