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:
1 parent
423afa658d
commit
60fb39f98f
28 files changed
+522
-69
No files matched your search
@@ -3,8 +3,9 @@ import type { ICommentRepository } from '../../domain/repositories/comment.repos
|
||||
import type { IIssueRepository } from '../../../issue/domain/repositories/issue.repository.interface.js';
|
||||
import { Comment } from '../../domain/entities/comment.entity.js';
|
||||
import { Issue } from '../../../issue/domain/entities/issue.entity.js';
|
||||
import { CommentAuthorExpanderService } from '../services/comment-author-expander.service.js';
|
||||
import { CommentExpanderService } from '../services/comment-expander.service.js';
|
||||
import { CommentApplicationMapper } from '../mappers/comment-application.mapper.js';
|
||||
import type { FileAccessService } from '../../../file/application/services/file-access.service.js';
|
||||
|
||||
export const buildComment = (
|
||||
overrides: Partial<{ id: string; issueId: number; authorId: string; deletedAt: Date | null }> = {},
|
||||
@@ -41,6 +42,8 @@ export const mockCommentRepository = (): ICommentRepository => ({
|
||||
findByIssue: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
findIssueIdsByAttachedFile: vi.fn(),
|
||||
findReferencedFileIds: vi.fn(),
|
||||
});
|
||||
|
||||
export const mockIssueRepository = (): IIssueRepository => ({
|
||||
@@ -53,11 +56,20 @@ export const mockIssueRepository = (): IIssueRepository => ({
|
||||
delete: vi.fn(),
|
||||
});
|
||||
|
||||
/** Экспандер без похода за пользователями: author всегда null */
|
||||
export const mockAuthorExpander = () => {
|
||||
/** Все файлы прикрепляемы, кроме перечисленных — для них бросается заданная ошибка */
|
||||
export const mockFileAccess = (rejections: Record<string, Error> = {}) =>
|
||||
({
|
||||
getAttachableFile: vi.fn(async (fileId: string) => {
|
||||
if (rejections[fileId]) throw rejections[fileId];
|
||||
return { id: fileId };
|
||||
}),
|
||||
}) as unknown as FileAccessService;
|
||||
|
||||
/** Экспандер без похода за пользователями и файлами: author всегда null, attachments пустые */
|
||||
export const mockCommentExpander = () => {
|
||||
const toDto = (comment: Comment) => CommentApplicationMapper.toDto(comment, new Map());
|
||||
return {
|
||||
expand: vi.fn(async (comment: Comment) => toDto(comment)),
|
||||
expandAll: vi.fn(async (comments: Comment[]) => comments.map(toDto)),
|
||||
} as unknown as CommentAuthorExpanderService;
|
||||
} as unknown as CommentExpanderService;
|
||||
};
|
||||
Reference in new issue
Block a user