import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, HeadBucketCommand, CreateBucketCommand } from "@aws-sdk/client-s3"; import { createReadStream } from "node:fs"; import { stat } from "node:fs/promises"; let instance: S3Client; export function storage() { return instance ??= new S3Client({ endpoint: process.env.S3_ENDPOINT, region: "us-east-1", forcePathStyle: true, credentials: { accessKeyId: process.env.S3_ACCESS_KEY!, secretAccessKey: process.env.S3_SECRET_KEY! }, requestChecksumCalculation: "WHEN_REQUIRED", responseChecksumValidation: "WHEN_REQUIRED", }); } export const bucket = () => process.env.S3_BUCKET || "prompt"; export async function ensureBucket() { try { await storage().send(new HeadBucketCommand({ Bucket: bucket() })); } catch (e) { if ((e as { $metadata?: { httpStatusCode: number } }).$metadata?.httpStatusCode !== 404) throw e; await storage().send(new CreateBucketCommand({ Bucket: bucket() })); } } export async function putFile(key: string, path: string, mime: string) { const size = (await stat(path)).size; await storage().send(new PutObjectCommand({ Bucket: bucket(), Key: key, Body: createReadStream(path), ContentLength: size, ContentType: mime })); return size; } export const getObject = (key: string, range?: string) => storage().send(new GetObjectCommand({ Bucket: bucket(), Key: key, Range: range })); export const removeObject = (key: string) => storage().send(new DeleteObjectCommand({ Bucket: bucket(), Key: key }));