import { optionsResponse, notFoundResponse } from '../utils/cors' import { handleHistory } from './history' import { handleConfig, handleHealth } from './config' import { handleWebMCPToken } from './webmcp' import { handleComponents, handleComponentById, handleComponentUsage } from './components' import { handleThemes, handleActiveTheme, handleDesignTokens, handleThemeById, handleThemeExport } from './themes' import { handleCanvas, handleCanvasById, handleToolbarCanvas, handleDefaultCanvas, handleCanvasComponents, handleCanvasComponentById } from './canvas' import { handleGiteaRepo, handleGiteaTree, handleGiteaFile } from './gitea' import { handleTables, handleStats, handleTableSchema, handleTableData, handleQuery } from './database' import { handleWhisperRoutes } from './whisper' import { handleRecordingsRoutes } from './recordings' import { handleClaudeStatus } from './claude-status' export async function handleRequest(req: Request): Promise { const url = new URL(req.url) const path = url.pathname // CORS preflight if (req.method === 'OPTIONS') { return optionsResponse() } // Health if (path === '/api/health') { return handleHealth() } // History if (path === '/api/history') { const res = await handleHistory(req, url) if (res) return res } // Config if (path === '/api/config') { const res = await handleConfig(req, url) if (res) return res } // WebMCP Token if (path === '/api/webmcp-token') { const res = await handleWebMCPToken(req) if (res) return res } // Claude Code status (thinking/idle) if (path === '/api/claude-status') { const res = await handleClaudeStatus(req) if (res) return res } // Components if (path === '/api/components') { const res = await handleComponents(req) if (res) return res } // Component usage const componentUsageMatch = path.match(/^\/api\/components\/([^/]+)\/usage$/) if (componentUsageMatch && req.method === 'GET') { return handleComponentUsage(componentUsageMatch[1]) } // Component by ID if (path.startsWith('/api/components/') && !path.includes('/usage')) { const id = path.split('/').pop()! const res = await handleComponentById(req, id) if (res) return res } // Themes if (path === '/api/themes') { const res = await handleThemes(req) if (res) return res } if (path === '/api/themes/active') { return handleActiveTheme() } if (path === '/api/design-tokens') { return handleDesignTokens() } // Theme export if (path.startsWith('/api/themes/export/')) { const id = path.split('/').pop()! if (req.method === 'GET') { return handleThemeExport(id) } } // Theme by ID if (path.startsWith('/api/themes/') && !path.includes('/active') && !path.includes('/export')) { const pathParts = path.split('/') const id = pathParts[3] const action = pathParts[4] const res = await handleThemeById(req, id, action) if (res) return res } // Canvas toolbar if (path === '/api/canvas/toolbar') { return handleToolbarCanvas() } // Canvas default if (path === '/api/canvas/default') { return handleDefaultCanvas() } // Canvas list/create if (path === '/api/canvas') { const res = await handleCanvas(req) if (res) return res } // Canvas components const canvasComponentsMatch = path.match(/^\/api\/canvas\/([^/]+)\/components\/?$/) if (canvasComponentsMatch) { const res = await handleCanvasComponents(req, canvasComponentsMatch[1]) if (res) return res } // Canvas component by ID const canvasComponentMatch = path.match(/^\/api\/canvas\/([^/]+)\/components\/([^/]+)$/) if (canvasComponentMatch) { const res = await handleCanvasComponentById(req, canvasComponentMatch[1], canvasComponentMatch[2]) if (res) return res } // Canvas by ID if (path.startsWith('/api/canvas/') && !path.includes('/components')) { const pathParts = path.split('/') const id = pathParts[3] const action = pathParts[4] const res = await handleCanvasById(req, id, action) if (res) return res } // Gitea if (path === '/api/gitea/repo' && req.method === 'POST') { return handleGiteaRepo(req) } if (path === '/api/gitea/tree' && req.method === 'POST') { return handleGiteaTree(req) } if (path === '/api/gitea/file' && req.method === 'POST') { return handleGiteaFile(req) } // Database Explorer if (path === '/api/database/tables') { return handleTables() } if (path === '/api/database/stats') { return handleStats() } // Table schema const tableSchemaMatch = path.match(/^\/api\/database\/tables\/([^/]+)\/schema$/) if (tableSchemaMatch && req.method === 'GET') { return handleTableSchema(decodeURIComponent(tableSchemaMatch[1])) } // Table data const tableDataMatch = path.match(/^\/api\/database\/tables\/([^/]+)\/data$/) if (tableDataMatch && req.method === 'GET') { return handleTableData(decodeURIComponent(tableDataMatch[1]), url) } // Database query if (path === '/api/database/query' && req.method === 'POST') { return handleQuery(req) } // Whisper (GPU speech-to-text) if (path.startsWith('/api/whisper/')) { const res = await handleWhisperRoutes(req) if (res) return res } // Voice recordings (for training custom models) if (path.startsWith('/api/recordings')) { const res = await handleRecordingsRoutes(req) if (res) return res } return notFoundResponse() }