# Storage Providers

This module provides a flexible storage abstraction for image uploads, supporting multiple storage providers.

## Supported Providers

### 1. Vercel Blob (Default)

Uses `@vercel/blob` for storage. Configure with:

```env
BLOB_READ_WRITE_TOKEN=your_token_here
```

### 2. Fly.io (Tigris)

Uses Fly.io's Tigris S3-compatible storage. Configure with:

```env
STORAGE_PROVIDER=fly-io
FLY_STORAGE_ACCESS_KEY_ID=your_access_key
FLY_STORAGE_SECRET_ACCESS_KEY=your_secret_key
FLY_STORAGE_ENDPOINT=https://fly.storage.tigris.dev
FLY_STORAGE_REGION=auto
FLY_STORAGE_BUCKET_NAME=your_bucket_name
FLY_STORAGE_PUBLIC_URL_BASE=https://your-bucket.fly.storage.tigris.dev  # Optional, auto-constructed if not set
```

**Setting up Fly.io Storage:**

### Quick Setup (Automated)

Use the setup script to automatically create a bucket and configure your `.env` file:

```bash
pnpm fly:storage:setup
# Or with a custom bucket name:
pnpm fly:storage:setup my-custom-bucket-name
```

The script will:
1. Check if Fly.io CLI is installed and authenticated
2. Create a public storage bucket
3. Extract credentials from the output
4. Add configuration to your `.env` file

### Manual Setup

1. Create a public storage bucket (required for serving images):
   ```bash
   fly storage create --public your-bucket-name
   ```

2. The command will output the required environment variables. Set them in your app's environment:
   - `AWS_ACCESS_KEY_ID` → `FLY_STORAGE_ACCESS_KEY_ID`
   - `AWS_SECRET_ACCESS_KEY` → `FLY_STORAGE_SECRET_ACCESS_KEY`
   - `AWS_ENDPOINT_URL_S3` → `FLY_STORAGE_ENDPOINT`
   - `AWS_REGION` → `FLY_STORAGE_REGION`
   - `BUCKET_NAME` → `FLY_STORAGE_BUCKET_NAME`

3. The public URL will be automatically constructed as `https://{bucket-name}.fly.storage.tigris.dev/{key}` unless you provide a custom `FLY_STORAGE_PUBLIC_URL_BASE`.

### Testing Locally

After setting up Fly.io storage:

1. Make sure your `.env` file has `STORAGE_PROVIDER=fly-io` and all required `FLY_STORAGE_*` variables
2. Restart your dev server: `pnpm dev`
3. Test the upload endpoint by uploading an image via `/api/upload-image`
4. Verify the returned URL uses Fly.io storage (should be `https://{bucket-name}.fly.storage.tigris.dev/...`)

### 3. Custom Provider

Extending apps can provide their own storage implementation:

```typescript
// In your extending app's server plugin or utility
import type { StorageProvider, StorageUploadOptions } from '@vernaillen/harmonic-saas/server/utils/storage/types'
import { useStorageProvider } from '@vernaillen/harmonic-saas/server/utils/storage'

class MyCustomStorage implements StorageProvider {
  async upload(key: string, blob: Blob, options?: StorageUploadOptions): Promise<string> {
    // Your custom implementation
    return 'https://example.com/file.jpg'
  }
}

// Then pass it when calling useStorageProvider()
const storage = useStorageProvider(new MyCustomStorage())
```

## Usage

The storage provider is automatically selected based on your configuration. The upload endpoint (`/api/upload-image`) uses the configured provider automatically.

## Configuration Priority

1. Custom provider (if `STORAGE_PROVIDER=custom` and a custom provider is passed)
2. Fly.io storage (if `STORAGE_PROVIDER=fly-io` and Fly.io config is present)
3. Vercel Blob (default, if `BLOB_READ_WRITE_TOKEN` is present)

