app.ts•2.18 kB
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import helmet from 'helmet';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs-extra';
import apiRoutes from './routes/api.js';
import { config, ensureDataDirs } from './utils/config.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* 创建Express应用
*/
export async function createApp() {
// 确保数据目录存在
await ensureDataDirs();
const app = express();
// 全局中间件
app.use(helmet({
contentSecurityPolicy: false
}));
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 静态文件服务
app.use(express.static(path.join(__dirname, '../public')));
// API路由
app.use('/api', apiRoutes);
// 前端路由 - SPA支持
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../public/index.html'));
});
// 错误处理
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error('应用错误:', err);
res.status(err.status || 500).json({
success: false,
error: err.message || '服务器内部错误'
});
});
return app;
}
/**
* 启动Web服务器
*/
export async function startWebServer() {
const app = await createApp();
const port = config.port;
return new Promise<void>((resolve, reject) => {
try {
const server = app.listen(port, () => {
console.log(`Memory Bank Web服务器已启动,端口: ${port}`);
resolve();
});
// 异常处理
server.on('error', (error: any) => {
if (error.code === 'EADDRINUSE') {
console.error(`端口 ${port} 已被占用`);
reject(new Error(`端口 ${port} 已被占用`));
} else {
console.error('Web服务器启动错误:', error);
reject(error);
}
});
} catch (error) {
console.error('Web服务器启动失败:', error);
reject(error);
}
});
}
export default createApp;