Add attachments to comments

- CommentAttachment link table (comment <-> file) + migration
- fileIds in create/update comment; update replaces the whole set,
  synced in one transaction with the comment
- CommentDto.attachments; empty for deleted comments
- Soft delete drops attachments so GC can collect the files
- Max 10 files per comment, ordered by upload time (uuid v7)
- Registers comments as a file owner
- Rename CommentAuthorExpanderService -> CommentExpanderService
  (expands authors and files)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
vadimandClaude Opus 5.5 committed 2026-10-02 09:18:08 +03:00
1 parent 423afa658d
commit 60fb39f98f
28 files changed
+522 -69

No files matched your search

@@ -10,7 +10,7 @@ import {
import { IssueNotFoundException } from '../../../../issue/domain/exceptions/issue-not-found.exception.js';
import { ListCommentsQuery } from './list-comments.query.js';
import { CommentDto } from '../../dto/comment.dto.js';
import { CommentAuthorExpanderService } from '../../services/comment-author-expander.service.js';
import { CommentExpanderService } from '../../services/comment-expander.service.js';
@Injectable()
export class ListCommentsUseCase {
@@ -19,7 +19,7 @@ export class ListCommentsUseCase {
private readonly commentRepository: ICommentRepository,
@Inject(ISSUE_REPOSITORY)
private readonly issueRepository: IIssueRepository,
private readonly commentAuthorExpander: CommentAuthorExpanderService,
private readonly commentExpander: CommentExpanderService,
) {}
async execute(query: ListCommentsQuery): Promise<{ list: CommentDto[]; nextCursor: string | null }> {
@@ -34,6 +34,6 @@ export class ListCommentsUseCase {
cursor: query.cursor,
});
return { list: await this.commentAuthorExpander.expandAll(list), nextCursor };
return { list: await this.commentExpander.expandAll(list), nextCursor };
}
}