/** * Use Case: DeleteMediaUseCase * * Handles the business logic for deleting media files. */ import type { Logger } from '@core/shared/domain/Logger'; import { Result } from '@core/shared/domain/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import { MediaRepository } from '../../domain/repositories/MediaRepository'; import type { MediaStoragePort } from '../ports/MediaStoragePort'; 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: MediaRepository, private readonly mediaStorage: MediaStoragePort, 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.logger.info('[DeleteMediaUseCase] Media deleted successfully', { mediaId: input.mediaId, }); return Result.ok({ mediaId: input.mediaId, deleted: true, }); } 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' }, }); } } }