UNPKG

ci-validation

Version:

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

191 lines 6.68 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FileSessionStorage = void 0; const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); /** * File-based session storage implementation * Stores sessions as JSON files in the filesystem */ class FileSessionStorage { constructor(options = {}) { this.sessionDir = options.sessionDir || (process.env.VERCEL ? "/tmp/sessions" : path_1.default.join(process.cwd(), "sessions")); this.expirationTime = options.expirationTime || 24 * 60 * 60 * 1000; // 24 hours this.autoCleanup = options.autoCleanup !== false; // Initialize session directory this.ensureSessionDirectory(); // Start cleanup timer if auto cleanup is enabled if (this.autoCleanup) { const cleanupInterval = options.cleanupInterval || 60 * 60 * 1000; // 1 hour this.cleanupTimer = setInterval(() => { this.cleanupExpiredSessions().catch(console.error); }, cleanupInterval); } } /** * Ensures the session directory exists */ async ensureSessionDirectory() { try { await fs_1.promises.mkdir(this.sessionDir, { recursive: true }); } catch (error) { console.error("Error creating session directory:", error); } } /** * Gets the file path for a session */ getSessionFilePath(sessionId) { return path_1.default.join(this.sessionDir, `${sessionId}.json`); } /** * Save session data to file */ async saveSession(sessionId, sessionData) { try { const now = Date.now(); const enrichedSessionData = { ...sessionData, createdAt: sessionData.createdAt || now, lastUsed: now, expiresAt: now + this.expirationTime, }; const filePath = this.getSessionFilePath(sessionId); await fs_1.promises.writeFile(filePath, JSON.stringify(enrichedSessionData, null, 2), "utf-8"); console.log(`✅ Session saved to file: ${sessionId}`); } catch (error) { console.error(`❌ Error saving session ${sessionId}:`, error); throw error; } } /** * Load session data from file */ async loadSession(sessionId) { try { const filePath = this.getSessionFilePath(sessionId); const sessionData = await fs_1.promises.readFile(filePath, "utf-8"); const parsedSession = JSON.parse(sessionData); // Check if session is expired if (parsedSession.expiresAt && Date.now() > parsedSession.expiresAt) { console.log(`⏰ Session ${sessionId} has expired, removing...`); await this.deleteSession(sessionId); return null; } // Update last used timestamp await this.touchSession(sessionId); console.log(`✅ Session loaded from file: ${sessionId}`); return parsedSession; } catch (error) { if (error.code === "ENOENT") { console.log(`ℹ️ Session file not found: ${sessionId}`); return null; } console.error(`❌ Error loading session ${sessionId}:`, error); throw error; } } /** * Delete session file */ async deleteSession(sessionId) { try { const filePath = this.getSessionFilePath(sessionId); await fs_1.promises.unlink(filePath); console.log(`🗑️ Session deleted: ${sessionId}`); } catch (error) { if (error.code === "ENOENT") { console.log(`ℹ️ Session file already deleted: ${sessionId}`); return; } console.error(`❌ Error deleting session ${sessionId}:`, error); throw error; } } /** * Check if session file exists */ async sessionExists(sessionId) { try { const filePath = this.getSessionFilePath(sessionId); await fs_1.promises.access(filePath); return true; } catch { return false; } } /** * Update session's last used timestamp */ async touchSession(sessionId) { try { const session = await this.loadSessionRaw(sessionId); if (session) { session.lastUsed = Date.now(); const filePath = this.getSessionFilePath(sessionId); await fs_1.promises.writeFile(filePath, JSON.stringify(session, null, 2), "utf-8"); } } catch (error) { console.error(`❌ Error touching session ${sessionId}:`, error); } } /** * Load session data without updating last used timestamp */ async loadSessionRaw(sessionId) { try { const filePath = this.getSessionFilePath(sessionId); const sessionData = await fs_1.promises.readFile(filePath, "utf-8"); return JSON.parse(sessionData); } catch { return null; } } /** * Clean up expired session files */ async cleanupExpiredSessions() { try { const files = await fs_1.promises.readdir(this.sessionDir); const now = Date.now(); let cleanedCount = 0; for (const file of files) { if (file.endsWith(".json")) { const sessionId = file.replace(".json", ""); const session = await this.loadSessionRaw(sessionId); if (session && session.expiresAt && now > session.expiresAt) { await this.deleteSession(sessionId); cleanedCount++; } } } if (cleanedCount > 0) { console.log(`🧹 Cleaned up ${cleanedCount} expired sessions`); } } catch (error) { console.error("❌ Error during session cleanup:", error); } } /** * Cleanup resources */ destroy() { if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = undefined; } } } exports.FileSessionStorage = FileSessionStorage; //# sourceMappingURL=FileSessionStorage.js.map