import { discoverBeadsDir } from "@/lib/discover"; import { loadBeadsData } from "@/lib/parse-beads"; import { watchBeadsFiles } from "@/lib/watch-beads"; // Prevent Next.js from statically optimizing this route export const dynamic = "force-dynamic"; export async function GET(request: Request) { let cleanup: (() => void) | null = null; const stream = new ReadableStream({ start(controller) { const encoder = new TextEncoder(); function send(data: unknown) { try { controller.enqueue( encoder.encode(`data: ${JSON.stringify(data)}\n\n`) ); } catch { // Stream closed — cleanup will handle } } try { const { beadsDir } = discoverBeadsDir(); // Send initial data const initialData = loadBeadsData(beadsDir); send(initialData); // Watch for changes and push updates cleanup = watchBeadsFiles(beadsDir, () => { try { const newData = loadBeadsData(beadsDir); send(newData); } catch (err) { console.error("Failed to reload beads data:", err); } }); // Heartbeat every 30s to keep connection alive through proxies/firewalls const heartbeat = setInterval(() => { try { controller.enqueue(encoder.encode(": heartbeat\n\n")); } catch { clearInterval(heartbeat); } }, 30000); // Clean up when client disconnects request.signal.addEventListener("abort", () => { clearInterval(heartbeat); if (cleanup) cleanup(); try { controller.close(); } catch { /* already closed */ } }); } catch (err: unknown) { // Discovery failed — send error and close const message = err instanceof Error ? err.message : "Unknown error"; send({ error: message }); controller.close(); } }, cancel() { if (cleanup) cleanup(); }, }); return new Response(stream, { headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache, no-transform", Connection: "keep-alive", "X-Accel-Buffering": "no", // Disable Nginx buffering }, }); }