/** * Use Case: DeleteMediaUseCase * * Handles the business logic for deleting media files. */ import type { IMediaRepository } from '../../domain/repositories/IMediaRepository'; import type { MediaStoragePort } from '../ports/MediaStoragePort'; import type { Logger, UseCaseOutputPort } from '@core/shared/application'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; export interface DeleteMediaInput { mediaId: string; } export interface DeleteMediaResult { mediaId: string; deleted: boolean; } export type DeleteMediaErrorCode = 'MEDIA_NOT_FOUND' | 'REPOSITORY_ERROR'; export type DeleteMediaApplicationError = ApplicationErrorCode< DeleteMediaErrorCode, { message: string } >; export class DeleteMediaUseCase { constructor( private readonly mediaRepo: IMediaRepository, private readonly mediaStorage: MediaStoragePort, private readonly output: UseCaseOutputPort, private readonly logger: Logger, ) {} async execute(input: DeleteMediaInput): Promise> { this.logger.info('[DeleteMediaUseCase] Deleting media', { mediaId: input.mediaId, }); try { const media = await this.mediaRepo.findById(input.mediaId); if (!media) { return Result.err({ code: 'MEDIA_NOT_FOUND', details: { message: 'Media not found' }, }); } await this.mediaStorage.deleteMedia(media.url.value); await this.mediaRepo.delete(input.mediaId); this.output.present({ mediaId: input.mediaId, deleted: true, }); this.logger.info('[DeleteMediaUseCase] Media deleted successfully', { mediaId: input.mediaId, }); return Result.ok(undefined); } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); this.logger.error('[DeleteMediaUseCase] Error deleting media', err, { mediaId: input.mediaId, }); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: err.message || 'Unexpected repository error' }, }); } } }