/** * Ecosystem-aware project structure detection. * * The Code Atlas groups files into "packages". That grouping used to be two * hardcoded npm-monorepo rules (`packages/` → `@wrongstack/`, `apps/` → * `app:`), which put every Go, Python, Rust or JVM file of any other repo * into a single `(root)` blob with no internal structure. * * This module derives the grouping from the markers each ecosystem actually * uses, and — importantly — at the granularity that ecosystem's developers * think in: * * | ecosystem | marker | one package node is… | * |-----------|-----------------------------|---------------------------------| * | npm | `package.json` | the package (marker directory) | * | Cargo | `Cargo.toml` | the crate (marker directory) | * | Go | `go.mod` | **a directory** — Go's own unit | * | Python | `pyproject.toml`/`setup.py` | the dotted package (`a.b.c`) | * | Maven | `pom.xml` | the project | * | Gradle | `build.gradle[.kts]` | the project | * | .NET | `*.csproj` | the project | * * Detection runs once per index over the already-discovered (and already * gitignore-filtered) file list, so it costs a bounded number of reads rather * than a second tree walk. */ /** Package-manager ecosystem a module root belongs to. */ type ModuleRootKind = 'npm' | 'cargo' | 'go' | 'python' | 'maven' | 'gradle' | 'dotnet'; interface ModuleRoot { /** Absolute directory holding the marker file, forward-slash normalized. */ dir: string; kind: ModuleRootKind; /** Human-facing grouping label, e.g. `@scope/pkg`, `crate:parser`. */ name: string; /** * Import prefix this root owns, when its ecosystem has one: * the `module` line of `go.mod`, the crate name for Cargo, the distribution * name for Python. `undefined` when imports are not prefixed by the root. */ importPath?: string | undefined; /** * Directories imports resolve against, forward-slash normalized absolute * paths. JVM layouts put this at `src/main/java`; Python projects commonly * use `src/`; most ecosystems just use the root directory itself. */ sourceRoots: string[]; } /** Everything the resolver and the package labeller need, computed once. */ export interface ProjectStructure { projectRoot: string; /** Sorted longest-dir-first so a nearest-ancestor lookup is a linear scan. */ roots: ModuleRoot[]; } /** Normalize to forward slashes; every path in this module is compared this way. */ export declare function toPortablePath(file: string): string; /** * Detect every module root reachable from the indexed file set. * * Candidate directories are the ancestors of directories that actually contain * files of the relevant language, so a repo with no Go code never stats a * single `go.mod`. */ export declare function detectModuleRoots(projectRoot: string, files: readonly string[]): Promise; /** Nearest module root that contains `file`, preferring the deepest match. */ export declare function findOwningRoot(structure: ProjectStructure, file: string, kinds?: readonly ModuleRootKind[]): ModuleRoot | undefined; /** * Legacy npm-monorepo fallback, kept for repos with no manifest at all (and for * the existing tests that assert on it). Only consulted when marker detection * finds no owning root. */ export declare function derivePackageFromLayout(filePath: string): string | undefined; /** * Assign every indexed file its Code Atlas package label. * * Go is grouped per directory because that is Go's compilation unit — one node * per module would collapse an entire repository into a single dot. Python is * grouped by its dotted package for the same reason. Every other ecosystem is * grouped by its manifest directory. */ export declare function assignPackageLabels(structure: ProjectStructure, files: readonly string[]): Map; export {}; //# sourceMappingURL=module-roots.d.ts.map