import { NextRequest } from 'next/server'; import { verifyToken } from '@/lib/auth/jwt'; import { broadcaster } from '@/lib/realtime/broadcaster'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; // Helper to get user from request function getUserFromRequest(request: NextRequest): { userId: string; email: string } | null { const authHeader = request.headers.get('authorization'); const token = authHeader?.replace('Bearer ', ''); if (!token) return null; try { const payload = verifyToken(token); return { userId: payload.userId, email: payload.email }; } catch { return null; } } export async function GET(request: NextRequest) { const user = getUserFromRequest(request); if (!user) { return new Response('Unauthorized', { status: 401 }); } const encoder = new TextEncoder(); const stream = new ReadableStream({ start(controller) { // Send initial connection message controller.enqueue( encoder.encode(`data: ${JSON.stringify({ type: 'connected', userId: user.userId })}\n\n`) ); // Subscribe to user's events const unsubscribe = broadcaster.subscribe(user.userId, (message) => { controller.enqueue( encoder.encode(`data: ${JSON.stringify(message)}\n\n`) ); }); // Also subscribe to global events const unsubscribeGlobal = broadcaster.subscribe('global', (message) => { controller.enqueue( encoder.encode(`data: ${JSON.stringify(message)}\n\n`) ); }); // Keep connection alive with heartbeat const heartbeat = setInterval(() => { controller.enqueue(encoder.encode(`: heartbeat\n\n`)); }, 30000); // Cleanup on close request.signal.addEventListener('abort', () => { clearInterval(heartbeat); unsubscribe(); unsubscribeGlobal(); }); }, }); return new Response(stream, { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, }); }