import { Buffer } from 'buffer' ; import { fs } from '@modern-js/utils' ; import LRU from 'lru-cache' ; const Byte = 1 ; const KB = 1024 * Byte ; const MB = 1024 * KB ; type FileCache = { content : Buffer ; mtime : Date ; } ; const getContentLength = ( cache ) => cache . content . length ; const createCacheItem = async ( filepath , mtime ) => { const content = await fs . readFile ( filepath ) ; return { content , mtime , } ; } ; class LruReader { private readonly cache : LRU < string , FileCache > ; constructor ( ) { this . cache = new LRU ( { max : 256 * MB , length : getContentLength , maxAge : 5 * 60 * 5000 , } ) ; } public init ( ) { } public close ( ) { } public async read ( filepath ) { if ( this . cache . has ( filepath ) ) { const { content } = this . cache . get ( filepath ) ! ; return { content } ; } if ( ! fs . existsSync ( filepath ) ) { return null ; } const stat = fs . statSync ( filepath ) ; if ( stat . isDirectory ( ) ) { return null ; } if ( stat . size > 20 * MB ) { return null ; } const item = await createCacheItem ( filepath , stat . mtime ) ; this . cache . set ( filepath , item ) ; return item ; } public update ( ) { const { cache } = this ; const files = cache . keys ( ) ; for ( const filepath of files ) { if ( ! fs . existsSync ( filepath ) ) { cache . del ( filepath ) ; } try { const item = cache . get ( filepath ) ! ; const stat = fs . statSync ( filepath ) ; const { mtime } = stat ; if ( item . mtime < mtime ) { cache . del ( filepath ) ; } } catch ( e ) { cache . del ( filepath ) ; } } } } const reader = new LruReader ( ) ; export const readFile = async ( filepath ) => { const file = await reader . read ( filepath ) ; return file ?. content ; } ; export const updateFile = ( ) => { reader . update ( ) ; } ; export const init = ( ) => { reader . init ( ) ; } ; export const close = ( ) => { reader . close ( ) ; } ;