/** * Incremental Scanner Cache * * Caches scanner results to enable incremental scanning. Only changed files * are re-scanned, dramatically improving performance on subsequent runs. * * Cache structure: * ``` * .vaspera/cache/scanners/{scanner}/{hash}.json * ``` * * Cache key: sha256(filePath + fileHash + scannerVersion + ruleHash) * * @module scanners/cache */ import type { ScannerType, DeterministicFinding, ScannerResult } from "./types.js"; /** * Cache entry for a single file's scanner results */ export interface ScannerCacheEntry { /** Cache format version */ version: 1; /** Scanner type */ scanner: ScannerType; /** Scanner version that produced this result */ scannerVersion: string; /** Hash of the rules/config used */ ruleHash: string; /** Relative file path */ filePath: string; /** Hash of file contents when scanned */ fileHash: string; /** Findings from the scan */ findings: DeterministicFinding[]; /** Timestamp when cached */ cachedAt: string; /** Scan duration in ms (for metrics) */ scanDuration: number; } /** * Cache statistics */ export interface CacheStats { /** Total entries in cache */ totalEntries: number; /** Total size in bytes */ totalSizeBytes: number; /** Entries by scanner */ byScanner: Record; /** Oldest entry timestamp */ oldestEntry?: string; /** Newest entry timestamp */ newestEntry?: string; } /** * Cache lookup result */ export interface CacheLookupResult { /** Whether a valid cache entry was found */ hit: boolean; /** The cached entry if found */ entry?: ScannerCacheEntry; /** Reason for cache miss */ missReason?: "not_found" | "version_mismatch" | "rule_mismatch" | "file_changed" | "expired"; } /** * Options for the scanner cache */ export interface ScannerCacheOptions { /** Maximum number of entries per scanner (default: 10000) */ maxEntriesPerScanner?: number; /** Maximum age of cache entries in ms (default: 7 days) */ maxAgeMs?: number; /** Cache directory path (default: .vaspera/cache/scanners) */ cacheDir?: string; } /** * Scanner cache manager * * Provides LRU cache with configurable limits per scanner type. */ export declare class ScannerCache { private readonly cacheDir; private readonly maxEntriesPerScanner; private readonly maxAgeMs; private readonly projectPath; constructor(projectPath: string, options?: ScannerCacheOptions); /** * Generate a cache key for a file + scanner + version + rules combination */ generateCacheKey(filePath: string, fileHash: string, scanner: ScannerType, scannerVersion: string, ruleHash: string): string; /** * Get the cache file path for a given key */ private getCachePath; /** * Ensure cache directory exists */ private ensureCacheDir; /** * Look up cached results for a file */ lookup(filePath: string, fileHash: string, scanner: ScannerType, scannerVersion: string, ruleHash: string): Promise; /** * Store scanner results in cache */ store(filePath: string, fileHash: string, scanner: ScannerType, scannerVersion: string, ruleHash: string, findings: DeterministicFinding[], scanDuration: number): Promise; /** * Invalidate cache for a specific file */ invalidate(filePath: string, scanner?: ScannerType): Promise; /** * Run LRU eviction to stay within limits */ evict(): Promise; /** * Get cache statistics */ getStats(): Promise; /** * Clear all cache entries */ clear(): Promise; } /** * Compute hash of file contents */ export declare function hashFileContents(filePath: string): Promise; /** * Compute hash of scanner rules/config * * This is used to invalidate cache when rules change. */ export declare function hashRules(rules: string[] | undefined, configFile?: string): string; /** * Run scanner with caching * * Wraps a scanner function to use the cache. Only scans files that: * 1. Are not in cache * 2. Have changed since last scan * 3. Were scanned with different scanner version or rules */ export declare function runScannerWithCache(cache: ScannerCache, scanner: ScannerType, scannerVersion: string, ruleHash: string, files: Array<{ path: string; hash: string; }>, scanFn: (filePaths: string[]) => Promise): Promise<{ result: T; cacheHits: number; cacheMisses: number; savedTimeMs: number; }>; /** * Create a default scanner cache instance */ export declare function createScannerCache(projectPath: string, options?: ScannerCacheOptions): ScannerCache; //# sourceMappingURL=cache.d.ts.map