refactor: Modularize server into separate concerns
Split monolithic index.ts (~1400 lines) into modular structure: - config.ts: Server configuration and constants - db/: Database initialization, migrations, and seeds - routes/: API handlers by domain (themes, canvas, components, etc.) - services/: Terminal WebSocket server - utils/: CORS helpers Entry point now only coordinates initialization.
This commit is contained in:
172
server/routes/index.ts
Normal file
172
server/routes/index.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
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'
|
||||
|
||||
export async function handleRequest(req: Request): Promise<Response> {
|
||||
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
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
return notFoundResponse()
|
||||
}
|
||||
Reference in New Issue
Block a user