/** * Dependency Graph Service * * Builds a complete graph of how files relate to each other through imports. * Provides metrics like in-degree, out-degree, betweenness centrality, and PageRank. * Detects clusters, cycles, and special nodes (centers, leaves, bridges, orphans). */ import { type ExportInfo } from './import-parser.js'; import { type HttpEdge } from './http-route-parser.js'; import type { ScoredFile } from '../../types/index.js'; /** * Node in the dependency graph */ export interface DependencyNode { id: string; file: ScoredFile; exports: ExportInfo[]; metrics: { inDegree: number; outDegree: number; betweenness: number; pageRank: number; }; cluster?: { id: string; name: string; color: string; }; } /** * Edge in the dependency graph */ export interface DependencyEdge { source: string; target: string; importedNames: string[]; isTypeOnly: boolean; weight: number; /** Present when this edge was derived from an HTTP call rather than a static import */ httpEdge?: HttpEdge; /** True when this edge was synthesized from a call-graph cross-file call (implicit import) */ isCallEdge?: boolean; } /** * Cluster of related files */ export interface FileCluster { id: string; name: string; files: string[]; internalEdges: number; externalEdges: number; cohesion: number; coupling: number; suggestedDomain: string; color: string; /** * True when the cluster has at least one internal edge (files actually * import each other). False clusters are pure directory groups with no * connectivity — useful for rendering at a lower visual prominence. */ isStructural: boolean; } /** * Complete dependency graph result */ export interface DependencyGraphResult { nodes: DependencyNode[]; edges: DependencyEdge[]; /** All clusters (structural + directory groups). Use the `isStructural` flag to filter. */ clusters: FileCluster[]; /** Only clusters with internalEdges > 0 — worth highlighting visually */ structuralClusters: FileCluster[]; rankings: { byImportance: string[]; byConnectivity: string[]; clusterCenters: string[]; leafNodes: string[]; bridgeNodes: string[]; orphanNodes: string[]; }; cycles: string[][]; statistics: { nodeCount: number; edgeCount: number; /** Edges derived from static imports */ importEdgeCount: number; /** Edges derived from HTTP call→route matching */ httpEdgeCount: number; avgDegree: number; density: number; /** Total clusters including directory-only groups */ clusterCount: number; /** Clusters with at least one internal edge */ structuralClusterCount: number; cycleCount: number; }; } /** * Options for building the dependency graph */ export interface DependencyGraphOptions { /** Root directory of the project */ rootDir: string; /** File extensions to consider for import resolution */ extensions?: string[]; /** Minimum cluster size to report */ minClusterSize?: number; /** PageRank damping factor */ dampingFactor?: number; /** Maximum PageRank iterations */ maxIterations?: number; } /** * Builds and analyzes a dependency graph from scored files */ export declare class DependencyGraphBuilder { private nodes; private edges; private adjacencyList; private reverseAdjacencyList; private httpEdgeCount; private parser; private options; constructor(options: DependencyGraphOptions); /** * Build the dependency graph from scored files */ build(files: ScoredFile[]): Promise; /** * Parse all files to extract imports/exports */ private parseFiles; /** * Build cross-language edges by matching HTTP calls in JS/TS files to * FastAPI/Flask/Django route definitions in Python files. * Only creates edges between files that are already nodes in the graph. */ private buildHttpCrossEdges; /** * Build edges from import relationships */ private buildEdges; /** * Calculate in-degree and out-degree for each node */ private calculateDegrees; /** * Calculate betweenness centrality using Brandes' algorithm */ private calculateBetweenness; /** * Calculate PageRank-style importance scores */ private calculatePageRank; /** * Detect clusters using a simple community detection approach * Groups files by their common directory prefix and connectivity */ private detectClusters; /** * Suggest a domain name based on directory and file contents */ private suggestDomainName; /** * Detect cycles in the dependency graph using DFS */ private detectCycles; /** * Check if a cycle is a duplicate or rotation of an existing cycle */ private isDuplicateCycle; /** * Normalize a cycle for comparison (smallest element first, then compare) */ private normalizeCycle; /** * Generate various rankings of nodes */ private generateRankings; /** * Calculate overall statistics */ private calculateStatistics; } /** * Build a dependency graph from scored files */ export declare function buildDependencyGraph(files: ScoredFile[], options: DependencyGraphOptions): Promise; /** * Languages that share a module-level namespace without explicit intra-file imports. * For these, dependency edges must be derived from the call graph rather than imports. */ declare const IMPLICIT_IMPORT_LANGS: Set; /** * Languages that DO use explicit imports for cross-package references but need * NO import for same-package classes (JVM package semantics). Their dependency * graph would otherwise show only the sparse cross-package import edges and miss * every same-package relationship — so call-graph edges are injected (deduped * against existing import edges) regardless of the import-edge count. See #138. */ declare const SAME_PACKAGE_IMPLICIT_LANGS: Set; /** * Synthesize dependency edges from cross-file call edges and inject them into * an existing DependencyGraphResult in-place. * * Use this for languages like Swift or C++ that don't have explicit intra-module * imports, resulting in an empty dep graph when only import-based edges are built. */ export declare function injectCallGraphEdges(depGraph: DependencyGraphResult, callEdges: Array<{ callerId: string; calleeId: string; }>, nodeFilePath: (id: string) => string | undefined): void; export { IMPLICIT_IMPORT_LANGS, SAME_PACKAGE_IMPLICIT_LANGS }; /** * Convert graph to D3.js force graph format */ export declare function toD3Format(result: DependencyGraphResult): { nodes: Array<{ id: string; group: number; score: number; }>; links: Array<{ source: string; target: string; value: number; }>; }; /** * Convert graph to Mermaid diagram syntax */ export declare function toMermaidFormat(result: DependencyGraphResult, maxNodes?: number): string; /** * Convert graph to DOT format (Graphviz) */ export declare function toDotFormat(result: DependencyGraphResult): string; //# sourceMappingURL=dependency-graph.d.ts.map