Files
GRH/water-api/src/index.ts
2026-02-01 20:54:13 -06:00

106 lines
2.8 KiB
TypeScript

import dotenv from 'dotenv';
dotenv.config();
import express, { Application, Request, Response, NextFunction } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import routes from './routes';
import logger from './utils/logger';
import { testConnection } from './config/database';
import { auditMiddleware } from './middleware/audit.middleware';
import { scheduleNegativeFlowDetection } from './jobs/negativeFlowDetection';
const app: Application = express();
const PORT = process.env.PORT || 3000;
const NODE_ENV = process.env.NODE_ENV || 'development';
// Security middleware
app.use(helmet());
// CORS configuration
const allowedOrigins = (process.env.CORS_ORIGIN || 'http://localhost:5173')
.split(',')
.map(origin => origin.trim());
app.use(cors({
origin: (origin, callback) => {
// Allow requests with no origin (mobile apps, curl, etc.)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
logger.warn(`CORS blocked origin: ${origin}`);
callback(null, true); // Allow all in development
}
},
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
// Body parsing middleware
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// Audit logging middleware (before routes)
app.use(auditMiddleware);
// Health check endpoint
app.get('/health', (_req: Request, res: Response) => {
res.status(200).json({
status: 'ok',
timestamp: new Date().toISOString(),
environment: NODE_ENV
});
});
// Mount all API routes
app.use('/api', routes);
// 404 handler
app.use((_req: Request, res: Response) => {
res.status(404).json({
success: false,
message: 'Resource not found',
error: 'NOT_FOUND'
});
});
// Global error handler
app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
console.error('Error:', err);
res.status(500).json({
success: false,
message: NODE_ENV === 'development' ? err.message : 'Internal server error',
error: 'INTERNAL_ERROR'
});
});
// Start server
const startServer = async () => {
try {
// Test database connection
await testConnection();
logger.info('Database connection established');
scheduleNegativeFlowDetection();
logger.info('Cron jobs initialized');
app.listen(PORT, () => {
logger.info(`Server running on port ${PORT} in ${NODE_ENV} mode`);
logger.info(`Health check available at http://localhost:${PORT}/health`);
logger.info(`API available at http://localhost:${PORT}/api`);
});
} catch (error) {
logger.error('Failed to start server:', error);
process.exit(1);
}
};
startServer();
export default app;