Files
AIclinicalresearch/backend/src/index.ts
HaHafeng 0c5310fb77 refactor(backend): incremental architecture evolution (Task 19)
- Add common/ layer for shared capabilities (LLM, RAG, document, middleware)
- Add legacy/ layer for existing business code
- Move files to new structure (controllers, routes, services)
- Update index.ts for new route registration
- System remains fully functional
2025-11-16 15:42:44 +08:00

140 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Fastify from 'fastify';
import cors from '@fastify/cors';
import multipart from '@fastify/multipart';
import { config, validateEnv } from './config/env.js';
import { testDatabaseConnection, prisma } from './config/database.js';
import { projectRoutes } from './legacy/routes/projects.js';
import { agentRoutes } from './legacy/routes/agents.js';
import { conversationRoutes } from './legacy/routes/conversations.js';
import knowledgeBaseRoutes from './legacy/routes/knowledgeBases.js';
import { chatRoutes } from './legacy/routes/chatRoutes.js';
import { batchRoutes } from './legacy/routes/batchRoutes.js';
import reviewRoutes from './legacy/routes/reviewRoutes.js';
// 全局处理BigInt序列化
(BigInt.prototype as any).toJSON = function() {
return Number(this);
};
const fastify = Fastify({
logger: {
level: config.logLevel,
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname',
},
},
},
});
// 注册CORS插件 - 完整配置
await fastify.register(cors, {
origin: true, // 开发环境允许所有来源
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'], // 明确允许的HTTP方法
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept', 'Origin'], // 允许的请求头
exposedHeaders: ['Content-Range', 'X-Content-Range'], // 暴露的响应头
maxAge: 600, // preflight请求缓存时间
preflightContinue: false, // Fastify处理preflight请求
});
console.log('✅ CORS已配置: 允许所有HTTP方法 (GET, POST, PUT, DELETE, PATCH, OPTIONS)');
// 注册文件上传插件
await fastify.register(multipart, {
limits: {
fileSize: 10 * 1024 * 1024, // 10MB
},
});
console.log('✅ 文件上传插件已配置: 最大文件大小 10MB');
// 健康检查路由
fastify.get('/health', async () => {
// 检查数据库连接
let dbStatus = 'unknown';
try {
await prisma.$queryRaw`SELECT 1`;
dbStatus = 'connected';
} catch {
dbStatus = 'disconnected';
}
return {
status: 'ok',
database: dbStatus,
timestamp: new Date().toISOString(),
uptime: process.uptime(),
};
});
// API路由前缀
fastify.get('/api/v1', async () => {
return {
message: 'AI Clinical Research Platform API',
version: '1.0.0',
environment: config.nodeEnv,
};
});
// 注册项目管理路由
await fastify.register(projectRoutes, { prefix: '/api/v1' });
// 注册智能体管理路由
await fastify.register(agentRoutes, { prefix: '/api/v1' });
// 注册对话管理路由
await fastify.register(conversationRoutes, { prefix: '/api/v1' });
// 注册知识库管理路由
await fastify.register(knowledgeBaseRoutes, { prefix: '/api/v1' });
// 注册通用对话路由
await fastify.register(chatRoutes, { prefix: '/api/v1' });
// Phase 3: 注册批处理路由
await fastify.register(batchRoutes, { prefix: '/api/v1' });
// 注册稿件审查路由
await fastify.register(reviewRoutes, { prefix: '/api/v1' });
// 启动服务器
const start = async () => {
try {
// 验证环境变量
validateEnv();
// 测试数据库连接
console.log('🔍 正在测试数据库连接...');
const dbConnected = await testDatabaseConnection();
if (!dbConnected) {
console.error('❌ 数据库连接失败,无法启动服务器');
process.exit(1);
}
// 启动Fastify服务器
await fastify.listen({
port: config.port,
host: config.host,
});
console.log('\n' + '='.repeat(60));
console.log('🚀 AI临床研究平台 - 后端服务器启动成功!');
console.log('='.repeat(60));
console.log(`📍 服务地址: http://${config.host === '0.0.0.0' ? 'localhost' : config.host}:${config.port}`);
console.log(`🔍 健康检查: http://localhost:${config.port}/health`);
console.log(`📡 API入口: http://localhost:${config.port}/api/v1`);
console.log(`🌍 运行环境: ${config.nodeEnv}`);
console.log('='.repeat(60) + '\n');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();