Skip to content

fix(shim): move npm global links to the reinstalled Node.js version - #3283

Open
mondaychen wants to merge 2 commits into
voidzero-dev:mainfrom
mondaychen:fix/npm-global-relink-node-version
Open

mondaychen wants to merge 2 commits into
voidzero-dev:mainfrom
mondaychen:fix/npm-global-relink-node-version

Conversation

@mondaychen

Copy link
Copy Markdown

Summary

Fixes #3279.

When the active Node.js version changes, npm install -g <pkg> installs a new copy into the new Node.js npm prefix. The ~/.vite-plus/bin/<bin> link kept pointing to the old copy, because Vite+ replaced an existing npm link only when a different package owned it. npm reported success and Vite+ printed nothing, so the command kept running the old version.

Now Vite+ also replaces the link when the same package owns it but the link does not point to the binary in the current npm bin dir. It records the new Node.js version in the BinConfig and prints a note:

note: Moving 'agent-browser' from Node.js 24.15.0 to 26.13.0
Linked 'agent-browser' to ~/.vite-plus/bin/agent-browser

A repeat install under the same Node.js version leaves the link and BinConfig unchanged and prints nothing new.

On Unix, the check compares the symlink target. On Windows, it checks the source path in the .cmd wrapper that create_bin_link writes.

Tests

  • Unit test test_npm_reinstall_under_new_node_version_moves_link: two npm prefixes, one per Node.js version. It fails with the old condition and passes with this change. It also checks that a repeat install changes nothing.
  • Snapshot case npm_global_install_node_version_relink (global flavor, Unix only, like the other npm link cases): install with Node.js 24, install again with VP_NODE_VERSION=26.12.1, remove the Node.js 24 copy, and run the command. The runner seeds the runtime folder from a shared cache, so each step sets a case-local NPM_CONFIG_PREFIX per Node.js version instead of writing into the runtime folder.
  • All 16 npm_global* snapshot cases pass locally. cargo fmt --check and clippy -p vp_global_cli --all-targets --deny warnings pass. I could not compile the cfg(windows) branch locally.

🤖 Generated with Claude Code

When the active Node.js version changes, `npm install -g <pkg>` installs a
new copy into the new Node.js npm prefix. The `~/.vite-plus/bin` link kept
the old target because Vite+ replaced a link only when a different package
owned it. The command then kept running the old version.

Replace the link also when the same package owns it but the link does not
point to the binary in the current npm bin dir, record the new Node.js
version, and tell the user that the link moved.

Fixes voidzero-dev#3279

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment on lines +304 to +307
let same_owner = config.package == package_name;
if source_path.as_path().exists()
&& !(same_owner
&& npm_bin_link_targets(&bin_dir, &bin_name, &source_path))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] Preserve the existing npm link during a dry run

When the same package already exists in two npm prefixes, this condition can switch the active binary after npm install -g --dry-run. For example, the Vite+ link points to version 2.0.0 in prefix B, while prefix A still contains 1.0.0. Running npm install -g --prefix <A> <local-v2-package> --dry-run succeeds without changing A's files, but the post-install hook sees A's existing binary and replaces the link to B with a link to A. I reproduced this on the PR head: the global command changed from 2.0.0 to 1.0.0, while A's installed package remained unchanged. The previous same-owner guard skipped this mutation. Please preserve the link and its BinConfig when npm's effective dry-run setting is enabled, including configuration from the environment or npmrc, and add a regression case with both prefixes already populated.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks! Fixed in ef2b9e7

@fengmk2 fengmk2 self-assigned this Oct 30, 2026
A dry run changes no files in the npm prefix, but the post-install hook
still saw an existing binary in that prefix and could move the link to it.
With the same package in two prefixes, `npm install -g --dry-run` into the
older prefix moved the command back to the older version.

Skip the post-install link step when npm's effective `dry-run` setting is
on. A CLI flag wins; otherwise `npm config get dry-run` reports the value
from the environment and npmrc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

npm install -g keeps the bin link on the old version after the default Node.js changes

2 participants