first commit
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
|
||||
import {
|
||||
ActivityReadModel,
|
||||
CommentAddedEvent,
|
||||
CommentDeletedEvent,
|
||||
CommentEditedEvent,
|
||||
IssueAssignedEvent,
|
||||
IssueCreatedEvent,
|
||||
IssueLinkedEvent,
|
||||
IssueReleaseChangedEvent,
|
||||
IssueStatusChangedEvent,
|
||||
IssueUnlinkedEvent,
|
||||
IssueUpdatedEvent,
|
||||
ProjectCreatedEvent,
|
||||
ProjectMemberAddedEvent,
|
||||
ProjectMemberRemovedEvent,
|
||||
ProjectMemberRoleChangedEvent,
|
||||
ProjectUpdatedEvent,
|
||||
ReleaseArchivedEvent,
|
||||
ReleaseCreatedEvent,
|
||||
ReleaseShippedEvent,
|
||||
ReleaseUpdatedEvent,
|
||||
TrackerEvent,
|
||||
} from '@task-stream/api/tracker/domain';
|
||||
import { ChangeFeed } from '../ports/change-feed';
|
||||
import { FindIssuesRepository } from '../ports/find-issues.repository';
|
||||
import { FindProjectsRepository } from '../ports/find-projects.repository';
|
||||
import { FindReleasesRepository } from '../ports/find-releases.repository';
|
||||
import { UpsertMaterializedActivityRepository } from '../ports/upsert-materialized-activity.repository';
|
||||
import { UserDirectory } from '../ports/user-directory';
|
||||
import { describeEvent } from './activity-summary';
|
||||
import { versionOf } from './read-model-notifier';
|
||||
|
||||
/** Project activity feed / ticket history: one entry per domain event. */
|
||||
@EventsHandler(
|
||||
ProjectCreatedEvent,
|
||||
ProjectUpdatedEvent,
|
||||
ProjectMemberAddedEvent,
|
||||
ProjectMemberRemovedEvent,
|
||||
ProjectMemberRoleChangedEvent,
|
||||
IssueCreatedEvent,
|
||||
IssueUpdatedEvent,
|
||||
IssueStatusChangedEvent,
|
||||
IssueAssignedEvent,
|
||||
IssueLinkedEvent,
|
||||
IssueUnlinkedEvent,
|
||||
IssueReleaseChangedEvent,
|
||||
CommentAddedEvent,
|
||||
CommentEditedEvent,
|
||||
CommentDeletedEvent,
|
||||
ReleaseCreatedEvent,
|
||||
ReleaseUpdatedEvent,
|
||||
ReleaseShippedEvent,
|
||||
ReleaseArchivedEvent,
|
||||
)
|
||||
export class ActivityEventHandler implements IEventHandler<TrackerEvent> {
|
||||
constructor(
|
||||
private readonly upsertMaterializedActivityRepository: UpsertMaterializedActivityRepository,
|
||||
private readonly findProjects: FindProjectsRepository,
|
||||
private readonly findIssues: FindIssuesRepository,
|
||||
private readonly findReleases: FindReleasesRepository,
|
||||
private readonly users: UserDirectory,
|
||||
private readonly changeFeed: ChangeFeed,
|
||||
) {}
|
||||
|
||||
async handle(event: TrackerEvent) {
|
||||
const issueId = this.issueIdOf(event);
|
||||
const issueKey =
|
||||
event instanceof IssueCreatedEvent
|
||||
? event.issue.key
|
||||
: issueId
|
||||
? ((await this.findIssues.findById(issueId))?.key ?? null)
|
||||
: null;
|
||||
const releaseId = this.releaseIdOf(event);
|
||||
const release = releaseId
|
||||
? await this.findReleases.findById(releaseId)
|
||||
: null;
|
||||
const project = await this.findProjects.findById(event.projectId);
|
||||
const mentioned = [
|
||||
event.actorId,
|
||||
(event as { userId?: string }).userId,
|
||||
(event as { assigneeId?: string }).assigneeId,
|
||||
];
|
||||
const users = await this.users.refs(mentioned);
|
||||
|
||||
const activity: ActivityReadModel = {
|
||||
id: `${event.aggregateId}:${versionOf(event)}`,
|
||||
type: event.constructor.name,
|
||||
projectId: event.projectId,
|
||||
issueId,
|
||||
issueKey,
|
||||
actor: users.of(event.actorId),
|
||||
summary: describeEvent(event, {
|
||||
actor: users.of(event.actorId).name,
|
||||
user: (id) => users.ofNullable(id)?.name ?? '?',
|
||||
issueKey: issueKey ?? '',
|
||||
projectKey: project?.key ?? '',
|
||||
releaseName: release?.name ?? '',
|
||||
}),
|
||||
occurredAt: event.occurredAt,
|
||||
};
|
||||
if (await this.upsertMaterializedActivityRepository.insert(activity)) {
|
||||
await this.changeFeed.publishActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
private issueIdOf(event: TrackerEvent): string | null {
|
||||
if (event.constructor.name.startsWith('Issue')) return event.aggregateId;
|
||||
if (event instanceof CommentAddedEvent) return event.comment.issueId;
|
||||
if (
|
||||
event instanceof CommentEditedEvent ||
|
||||
event instanceof CommentDeletedEvent
|
||||
)
|
||||
return event.issueId;
|
||||
return null;
|
||||
}
|
||||
|
||||
private releaseIdOf(event: TrackerEvent): string | null {
|
||||
if (event.constructor.name.startsWith('Release')) return event.aggregateId;
|
||||
if (event instanceof IssueReleaseChangedEvent) return event.releaseId;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user