144 lines
3.6 KiB
TypeScript
144 lines
3.6 KiB
TypeScript
/**
|
|
* 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<UploadResult>;
|
|
|
|
/**
|
|
* List all files in storage
|
|
*/
|
|
listAllFiles(prefix?: string): Promise<FileInfo[]>;
|
|
|
|
/**
|
|
* List all folders in storage
|
|
*/
|
|
listAllFolders(prefix?: string): Promise<string[]>;
|
|
|
|
/**
|
|
* Generate a presigned/secure URL for file access
|
|
*/
|
|
getPresignedUrl(key: string, expiresIn?: number): Promise<string>;
|
|
|
|
/**
|
|
* Delete a file from storage
|
|
*/
|
|
deleteFile(key: string): Promise<void>;
|
|
|
|
/**
|
|
* Check if a file exists
|
|
*/
|
|
fileExists(key: string): Promise<boolean>;
|
|
|
|
/**
|
|
* Get file metadata
|
|
*/
|
|
getFileMetadata(key: string): Promise<any>;
|
|
|
|
/**
|
|
* Get file content as buffer
|
|
*/
|
|
getFileContent(key: string): Promise<Buffer>;
|
|
|
|
/**
|
|
* Get streaming URL for a file
|
|
*/
|
|
getStreamingUrl(key: string): Promise<string>;
|
|
|
|
/**
|
|
* Test the connection to the storage provider
|
|
*/
|
|
testConnection(): Promise<boolean>;
|
|
}
|
|
|
|
/**
|
|
* Storage Provider Factory
|
|
* Creates the appropriate storage provider based on configuration
|
|
*/
|
|
export class StorageProviderFactory {
|
|
static async createProvider(config: StorageConfig): Promise<StorageProvider> {
|
|
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<StorageConfig> {
|
|
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';
|