9d9dfb46c6
Cooking mode step-by-step view. OpenAPI 3.1 spec auto-generated from Zod schemas. Email lib (resend). Redis client. S3 storage helper. Photo upload endpoint. Landing page. Short recipe URL redirect /r/[id]. API docs page.
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
import { S3Client, PutObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
|
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
|
|
const bucket = process.env["STORAGE_BUCKET"] ?? "epicure-uploads";
|
|
const endpoint = process.env["STORAGE_ENDPOINT"] ?? "http://localhost:9000";
|
|
const publicUrl = process.env["STORAGE_PUBLIC_URL"] ?? "http://localhost:9000";
|
|
|
|
const s3 = new S3Client({
|
|
region: process.env["STORAGE_REGION"] ?? "us-east-1",
|
|
endpoint,
|
|
forcePathStyle: true,
|
|
credentials: {
|
|
accessKeyId: process.env["STORAGE_ACCESS_KEY"] ?? "minioadmin",
|
|
secretAccessKey: process.env["STORAGE_SECRET_KEY"] ?? "minioadmin",
|
|
},
|
|
});
|
|
|
|
export async function createPresignedUploadUrl(key: string, contentType: string): Promise<string> {
|
|
const command = new PutObjectCommand({ Bucket: bucket, Key: key, ContentType: contentType });
|
|
return getSignedUrl(s3, command, { expiresIn: 300 });
|
|
}
|
|
|
|
export async function deleteObject(key: string): Promise<void> {
|
|
await s3.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
|
|
}
|
|
|
|
export function getPublicUrl(key: string): string {
|
|
return `${publicUrl}/${bucket}/${key}`;
|
|
}
|