Skip to content

outdated, why: match an aliased dependency by either name and print both - #43338

Open
robobun wants to merge 1 commit into
mainfrom
robobun/fd46c9f0/outdated-why-alias-names
Open

robobun wants to merge 1 commit into
mainfrom
robobun/fd46c9f0/outdated-why-alias-names

Conversation

@robobun

@robobun robobun commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • For "my-alias": "npm:dep@1.0.0", bun outdated prints the row as dep. bun outdated dep prints nothing and bun outdated my-alias prints the dep row.
  • bun why my-alias fails with error: No packages matching 'my-alias' found in lockfile. bun why dep works and does not show the alias.
  • The cause: collect_outdated matches patterns against the dependency name (src/runtime/cli/outdated_command.rs:403) and prints the package name (:419). bun why selects by package name only (src/runtime/cli/why_command.rs:445).

Fix

  • bun outdated matches a pattern against both names, as bun update <name> already does (src/install/update_scope.rs:453). A !pattern keeps a row only when neither name matches. An aliased row prints as my-alias@npm:dep, the form bun add prints.
  • bun why also selects a package through the name of a dependency that resolves to it. The dependent's line prints that name: (requires my-alias@npm:dep@1.0.0).
  • Both commands use one new helper, DependencyExt::alias_for. The Notes list the other commands with the same gap. They do not change here.
  • Verified: new tests in test/cli/install/bun-install-registry.test.ts (outdated) and test/cli/install/bun-pm-why.test.ts fail on the 1.4.3 canary. Both full files pass. Self-reviewed: 6 concerns raised, 6 addressed, one in part (Notes).

Background

  • An npm alias installs a package under another name. "my-alias": "npm:dep@1.0.0" puts the registry package dep in node_modules/my-alias.
  • The lockfile has two names for that edge: the dependency name (my-alias, the package.json key) and the package name (dep).
  • bun update and bun add take the dependency name. The registry versions belong to the package name. So the table shows both.
Notes

Output after the fix, for dependencies: {"my-alias": "npm:dep@1.0.0", "other": "1.0.0"} and devDependencies: {"dev-alias": "npm:dep@1.0.0"}:

| Package                 | Current | Update | Latest |
| my-alias@npm:dep        | 1.0.0   | 1.0.0  | 2.0.0  |
| other                   | 1.0.0   | 1.0.0  | 2.0.0  |
| dev-alias@npm:dep (dev) | 1.0.0   | 1.0.0  | 2.0.0  |

$ bun why my-alias
dep@1.0.0
  ├─ root (requires my-alias@npm:dep@1.0.0)
  └─ dev root (requires dev-alias@npm:dep@1.0.0)

bun outdated dep lists both alias rows, bun outdated my-alias lists one, bun outdated '!dep' lists only other, bun outdated '!my-*' lists other and dev-alias@npm:dep (dev). So p and !p split the table in two.

The printed form. The report suggested my-alias (dep). I used my-alias@npm:dep because the column already ends in (dev), (peer) or (optional), and because installed my-alias@npm:dep@1.0.0 is what bun add prints (print_installed_update_request in src/install/lockfile/printer/tree_printer.rs). The row can be pasted into bun add my-alias@npm:dep@2.0.0.

Where the alias goes in bun why. The alias belongs to the edge, not to the package. One package can have several aliases and a dependent under its own name at once. So the header stays dep@1.0.0 and each dependent line carries its own name for the package. The rule is "the dependency name differs from the resolved package name", so it also covers a catalog: alias, an overridden dependency, and a git, tarball or folder dependency whose key is not the name in its package.json. Dependency::realname() does not see the first two.

Width. An alias is a package.json key, so it can hold wide characters ("別名": "npm:dep@1.0.0" installs). The alias part of the cell is measured in terminal columns. The test has such a row and checks that every line of the table has the same Bun.stringWidth.

Other open PRs in the same lines.

