Files
Epicure/apps/web/app/api/v1/recipes/bulk/route.ts
T
Arnaud 84d6cfeb07 feat(recipes): full recipe CRUD with photos, print, version history
List, detail, new, edit pages. Server-side pagination, dietary tags, difficulty.
Photo upload to S3-compatible storage. Version history. Multi-select grid with
bulk delete/visibility. Print view. Delete confirmation dialog.
2026-07-01 08:10:11 +02:00

46 lines
1.5 KiB
TypeScript

import { type NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { requireSession } 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(),
});
export async function DELETE(req: NextRequest) {
const session = await requireSession();
if (session instanceof NextResponse) return session;
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 = await requireSession();
if (session instanceof NextResponse) return session;
const body = BulkUpdateSchema.safeParse(await req.json());
if (!body.success) return NextResponse.json({ error: "Invalid request" }, { status: 400 });
const { ids, visibility } = body.data;
if (!visibility) return NextResponse.json({ error: "Nothing to update" }, { status: 400 });
await db
.update(recipes)
.set({ visibility, updatedAt: new Date() })
.where(and(inArray(recipes.id, ids), eq(recipes.authorId, session.user.id)));
return NextResponse.json({ ok: true });
}