import { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectCommand, ListObjectsV2Command, HeadObjectCommand } from "@aws-sdk/client-s3"; const R2_ACCOUNT_ID = process.env.R2_ACCOUNT_ID!; const R2_ACCESS_KEY_ID = process.env.R2_ACCESS_KEY_ID!; const R2_SECRET_ACCESS_KEY = process.env.R2_SECRET_ACCESS_KEY!; export const R2_BUCKET_NAME = process.env.R2_BUCKET_NAME || "gitbruv-repos"; export const r2Client = new S3Client({ region: "auto", endpoint: `https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`, credentials: { accessKeyId: R2_ACCESS_KEY_ID, secretAccessKey: R2_SECRET_ACCESS_KEY, }, }); export async function r2Get(key: string): Promise { try { const response = await r2Client.send( new GetObjectCommand({ Bucket: R2_BUCKET_NAME, Key: key, }) ); if (!response.Body) return null; const bytes = await response.Body.transformToByteArray(); return Buffer.from(bytes); } catch (err: unknown) { if ((err as { name?: string })?.name === "NoSuchKey") return null; throw err; } } export async function r2Put(key: string, data: Buffer | Uint8Array | string): Promise { await r2Client.send( new PutObjectCommand({ Bucket: R2_BUCKET_NAME, Key: key, Body: data instanceof Buffer ? data : Buffer.from(data), }) ); } export async function r2Delete(key: string): Promise { await r2Client.send( new DeleteObjectCommand({ Bucket: R2_BUCKET_NAME, Key: key, }) ); } export async function r2Exists(key: string): Promise { try { await r2Client.send( new HeadObjectCommand({ Bucket: R2_BUCKET_NAME, Key: key, }) ); return true; } catch { return false; } } export async function r2List(prefix: string): Promise { const keys: string[] = []; let continuationToken: string | undefined; do { const response = await r2Client.send( new ListObjectsV2Command({ Bucket: R2_BUCKET_NAME, Prefix: prefix, ContinuationToken: continuationToken, }) ); if (response.Contents) { for (const obj of response.Contents) { if (obj.Key) keys.push(obj.Key); } } continuationToken = response.NextContinuationToken; } while (continuationToken); return keys; } export async function r2DeletePrefix(prefix: string): Promise { const keys = await r2List(prefix); for (const key of keys) { await r2Delete(key); } }