Dependency graph operations on the lockfile.
Provides adjacency-list based graph algorithms for analyzing the dependency structure: detecting cycles, computing fan-in/out, and finding orphans.
Summary
Functions
Build an adjacency list from the lockfile.
Detect circular dependencies. Returns list of cycle paths.
Compute fan-in (number of dependents) for each package.
Compute fan-out (number of dependencies) for each package.
Compute impact score — how many packages transitively depend on a package.
Find leaf packages (no dependencies).
Compute the maximum dependency depth from a package.
Reverse the graph so all edges point from dependencies to dependents.
Find root packages (not depended on by any other package).
Find the shortest path between two packages.
Compute the transitive closure — all reachable packages from a root.
Functions
@spec adjacency_list(%{required(String.t()) => NPM.Lockfile.entry()}) :: %{ required(String.t()) => [String.t()] }
Build an adjacency list from the lockfile.
Returns %{name => [dep_name, ...]}.
Detect circular dependencies. Returns list of cycle paths.
Uses Erlang's :digraph_utils for reliable cycle detection.
@spec fan_in(%{required(String.t()) => [String.t()]}) :: %{ required(String.t()) => non_neg_integer() }
Compute fan-in (number of dependents) for each package.
@spec fan_out(%{required(String.t()) => [String.t()]}) :: %{ required(String.t()) => non_neg_integer() }
Compute fan-out (number of dependencies) for each package.
@spec impact(%{required(String.t()) => [String.t()]}, String.t()) :: non_neg_integer()
Compute impact score — how many packages transitively depend on a package.
Find leaf packages (no dependencies).
@spec max_depth(%{required(String.t()) => [String.t()]}, String.t()) :: non_neg_integer()
Compute the maximum dependency depth from a package.
Reverse the graph so all edges point from dependencies to dependents.
Find root packages (not depended on by any other package).
@spec shortest_path(%{required(String.t()) => [String.t()]}, String.t(), String.t()) :: [String.t()] | nil
Find the shortest path between two packages.
Compute the transitive closure — all reachable packages from a root.