import { type NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { requireSessionOrApiKey } from "@/lib/api-auth"; import { db, recipes, eq, and, inArray } from "@epicure/db"; const BulkDeleteSchema = z.object({ ids: z.array(z.string()).min(1).max(100), }); const BulkUpdateSchema = z.object({ ids: z.array(z.string()).min(1).max(100), visibility: z.enum(["private", "unlisted", "public"]).optional(), addTags: z.array(z.string().min(1).max(40)).max(20).optional(), removeTags: z.array(z.string().min(1).max(40)).max(20).optional(), }); export async function DELETE(req: NextRequest) { const { session, response } = await requireSessionOrApiKey(req); if (response) return response; const body = BulkDeleteSchema.safeParse(await req.json()); if (!body.success) return NextResponse.json({ error: "Invalid request" }, { status: 400 }); await db .delete(recipes) .where(and(inArray(recipes.id, body.data.ids), eq(recipes.authorId, session!.user.id))); return NextResponse.json({ ok: true }); } export async function PATCH(req: NextRequest) { const { session, response } = await requireSessionOrApiKey(req); if (response) return response; const body = BulkUpdateSchema.safeParse(await req.json()); if (!body.success) return NextResponse.json({ error: "Invalid request" }, { status: 400 }); const { ids, visibility, addTags, removeTags } = body.data; if (!visibility && !addTags?.length && !removeTags?.length) { return NextResponse.json({ error: "Nothing to update" }, { status: 400 }); } if (visibility) { await db .update(recipes) .set({ visibility, updatedAt: new Date() }) .where(and(inArray(recipes.id, ids), eq(recipes.authorId, session!.user.id))); } if (addTags?.length || removeTags?.length) { const owned = await db.query.recipes.findMany({ where: and(inArray(recipes.id, ids), eq(recipes.authorId, session!.user.id)), columns: { id: true, tags: true }, }); await Promise.all( owned.map((r) => { let nextTags = r.tags; if (addTags?.length) nextTags = [...new Set([...nextTags, ...addTags])]; if (removeTags?.length) nextTags = nextTags.filter((tag) => !removeTags.includes(tag)); return db.update(recipes).set({ tags: nextTags, updatedAt: new Date() }).where(eq(recipes.id, r.id)); }) ); } return NextResponse.json({ ok: true }); }