import { NextRequest, NextResponse } from "next/server"; import { createDirectus, rest, staticToken, createItem, readItems, } from "@directus/sdk"; export interface CMSConfig { url: string; token: string; } export function createCMSClient(config: CMSConfig) { return createDirectus(config.url) .with(staticToken(config.token)) .with(rest()); } export async function handleFeedbackRequest( req: NextRequest, config: CMSConfig, ) { const client = createCMSClient(config); if (req.method === "GET") { try { const items = await client.request( readItems("visual_feedback", { fields: ["*", { comments: ["*"] }], sort: ["-date_created"], }), ); return NextResponse.json(items); } catch (error: any) { return NextResponse.json({ error: error.message }, { status: 500 }); } } if (req.method === "POST") { try { const body = await req.json(); const { action, screenshot_base64, ...data } = body; if (action === "reply") { const reply = await client.request( createItem("visual_feedback_comments", { feedback_id: data.feedbackId, user_name: data.userName, text: data.text, }), ); return NextResponse.json(reply); } let screenshotId = null; if (screenshot_base64) { try { const base64Data = screenshot_base64.split(";base64,").pop(); const buffer = Buffer.from(base64Data, "base64"); const formData = new FormData(); const blob = new Blob([buffer], { type: "image/png" }); formData.append("file", blob, `feedback-${Date.now()}.png`); const fileRes = await fetch(`${config.url}/files`, { method: "POST", headers: { Authorization: `Bearer ${config.token}` }, body: formData, }); if (fileRes.ok) { const fileData = await fileRes.json(); screenshotId = fileData.data.id; } } catch (e) { console.error("Failed to upload screenshot:", e); } } const feedback = await client.request( createItem("visual_feedback", { project: data.project || req.headers.get("host") || "unknown", url: data.url, selector: data.selector, x: data.x, y: data.y, type: data.type, text: data.text, user_name: data.userName, user_identity: data.userIdentity, status: "open", screenshot: screenshotId, company: data.companyId, }), ); return NextResponse.json(feedback); } catch (error: any) { return NextResponse.json({ error: error.message }, { status: 500 }); } } return NextResponse.json({ error: "Method not allowed" }, { status: 405 }); } export async function handleWhoAmIRequest( req: NextRequest, gatekeeperUrl: string, ) { try { const bypass = req.nextUrl.searchParams.get("gatekeeper_bypass"); const targetUrl = bypass ? `${gatekeeperUrl}/api/whoami?gatekeeper_bypass=${bypass}` : `${gatekeeperUrl}/api/whoami`; // Forward cookies const cookieHeader = req.headers.get("cookie") || ""; const res = await fetch(targetUrl, { headers: { Cookie: cookieHeader }, }); if (res.ok) { return NextResponse.json(await res.json()); } return NextResponse.json({ identity: "Guest" }); } catch (_e) { return NextResponse.json({ identity: "Guest" }); } }