Same gap, not changed here. Only the two-name rule is shared (alias_for). bun update, bun outdated and bun why still have three glob dialects, and I did not unify them.

  • bun patch: bun patch dep prints error: package dep not found. bun patch my-alias works and prints To patch dep, edit the following folder: node_modules/my-alias. Reported separately.
  • bun pm ls and the bun install summary print the alias only (my-alias@1.0.0).
  • bun update -i lists the alias only (update_interactive_command.rs, name: Box::from(name_slice)).
  • bun audit compares the dependency name with the advisory's package name when it marks a direct dependency (audit_command.rs). I did not run it against an advisory server.
  • bun pm trust: install: trust npm: aliased packages by the same name in bun pm trust, the installer and bun.lock #39443 is open for it.
  • bun install --yarn: yarn lockfile output ignores alias name #17089 is open for it.
  • bun remove and bun update <name> are right as they are: the first edits a package.json key, the second already takes either name.

Self-review. Six concerns were raised: the width of the alias, the two open PRs above, the two private copies of the alias rule, a warning not to merge the glob matchers, the unnamed sibling commands, and the bun why help text. All are addressed in the diff or in these Notes. One part is rejected: a shared Display for alias@npm:pkg. bun add, bun outdated and bun why color the parts differently, and bun why prints the spec (alias@npm:dep@1.0.0), not the package name.

Test notes. The new why test replaces should handle npm aliases. That test accepted exit 1 through else { expect(true).toBe(true) } and used the public registry. The new one uses the local verdaccio registry, a root alias, a glob on the alias, and an alias declared by a registry package (alias-loop-1 depends on alias-loop-2 as alias1).

Found on the way, fixed in other PRs:

For "my-alias": "npm:dep@1.0.0", bun outdated printed the row as dep but
matched its name patterns against my-alias only, and bun why knew the
package as dep only.

bun outdated now matches a pattern against the package.json name and the
package name, as bun update <name> does, and prints the row as
my-alias@npm:dep. A negated pattern keeps the row only when neither name
matches. The alias part of the cell is sized in terminal columns, because
a package.json key can hold wide characters.

bun why now also selects a package through the name of a dependency that
resolves to it, and prints that name in the dependent's line:
(requires my-alias@npm:dep@1.0.0).

Both commands get the alias from DependencyExt::alias_for.
@coderabbitai

coderabbitai Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Review paused — included plan limit reached

Keep your review moving with free on-demand reviews.

  • Run this review for free

On-demand reviews are free for the next 2 days.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Promotion and pricing details

On-demand reviews are free for the next 2 days. After that, they cost $0.25 per reviewed file.

Review limit details

Or wait 5 minutes for your next included review.

Check out review usage here.

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Essentials

Run ID: 78f0ee43-f4cd-4075-888b-deda43f513fb

📥 Commits

Reviewing files that changed from the base of the PR and between 367d939 and 71cbbae.

📒 Files selected for processing (8)
  • docs/pm/cli/outdated.mdx
  • docs/pm/cli/why.mdx
  • src/install/dependency.rs
  • src/runtime/cli/mod.rs
  • src/runtime/cli/outdated_command.rs
  • src/runtime/cli/why_command.rs
  • test/cli/install/bun-install-registry.test.ts
  • test/cli/install/bun-pm-why.test.ts

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 11:52 AM PT - Sep 18th, 2026

✅ @robobun, your commit 71cbbae4f967a65a5660d35e23c26736835a14db passed in Build #117854! 🎉


🧪   To try this PR locally:

bunx bun-pr 43338

That installs a local version of the PR into your bun-43338 executable, so you can run:

bun-43338 --bun

@robobun

robobun commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator Author

Status

How I reproduced it, on 1.4.3-canary (b52d513) and on main:

  1. Serve one package dep (1.0.0 and 2.0.0) from a loopback registry.
  2. Install with "dependencies": { "my-alias": "npm:dep@1.0.0" }.
  3. bun outdated prints the row dep. bun outdated dep prints no row. bun outdated my-alias prints the dep row.
  4. bun why my-alias prints error: No packages matching 'my-alias' found in lockfile and exits 1. bun why dep works.

The same steps are in the two new tests, with the local verdaccio registry (no-deps in place of dep):

  • test/cli/install/bun-install-registry.test.ts, outdated > an aliased dependency prints both of its names and a pattern matches either
  • test/cli/install/bun-pm-why.test.ts, should find a package by its own name and by the alias a dependent gives it

Both fail on the canary and pass on this branch. Both files pass in full with the debug build.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Comment thread src/runtime/cli/outdated_command.rs
Comment thread src/runtime/cli/why_command.rs
Comment thread src/runtime/cli/why_command.rs
Comment thread src/runtime/cli/outdated_command.rs

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants