import { getDays, getDayDetail, getStats } from '../core/db'; import { processCommand } from '../cli/process'; type ApiHandler = (req: Request, url: URL) => Promise; const routes: Record = { 'GET /api/days': handleGetDays, 'GET /api/days/:date': handleGetDayDetail, 'GET /api/days/:date/brag': handleGetDayBrag, 'GET /api/stats': handleGetStats, 'POST /api/refresh': handleRefresh, }; export async function handleApiRequest( req: Request, url: URL ): Promise { const method = req.method; const path = url.pathname; // Match routes for (const [route, handler] of Object.entries(routes)) { const [routeMethod, routePath] = route.split(' '); if (method !== routeMethod) continue; const params = matchPath(routePath, path); if (params !== null) { try { // Attach params to URL for handler access (url as any).params = params; return await handler(req, url); } catch (error) { console.error('API error:', error); return jsonResponse({ error: 'Internal server error' }, 500); } } } return jsonResponse({ error: 'Not found' }, 404); } function matchPath( pattern: string, path: string ): Record | null { const patternParts = pattern.split('/'); const pathParts = path.split('/'); if (patternParts.length !== pathParts.length) return null; const params: Record = {}; for (let i = 0; i < patternParts.length; i++) { const patternPart = patternParts[i]; const pathPart = pathParts[i]; if (patternPart.startsWith(':')) { params[patternPart.slice(1)] = pathPart; } else if (patternPart !== pathPart) { return null; } } return params; } function jsonResponse(data: unknown, status = 200): Response { return new Response(JSON.stringify(data), { status, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } // Handlers async function handleGetDays(req: Request, url: URL): Promise { const limit = parseInt(url.searchParams.get('limit') || '30'); const days = getDays(limit); return jsonResponse(days); } async function handleGetDayDetail(req: Request, url: URL): Promise { const params = (url as any).params as Record; const date = params.date; const detail = getDayDetail(date); if (!detail) { return jsonResponse({ error: 'Day not found' }, 404); } return jsonResponse(detail); } async function handleGetDayBrag(req: Request, url: URL): Promise { const params = (url as any).params as Record; const date = params.date; const detail = getDayDetail(date); if (!detail) { return jsonResponse({ error: 'Day not found' }, 404); } return jsonResponse({ date, bragSummary: detail.bragSummary || 'No summary available', projectCount: detail.projects.length, sessionCount: detail.stats.totalSessions, }); } async function handleGetStats(req: Request, url: URL): Promise { const stats = getStats(); return jsonResponse(stats); } async function handleRefresh(req: Request, url: URL): Promise { // Run processing in background const startTime = Date.now(); try { const result = await processCommand({ force: false, verbose: false, }); return jsonResponse({ success: true, sessionsProcessed: result.sessionsProcessed, errors: result.errors, durationMs: Date.now() - startTime, }); } catch (error) { return jsonResponse( { success: false, error: error instanceof Error ? error.message : 'Unknown error', }, 500 ); } }