UNPKG

@claude-vector/core

Version:

Core vector search engine for code intelligence

172 lines (147 loc) 3.96 kB
/** * Simple file-based cache implementation */ import fs from 'fs/promises'; import path from 'path'; import crypto from 'crypto'; export class SimpleCache { constructor(cachePath, ttl = 3600) { this.cachePath = cachePath; this.ttl = ttl * 1000; // Convert seconds to milliseconds } /** * Generate cache key hash */ hashKey(key) { return crypto.createHash('md5').update(key).digest('hex'); } /** * Get value from cache */ async get(key) { try { const hash = this.hashKey(key); const filePath = path.join(this.cachePath, `${hash}.json`); const stats = await fs.stat(filePath); const now = Date.now(); // Check if cache has expired if (now - stats.mtime.getTime() > this.ttl) { await fs.unlink(filePath); return null; } const data = await fs.readFile(filePath, 'utf-8'); const cached = JSON.parse(data); return cached.value; } catch (error) { // Cache miss or error return null; } } /** * Set value in cache */ async set(key, value) { try { const hash = this.hashKey(key); const filePath = path.join(this.cachePath, `${hash}.json`); // Ensure cache directory exists await fs.mkdir(this.cachePath, { recursive: true }); const cacheData = { key, value, timestamp: Date.now() }; await fs.writeFile(filePath, JSON.stringify(cacheData, null, 2)); return true; } catch (error) { console.error('Cache write error:', error); return false; } } /** * Delete value from cache */ async delete(key) { try { const hash = this.hashKey(key); const filePath = path.join(this.cachePath, `${hash}.json`); await fs.unlink(filePath); return true; } catch (error) { return false; } } /** * Clear all cache entries */ async clear() { try { const files = await fs.readdir(this.cachePath); const deletions = files .filter(file => file.endsWith('.json')) .map(file => fs.unlink(path.join(this.cachePath, file))); await Promise.all(deletions); return true; } catch (error) { return false; } } /** * Clean up expired cache entries */ async cleanup() { try { const files = await fs.readdir(this.cachePath); const now = Date.now(); let cleaned = 0; for (const file of files) { if (!file.endsWith('.json')) continue; const filePath = path.join(this.cachePath, file); const stats = await fs.stat(filePath); if (now - stats.mtime.getTime() > this.ttl) { await fs.unlink(filePath); cleaned++; } } return { cleaned, total: files.length }; } catch (error) { return { cleaned: 0, total: 0, error: error.message }; } } /** * Get cache statistics */ async getStats() { try { const files = await fs.readdir(this.cachePath); const jsonFiles = files.filter(file => file.endsWith('.json')); const now = Date.now(); let totalSize = 0; let expired = 0; let valid = 0; for (const file of jsonFiles) { const filePath = path.join(this.cachePath, file); const stats = await fs.stat(filePath); totalSize += stats.size; if (now - stats.mtime.getTime() > this.ttl) { expired++; } else { valid++; } } return { total: jsonFiles.length, valid, expired, totalSize: `${(totalSize / 1024).toFixed(2)} KB`, cachePath: this.cachePath, ttl: this.ttl / 1000 // Convert back to seconds }; } catch (error) { return { error: error.message, cachePath: this.cachePath }; } } }