/** * Storage Provider Interface * * This interface defines the contract that all storage providers (S3, WebDAV, etc.) * must implement to ensure consistent behavior across different storage backends. */ export interface StorageConfig { provider: 's3' | 'webdav'; [key: string]: any; // Allow additional provider-specific config } export interface UploadResult { key: string; url: string; size: number; contentType: string; } export interface FileInfo { key: string; size: number; lastModified: Date; contentType?: string; } export interface StorageProvider { /** * Upload a file to storage */ uploadFile( file: Buffer, originalName: string, contentType: string, targetFolder?: string ): Promise; /** * List all files in storage */ listAllFiles(prefix?: string): Promise; /** * List all folders in storage */ listAllFolders(prefix?: string): Promise; /** * Generate a presigned/secure URL for file access */ getPresignedUrl(key: string, expiresIn?: number): Promise; /** * Delete a file from storage */ deleteFile(key: string): Promise; /** * Check if a file exists */ fileExists(key: string): Promise; /** * Get file metadata */ getFileMetadata(key: string): Promise; /** * Get file content as buffer */ getFileContent(key: string): Promise; /** * Get streaming URL for a file */ getStreamingUrl(key: string): Promise; /** * Test the connection to the storage provider */ testConnection(): Promise; } /** * Storage Provider Factory * Creates the appropriate storage provider based on configuration */ export class StorageProviderFactory { static async createProvider(config: StorageConfig): Promise { switch (config.provider) { case 's3': const { S3Service } = await import('./s3Service.js'); return new S3Service(config as any); case 'webdav': const { WebDAVService } = await import('./webdavService.js'); return new WebDAVService(config as any); default: throw new Error(`Unsupported storage provider: ${config.provider}`); } } /** * Load storage configuration from file or environment */ static async loadConfig(): Promise { try { const configPath = path.join(process.cwd(), 'storage-config.json'); const configData = await fs.readFile(configPath, 'utf-8'); return JSON.parse(configData); } catch (error) { console.warn('Failed to load storage-config.json, using environment variables as fallback'); // Determine provider from environment const provider = process.env.STORAGE_PROVIDER || 's3'; if (provider === 'webdav') { return { provider: 'webdav', url: process.env.WEBDAV_URL || '', username: process.env.WEBDAV_USERNAME || '', password: process.env.WEBDAV_PASSWORD || '', basePath: process.env.WEBDAV_BASE_PATH || '/music-files', }; } else { return { provider: 's3', endpoint: process.env.S3_ENDPOINT || 'http://localhost:9000', accessKeyId: process.env.S3_ACCESS_KEY_ID || 'minioadmin', secretAccessKey: process.env.S3_SECRET_ACCESS_KEY || 'minioadmin', bucketName: process.env.S3_BUCKET_NAME || 'music-files', region: process.env.S3_REGION || 'us-east-1', useSSL: process.env.S3_USE_SSL !== 'false', }; } } } } // Import required modules import fs from 'fs/promises'; import path from 'path';