Repository Public
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// POST /api/favorites/toggle — bascule un ♥ « Mon univers Ka » au hub Groupe KA.3// Corps : { item_id, title?, subtitle?, price_label?, image_url?, url?, meta?,4// action? } — sans `action` explicite (« add » / « remove »), on bascule selon5// la présence de l'item dans la liste du hub. SYNCHRONE (aucun stockage6// local) : 401 sans session, 400 item invalide, 502 hub injoignable/refus.7import { NextRequest, NextResponse } from "next/server";8import { SESSION_COOKIE, readSession } from "@/lib/ka-auth";9import { cleanItem, hubList, hubToggle } from "@/lib/hubfav";1011export const dynamic = "force-dynamic";1213export async function POST(req: NextRequest) {14 const s = readSession(req.cookies.get(SESSION_COOKIE)?.value);15 if (!s) {16 return NextResponse.json({ error: "auth_required" }, { status: 401 });17 }18 let body: unknown;19 try {20 body = await req.json();21 } catch {22 return NextResponse.json({ error: "invalid_json" }, { status: 400 });23 }24 const item = cleanItem(body);25 if (!item) {26 return NextResponse.json({ error: "item_id_required" }, { status: 400 });27 }28 const requested = (body as { action?: unknown }).action;29 let action: "add" | "remove";30 if (requested === "add" || requested === "remove") {31 action = requested;32 } else {33 const list = await hubList(s.ka_id);34 if (list === null) {35 return NextResponse.json({ error: "hub_unreachable" }, { status: 502 });36 }37 action = list.some((f) => f.item_id === item.item_id) ? "remove" : "add";38 }39 const ok = await hubToggle(s.ka_id, action, item);40 if (!ok) {41 return NextResponse.json({ error: "hub_error" }, { status: 502 });42 }43 return NextResponse.json({ ok: true, favorited: action === "add" });44}45