/** * Use Case: UploadMediaUseCase * * Handles the business logic for uploading 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'; import { Media } from '../../domain/entities/Media'; import { v4 as uuidv4 } from 'uuid'; export interface UploadMediaInput { file: Express.Multer.File; uploadedBy: string; metadata?: Record; } export interface UploadMediaResult { mediaId: string; url: string | undefined; } export type UploadMediaErrorCode = | 'UPLOAD_FAILED' | 'REPOSITORY_ERROR'; export class UploadMediaUseCase { constructor( private readonly mediaRepo: IMediaRepository, private readonly mediaStorage: MediaStoragePort, private readonly output: UseCaseOutputPort, private readonly logger: Logger, ) {} async execute( input: UploadMediaInput, ): Promise>> { this.logger.info('[UploadMediaUseCase] Starting media upload', { filename: input.file.originalname, size: input.file.size, uploadedBy: input.uploadedBy, }); try { // Upload file to storage service const uploadResult = await this.mediaStorage.uploadMedia(input.file.buffer, { filename: input.file.originalname, mimeType: input.file.mimetype, metadata: input.metadata, }); if (!uploadResult.success) { return Result.err({ code: 'UPLOAD_FAILED', details: { message: uploadResult.errorMessage ?? 'Failed to upload media', }, }); } // Determine media type const mediaType: 'image' | 'video' | 'document' = input.file.mimetype.startsWith('image/') ? 'image' : input.file.mimetype.startsWith('video/') ? 'video' : 'document'; // Create media entity const mediaId = uuidv4(); const media = Media.create({ id: mediaId, filename: uploadResult.filename || input.file.originalname, originalName: input.file.originalname, mimeType: input.file.mimetype, size: input.file.size, url: uploadResult.url, type: mediaType, uploadedBy: input.uploadedBy, metadata: input.metadata, }); // Save to repository await this.mediaRepo.save(media); this.output.present({ mediaId, url: uploadResult.url, }); this.logger.info('[UploadMediaUseCase] Media uploaded successfully', { mediaId, url: uploadResult.url, }); return Result.ok(undefined); } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); this.logger.error('[UploadMediaUseCase] Error uploading media', { error: err.message, filename: input.file.originalname, }); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: err.message }, }); } } }