159 lines
3.7 KiB
TypeScript
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;
|
|
}
|