import { AggregateRoot, UniqueID } from '../entities'; import { IDomainEvent } from './DomainEventInterface'; export class DomainEvents { private static handlersMap: { [key: string]: any } = {}; private static markedAggregates: AggregateRoot[] = []; /** * @method markAggregateForDispatch * @static * @desc Called by aggregate root objects that have created domain * events to eventually be dispatched when the infrastructure commits * the unit of work. */ public static markAggregateForDispatch( aggregate: AggregateRoot ): void { const aggregateFound = !!this.findMarkedAggregateByID(aggregate.id); if (!aggregateFound) { this.markedAggregates.push(aggregate); } } private static dispatchAggregateEvents( aggregate: AggregateRoot ): void { aggregate.domainEvents.forEach((event: IDomainEvent) => this.dispatch(event) ); } private static removeAggregateFromMarkedDispatchList( aggregate: AggregateRoot ): void { const index = this.markedAggregates.findIndex((a) => a.equals(aggregate) ); this.markedAggregates.splice(index, 1); } private static findMarkedAggregateByID( id: UniqueID ): AggregateRoot | undefined { let found: AggregateRoot | undefined = undefined; for (const aggregate of this.markedAggregates) { if (aggregate.id.equals(id)) { found = aggregate; } } return found; } public static dispatchEventsForAggregate(id: UniqueID): void { const aggregate = this.findMarkedAggregateByID(id); if (aggregate) { this.dispatchAggregateEvents(aggregate); aggregate.clearEvents(); this.removeAggregateFromMarkedDispatchList(aggregate); } } public static register( callback: (event: IDomainEvent) => void, eventClassName: string ): void { if (!this.handlersMap.hasOwnProperty(eventClassName)) { this.handlersMap[eventClassName] = []; } this.handlersMap[eventClassName].push(callback); } public static clearHandlers(): void { this.handlersMap = {}; } public static clearMarkedAggregates(): void { this.markedAggregates = []; } private static dispatch(event: IDomainEvent): void { const eventClassName: string = event.constructor.name; if (this.handlersMap.hasOwnProperty(eventClassName)) { const handlers: any[] = this.handlersMap[eventClassName]; for (const handler of handlers) { handler(event); } } } }