diff --git a/src/utils/fileFinder.ts b/src/utils/fileFinder.ts new file mode 100644 index 0000000..942b547 --- /dev/null +++ b/src/utils/fileFinder.ts @@ -0,0 +1,117 @@ +import * as glob from 'glob'; +import * as fs from 'fs'; +import * as path from 'path'; + +export interface FileFinderOptions { + includePatterns: string[]; + excludePatterns: string[]; + maxDepth?: number; +} + +export interface FoundFile { + filePath: string; + relativePath: string; + extension: string; + size: number; + modifiedAt: Date; +} + +export class FileFinder { + private options: FileFinderOptions; + + constructor(options: Partial = {}) { + this.options = { + includePatterns: options.includePatterns || ['**/*.ts', '**/*.tsx'], + excludePatterns: options.excludePatterns || ['node_modules', 'dist', '*.d.ts'], + maxDepth: options.maxDepth || 10 + }; + } + + find(baseDirectory: string): FoundFile[] { + const files: FoundFile[] = []; + + for (const pattern of this.options.includePatterns) { + const matches = glob.sync(pattern, { + cwd: baseDirectory, + ignore: this.options.excludePatterns, + nodir: true, + maxDepth: this.options.maxDepth + }); + + for (const match of matches) { + const filePath = path.resolve(baseDirectory, match); + const stats = fs.statSync(filePath); + + if (stats.isFile()) { + files.push({ + filePath, + relativePath: match, + extension: path.extname(filePath), + size: stats.size, + modifiedAt: stats.mtime + }); + } + } + } + + return files.sort((a, b) => a.filePath.localeCompare(b.filePath)); + } + + findSync(baseDirectory: string): FoundFile[] { + return this.find(baseDirectory); + } + + async findAsync(baseDirectory: string): Promise { + return new Promise((resolve, reject) => { + const results: FoundFile[] = []; + + const processPattern = (pattern: string): Promise => { + return new Promise((res, rej) => { + glob(pattern, { + cwd: baseDirectory, + ignore: this.options.excludePatterns, + nodir: true, + maxDepth: this.options.maxDepth + }, (err: Error | null, matches: string[]) => { + if (err) { + rej(err); + return; + } + + for (const match of matches) { + const filePath = path.resolve(baseDirectory, match); + try { + const stats = fs.statSync(filePath); + if (stats.isFile()) { + results.push({ + filePath, + relativePath: match, + extension: path.extname(filePath), + size: stats.size, + modifiedAt: stats.mtime + }); + } + } catch { + } + } + res(); + }); + }); + }; + + Promise.all(this.options.includePatterns.map(processPattern)) + .then(() => { + resolve(results.sort((a, b) => a.filePath.localeCompare(b.filePath))); + }) + .catch(reject); + }); + } +} + +export function findTypeScriptFiles( + directory: string, + options?: Partial +): FoundFile[] { + const finder = new FileFinder(options); + return finder.find(directory); +}