- IssueAttachment link table (issue <-> file) + migration - GET/POST /issues/:issueId/attachments, DELETE .../attachments/:fileId - Only own uploaded files can be attached; attach is idempotent - Registers issues as a file owner: attached files stay visible to issue participants and are not collected by GC - IssueDetail.attachments GraphQL field via @ResolveField, issue module untouched Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
22 lines
1.2 KiB
TypeScript
22 lines
1.2 KiB
TypeScript
import { IssueAttachment } from '../entities/issue-attachment.entity.js';
|
|
|
|
/** DI-токен, т.к. интерфейсы стираются при компиляции TS */
|
|
export const ISSUE_ATTACHMENT_REPOSITORY = Symbol('ISSUE_ATTACHMENT_REPOSITORY');
|
|
|
|
export interface IIssueAttachmentRepository {
|
|
/** Вложения задачи от старых к новым */
|
|
findByIssue(issueId: number): Promise<IssueAttachment[]>;
|
|
/** Задачи, к которым прикреплён файл */
|
|
findIssueIdsByFile(fileId: string): Promise<number[]>;
|
|
/** Подмножество fileIds, прикреплённых хотя бы к одной задаче */
|
|
findReferencedFileIds(fileIds: string[]): Promise<string[]>;
|
|
/**
|
|
* Идемпотентно: повторное прикрепление возвращает существующее вложение.
|
|
* Бросает IssueNotFoundException / FileNotFoundException, если задачу
|
|
* или файл удалили между проверкой и вставкой.
|
|
*/
|
|
create(attachment: IssueAttachment): Promise<IssueAttachment>;
|
|
/** false — такого вложения не было */
|
|
delete(issueId: number, fileId: string): Promise<boolean>;
|
|
}
|