import express from 'express'; import morgan from 'morgan'; import helmet from 'helmet'; import cors from 'cors'; import cookieParser from 'cookie-parser'; import { validateBody } from './middlewares/global/validateBody.js'; import { notFound } from './middlewares/global/notFound.js'; import { errorHandler } from './middlewares/global/errorHandler.js'; import { apiRateLimiter } from './middlewares/security/rateLimiter.js'; import { logger } from './utils/logger.js'; // Import routes import authRoutes from './routes/auth.routes.js'; import adminRoutes from './routes/admin.routes.js'; import contactRoutes from './routes/contact.routes.js'; import personalContactRoutes from './routes/personal-contact.routes.js'; import crmEmailRoutes from './routes/crm-email.routes.js'; import emailAccountRoutes from './routes/email-account.routes.js'; import timesheetRoutes from './routes/timesheet.routes.js'; import companyRoutes from './routes/company.routes.js'; import projectRoutes from './routes/project.routes.js'; import todoRoutes from './routes/todo.routes.js'; import timeTrackingRoutes from './routes/time-tracking.routes.js'; import noteRoutes from './routes/note.routes.js'; import auditRoutes from './routes/audit.routes.js'; import eventRoutes from './routes/event.routes.js'; import messageRoutes from './routes/message.routes.js'; import userRoutes from './routes/user.routes.js'; import serviceRoutes from './routes/service.routes.js'; import emailSignatureRoutes from './routes/email-signature.routes.js'; const app = express(); // HTTP request logging - only errors by default (LOG_LEVEL=debug shows all) app.use(morgan((tokens, req, res) => { const status = parseInt(tokens.status(req, res)) || 0; const message = `${tokens.method(req, res)} ${tokens.url(req, res)} ${status} ${tokens['response-time'](req, res)} ms`; logger.http(message, status); return null; // Don't write to stdout, logger handles it })); app.use( helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'"], }, }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true, }, }) ); // CORS configuration - allow local network access const corsOptions = { origin: (origin, callback) => { // Allow requests with no origin (mobile apps, curl, etc.) if (!origin) return callback(null, true); // Allow localhost and local network IPs const allowedPatterns = [ /^http:\/\/localhost(:\d+)?$/, /^http:\/\/127\.0\.0\.1(:\d+)?$/, /^http:\/\/192\.168\.\d{1,3}\.\d{1,3}(:\d+)?$/, /^http:\/\/10\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d+)?$/, /^http:\/\/172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}(:\d+)?$/, ]; // Check if origin matches allowed patterns or CORS_ORIGIN env const corsOrigin = process.env.CORS_ORIGIN; if (corsOrigin && origin === corsOrigin) { return callback(null, true); } if (allowedPatterns.some(pattern => pattern.test(origin))) { return callback(null, true); } callback(new Error('Not allowed by CORS')); }, credentials: true, optionsSuccessStatus: 200, }; app.use(cors(corsOptions)); // Body parsing middleware app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); app.use(cookieParser()); // Custom body validation middleware app.use(validateBody); // Rate limiting for all API routes app.use('/api', apiRateLimiter); // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ success: true, message: 'CRM API is running', timestamp: new Date().toISOString(), }); }); // API Routes app.use('/api/auth', authRoutes); app.use('/api/admin', adminRoutes); app.use('/api/contacts', contactRoutes); app.use('/api/personal-contacts', personalContactRoutes); app.use('/api/emails', crmEmailRoutes); app.use('/api/email-accounts', emailAccountRoutes); app.use('/api/timesheets', timesheetRoutes); app.use('/api/companies', companyRoutes); app.use('/api/projects', projectRoutes); app.use('/api/todos', todoRoutes); app.use('/api/time-tracking', timeTrackingRoutes); app.use('/api/notes', noteRoutes); app.use('/api/audit-logs', auditRoutes); app.use('/api/events', eventRoutes); app.use('/api/messages', messageRoutes); app.use('/api/users', userRoutes); app.use('/api/services', serviceRoutes); app.use('/api/email-signature', emailSignatureRoutes); // Basic route app.get('/', (req, res) => { res.json({ success: true, message: 'CRM API Server', version: '1.0.0', }); }); // Global Middlewares (must be last) app.use(notFound); app.use(errorHandler); export default app;