"use server"; import { getAdminUser } from "@/lib/admin-permissions"; import { withBrand } from "@/db/client"; import { productImages } from "@/db/schema"; import { uploadObject, BUCKETS } from "@/lib/storage"; export type UploadProductImageResult = | { success: true; imageUrl: string } | { success: false; error: string }; export async function uploadProductImage( productId: string, file: File ): Promise { const adminUser = await getAdminUser(); if (!adminUser) return { success: false, error: "Not authenticated" }; const validTypes = ["image/png", "image/jpeg", "image/webp"]; if (!validTypes.includes(file.type)) { return { success: false, error: "Invalid file type. Use PNG, JPEG, or WebP." }; } if (file.size > 5 * 1024 * 1024) { return { success: false, error: "File too large. Max 5MB." }; } const ext = file.type.split("/")[1] === "jpeg" ? "jpg" : file.type.split("/")[1]; const storageKey = `products/${productId}/${crypto.randomUUID()}.${ext}`; try { const buffer = Buffer.from(await file.arrayBuffer()); const imageUrl = await uploadObject({ bucket: BUCKETS.PRODUCTS, key: storageKey, body: buffer, contentType: file.type, }); await withBrand(adminUser.brand_id ?? "__missing__", (db) => db.insert(productImages).values({ productId, storageKey, position: 0, altText: null, }) ); return { success: true, imageUrl }; } catch (err) { return { success: false, error: `Upload failed: ${err instanceof Error ? err.message : String(err)}` }; } } export async function deleteProductImage( productId: string ): Promise<{ success: boolean; error?: string }> { const adminUser = await getAdminUser(); if (!adminUser) return { success: false, error: "Not authenticated" }; // In the new schema, "clearing" an image means removing the row(s) // from `product_images` for this product. The legacy `image_url` PATCH // pathway is gone (that column no longer exists on `products`). try { await withBrand(adminUser.brand_id ?? "__missing__", (db) => db.delete(productImages).where(eq(productImages.productId, productId)) ); return { success: true }; } catch (err) { return { success: false, error: `Failed to clear image: ${err instanceof Error ? err.message : String(err)}` }; } } // Imported lazily to avoid a circular dep with the table ref above. import { eq } from "drizzle-orm";