Walk project source files (bounded), skipping heavy/ignored dirs.
(root: string, cap: number)
| 318 | |
| 319 | /** Walk project source files (bounded), skipping heavy/ignored dirs. */ |
| 320 | async function walkProjectSource(root: string, cap: number): Promise<Array<{ rel: string; content: string }>> { |
| 321 | const out: Array<{ rel: string; content: string }> = []; |
| 322 | const SKIP = new Set(['node_modules', '.git', 'dist', 'build', '.next', 'coverage', '.qodex']); |
| 323 | const exts = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']); |
| 324 | |
| 325 | async function walk(dir: string) { |
| 326 | if (out.length >= cap) return; |
| 327 | let entries; |
| 328 | try { entries = await fs.readdir(dir, { withFileTypes: true }); } catch { return; } |
| 329 | for (const e of entries) { |
| 330 | if (out.length >= cap) return; |
| 331 | if (e.name.startsWith('.') && e.name !== '.qodex') { /* allow dotfiles except heavy */ } |
| 332 | const abs = path.join(dir, e.name); |
| 333 | if (e.isDirectory()) { |
| 334 | if (SKIP.has(e.name)) continue; |
| 335 | await walk(abs); |
| 336 | } else if (exts.has(path.extname(e.name))) { |
| 337 | try { |
| 338 | const content = await fs.readFile(abs, 'utf-8'); |
| 339 | out.push({ rel: path.relative(root, abs), content }); |
| 340 | } catch { /* skip unreadable */ } |
| 341 | } |
| 342 | } |
| 343 | } |
| 344 | await walk(root); |
| 345 | return out; |
| 346 | } |