- Add new database migrations for analysis data and job tracking - Implement enhanced document processing service with LLM integration - Add processing progress and queue status components - Create testing guides and utility scripts for CIM processing - Update frontend components for better user experience - Add environment configuration and backup files - Implement job queue service and upload progress tracking
137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
import express from 'express';
|
|
import cors from 'cors';
|
|
import helmet from 'helmet';
|
|
import morgan from 'morgan';
|
|
import rateLimit from 'express-rate-limit';
|
|
import { config } from './config/env';
|
|
import { logger } from './utils/logger';
|
|
import authRoutes from './routes/auth';
|
|
import documentRoutes from './routes/documents';
|
|
import { errorHandler } from './middleware/errorHandler';
|
|
import { notFoundHandler } from './middleware/notFoundHandler';
|
|
import { jobQueueService } from './services/jobQueueService';
|
|
|
|
const app = express();
|
|
const PORT = config.port || 5000;
|
|
|
|
// Security middleware
|
|
app.use(helmet({
|
|
contentSecurityPolicy: {
|
|
directives: {
|
|
defaultSrc: ["'self'"],
|
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
scriptSrc: ["'self'"],
|
|
imgSrc: ["'self'", "data:", "https:"],
|
|
},
|
|
},
|
|
}));
|
|
|
|
// CORS configuration
|
|
app.use(cors({
|
|
origin: config.frontendUrl || 'http://localhost:3000',
|
|
credentials: true,
|
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
|
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
}));
|
|
|
|
// Rate limiting
|
|
const limiter = rateLimit({
|
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
max: 1000, // limit each IP to 1000 requests per windowMs (increased for testing)
|
|
message: {
|
|
error: 'Too many requests from this IP, please try again later.',
|
|
},
|
|
standardHeaders: true,
|
|
legacyHeaders: false,
|
|
});
|
|
|
|
app.use(limiter);
|
|
|
|
// Body parsing middleware
|
|
app.use(express.json({ limit: '10mb' }));
|
|
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
|
|
// Logging middleware
|
|
app.use(morgan('combined', {
|
|
stream: {
|
|
write: (message: string) => logger.info(message.trim()),
|
|
},
|
|
}));
|
|
|
|
// Health check endpoint
|
|
app.get('/health', (_req, res) => { // _req to fix TS6133
|
|
res.status(200).json({
|
|
status: 'ok',
|
|
timestamp: new Date().toISOString(),
|
|
uptime: process.uptime(),
|
|
environment: config.nodeEnv,
|
|
});
|
|
});
|
|
|
|
// API routes
|
|
app.use('/api/auth', authRoutes);
|
|
app.use('/api/documents', documentRoutes);
|
|
|
|
// API root endpoint
|
|
app.get('/api', (_req, res) => { // _req to fix TS6133
|
|
res.json({
|
|
message: 'CIM Document Processor API',
|
|
version: '1.0.0',
|
|
endpoints: {
|
|
auth: '/api/auth',
|
|
documents: '/api/documents',
|
|
health: '/health',
|
|
},
|
|
});
|
|
});
|
|
|
|
// 404 handler
|
|
app.use(notFoundHandler);
|
|
|
|
// Global error handler (must be last)
|
|
app.use(errorHandler);
|
|
|
|
// Start server
|
|
const server = app.listen(PORT, () => {
|
|
logger.info(`🚀 Server running on port ${PORT}`);
|
|
logger.info(`📊 Environment: ${config.nodeEnv}`);
|
|
logger.info(`🔗 API URL: http://localhost:${PORT}/api`);
|
|
logger.info(`🏥 Health check: http://localhost:${PORT}/health`);
|
|
});
|
|
|
|
// Start job queue service
|
|
jobQueueService.start();
|
|
logger.info('📋 Job queue service started');
|
|
|
|
// Graceful shutdown
|
|
const gracefulShutdown = (signal: string) => {
|
|
logger.info(`${signal} received, shutting down gracefully`);
|
|
|
|
// Stop accepting new connections
|
|
server.close(() => {
|
|
logger.info('HTTP server closed');
|
|
|
|
// Stop job queue service
|
|
jobQueueService.stop();
|
|
logger.info('Job queue service stopped');
|
|
|
|
// Stop upload progress service
|
|
const { uploadProgressService } = require('./services/uploadProgressService');
|
|
uploadProgressService.stop();
|
|
logger.info('Upload progress service stopped');
|
|
|
|
logger.info('Process terminated');
|
|
process.exit(0);
|
|
});
|
|
|
|
// Force close after 30 seconds
|
|
setTimeout(() => {
|
|
logger.error('Could not close connections in time, forcefully shutting down');
|
|
process.exit(1);
|
|
}, 30000);
|
|
};
|
|
|
|
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
|
|
export default app;
|