source dump of claude code
at main 96 lines 2.4 kB view raw
1import { detectFileEncoding } from './file.js' 2import { getFsImplementation } from './fsOperations.js' 3 4type CachedFileData = { 5 content: string 6 encoding: BufferEncoding 7 mtime: number 8} 9 10/** 11 * A simple in-memory cache for file contents with automatic invalidation based on modification time. 12 * This eliminates redundant file reads in FileEditTool operations. 13 */ 14class FileReadCache { 15 private cache = new Map<string, CachedFileData>() 16 private readonly maxCacheSize = 1000 17 18 /** 19 * Reads a file with caching. Returns both content and encoding. 20 * Cache key includes file path and modification time for automatic invalidation. 21 */ 22 readFile(filePath: string): { content: string; encoding: BufferEncoding } { 23 const fs = getFsImplementation() 24 25 // Get file stats for cache invalidation 26 let stats 27 try { 28 stats = fs.statSync(filePath) 29 } catch (error) { 30 // File was deleted, remove from cache and re-throw 31 this.cache.delete(filePath) 32 throw error 33 } 34 35 const cacheKey = filePath 36 const cachedData = this.cache.get(cacheKey) 37 38 // Check if we have valid cached data 39 if (cachedData && cachedData.mtime === stats.mtimeMs) { 40 return { 41 content: cachedData.content, 42 encoding: cachedData.encoding, 43 } 44 } 45 46 // Cache miss or stale data - read the file 47 const encoding = detectFileEncoding(filePath) 48 const content = fs 49 .readFileSync(filePath, { encoding }) 50 .replaceAll('\r\n', '\n') 51 52 // Update cache 53 this.cache.set(cacheKey, { 54 content, 55 encoding, 56 mtime: stats.mtimeMs, 57 }) 58 59 // Evict oldest entries if cache is too large 60 if (this.cache.size > this.maxCacheSize) { 61 const firstKey = this.cache.keys().next().value 62 if (firstKey) { 63 this.cache.delete(firstKey) 64 } 65 } 66 67 return { content, encoding } 68 } 69 70 /** 71 * Clears the entire cache. Useful for testing or memory management. 72 */ 73 clear(): void { 74 this.cache.clear() 75 } 76 77 /** 78 * Removes a specific file from the cache. 79 */ 80 invalidate(filePath: string): void { 81 this.cache.delete(filePath) 82 } 83 84 /** 85 * Gets cache statistics for debugging/monitoring. 86 */ 87 getStats(): { size: number; entries: string[] } { 88 return { 89 size: this.cache.size, 90 entries: Array.from(this.cache.keys()), 91 } 92 } 93} 94 95// Export a singleton instance 96export const fileReadCache = new FileReadCache()