Initial commit: DrinkTracker full-stack app
Next.js 14 drink collection tracker with AI-powered search, menu scanning, ratings, wishlist, sharing, and CSV backup/restore. Features: - Auth (credentials + OAuth ready) - Drink collection with ratings and reviews - AI search via Claude/OpenAI with search history - Menu photo scanning with AI extraction - Wishlist / Try Later system - Public sharing via slug URLs - CSV backup and restore (merge/replace modes) - Docker Compose for Postgres + MinIO + dev server Security: docker-compose files use env var interpolation instead of hardcoded secrets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
62
src/lib/s3.ts
Normal file
62
src/lib/s3.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
S3Client,
|
||||
PutObjectCommand,
|
||||
GetObjectCommand,
|
||||
DeleteObjectCommand,
|
||||
} from "@aws-sdk/client-s3"
|
||||
|
||||
const s3Client = new S3Client({
|
||||
endpoint: `http${process.env.MINIO_USE_SSL === "true" ? "s" : ""}://${process.env.MINIO_ENDPOINT}:${process.env.MINIO_PORT}`,
|
||||
region: "us-east-1",
|
||||
credentials: {
|
||||
accessKeyId: process.env.MINIO_ACCESS_KEY!,
|
||||
secretAccessKey: process.env.MINIO_SECRET_KEY!,
|
||||
},
|
||||
forcePathStyle: true,
|
||||
})
|
||||
|
||||
const BUCKET = process.env.MINIO_BUCKET || "drink-images"
|
||||
|
||||
export async function uploadImage(
|
||||
key: string,
|
||||
body: Buffer,
|
||||
contentType: string
|
||||
): Promise<string> {
|
||||
await s3Client.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: BUCKET,
|
||||
Key: key,
|
||||
Body: body,
|
||||
ContentType: contentType,
|
||||
})
|
||||
)
|
||||
|
||||
const useSSL = process.env.MINIO_USE_SSL === "true"
|
||||
const protocol = useSSL ? "https" : "http"
|
||||
return `${protocol}://${process.env.MINIO_ENDPOINT}:${process.env.MINIO_PORT}/${BUCKET}/${key}`
|
||||
}
|
||||
|
||||
export async function getImage(key: string) {
|
||||
const response = await s3Client.send(
|
||||
new GetObjectCommand({
|
||||
Bucket: BUCKET,
|
||||
Key: key,
|
||||
})
|
||||
)
|
||||
return response
|
||||
}
|
||||
|
||||
export async function deleteImage(key: string) {
|
||||
await s3Client.send(
|
||||
new DeleteObjectCommand({
|
||||
Bucket: BUCKET,
|
||||
Key: key,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export function getImageUrl(key: string): string {
|
||||
const useSSL = process.env.MINIO_USE_SSL === "true"
|
||||
const protocol = useSSL ? "https" : "http"
|
||||
return `${protocol}://${process.env.MINIO_ENDPOINT}:${process.env.MINIO_PORT}/${BUCKET}/${key}`
|
||||
}
|
||||
Reference in New Issue
Block a user