diff --git a/.changeset/upset-chefs-lie.md b/.changeset/upset-chefs-lie.md new file mode 100644 index 000000000..ef40f6c7b --- /dev/null +++ b/.changeset/upset-chefs-lie.md @@ -0,0 +1,5 @@ +--- +"fnm": patch +--- + +Only enable Corepack on Node.js versions that bundle it diff --git a/docs/configuration.md b/docs/configuration.md index a205a4e44..ec98ad51b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -52,6 +52,12 @@ error: Can't find version in dotfiles. Please provide a version manually to the Runs [`corepack enable`](https://nodejs.org/api/corepack.html#enabling-the-feature) when a new version of Node.js is installed. Experimental due to the fact Corepack itself is experimental. +> [!NOTE] +> Corepack is only bundled with Node.js v14.19.0+, v16.9.0+ and up to, but not including v25.0.0+, i.e. `^14.19.0 || 16.9.0 - 24.x.x`. +> +> When installing Node.js versions outside the range, +> you will see a hint that you need to manually install and enable Corepack via `npm install -g corepack && corepack enable`. + ### `--resolve-engines` **🧪 Experimental** diff --git a/e2e/__snapshots__/corepack.test.ts.snap b/e2e/__snapshots__/corepack.test.ts.snap index 03b21b911..8611a460d 100644 --- a/e2e/__snapshots__/corepack.test.ts.snap +++ b/e2e/__snapshots__/corepack.test.ts.snap @@ -7,12 +7,23 @@ fnm install 18 fnm exec --using=18 node test-pnpm-corepack.js" `; +exports[`Bash skips enabling Corepack if it's not bundled with Node.js: Bash 1`] = ` +"set -e +eval "$(fnm env --corepack-enabled)" +(fnm install 14.18.0) | grep "npm install -g corepack" || (echo "Expected output to contain "npm install -g corepack"" && exit 1)" +`; + exports[`Fish installs corepack: Fish 1`] = ` "fnm env --corepack-enabled | source fnm install 18 fnm exec --using=18 node test-pnpm-corepack.js" `; +exports[`Fish skips enabling Corepack if it's not bundled with Node.js: Fish 1`] = ` +"fnm env --corepack-enabled | source +begin; fnm install 14.18.0; end | grep "npm install -g corepack"; or echo "Expected output to contain "npm install -g corepack"" && exit 1" +`; + exports[`PowerShell installs corepack: PowerShell 1`] = ` "$ErrorActionPreference = "Stop" fnm env --corepack-enabled | Out-String | Invoke-Expression @@ -20,9 +31,21 @@ fnm install 18 fnm exec --using=18 node test-pnpm-corepack.js" `; +exports[`PowerShell skips enabling Corepack if it's not bundled with Node.js: PowerShell 1`] = ` +"$ErrorActionPreference = "Stop" +fnm env --corepack-enabled | Out-String | Invoke-Expression +$($__out__ = $(fnm install 14.18.0 | Select-String "npm install -g corepack"); if ($__out__ -eq $null) { exit 1 } else { $__out__ })" +`; + exports[`Zsh installs corepack: Zsh 1`] = ` "set -e eval "$(fnm env --corepack-enabled)" fnm install 18 fnm exec --using=18 node test-pnpm-corepack.js" `; + +exports[`Zsh skips enabling Corepack if it's not bundled with Node.js: Zsh 1`] = ` +"set -e +eval "$(fnm env --corepack-enabled)" +(fnm install 14.18.0) | grep "npm install -g corepack" || (echo "Expected output to contain "npm install -g corepack"" && exit 1)" +`; diff --git a/e2e/corepack.test.ts b/e2e/corepack.test.ts index 6917ea1ea..408feb10b 100644 --- a/e2e/corepack.test.ts +++ b/e2e/corepack.test.ts @@ -50,5 +50,18 @@ for (const shell of [Bash, Fish, PowerShell, Zsh]) { // .addExtraEnvVar("RUST_LOG", "fnm=debug") .execute(shell) }) + + test(`skips enabling Corepack if it's not bundled with Node.js`, async () => { + await script(shell) + .then(shell.env({ corepackEnabled: true })) + .then( + shell.scriptOutputContains( + shell.call("fnm", ["install", "14.18.0"]), + `"npm install -g corepack"`, + ) + ) + .takeSnapshot(shell) + .execute(shell) + }) }) } diff --git a/src/commands/install.rs b/src/commands/install.rs index 594fcff87..4a8cb8b75 100644 --- a/src/commands/install.rs +++ b/src/commands/install.rs @@ -193,6 +193,23 @@ fn tag_alias(config: &FnmConfig, matched_version: &Version, alias: &Version) -> } fn enable_corepack(version: &Version, config: &FnmConfig) -> Result<(), Error> { + let Version::Semver(nodejs_version) = version else { + return Ok(()); + }; + + let corepack_range: node_semver::Range = "^14.19.0 || 16.9.0 - 24.x.x".parse().unwrap(); + + if !nodejs_version.satisfies(&corepack_range) { + let message = format!( + "Note: Corepack is not bundled with Node.js {nodejs_version}, \ + so you have to manually install and enable it by running:\ + \nnpm install -g corepack && corepack enable" + ); + outln!(config, Info, "{}", message.yellow()); + + return Ok(()); + } + let corepack_path = version.installation_path(config); let corepack_path = if cfg!(windows) { corepack_path.join("corepack.cmd")