import { EventsHandler, IEventHandler } from '@nestjs/cqrs'; import { SprintClosedEvent, SprintCreatedEvent, SprintDeletedEvent, SprintStartedEvent, SprintStatus, SprintUpdatedEvent, } from '@task-stream/api/tracker/domain'; import { UpsertMaterializedIssueRepository } from '../ports/upsert-materialized-issue.repository'; import { UpsertMaterializedSprintRepository } from '../ports/upsert-materialized-sprint.repository'; import { ReadModelNotifier, versionOf } from './read-model-notifier'; type SprintEvent = | SprintCreatedEvent | SprintUpdatedEvent | SprintStartedEvent | SprintClosedEvent | SprintDeletedEvent; /** The sprints view (`sprints_view`), one document per sprint. */ @EventsHandler( SprintCreatedEvent, SprintUpdatedEvent, SprintStartedEvent, SprintClosedEvent, SprintDeletedEvent, ) export class SprintEventHandler implements IEventHandler { constructor( private readonly sprints: UpsertMaterializedSprintRepository, private readonly issues: UpsertMaterializedIssueRepository, private readonly notifier: ReadModelNotifier, ) {} async handle(event: SprintEvent) { const version = versionOf(event); const id = event.aggregateId; if (event instanceof SprintCreatedEvent) { await this.sprints.upsert({ ...event.sprint, version }); } else if (event instanceof SprintUpdatedEvent) { await this.sprints.upsert({ id, ...event.changes, version }); // Tickets show its name. if (event.changes.name) await this.issues.renameSprint(id, event.changes.name); } else if (event instanceof SprintStartedEvent) { await this.sprints.upsert({ id, status: SprintStatus.ACTIVE, startedAt: event.occurredAt, version, }); } else if (event instanceof SprintClosedEvent) { await this.sprints.upsert({ id, status: SprintStatus.CLOSED, closedAt: event.occurredAt, version, }); } else { await this.sprints.remove(id); } await this.notifier.sprint(id, event); } }