import { S3Client, PutObjectCommand, DeleteObjectCommand, CopyObjectCommand, ListObjectsV2Command } from '@aws-sdk/client-s3' import { R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET, R2_PUBLIC_URL } from './config.js' function makeClient() { return new S3Client({ region: 'auto', endpoint: `https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`, credentials: { accessKeyId: R2_ACCESS_KEY_ID, secretAccessKey: R2_SECRET_ACCESS_KEY }, }) } export function isR2Configured() { return Boolean(R2_ACCOUNT_ID && R2_ACCESS_KEY_ID && R2_SECRET_ACCESS_KEY && R2_BUCKET && R2_PUBLIC_URL) } export async function uploadToR2(buffer, key, contentType) { await makeClient().send(new PutObjectCommand({ Bucket: R2_BUCKET, Key: key, Body: buffer, ContentType: contentType, })) return `${R2_PUBLIC_URL}/${key}` } export async function deleteFromR2(key) { await makeClient().send(new DeleteObjectCommand({ Bucket: R2_BUCKET, Key: key })) } export async function copyInR2(fromKey, toKey) { await makeClient().send(new CopyObjectCommand({ Bucket: R2_BUCKET, CopySource: `${R2_BUCKET}/${fromKey.split('/').map(encodeURIComponent).join('/')}`, Key: toKey, })) return `${R2_PUBLIC_URL}/${toKey}` } export async function listR2Objects(prefix) { const objects = [] let continuationToken const client = makeClient() do { const resp = await client.send(new ListObjectsV2Command({ Bucket: R2_BUCKET, Prefix: prefix, ContinuationToken: continuationToken, })) for (const obj of resp.Contents ?? []) objects.push(obj) continuationToken = resp.IsTruncated ? resp.NextContinuationToken : undefined } while (continuationToken) return objects }