@prood/storage-s3
S3-compatible storage provider for AWS S3, Cloudflare R2, and MinIO.
@prood/storage-s3 implements the StorageProvider interface for any S3-compatible object storage — AWS S3, Cloudflare R2, MinIO, or other compatible services.
Installation
Workspace package. Available from the source repo for now.
Configuration
| Variable | Required | Description |
|---|---|---|
S3_ENDPOINT | Yes | S3-compatible endpoint URL |
S3_BUCKET | Yes | Bucket name |
S3_ACCESS_KEY_ID | Yes | Access key |
S3_SECRET_ACCESS_KEY | Yes | Secret key |
S3_PUBLIC_URL | Yes | Public URL prefix for uploaded files. The apps allow it in next/image |
Cloudflare R2
S3_ENDPOINT=https://<account>.eu.r2.cloudflarestorage.com
S3_BUCKET=prood-public
S3_ACCESS_KEY_ID=your_access_key
S3_SECRET_ACCESS_KEY=your_secret_key
S3_PUBLIC_URL=https://prood-media.rbarona.workers.devUsage
Via @prood/commerce (preferred):
import { uploadForTenant } from '@prood/commerce'
const result = await uploadForTenant(orgId, {
file: buffer,
filename: 'product-image.jpg',
contentType: 'image/jpeg',
directory: `products/${productId}`,
})Direct usage:
import { S3StorageProvider } from '@prood/storage-s3'
const storage = new S3StorageProvider({
endpoint: process.env.S3_ENDPOINT!,
region: 'auto',
bucket: process.env.S3_BUCKET!,
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
publicUrl: process.env.S3_PUBLIC_URL,
})Tenant namespacing
All keys are prefixed with org/{orgId}/:
org/org_demo/products/prod_abc/image.jpgAlways upload via uploadForTenant() to ensure proper namespacing.