import express, { type Express } from 'express'; import cors from 'cors'; import helmet from 'helmet'; import { env, getCorsOrigins } from './config/env.js'; import { errorMiddleware } from './middlewares/error.middleware.js'; import { authRoutes } from './routes/auth.routes.js'; import { dashboardRoutes } from './routes/dashboard.routes.js'; import { cfdiRoutes } from './routes/cfdi.routes.js'; import { impuestosRoutes } from './routes/impuestos.routes.js'; import { exportRoutes } from './routes/export.routes.js'; import { alertasRoutes } from './routes/alertas.routes.js'; import { notificationPreferencesRoutes } from './routes/notification-preferences.routes.js'; import { tareasRoutes } from './routes/tareas.routes.js'; import { papeleriaRoutes } from './routes/papeleria.routes.js'; import { despachoStatsRoutes } from './routes/despacho-stats.routes.js'; import { calendarioRoutes } from './routes/calendario.routes.js'; import { reportesRoutes } from './routes/reportes.routes.js'; import { usuariosRoutes } from './routes/usuarios.routes.js'; import { tenantsRoutes } from './routes/tenants.routes.js'; import fielRoutes from './routes/fiel.routes.js'; import satRoutes from './routes/sat.routes.js'; import { webhookRoutes } from './routes/webhook.routes.js'; import { subscriptionRoutes } from './routes/subscription.routes.js'; import { regimenRoutes } from './routes/regimen.routes.js'; import { bancosRoutes } from './routes/bancos.routes.js'; import { conciliacionRoutes } from './routes/conciliacion.routes.js'; import { facturacionRoutes } from './routes/facturacion.routes.js'; import { catalogosRoutes } from './routes/catalogos.routes.js'; import { documentosRoutes } from './routes/documentos.routes.js'; import { auditLogRoutes } from './routes/audit-log.routes.js'; import { platformStaffRoutes } from './routes/platform-staff.routes.js'; import despachoRoutes from './routes/despacho.routes.js'; import contribuyenteRoutes from './routes/contribuyente.routes.js'; import carteraRoutes from './routes/cartera.routes.js'; import planCatalogoRoutes from './routes/plan-catalogo.routes.js'; import connectorRoutes from './routes/connector.routes.js'; import adminDashboardRoutes from './routes/admin-dashboard.routes.js'; import adminImpersonateRoutes from './routes/admin-impersonate.routes.js'; import adminClientesRoutes from './routes/admin-clientes.routes.js'; import adminAddonsRoutes from './routes/admin-addons.routes.js'; import despachoAuditRoutes from './routes/despacho-audit.routes.js'; import metricasRoutes from './routes/metricas.routes.js'; const app: Express = express(); // Security. Helmet default incluye un CSP restrictivo que puede chocar con el // frontend cuando éste embebe recursos propios (ej: /terminos embebe el PDF de // /legal/). Dejamos CSP off en el API y centralizamos los headers de seguridad // en next.config del web (X-Frame-Options, CSP frame-ancestors, HSTS, nosniff, // Referrer-Policy) que es quien sirve la UI. El API solo responde JSON y // archivos binarios (PDFs, XMLs) — no tiene contenido HTML que requiera CSP. app.use(helmet({ contentSecurityPolicy: false, crossOriginResourcePolicy: { policy: 'cross-origin' }, // permite /legal/*.pdf embebido })); app.use(cors({ origin: getCorsOrigins(), credentials: true, })); // Body parsing - 10MB default, bulk CFDI route has its own higher limit app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Health check app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); // API Routes app.use('/api/auth', authRoutes); app.use('/api/dashboard', dashboardRoutes); app.use('/api/cfdi', cfdiRoutes); app.use('/api/impuestos', impuestosRoutes); app.use('/api/export', exportRoutes); app.use('/api/alertas', alertasRoutes); app.use('/api/notificaciones', notificationPreferencesRoutes); app.use('/api/tareas', tareasRoutes); app.use('/api/papeleria', papeleriaRoutes); app.use('/api/despachos', despachoStatsRoutes); app.use('/api/calendario', calendarioRoutes); app.use('/api/reportes', reportesRoutes); app.use('/api/usuarios', usuariosRoutes); app.use('/api/tenants', tenantsRoutes); app.use('/api/fiel', fielRoutes); app.use('/api/sat', satRoutes); app.use('/api/webhooks', webhookRoutes); app.use('/api/subscriptions', subscriptionRoutes); app.use('/api/regimenes', regimenRoutes); app.use('/api/bancos', bancosRoutes); app.use('/api/conciliacion', conciliacionRoutes); app.use('/api/facturacion', facturacionRoutes); app.use('/api/catalogos', catalogosRoutes); app.use('/api/documentos', documentosRoutes); app.use('/api/audit-log', auditLogRoutes); app.use('/api/platform-staff', platformStaffRoutes); app.use('/api/despachos', despachoRoutes); app.use('/api/contribuyentes', contribuyenteRoutes); app.use('/api/carteras', carteraRoutes); app.use('/api/planes', planCatalogoRoutes); app.use('/api/connector', connectorRoutes); app.use('/api/admin/dashboard', adminDashboardRoutes); app.use('/api/admin/impersonate', adminImpersonateRoutes); app.use('/api/admin/clientes', adminClientesRoutes); app.use('/api/admin/addons', adminAddonsRoutes); app.use('/api/despacho/audit-log', despachoAuditRoutes); app.use('/api/metricas', metricasRoutes); // Error handling app.use(errorMiddleware); export { app };