π File detail
utils/fileReadCache.ts
π§© .tsπ 97 linesπΎ 2,432 bytesπ text
β Back to All Filesπ― Use case
This file lives under βutils/β, which covers cross-cutting helpers (shell, tempfiles, settings, messages, process input, β¦). On the API surface it exposes fileReadCache β mainly functions, hooks, or classes. It composes internal code from file and fsOperations (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import { detectFileEncoding } from './file.js' import { getFsImplementation } from './fsOperations.js' type CachedFileData = { content: string
π€ Exports (heuristic)
fileReadCache
π₯οΈ Source preview
import { detectFileEncoding } from './file.js'
import { getFsImplementation } from './fsOperations.js'
type CachedFileData = {
content: string
encoding: BufferEncoding
mtime: number
}
/**
* A simple in-memory cache for file contents with automatic invalidation based on modification time.
* This eliminates redundant file reads in FileEditTool operations.
*/
class FileReadCache {
private cache = new Map<string, CachedFileData>()
private readonly maxCacheSize = 1000
/**
* Reads a file with caching. Returns both content and encoding.
* Cache key includes file path and modification time for automatic invalidation.
*/
readFile(filePath: string): { content: string; encoding: BufferEncoding } {
const fs = getFsImplementation()
// Get file stats for cache invalidation
let stats
try {
stats = fs.statSync(filePath)
} catch (error) {
// File was deleted, remove from cache and re-throw
this.cache.delete(filePath)
throw error
}
const cacheKey = filePath
const cachedData = this.cache.get(cacheKey)
// Check if we have valid cached data
if (cachedData && cachedData.mtime === stats.mtimeMs) {
return {
content: cachedData.content,
encoding: cachedData.encoding,
}
}
// Cache miss or stale data - read the file
const encoding = detectFileEncoding(filePath)
const content = fs
.readFileSync(filePath, { encoding })
.replaceAll('\r\n', '\n')
// Update cache
this.cache.set(cacheKey, {
content,
encoding,
mtime: stats.mtimeMs,
})
// Evict oldest entries if cache is too large
if (this.cache.size > this.maxCacheSize) {
const firstKey = this.cache.keys().next().value
if (firstKey) {
this.cache.delete(firstKey)
}
}
return { content, encoding }
}
/**
* Clears the entire cache. Useful for testing or memory management.
*/
clear(): void {
this.cache.clear()
}
/**
* Removes a specific file from the cache.
*/
invalidate(filePath: string): void {
this.cache.delete(filePath)
}
/**
* Gets cache statistics for debugging/monitoring.
*/
getStats(): { size: number; entries: string[] } {
return {
size: this.cache.size,
entries: Array.from(this.cache.keys()),
}
}
}
// Export a singleton instance
export const fileReadCache = new FileReadCache()