import fs from 'fs/promises'; import path from 'path'; /** * Read and parse .gitignore file */ export async function readGitignore(dir: string): Promise { const gitignorePath = path.join(dir, '.gitignore'); try { const content = await fs.readFile(gitignorePath, 'utf-8'); return content .split('\n') .map((line) => line.trim()) .filter((line) => line && !line.startsWith('#')); } catch (error) { // No .gitignore file found, return empty array return []; } } /** * Check if a path should be ignored based on .gitignore patterns */ export function shouldIgnore(filePath: string, patterns: string[]): boolean { const relativePath = filePath.replace(/^\.\//, ''); // Default ignore patterns const defaultIgnores = [ 'node_modules', '.git', 'dist', 'build', '.next', '.turbo', 'coverage', '.env', '.env.local', ]; const allPatterns = [...defaultIgnores, ...patterns]; for (const pattern of allPatterns) { if (pattern.endsWith('/')) { // Directory pattern const dir = pattern.slice(0, -1); if (relativePath.includes(`${dir}/`) || relativePath === dir) { return true; } } else if (pattern.includes('*')) { // Glob pattern - simple implementation const regex = new RegExp( '^' + pattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$' ); if (regex.test(relativePath)) { return true; } } else { // Exact match or contains if (relativePath.includes(pattern)) { return true; } } } return false; } /** * Check if file is a code file based on extension */ export function isCodeFile(filePath: string): boolean { const codeExtensions = [ '.js', '.jsx', '.ts', '.tsx', '.py', '.java', '.go', '.rb', '.php', '.c', '.cpp', '.h', '.cs', '.swift', '.kt', '.rs', '.vue', '.svelte', ]; const ext = path.extname(filePath).toLowerCase(); return codeExtensions.includes(ext); } /** * Read the last N lines of a file */ export async function tailFile(filePath: string, lineCount: number = 10): Promise { try { const content = await fs.readFile(filePath, 'utf-8'); const lines = content.split('\n').filter(l => l.trim() !== ''); return lines.slice(-lineCount); } catch (e) { return []; } }