/** * ts-morph scanner. Walks a consumer's `src/` tree and produces a structured * CodeMap. Covers five entity kinds the brewing agent benefits from seeing * without having to open every file: * * 1. API routes — Next.js App Router (`src/app/**\/route.ts(x)`) * 2. Pages — Next.js App Router (`src/app/**\/page.tsx`) * 3. Components — `src/components/**\/*.tsx` (exported React components) * 4. Helpers — `src/lib/**\/*.ts`, `src/utils/**\/*.ts` (exported fns/consts/classes) * 5. Types — `src/types/**\/*.ts` (exported types/interfaces/enums) * * Scope is deliberately Next.js + TypeScript-centric for v1 — the engine is * general enough to extend (different frameworks would register their own * route-URL derivation), but today we only ship Next.js App Router detection. * * Output is a plain object — the CLI entry serialises to JSON + renders * Markdown. No I/O here beyond reading source files via ts-morph. */ /** * 0.12.7+ (Phase 2A of brownfield-retrieval) — every exported symbol * carries a 1-based `line` (declaration site) and `callers` (count of * non-declaration references across src/) so brew can answer * "how widely is this used?" without reading every file. * * `callers` is approximate: based on a name-only AST scan that doesn't * perform type resolution. Two unrelated symbols sharing a name will * pool their callers. Trade-off: cheap (single pass) and useful for * "should I extend or duplicate?" judgement calls; not authoritative * for refactor planning. */ export interface ApiRouteEntry { method: string; path: string; file: string; function: string; /** 1-based line where the handler function is declared. */ line?: number; /** Reference count across src/ (excluding the declaration itself). */ callers?: number; jsdoc?: string; imports: string[]; } export interface PageEntry { path: string; file: string; component?: string; /** 1-based line where the page's default-export component is declared. */ line?: number; jsdoc?: string; } export interface ComponentEntry { name: string; file: string; exportKind: "default" | "named"; props_type?: string; /** 1-based line of the component declaration. */ line?: number; callers?: number; jsdoc?: string; } export interface HelperEntry { name: string; kind: "function" | "const" | "class"; file: string; signature: string; /** 1-based line of the helper declaration. */ line?: number; callers?: number; jsdoc?: string; } export interface TypeEntry { name: string; kind: "interface" | "type" | "enum"; file: string; declaration: string; /** 1-based line of the type declaration. */ line?: number; callers?: number; jsdoc?: string; } export interface CodeMap { schema_version: 1; slowcook_version: string; generated_at: string; repo_root: string; api_routes: ApiRouteEntry[]; pages: PageEntry[]; components: ComponentEntry[]; helpers: HelperEntry[]; types: TypeEntry[]; } export interface GenerateMapOptions { repoRoot: string; slowcookVersion: string; now?: Date; } export declare function generateMap(opts: GenerateMapOptions): CodeMap; /** * Phase 2B (0.12.8+) — return a copy of `map` containing only entries * whose `file` is in `scope.files` OR whose `name` is in `scope.names`. * * The brew agent uses this to read a target-scoped slice instead of the * full code-map every iteration. Scope is derived per-iter from the * current target test (mirrored src/ dir + identifier names mentioned * in the test source). Falls back to the full map if scope is empty. * * Pure function — does not mutate input. Schema metadata (slowcook * version, generated_at, etc.) is preserved verbatim. */ export declare function sliceCodeMap(map: CodeMap, scope: { files?: ReadonlySet; names?: ReadonlySet; }): CodeMap; //# sourceMappingURL=scan.d.ts.map