import { Readable } from 'stream'; export interface FileMetadata { filename: string; size: number; contentType: string; lastModified: Date; etag?: string; path: string; } export interface UploadResult { success: boolean; filename: string; // UUID (same as image.id) path: string; url: string; // CDN URL for accessing the file size: number; contentType: string; originalFilename?: string; // User's original filename fileExtension?: string; // Original extension (png, jpg, etc.) error?: string; } export interface StorageService { /** * Create the main bucket if it doesn't exist */ createBucket(): Promise; /** * Check if the main bucket exists */ bucketExists(): Promise; /** * Upload a file to storage * Path format: {orgSlug}/{projectSlug}/img/{imageId} * * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID for the file (same as image.id in DB) * @param buffer File buffer * @param contentType MIME type * @param originalFilename Original filename from user (for metadata) */ uploadFile( orgSlug: string, projectSlug: string, imageId: string, buffer: Buffer, contentType: string, originalFilename?: string, ): Promise; /** * Download a file from storage * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename */ downloadFile( orgSlug: string, projectSlug: string, imageId: string, ): Promise; /** * Stream a file from storage (memory efficient) * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename */ streamFile( orgSlug: string, projectSlug: string, imageId: string, ): Promise; /** * Generate a presigned URL for downloading a file * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename * @param expirySeconds URL expiry time in seconds */ getPresignedDownloadUrl( orgSlug: string, projectSlug: string, imageId: string, expirySeconds: number, ): Promise; /** * Generate a presigned URL for uploading a file * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename * @param expirySeconds URL expiry time in seconds * @param contentType MIME type */ getPresignedUploadUrl( orgSlug: string, projectSlug: string, imageId: string, expirySeconds: number, contentType: string, ): Promise; /** * List files in a project's img folder * @param orgSlug Organization slug * @param projectSlug Project slug * @param prefix Optional prefix to filter files */ listFiles( orgSlug: string, projectSlug: string, prefix?: string, ): Promise; /** * Delete a file from storage * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename to delete */ deleteFile( orgSlug: string, projectSlug: string, imageId: string, ): Promise; /** * Check if a file exists * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename to check */ fileExists( orgSlug: string, projectSlug: string, imageId: string, ): Promise; /** * Get the public CDN URL for a file * Returns: https://cdn.banatie.app/{orgSlug}/{projectSlug}/img/{imageId} * * @param orgSlug Organization slug * @param projectSlug Project slug * @param imageId UUID filename */ getPublicUrl( orgSlug: string, projectSlug: string, imageId: string, ): string; }