Files
gridpilot.gg/core/media/application/use-cases/UploadMediaUseCase.ts
2025-12-19 01:22:45 +01:00

111 lines
3.1 KiB
TypeScript

/**
* 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 } from '@core/shared/application';
import { Media } from '../../domain/entities/Media';
import type { IUploadMediaPresenter } from '../presenters/IUploadMediaPresenter';
import { v4 as uuidv4 } from 'uuid';
export interface UploadMediaInput {
file: Express.Multer.File;
uploadedBy: string;
metadata?: Record<string, any>;
}
export interface UploadMediaResult {
success: boolean;
mediaId?: string;
url?: string;
errorMessage?: string;
}
export interface IUploadMediaPresenter {
present(result: UploadMediaResult): void;
}
export class UploadMediaUseCase {
constructor(
private readonly mediaRepo: IMediaRepository,
private readonly mediaStorage: MediaStoragePort,
private readonly logger: Logger,
) {}
async execute(
input: UploadMediaInput,
presenter: IUploadMediaPresenter,
): Promise<void> {
try {
this.logger.info('[UploadMediaUseCase] Starting media upload', {
filename: input.file.originalname,
size: input.file.size,
uploadedBy: input.uploadedBy,
});
// 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) {
presenter.present({
success: false,
errorMessage: uploadResult.errorMessage || 'Failed to upload media',
});
return;
}
// 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);
presenter.present({
success: true,
mediaId,
url: uploadResult.url,
});
this.logger.info('[UploadMediaUseCase] Media uploaded successfully', {
mediaId,
url: uploadResult.url,
});
} catch (error) {
this.logger.error('[UploadMediaUseCase] Error uploading media', {
error: error instanceof Error ? error.message : 'Unknown error',
filename: input.file.originalname,
});
presenter.present({
success: false,
errorMessage: 'Internal error occurred during media upload',
});
}
}
}