111 lines
3.1 KiB
TypeScript
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',
|
|
});
|
|
}
|
|
}
|
|
} |