// GET /api/note/files/[id]/bootstrap — ข้อมูลเริ่มต้นของ viewer (file + annotations // + bookmarks + replies เป็น DTO) ให้ client gate ของหน้า /note/annotate/[id] // ดึงหลังมี access_token (ฉบับ token 2026-10-30 — เดิมหน้านี้เป็น server component // อ่าน cookie ผ่าน getSessionUser) · Bearer บังคับ (401) · ไม่ publish SSE · // query ชุดเดียวกับหน้าเดิมตอนเป็น server component import { asc, eq, inArray } from "drizzle-orm"; import { NextResponse } from "next/server"; import { db } from "@/db"; import { annotationReplies, annotations, bookmarks, files, toAnnotationDTO, toBookmarkDTO, toReplyDTO, } from "@/db/schema"; import { noteUserFromRequest } from "@/lib/note-token"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; export async function GET( request: Request, { params }: { params: { id: string } }, ): Promise { const user = noteUserFromRequest(request); if (user === null) { return NextResponse.json( { error: "session หมดอายุ — กรุณากลับ e-Court กดลิงก์เปิดเอกสารใหม่" }, { status: 401, headers: { "cache-control": "no-store" } }, ); } const { id } = params; if (!UUID_RE.test(id)) { return NextResponse.json({ error: "ไม่พบไฟล์นี้" }, { status: 404 }); } const [file] = await db.select().from(files).where(eq(files.id, id)); if (!file) { return NextResponse.json({ error: "ไม่พบไฟล์นี้" }, { status: 404 }); } const [annotationRows, bookmarkRows] = await Promise.all([ db .select() .from(annotations) .where(eq(annotations.fileId, id)) .orderBy(asc(annotations.createdAt)), db .select() .from(bookmarks) .where(eq(bookmarks.fileId, id)) .orderBy(asc(bookmarks.createdAt)), ]); // replies ของทุก comment ในไฟล์นี้ (F9) — แม่ถูก CASCADE ไปแล้ว row ก็หายตาม const annotationIds = annotationRows.map((r) => r.id); const replyRows = annotationIds.length ? await db .select() .from(annotationReplies) .where(inArray(annotationReplies.annotationId, annotationIds)) .orderBy(asc(annotationReplies.createdAt)) : []; return NextResponse.json( { file: { id: file.id, title: file.title, pdfUrl: file.pdfUrl }, annotations: annotationRows.map(toAnnotationDTO), bookmarks: bookmarkRows.map(toBookmarkDTO), replies: replyRows.map(toReplyDTO), user: { userId: user.userid, userName: user.username }, }, { headers: { "cache-control": "no-store" } }, ); }