import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { ReleaseIssuesRepository } from '../ports/release-issues.repository'; import { CommandResult, ack } from './command-result'; import { PublishReleaseCommand } from './publish-release.command'; import { WriteAccess } from './write-access'; @CommandHandler(PublishReleaseCommand) export class PublishReleaseCommandHandler implements ICommandHandler { constructor( private readonly access: WriteAccess, private readonly releaseIssues: ReleaseIssuesRepository, ) {} async execute(command: PublishReleaseCommand): Promise { const release = await this.access.release(command.releaseId); const project = await this.access.project(release.projectId); project.assertCanManage(command.actorId); const workflow = project.workflow; // Rebuilt from the event store (source of truth), not from the read model. const candidates = await this.releaseIssues.findIssueIds(release.id); const issues = await Promise.all( candidates.map((id) => this.access.issue(id)), ); const unfinished = issues.filter( (issue) => issue.releaseId === release.id && !workflow.isFinished(issue.status), ).length; release.ship(command.actorId, unfinished, command.force); await release.commitAndWait(); return ack(release); } }