Skip to content

refactor: simplify dependenciesHierarchyForPackage by delegating to getTree#10616

Merged
zkochan merged 1 commit intomainfrom
refactor-deps-hierarchy
Feb 13, 2026
Merged

refactor: simplify dependenciesHierarchyForPackage by delegating to getTree#10616
zkochan merged 1 commit intomainfrom
refactor-deps-hierarchy

Conversation

@zkochan
Copy link
Member

@zkochan zkochan commented Feb 13, 2026

Instead of manually iterating over top-level dependencies, calling getPkgInfo/getTreeNodeChildId/getTree per dependency, and handling dedup/search logic in parallel with materializeChildren, delegate entirely to a single getTree call with the importer as root.

The returned PackageNode[] are then post-categorized into their dependency fields (dependencies, devDependencies, optionalDependencies) using a fieldMap built from the lockfile importer snapshot.

This eliminates the duplicated dedup/search handling between dependenciesHierarchyForPackage and materializeChildren, and removes the GetTreeResult wrapper type from getTree (now returns PackageNode[] directly). The materializeChildren cache is now the sole mechanism for cross-importer deduplication.

…etTree

Instead of manually iterating over top-level dependencies, calling
getPkgInfo/getTreeNodeChildId/getTree per dependency, and handling
dedup/search logic in parallel with materializeChildren, delegate
entirely to a single getTree call with the importer as root.

The returned PackageNode[] are then post-categorized into their
dependency fields (dependencies, devDependencies, optionalDependencies)
using a fieldMap built from the lockfile importer snapshot.

This eliminates the duplicated dedup/search handling between
dependenciesHierarchyForPackage and materializeChildren, and removes
the GetTreeResult wrapper type from getTree (now returns PackageNode[]
directly). The materializeChildren cache is now the sole mechanism for
cross-importer deduplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 13, 2026 20:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors dependenciesHierarchyForPackage to delegate dependency tree building to a single getTree call using the importer as the root, rather than making separate calls for each top-level dependency. The returned nodes are then post-categorized into their dependency fields. This eliminates duplicated deduplication and search handling logic, simplifies the codebase, and removes the GetTreeResult wrapper type in favor of returning PackageNode[] directly.

Changes:

  • Simplified getTree to return PackageNode[] directly instead of a GetTreeResult wrapper
  • Refactored dependenciesHierarchyForPackage to make a single getTree call with the importer as root
  • Unified deduplication logic in materializeChildren as the sole cross-importer dedup mechanism

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
reviewing/dependencies-hierarchy/src/getTree.ts Removed GetTreeResult interface and simplified getTree to return PackageNode[] directly, moving all dedup handling to materializeChildren
reviewing/dependencies-hierarchy/src/buildDependenciesHierarchy.ts Refactored to call getTree once per importer with maxDepth: opts.depth + 1, then categorize nodes into dependency fields using a fieldMap; removed unused imports
reviewing/dependencies-hierarchy/test/getTree.test.ts Updated tests to expect PackageNode[] return type and verify dedup behavior at node level instead of result wrapper level
cspell.json Added "dedup" to dictionary

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +161 to +167
for (const field of DEPENDENCIES_FIELDS.sort().filter(f => opts.include[f])) {
result[field] = []
const fieldDeps = currentLockfile.importers[importerId][field] ?? {}
for (const alias in fieldDeps) {
fieldMap.set(alias, field)
}
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filter condition opts.include[f] only includes fields where the value is truthy. However, in buildDependencyGraph, dependencies and devDependencies are included unless explicitly set to false (using !== false checks). This creates a mismatch: if opts.include.dependencies or opts.include.devDependencies is undefined, those dependencies will be included in the graph and returned by getTree, but they won't be added to fieldMap, causing nodes to be silently dropped during categorization. The filter should use opts.include[f] !== false to match the graph building logic.

Copilot uses AI. Check for mistakes.
@zkochan zkochan merged commit 491813f into main Feb 13, 2026
18 of 19 checks passed
@zkochan zkochan deleted the refactor-deps-hierarchy branch February 13, 2026 21:08
zkochan added a commit that referenced this pull request Feb 13, 2026
…etTree (#10616)

Instead of manually iterating over top-level dependencies, calling
getPkgInfo/getTreeNodeChildId/getTree per dependency, and handling
dedup/search logic in parallel with materializeChildren, delegate
entirely to a single getTree call with the importer as root.

The returned PackageNode[] are then post-categorized into their
dependency fields (dependencies, devDependencies, optionalDependencies)
using a fieldMap built from the lockfile importer snapshot.

This eliminates the duplicated dedup/search handling between
dependenciesHierarchyForPackage and materializeChildren, and removes
the GetTreeResult wrapper type from getTree (now returns PackageNode[]
directly). The materializeChildren cache is now the sole mechanism for
cross-importer deduplication.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
zkochan added a commit to teambit/bit that referenced this pull request Feb 17, 2026
`bit why` now shows a reverse dependency tree. The searched package
appears at the root with its dependents as branches, walking back to
workspace components. This replaces the previous forward-tree output
which was noisy and hard to read for deeply nested dependencies.

Also with the complete rewrite of the dependency tree builder we have
fixed the out-of-memory errors that were frequent with the why command.
The command also became a lot faster.

## Proposed Changes

Related PRs:
- pnpm/pnpm#10582
- pnpm/pnpm#10586
- pnpm/pnpm#10615
- pnpm/pnpm#10616
- pnpm/pnpm#10627
- pnpm/pnpm#10629
- pnpm/pnpm#10596

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants