/** * EMERGES TES - Backend API Server * * FASE 1: Infraestructura Base * * IMPORTANTE: Este es un esqueleto básico. * La implementación completa se hará progresivamente. */ import express from 'express'; import cors from 'cors'; import dotenv from 'dotenv'; import { join } from 'path'; import { testConnection } from '../config/database.js'; import { validateSecurityConfig } from './config/security.js'; import { validateEnv } from './config/env.js'; import { getCorsConfig } from './config/cors.js'; import { securityHeaders } from './middleware/security-headers.js'; import { generalLimiter } from './middleware/rate-limit.js'; import logger, { logError } from './utils/logger.js'; import requestLogger from './middleware/request-logger.js'; import authRoutes from './routes/auth.js'; // TypeScript import contentRoutes from './routes/content.js'; // TypeScript import statsRoutes from './routes/stats.js'; // TypeScript import contentPackRoutes from './routes/content-pack.js'; // TypeScript import contentPackAdminRoutes from './routes/content-pack-admin.js'; // TypeScript import mediaRoutes from './routes/media.js'; // TypeScript import contentResourcesRoutes from './routes/content-resources.js'; // TypeScript import scormRoutes from './routes/scorm.js'; // TypeScript import validationRoutes from './routes/validation.js'; // TypeScript import drugsRoutes from './routes/drugs.js'; // TypeScript import webhookRoutes from './routes/webhook.js'; // TypeScript import healthRoutes from './routes/health.js'; // TypeScript dotenv.config(); // ✅ VALIDACIÓN CRÍTICA DE SEGURIDAD AL STARTUP // Si alguna validación falla, la app no arranca logger.info('🔒 Validando configuración de seguridad...'); validateSecurityConfig(); validateEnv(); logger.info('✅ Configuración validada correctamente'); const app = express(); const PORT = process.env.PORT || process.env.API_PORT || 3000; // ✅ SECURITY HEADERS (Helmet.js) app.use(securityHeaders); // ✅ CORS MEJORADO (con validación de orígenes) app.use(cors(getCorsConfig())); // ✅ RATE LIMITING GENERAL app.use(generalLimiter); // ✅ REQUEST LOGGING app.use(requestLogger); // ✅ JSON PARSING app.use(express.json({ limit: '10mb' })); // Limitar tamaño de payload // Servir archivos estáticos de media app.use('/storage/media', express.static(join(process.cwd(), 'storage', 'media'))); // Health check básico (mantener para compatibilidad) app.get('/health', async (_req, res) => { const dbStart = Date.now(); const dbConnected = await testConnection(); const dbResponseTime = Date.now() - dbStart; const health = { status: dbConnected ? 'ok' : 'degraded', timestamp: new Date().toISOString(), database: dbConnected ? 'connected' : 'disconnected', databaseResponseTime: dbResponseTime, uptime: process.uptime(), memory: { used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024), total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024), }, }; if (!dbConnected) { logger.warn('Health check: Database disconnected'); } res.json(health); }); // Root endpoint app.get('/', (_req, res) => { res.json({ message: 'EMERGES TES Backend API', version: '1.0.0', endpoints: { auth: '/api/auth', content: '/api/content', stats: '/api/stats', contentPack: '/api/content-pack', health: '/health', }, }); }); // API Routes app.use('/api/auth', authRoutes); app.use('/api/content', contentRoutes); app.use('/api/stats', statsRoutes); app.use('/api/content-pack', contentPackRoutes); app.use('/api/admin/content-pack', contentPackAdminRoutes); app.use('/api/media', mediaRoutes); app.use('/api/content', contentResourcesRoutes); app.use('/api/scorm', scormRoutes); app.use('/api/validation', validationRoutes); app.use('/api/drugs', drugsRoutes); app.use('/api/webhook', webhookRoutes); app.use('/api/health', healthRoutes); // Iniciar servidor app.listen(PORT, async () => { logger.info('🚀 EMERGES TES Backend API iniciado', { port: PORT, environment: process.env.NODE_ENV || 'development', nodeVersion: process.version, }); logger.info('📍 Endpoints disponibles', { health: `http://localhost:${PORT}/health`, auth: `http://localhost:${PORT}/api/auth`, content: `http://localhost:${PORT}/api/content`, }); // Test de conexión a BD const dbConnected = await testConnection(); if (dbConnected) { logger.info('✅ Conexión a base de datos establecida'); } else { logger.error('❌ Error conectando a base de datos'); } }); // Manejo de errores process.on('SIGTERM', async () => { logger.info('SIGTERM recibido, cerrando servidor...'); process.exit(0); }); process.on('unhandledRejection', (error) => { logError(error instanceof Error ? error : new Error(String(error)), { type: 'unhandledRejection' }); }); process.on('uncaughtException', (error) => { logError(error, { type: 'uncaughtException' }); process.exit(1); }); //# sourceMappingURL=index.js.map