UNPKG

ci-validation

Version:

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

265 lines • 10 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SisiService = void 0; const axios_1 = __importDefault(require("axios")); const form_data_1 = __importDefault(require("form-data")); /** * Sisi Service Class * Handles verification of users in the Sisi system (sisi.com.uy) * * This service checks if a user exists in the Sisi loyalty program * by making requests to their sisipuntos-consulta endpoint. */ class SisiService { constructor() { this.baseUrl = "https://sisi.com.uy"; this.endpoint = "/sisipuntos-consulta"; this.timeout = 10000; // 10 seconds timeout } /** * Default headers for Sisi requests * Based on the original curl request */ getDefaultHeaders() { return { Accept: "application/json, text/javascript, */*; q=0.01", "Accept-Language": "es-ES,es;q=0.9,bg;q=0.8", "Cache-Control": "no-cache", Connection: "keep-alive", Origin: "https://sisi.com.uy", Pragma: "no-cache", Referer: "https://sisi.com.uy/saldo", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36", "X-Requested-With": "XMLHttpRequest", "sec-ch-ua": '"Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', }; } /** * Creates form data for the Sisi API request * @param ci - Cédula de identidad (without dots or dashes) * @param pais - Country code (default: "001" for Uruguay) * @returns FormData object */ createFormData(ci, pais = "001") { const formData = new form_data_1.default(); formData.append("ci", ci); formData.append("pais", pais); return formData; } /** * Validates CI format before making the request * @param ci - Cédula de identidad * @returns boolean */ validateCI(ci) { // Remove any non-numeric characters const cleanCi = ci.replace(/\D/g, ""); // Check if it's between 7 and 8 digits return cleanCi.length >= 7 && cleanCi.length <= 8; } /** * Normalizes CI by removing any formatting * @param ci - Cédula de identidad * @returns Normalized CI string */ normalizeCI(ci) { return ci.replace(/\D/g, ""); } /** * Parses the Sisi API response to determine user existence * @param response - Axios response * @returns Parsed SisiResponse */ parseResponse(response, ci, country) { const executionTime = Date.now(); try { const data = response.data; // Check if response indicates user exists based on message content const hasUser = this.determineUserExistence(data); const status = hasUser ? "exists" : "not_found"; const message = this.extractMessage(data, hasUser); return { success: true, hasUser: hasUser, userInfo: { ci: ci, country: country, status: status, message: message, executionTime: executionTime, }, }; } catch (error) { return { success: false, hasUser: false, error: `Error parsing response: ${error instanceof Error ? error.message : "Unknown error"}`, userInfo: { ci: ci, country: country, status: "error", message: "Error al procesar la respuesta del servidor", executionTime: executionTime, }, }; } } /** * Determines if user exists based on response message * @param data - Response data * @returns boolean indicating if user exists */ determineUserExistence(data) { if (!data || !data.msg) { return false; } const message = data.msg.toLowerCase(); // If message contains "no se encontro" or "registrate", user doesn't exist if (message.includes("no se encontro") || message.includes("registrate")) { return false; } // If message contains "debes loguearte", user exists but needs login if (message.includes("debes loguearte") || message.includes("loguearte")) { return true; } // Default to false for unknown responses return false; } /** * Extracts user-friendly message from response * @param data - Response data * @param hasUser - Whether user exists * @returns User-friendly message */ extractMessage(data, hasUser) { if (hasUser) { return "Usuario registrado en el sistema Sisi (requiere login para más detalles)"; } else { return "Usuario no encontrado en el sistema Sisi"; } } /** * Checks if a user exists in the Sisi system * @param request - Sisi request parameters * @returns Promise<SisiResponse> */ async checkUser(request) { const startTime = Date.now(); try { // Validate input if (!request.ci) { throw new Error("CI (Cédula de Identidad) is required"); } const normalizedCI = this.normalizeCI(request.ci); if (!this.validateCI(normalizedCI)) { throw new Error("CI must be between 7 and 8 digits"); } // Prepare request data const formData = this.createFormData(normalizedCI, request.pais); const headers = { ...this.getDefaultHeaders(), ...formData.getHeaders(), }; // Make the request const response = await axios_1.default.post(`${this.baseUrl}${this.endpoint}`, formData, { headers, timeout: this.timeout, validateStatus: (status) => status < 500, // Accept 4xx as valid responses }); const executionTime = Date.now() - startTime; const result = this.parseResponse(response, normalizedCI, request.pais || "001"); // Update execution time if (result.userInfo) { result.userInfo.executionTime = executionTime; } return result; } catch (error) { const executionTime = Date.now() - startTime; if (axios_1.default.isAxiosError(error)) { // Handle specific HTTP errors if (error.response?.status === 404) { return { success: true, hasUser: false, error: "User not found in Sisi system", userInfo: { ci: this.normalizeCI(request.ci), country: request.pais || "001", status: "not_found", message: "Usuario no encontrado en el sistema Sisi", executionTime: executionTime, }, }; } if (error.response?.status === 403 || error.response?.status === 401) { return { success: false, hasUser: false, error: "Access denied or authentication required", userInfo: { ci: this.normalizeCI(request.ci), country: request.pais || "001", status: "error", message: "Acceso denegado al sistema Sisi", executionTime: executionTime, }, }; } return { success: false, hasUser: false, error: `HTTP Error: ${error.response?.status} - ${error.message}`, userInfo: { ci: this.normalizeCI(request.ci), country: request.pais || "001", status: "error", message: "Error al consultar el sistema Sisi", executionTime: executionTime, }, }; } return { success: false, hasUser: false, error: `Network or system error: ${error instanceof Error ? error.message : "Unknown error"}`, userInfo: { ci: this.normalizeCI(request.ci), country: request.pais || "001", status: "error", message: "Error de conexión con el sistema Sisi", executionTime: executionTime, }, }; } } /** * Convenience method to check if a user exists by CI only * @param ci - Cédula de identidad * @returns Promise<boolean> */ async hasUser(ci) { try { const result = await this.checkUser({ ci }); return result.hasUser || false; } catch (error) { console.error("Error checking user in Sisi:", error); return false; } } } exports.SisiService = SisiService; // Export a default instance exports.default = new SisiService(); //# sourceMappingURL=Sisi.js.map