Files
pi-map/src/discover.ts
T
alex fd958671ca Initial commit: pi-project-map skill scaffolding
- Design doc with full spec (dense markdown format, hybrid AST+LLM pipeline,
  consumption model, stale data mitigation)
- Implementation plan with 6 milestones and rollout strategy
- TypeScript package structure with all source stubs
- CLI entry point, formatter, discover, init, patch, validate, extract, merge
- Pi SKILL.md with tool definitions and format documentation
2026-06-09 17:45:19 +02:00

57 lines
1.4 KiB
TypeScript

import { readdirSync, statSync } from 'fs';
import { join, relative } from 'path';
import ignore from 'ignore';
const DEFAULT_IGNORE = [
'node_modules', '.git', 'dist', 'build', 'coverage',
'.next', '.venv', '__pycache__', '.DS_Store', '*.log'
];
export interface DirectoryEntry {
dirPath: string;
relativePath: string;
files: string[];
}
export function discoverProject(rootPath: string): DirectoryEntry[] {
const ig = ignore().add(DEFAULT_IGNORE);
const gitignorePath = join(rootPath, '.gitignore');
try {
const gitignoreContent = require('fs').readFileSync(gitignorePath, 'utf8');
ig.add(gitignoreContent);
} catch { /* no .gitignore */ }
const entries: DirectoryEntry[] = [];
function walk(dir: string) {
const relDir = relative(rootPath, dir) || '.';
if (ig.ignores(relDir)) return;
const items = readdirSync(dir);
const files: string[] = [];
const subdirs: string[] = [];
for (const item of items) {
const relPath = join(relDir, item);
if (ig.ignores(relPath)) continue;
const fullPath = join(dir, item);
const st = statSync(fullPath);
if (st.isDirectory()) {
subdirs.push(fullPath);
} else {
files.push(item);
}
}
entries.push({ dirPath: dir, relativePath: relDir, files });
for (const subdir of subdirs) {
walk(subdir);
}
}
walk(rootPath);
return entries;
}