/** * Express 应用入口 * 处理持久化 API 路由 */ import express from 'express'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { prisma } from './db/client.js'; import { requireAuth } from './auth/middleware.js'; // 导入路由(稍后创建) import documentsRouter from './routes/documents.js'; import userRouter from './routes/user.js'; import glossaryRouter from './routes/glossary.js'; import chatRouter from './routes/chat.js'; import referencesRouter from './routes/references.js'; import promptPoolRouter from './routes/prompt-pool.js'; const app = express(); const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const projectRoot = join(__dirname, '..'); // ==================== 中间件配置 ==================== // JSON 解析 app.use(express.json({ limit: '50mb' })); app.use(express.urlencoded({ extended: true, limit: '50mb' })); // CORS app.use((req, res, next) => { const origin = req.headers.origin || '*'; res.header('Access-Control-Allow-Origin', origin); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key'); res.header('Access-Control-Expose-Headers', 'Content-Length, Content-Range'); if (req.method === 'OPTIONS') { return res.sendStatus(200); } next(); }); // 请求日志(开发环境) if (process.env.NODE_ENV !== 'production') { app.use((req, res, next) => { console.log(`[Express] ${req.method} ${req.path}`); next(); }); } // 开发模式下让 Vite 代理过来的 PDF.js 静态资源可用。 app.use('/pdfjs', express.static(join(projectRoot, 'pdfjs'))); // ==================== 路由注册 ==================== // 健康检查(无需认证) app.get('/health', async (req, res) => { try { // 测试数据库连接 await prisma.$queryRaw`SELECT 1`; res.json({ status: 'ok', database: 'connected', authDisabled: process.env.AUTH_DISABLED === 'true', timestamp: Date.now() }); } catch (error) { res.json({ status: 'ok', database: 'disconnected', authDisabled: process.env.AUTH_DISABLED === 'true', timestamp: Date.now() }); } }); // 持久化路由(需要认证) app.use('/api/documents', requireAuth, documentsRouter); app.use('/api/user', requireAuth, userRouter); app.use('/api/glossary', requireAuth, glossaryRouter); app.use('/api/chat', requireAuth, chatRouter); app.use('/api/references', requireAuth, referencesRouter); app.use('/api/prompt-pool', requireAuth, promptPoolRouter); // ==================== 错误处理 ==================== // 404 app.use((req, res) => { res.status(404).json({ error: 'Not Found' }); }); // 统一错误处理 app.use((err, req, res, next) => { console.error('[Express] Error:', err.message); res.status(err.status || 500).json({ error: err.message || 'Internal Server Error' }); }); export default app;