/** * Supabase Storage Adapter * @module @plyaz/storage/adapters/supabase * * Production-ready storage adapter for Supabase Storage * Uses @supabase/supabase-js SDK for file operations * * Features: * - Upload files with metadata to Supabase buckets * - Download files as buffers * - Soft delete with grace period (60 days) * - Hard delete (permanent removal) * - File restoration from soft delete * - Presigned URLs for secure access * - Health monitoring * - Comprehensive error handling * * @example * ```typescript * const adapter = new SupabaseStorageAdapter({ * name: 'supabase-primary', * type: STORAGE_ADAPTER_TYPE.SupabaseStorage, * supabaseUrl: process.env.SUPABASE_URL!, * serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY!, * bucket: 'files', * publicUrl: 'https://your-project.supabase.co/storage/v1/object/public', * }); * * const result = await adapter.upload({ * fileId: 'file-123', * filename: 'document.pdf', * file: buffer, * mimeType: 'application/pdf', * size: 1024000, * category: 'DOCUMENT' as FILE_CATEGORY, * entityType: 'USER' as ENTITY_TYPE, * entityId: 'user-123', * accessLevel: FILE_ACCESS_LEVEL.PRIVATE, * }); * ``` */ import { BaseStorageAdapter } from '../base/BaseStorageAdapter'; import type { SupabaseStorageConfig, UploadParams, UploadResult, DownloadParams, DownloadResult, DeleteParams, FileDeleteResult, PresignedUrlOptions, PresignedUrlResult, AdapterHealthCheck, FileMetadata, BucketConfiguration, StorageMoveFileParams, StorageListFilesParams, StorageListFilesResult, StorageUpdateBucketParams, StorageBucketInfo, StorageListBucketsResult, StoragePublicUrlParams, StorageSignedUploadUrlParams, StorageSignedUploadUrlResult, StorageCopyFileParams, StorageReplaceFileParams, BucketDeletionResult } from '@plyaz/types/storage'; import { BUCKET_PURPOSE } from '@plyaz/types/storage'; /** * Supabase Storage Adapter * Implements storage operations using Supabase Storage backend */ export declare class SupabaseStorageAdapter extends BaseStorageAdapter { private readonly supabaseClient; private readonly bucket?; private readonly publicUrl?; private readonly validation?; private readonly uploadMetadataStore; constructor(config: SupabaseStorageConfig); /** * Upload a file to Supabase Storage * * Uses signed URL with progress tracking for intermediate progress events. * Falls back to SDK upload if signed URL approach fails. */ upload(params: UploadParams): Promise; /** * Download a file from Supabase Storage */ download(params: DownloadParams): Promise; /** * Delete a file from Supabase Storage * Supports both soft delete (default) and hard delete */ delete(params: DeleteParams): Promise; /** * Generate a presigned URL for secure file access */ getSignedUrl(options: PresignedUrlOptions): Promise; /** * Check if the adapter is available and properly configured */ isAvailable(): boolean; /** * Perform health check on the adapter */ healthCheck(): Promise; /** * Get file metadata from Supabase Storage */ getFileMetadata(fileId: string, bucket?: string): Promise; /** * Restore a soft-deleted file */ restoreFile(fileId: string, bucket?: string): Promise; /** * Soft delete a file by updating its metadata * @private */ private softDelete; /** * Generate a file key/path for storage */ protected generateFileKey(params: UploadParams): string; /** /** * Map Supabase Storage errors to StoragePackageError * @private */ private mapSupabaseError; /** * Translate bucket purpose to Supabase-specific bucket name * * Pattern: {purpose} * Enterprise with org: {purpose}-{org} * * Examples: * - COMPLIANCE → "compliance" * - MEDIA_IMAGES → "media-images" * - COMPLIANCE (enterprise, acme-corp) → "compliance-acme-corp" * * Note: Supabase projects handle environment separation, so no env prefix needed */ translateBucketPurpose(purpose: BUCKET_PURPOSE, config: BucketConfiguration): string; /** * Create Supabase bucket if it doesn't exist * Idempotent: Returns success if bucket already exists */ createBucket(bucketName: string, purpose: BUCKET_PURPOSE): Promise; /** * Delete buckets by name * Useful for cleanup in tests or migrations */ deleteBuckets(bucketNames: string[]): Promise; /** * Get purpose-specific bucket name */ private getPurposeName; /** * Check if purpose should use public bucket */ private isPublicPurpose; /** * Get file size limit for bucket purpose * Used by StorageService for validation */ getFileSizeLimit(purpose: BUCKET_PURPOSE): number | undefined; /** * Get allowed MIME types for bucket purpose * Used by StorageService for validation */ getAllowedMimeTypes(purpose: BUCKET_PURPOSE): string[] | undefined; /** * Sanitize name for bucket naming (lowercase, alphanumeric, hyphens) */ private sanitizeName; /** * List all buckets */ listBuckets(): Promise; /** * Get bucket details */ getBucket(bucketName: string): Promise; /** * Update bucket settings */ updateBucket(params: StorageUpdateBucketParams): Promise; /** * List files in a bucket */ listFiles(params: StorageListFilesParams): Promise; /** * Move a file */ moveFile(params: StorageMoveFileParams): Promise; /** * Copy a file */ copyFile(params: StorageCopyFileParams): Promise; /** * Replace an existing file */ replaceFile(params: StorageReplaceFileParams): Promise; /** * Create a signed upload URL */ createSignedUploadUrl(params: StorageSignedUploadUrlParams): Promise; /** * Get public URL for a file */ getPublicUrl(params: StoragePublicUrlParams): Promise; /** * Upload large file using chunked/resumable upload * Handles entire chunked upload flow using Supabase SDK */ uploadChunked(params: UploadParams): Promise; /** * Helper: Handle bucket deletion error (idempotent delete) */ private handleBucketDeleteError; }