import 'reflect-metadata'; import express, { Application, Request, Response, NextFunction } from 'express'; import cors from 'cors'; import helmet from 'helmet'; import compression from 'compression'; import morgan from 'morgan'; // Route imports import branchRoutes from './modules/branches/routes/branch.routes'; import posRoutes from './modules/pos/routes/pos.routes'; // Error type interface AppError extends Error { statusCode?: number; status?: string; isOperational?: boolean; } // Create Express app const app: Application = express(); // Security middleware app.use(helmet()); // CORS configuration app.use(cors({ origin: process.env.CORS_ORIGIN?.split(',') || ['http://localhost:3000', 'http://localhost:5173'], credentials: true, methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'X-Tenant-ID', 'X-Branch-ID'], })); // Compression app.use(compression()); // Body parsing app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Request logging if (process.env.NODE_ENV !== 'test') { app.use(morgan(process.env.NODE_ENV === 'production' ? 'combined' : 'dev')); } // Health check endpoint app.get('/health', (_req: Request, res: Response) => { res.json({ status: 'healthy', timestamp: new Date().toISOString(), version: process.env.npm_package_version || '0.1.0', environment: process.env.NODE_ENV || 'development', }); }); // API version info app.get('/api', (_req: Request, res: Response) => { res.json({ name: 'ERP Retail API', version: '0.1.0', modules: [ 'branches', 'pos', 'cash', 'inventory', 'customers', 'pricing', 'invoicing', 'ecommerce', 'purchases', ], }); }); // API Routes app.use('/api/branches', branchRoutes); app.use('/api/pos', posRoutes); // TODO: Add remaining route modules as they are implemented // app.use('/api/cash', cashRouter); // app.use('/api/inventory', inventoryRouter); // app.use('/api/customers', customersRouter); // app.use('/api/pricing', pricingRouter); // app.use('/api/invoicing', invoicingRouter); // app.use('/api/ecommerce', ecommerceRouter); // app.use('/api/purchases', purchasesRouter); // 404 handler app.use((_req: Request, res: Response) => { res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: 'The requested resource was not found', }, }); }); // Global error handler app.use((err: AppError, _req: Request, res: Response, _next: NextFunction) => { const statusCode = err.statusCode || 500; const status = err.status || 'error'; // Log error console.error('Error:', { message: err.message, stack: process.env.NODE_ENV === 'development' ? err.stack : undefined, statusCode, }); // Send response res.status(statusCode).json({ success: false, error: { code: status.toUpperCase().replace(/ /g, '_'), message: err.isOperational ? err.message : 'An unexpected error occurred', ...(process.env.NODE_ENV === 'development' && { stack: err.stack }), }, }); }); export default app;