UNPKG

@stylable/core

Version:

CSS for Components

78 lines (68 loc) 2.36 kB
export type processFn<T> = (fullpath: string, content: string) => T; export interface CacheItem<T> { value: T; stat: { mtime: Date }; } export interface MinimalFS { statSync: (fullpath: string) => { mtime: Date }; readFileSync: (fullpath: string, encoding: 'utf8') => string; readlinkSync(path: string): string; } export interface FileProcessor<T> { process: (fullpath: string, ignoreCache?: boolean, context?: string) => T; add: (fullpath: string, value: T) => void; processContent: (content: string, fullpath: string) => T; cache: Record<string, CacheItem<T>>; postProcessors: Array<(value: T, path: string) => T>; resolvePath: (path: string, context?: string) => string; } export function cachedProcessFile<T = any>( processor: processFn<T>, fs: MinimalFS, resolvePath: (path: string, context?: string) => string ): FileProcessor<T> { const cache: { [key: string]: CacheItem<T> } = {}; const postProcessors: Array<(value: T, path: string) => T> = []; function process(fullpath: string, ignoreCache = false, context?: string) { const resolvedPath = resolvePath(fullpath, context); const stat = fs.statSync(resolvedPath); const cached = cache[resolvedPath]; if ( ignoreCache || !cached || (cached && cached.stat.mtime.valueOf() !== stat.mtime.valueOf()) ) { const content = fs.readFileSync(resolvedPath, 'utf8'); const value = processContent(content, resolvedPath); cache[resolvedPath] = { value, stat: { mtime: stat.mtime } }; } return cache[resolvedPath].value; } function processContent(content: string, filePath: string): T { return postProcessors.reduce<T>((value, postProcessor) => { return postProcessor(value, filePath); }, processor(filePath, content)); } function add(fullpath: string, value: T) { let mtime; try { mtime = fs.statSync(fullpath).mtime; } catch (e) { mtime = new Date(); } cache[fullpath] = { value, stat: { mtime, }, }; } return { processContent, postProcessors, cache, process, add, resolvePath, }; }