UNPKG

ubon

Version:

Security scanner for AI-generated React/Next.js and Python apps. Catches hardcoded secrets, accessibility issues, and vulnerabilities that traditional linters miss.

139 lines (138 loc) 4.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CACHE_TTL = exports.FileCache = void 0; exports.createOSVCacheKey = createOSVCacheKey; const crypto_1 = require("crypto"); const fs_1 = require("fs"); const path_1 = require("path"); const os_1 = require("os"); class FileCache { constructor(name) { // Use ~/.ubon/cache/ directory this.cacheDir = (0, path_1.join)((0, os_1.homedir)(), '.ubon', 'cache', name); this.ensureCacheDir(); } ensureCacheDir() { try { (0, fs_1.mkdirSync)(this.cacheDir, { recursive: true }); } catch (error) { // Cache directory creation failed, will fall back to no caching } } getCacheFilePath(key) { // Create a safe filename from the key const hash = (0, crypto_1.createHash)('sha256').update(key).digest('hex'); return (0, path_1.join)(this.cacheDir, `${hash}.json`); } /** * Get cached data if it exists and hasn't expired */ get(key) { try { const filePath = this.getCacheFilePath(key); if (!(0, fs_1.existsSync)(filePath)) { return null; } const content = (0, fs_1.readFileSync)(filePath, 'utf8'); const entry = JSON.parse(content); // Check if expired const now = Date.now(); if (now - entry.timestamp > entry.ttl) { return null; } return entry.data; } catch (error) { // Cache read failed, return null return null; } } /** * Store data in cache with TTL */ set(key, data, ttlMs) { try { const filePath = this.getCacheFilePath(key); const entry = { data, timestamp: Date.now(), ttl: ttlMs }; (0, fs_1.writeFileSync)(filePath, JSON.stringify(entry), 'utf8'); } catch (error) { // Cache write failed, silently continue } } /** * Clear all cached entries (cleanup utility) */ clear() { try { const fs = require('fs'); if ((0, fs_1.existsSync)(this.cacheDir)) { const files = fs.readdirSync(this.cacheDir); for (const file of files) { if (file.endsWith('.json')) { fs.unlinkSync((0, path_1.join)(this.cacheDir, file)); } } } } catch (error) { // Clear failed, silently continue } } /** * Remove expired entries (maintenance utility) */ cleanup() { try { const fs = require('fs'); if (!(0, fs_1.existsSync)(this.cacheDir)) return; const files = fs.readdirSync(this.cacheDir); const now = Date.now(); for (const file of files) { if (!file.endsWith('.json')) continue; try { const filePath = (0, path_1.join)(this.cacheDir, file); const content = (0, fs_1.readFileSync)(filePath, 'utf8'); const entry = JSON.parse(content); if (now - entry.timestamp > entry.ttl) { fs.unlinkSync(filePath); } } catch { // Skip invalid cache files } } } catch (error) { // Cleanup failed, silently continue } } } exports.FileCache = FileCache; /** * Create a cache key for OSV queries */ function createOSVCacheKey(queries) { // Sort queries to ensure consistent cache keys const sortedQueries = queries .map(q => `${q.package.ecosystem}:${q.package.name}@${q.version}`) .sort() .join('|'); return `osv-batch:${sortedQueries}`; } /** * Default TTL values */ exports.CACHE_TTL = { OSV_VULNERABILITIES: 24 * 60 * 60 * 1000, // 24 hours SHORT: 60 * 60 * 1000, // 1 hour MEDIUM: 6 * 60 * 60 * 1000, // 6 hours LONG: 7 * 24 * 60 * 60 * 1000 // 7 days };