Files
task-stream/libs/api/tracker/application/src/lib/queries/get-release-notes-draft.query.ts
Josep Piguillem 24b37b6628 feat: release notes
Each release can carry notes in Markdown, written before or after it
ships. A draft is generated from its finished tickets grouped by type, to
edit and copy from the releases page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:19:23 +02:00

61 lines
1.9 KiB
TypeScript

import { IQueryHandler, Query, QueryHandler } from '@nestjs/cqrs';
import {
DEFAULT_PROJECT_SETTINGS,
ProjectWorkflow,
} from '@task-stream/api/tracker/domain';
import { FindIssuesRepository } from '../ports/find-issues.repository';
import { FindProjectsRepository } from '../ports/find-projects.repository';
import { FindReleasesRepository } from '../ports/find-releases.repository';
import { draftReleaseNotes } from '../releases/release-notes';
import { ReadAccess } from './read-access';
/** A Markdown draft of a release's notes, from its finished tickets. */
export class GetReleaseNotesDraftQuery extends Query<string> {
constructor(
public readonly viewerId: string | null,
public readonly releaseId: string,
) {
super();
}
}
@QueryHandler(GetReleaseNotesDraftQuery)
export class GetReleaseNotesDraftQueryHandler
implements IQueryHandler<GetReleaseNotesDraftQuery, string>
{
constructor(
private readonly findReleases: FindReleasesRepository,
private readonly findIssues: FindIssuesRepository,
private readonly findProjects: FindProjectsRepository,
private readonly access: ReadAccess,
) {}
async execute(query: GetReleaseNotesDraftQuery): Promise<string> {
const release = this.access.assertFound(
await this.findReleases.findById(query.releaseId),
'Release',
query.releaseId,
);
await this.access.assertCanView(release.projectId, query.viewerId, {
entity: 'Release',
ref: query.releaseId,
});
const [page, project] = await Promise.all([
this.findIssues.search({
projectId: release.projectId,
releaseId: release.id,
limit: 500,
offset: 0,
}),
this.findProjects.findById(release.projectId),
]);
return draftReleaseNotes({
release,
issues: page.items,
workflow: new ProjectWorkflow(
project?.settings ?? DEFAULT_PROJECT_SETTINGS,
),
});
}
}