banatie-service/apps/api-service/src/services/StorageService.ts

159 lines
3.7 KiB
TypeScript

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<void>;
/**
* Check if the main bucket exists
*/
bucketExists(): Promise<boolean>;
/**
* 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<UploadResult>;
/**
* 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<Buffer>;
/**
* 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<Readable>;
/**
* 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<string>;
/**
* 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<string>;
/**
* 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<FileMetadata[]>;
/**
* 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<void>;
/**
* 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<boolean>;
/**
* 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;
}