UNPKG

ci-validation

Version:

🇺🇾 Complete TypeScript/JavaScript library for validating Uruguayan CI (Cédula de Identidad) with official algorithm and government service integration

205 lines 8.22 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const cors_1 = __importDefault(require("cors")); const dotenv_1 = __importDefault(require("dotenv")); const express_1 = __importDefault(require("express")); const fs_1 = __importDefault(require("fs")); const helmet_1 = __importDefault(require("helmet")); const path_1 = __importDefault(require("path")); const swagger_ui_express_1 = __importDefault(require("swagger-ui-express")); const errorHandler_1 = require("./middleware/errorHandler"); const rateLimiter_1 = require("./middleware/rateLimiter"); const ciRoutes_1 = require("./routes/ciRoutes"); const dependencyContainer_1 = require("./utils/dependencyContainer"); // Load environment variables dotenv_1.default.config(); /** * Configuración principal de la aplicación Express * Siguiendo principios SOLID y buenas prácticas de seguridad */ class App { constructor() { this.app = (0, express_1.default)(); this.port = parseInt(process.env.PORT || "3000", 10); this.initializeMiddlewares(); this.initializeRoutes(); this.initializeErrorHandling(); } /** * Configura middlewares de seguridad y utilidad */ initializeMiddlewares() { // Seguridad this.app.use((0, helmet_1.default)({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], styleSrc: ["'self'", "'unsafe-inline'", "https://cdn.jsdelivr.net", "https://cdnjs.cloudflare.com", "https://unpkg.com"], scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://unpkg.com"], fontSrc: ["'self'", "https://cdnjs.cloudflare.com", "https://unpkg.com"], imgSrc: ["'self'", "data:", "https:"], connectSrc: ["'self'"], }, }, })); // CORS this.app.use((0, cors_1.default)({ origin: process.env.NODE_ENV === "production" ? true // Allow all origins for demo purposes : true, credentials: true, optionsSuccessStatus: 200, })); // Rate limiting this.app.use(rateLimiter_1.rateLimiter); // Serve static files from public directory const publicPath = path_1.default.join(__dirname, "../public"); this.app.use(express_1.default.static(publicPath)); // Parsing de body this.app.use(express_1.default.json({ limit: "10mb" })); this.app.use(express_1.default.urlencoded({ extended: true, limit: "10mb" })); // Logging básico this.app.use((req, res, next) => { console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`); next(); }); } /** * Configura las rutas de la aplicación */ initializeRoutes() { const container = dependencyContainer_1.DependencyContainer.getInstance(); const ciController = container.getCiController(); // Configurar Swagger this.setupSwagger(); // Health check this.app.get("/health", async (req, res) => { await ciController.healthCheck(req, res); }); // Rutas de la API this.app.use("/api/ci", (0, ciRoutes_1.createCiRoutes)()); // Demo page route this.app.get("/demo", (req, res) => { res.sendFile(path_1.default.join(__dirname, "../public/index.html")); }); // Ruta raíz con información básica this.app.get("/", (req, res) => { res.json({ name: "API de Validación de Cédulas Uruguayas", version: "1.0.0", description: "API para validar cédulas de identidad uruguayas", endpoints: { health: "GET /health", validate: "POST /api/ci/validate (body) | GET /api/ci/validate?ci=xxx (query)", demo: "GET /api/ci/demo", demoPage: "GET /demo", docs: "GET /api-docs", swaggerJson: "GET /api/swagger.json", }, documentation: "Ver README.md para más información", demoUrl: "/demo", docsUrl: "/api-docs", }); }); } /** * Configura Swagger UI para documentación de la API */ setupSwagger() { try { const swaggerPath = path_1.default.join(__dirname, "../swagger.json"); if (fs_1.default.existsSync(swaggerPath)) { const swaggerDocument = JSON.parse(fs_1.default.readFileSync(swaggerPath, "utf8")); // Actualizar URLs del servidor para desarrollo local swaggerDocument.servers = [ { url: `http://localhost:${this.port}`, description: "Development server", }, { url: "https://ci-validation.vercel.app", description: "Production server", }, ]; // Configurar Swagger UI this.app.use("/api-docs", swagger_ui_express_1.default.serve, swagger_ui_express_1.default.setup(swaggerDocument, { explorer: true, customCss: ` .swagger-ui .topbar { background-color: #667eea; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .swagger-ui .topbar .download-url-wrapper { display: none; } `, customSiteTitle: "API de Validación de Cédulas Uruguayas - Documentación", swaggerOptions: { tryItOutEnabled: true, filter: true, displayRequestDuration: true, }, })); // Endpoint para obtener el JSON de Swagger this.app.get("/api/swagger.json", (req, res) => { res.json(swaggerDocument); }); console.log(`📚 Swagger UI disponible en http://localhost:${this.port}/api-docs`); } else { console.warn("⚠️ swagger.json no encontrado - documentación no disponible"); } } catch (error) { console.error("❌ Error configurando Swagger:", error); } } /** * Configura el manejo de errores */ initializeErrorHandling() { // Middleware para rutas no encontradas this.app.use(errorHandler_1.ErrorHandler.notFoundHandler); // Middleware para errores globales this.app.use(errorHandler_1.ErrorHandler.globalErrorHandler); } /** * Inicia el servidor */ start() { this.app.listen(this.port, () => { console.log(`🚀 Servidor iniciado en puerto ${this.port}`); console.log(`📋 Health check: http://localhost:${this.port}/health`); console.log(`🔍 Demo: http://localhost:${this.port}/demo`); console.log(`📚 API Docs: http://localhost:${this.port}/api-docs`); console.log(`📖 Documentación: Ver README.md`); }); } /** * Obtiene la instancia de Express (útil para testing) */ getApp() { return this.app; } } // Crear e iniciar la aplicación const app = new App(); // Manejar cierre graceful process.on("SIGTERM", () => { console.log("🛑 Recibida señal SIGTERM, cerrando servidor..."); process.exit(0); }); process.on("SIGINT", () => { console.log("🛑 Recibida señal SIGINT, cerrando servidor..."); process.exit(0); }); // Exportar para uso en testing o deployment exports.default = app; // Iniciar servidor solo si este archivo es ejecutado directamente if (require.main === module) { app.start(); } //# sourceMappingURL=index.js.map