import { NextRequest, NextResponse } from "next/server"; import { getServerSession } from "next-auth/next"; import { authOptions } from "@/lib/auth/authOptions"; import { query } from "@/lib/db-postgres"; async function assertOwnership(projectId: string, email: string): Promise { const rows = await query( `SELECT p.id FROM fs_projects p JOIN fs_users u ON u.id = p.user_id WHERE p.id = $1 AND u.data->>'email' = $2 LIMIT 1`, [projectId, email] ); return rows.length > 0; } // GET /api/projects/[projectId]/knowledge export async function GET( _req: NextRequest, { params }: { params: Promise<{ projectId: string }> } ) { const session = await getServerSession(authOptions); if (!session?.user?.email) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); const { projectId } = await params; if (!(await assertOwnership(projectId, session.user.email))) { return NextResponse.json({ error: "Not found" }, { status: 404 }); } const rows = await query<{ id: string; data: any; updated_at: string }>( `SELECT id, data, updated_at FROM fs_knowledge_items WHERE project_id = $1 ORDER BY updated_at DESC`, [projectId] ); return NextResponse.json({ items: rows.map((r) => ({ id: r.id, ...r.data, updatedAt: r.updated_at })), }); } // POST /api/projects/[projectId]/knowledge — add or update an item export async function POST( req: NextRequest, { params }: { params: Promise<{ projectId: string }> } ) { const session = await getServerSession(authOptions); if (!session?.user?.email) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); const { projectId } = await params; if (!(await assertOwnership(projectId, session.user.email))) { return NextResponse.json({ error: "Not found" }, { status: 404 }); } const { key, type, value } = await req.json(); if (!key || !value) { return NextResponse.json({ error: "key and value are required" }, { status: 400 }); } const itemType = type ?? "note"; const data = JSON.stringify({ key, type: itemType, value, source: "user" }); // Upsert by key const existing = await query<{ id: string }>( `SELECT id FROM fs_knowledge_items WHERE project_id = $1 AND data->>'key' = $2 LIMIT 1`, [projectId, key] ); if (existing.length > 0) { await query( `UPDATE fs_knowledge_items SET data = $1::jsonb, updated_at = NOW() WHERE id = $2`, [data, existing[0].id] ); return NextResponse.json({ id: existing[0].id, key, type: itemType, value, updated: true }); } else { const rows = await query<{ id: string }>( `INSERT INTO fs_knowledge_items (project_id, data) VALUES ($1, $2::jsonb) RETURNING id`, [projectId, data] ); return NextResponse.json({ id: rows[0].id, key, type: itemType, value, created: true }); } } // DELETE /api/projects/[projectId]/knowledge?id=xxx export async function DELETE( req: NextRequest, { params }: { params: Promise<{ projectId: string }> } ) { const session = await getServerSession(authOptions); if (!session?.user?.email) return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); const { projectId } = await params; if (!(await assertOwnership(projectId, session.user.email))) { return NextResponse.json({ error: "Not found" }, { status: 404 }); } const id = req.nextUrl.searchParams.get("id"); if (!id) return NextResponse.json({ error: "id is required" }, { status: 400 }); await query( `DELETE FROM fs_knowledge_items WHERE id = $1 AND project_id = $2`, [id, projectId] ); return NextResponse.json({ deleted: true }); }