import { z } from "zod"; import { readJson, readPaging, withApi } from "@/lib/api"; import { getLibrary } from "@/lib/queries"; import { addToLibrary } from "@/lib/library"; import { ensureTitle } from "@/lib/catalog"; import type { EntryStatus, TitleType } from "@/generated/prisma/client"; const STATUSES = ["WATCHING", "PAUSED", "COMPLETED", "DROPPED", "WATCHLIST"] as const; /** GET /api/v1/bibliothek — Bibliothek lesen, mit denselben Filtern wie im UI. */ export const GET = withApi(async (request, user) => { const url = new URL(request.url); const { limit, offset } = readPaging(request); const status = url.searchParams.get("status"); const type = url.searchParams.get("typ"); const items = await getLibrary(user.id, { query: url.searchParams.get("q") ?? undefined, status: STATUSES.includes(status as EntryStatus) ? (status as EntryStatus) : undefined, type: type === "SERIES" || type === "MOVIE" ? (type as TitleType) : undefined, genre: url.searchParams.get("genre") ?? undefined, tag: url.searchParams.get("tag") ?? undefined, provider: url.searchParams.get("dienst") ?? undefined, owned: url.searchParams.get("sammlung") === "1" ? true : undefined, }); return { total: items.length, limit, offset, items: items.slice(offset, offset + limit), }; }); const addSchema = z .object({ titleId: z.string().min(1).optional(), tmdbId: z.number().int().positive().optional(), type: z.enum(["SERIES", "MOVIE"]).optional(), status: z.enum(STATUSES).default("WATCHLIST"), }) .refine((value) => Boolean(value.titleId) || Boolean(value.tmdbId && value.type), { message: "Entweder titleId oder tmdbId zusammen mit type angeben.", }); /** POST /api/v1/bibliothek — Titel aufnehmen, per interner ID oder TMDB-ID. */ export const POST = withApi(async (request, user) => { const body = await readJson(request, addSchema); let titleId = body.titleId; if (!titleId && body.tmdbId && body.type) { const title = await ensureTitle(body.type, body.tmdbId, { region: user.region }); titleId = title.id; } if (!titleId) { throw new z.ZodError([ { code: "custom", path: ["titleId"], message: "Kein Titel angegeben." }, ]); } const entry = await addToLibrary(user.id, titleId, body.status); return { id: entry.id, titleId: entry.titleId, status: entry.status }; });