diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md index 79254b603c..1829c4ad14 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/cli_helper_message/snapshots/cli_helper_message.md @@ -117,7 +117,7 @@ Options: -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile - --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) + --fix-lockfile Fix broken lockfile entries (pnpm and yarn@4+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) --resolution-only Re-run resolution for peer dependency analysis (pnpm only) --silent Suppress output (silent mode) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md index a5df7fedb3..a0e7e921a1 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9/snapshots/command_add_pnpm9.md @@ -106,8 +106,7 @@ should error because allow-build is not supported at pnpm@9 **Exit code:** 1 ``` - ERROR  Unknown option: 'allow-build' -For help, run: pnpm help add +pnpm < 10.4.0 does not support --allow-build. ``` ## `vp install test-vite-plus-package@1.0.0 --save-peer` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots.toml index 039b65d4ce..47a680bde4 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots.toml @@ -18,4 +18,5 @@ steps = [ { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/utils/package.json", "pnpm-workspace.yaml"], continue-on-failure = true }, { argv = ["vp", "add", "--filter", "app", "test-vite-plus-package-optional", "--save-catalog-name", "v1"], comment = "should error because save-catalog-name is not supported at pnpm@9", continue-on-failure = true }, { argv = ["vp", "add", "--filter=./packages/utils", "test-vite-plus-package-optional", "-O", "--save-catalog", "v2"], comment = "should error because save-catalog is not supported at pnpm@9", continue-on-failure = true }, + { argv = ["vp", "install", "testnpm2", "--save-catalog"], comment = "The install alias must apply the add catalog version guard.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots/command_add_pnpm9_with_workspace.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots/command_add_pnpm9_with_workspace.md index 2e91b4d02a..c8dc55132e 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots/command_add_pnpm9_with_workspace.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_pnpm9_with_workspace/snapshots/command_add_pnpm9_with_workspace.md @@ -203,9 +203,7 @@ should error because save-catalog-name is not supported at pnpm@9 **Exit code:** 1 ``` - ERROR  Unknown option: 'save-catalog-name' -Did you mean 'save-optional'? Use "--config.unknown=value" to force an unknown option. -For help, run: pnpm help add +pnpm < 10.12.0 does not support --save-catalog-name. ``` ## `vp add --filter=./packages/utils test-vite-plus-package-optional -O --save-catalog v2` @@ -215,7 +213,17 @@ should error because save-catalog is not supported at pnpm@9 **Exit code:** 1 ``` - ERROR  Unknown option: 'save-catalog' -Did you mean 'save-exact', or 'save-prod'? Use "--config.unknown=value" to force an unknown option. -For help, run: pnpm help add +pnpm < 10.12.0 does not support --save-catalog. +``` + +## `vp install testnpm2 --save-catalog` + +The install alias must apply the add catalog version guard. + +**Exit code:** 1 + +``` +VITE+ - The Unified Toolchain for the Web + +pnpm < 10.12.0 does not support --save-catalog. ``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots.toml index 525840ac3b..ada66c9031 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots.toml @@ -14,4 +14,6 @@ steps = [ { argv = ["vpt", "print-file", "package.json"], continue-on-failure = true }, { argv = ["vp", "add", "test-vite-plus-package-optional", "--", "--tilde"], comment = "support pass through arguments" }, { argv = ["vpt", "print-file", "package.json"], continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "yarn@2.4.2"], snapshot = false }, + { argv = ["vp", "add", "testnpm2", "--ignore-scripts"], comment = "Yarn 2 supports skip-builds for install, but not for add.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md index 4d8a43084d..4f7f3f217f 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_add_yarn4/snapshots/command_add_yarn4.md @@ -201,3 +201,16 @@ support pass through arguments } } ``` + +## `vpt json-edit package.json packageManager yarn@2.4.2` + + +## `vp add testnpm2 --ignore-scripts` + +Yarn 2 supports skip-builds for install, but not for add. + +**Exit code:** 1 + +``` +yarn >= 2 && < 3 does not support --ignore-scripts. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots.toml index 1e1d19f7fb..ce7de0451f 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots.toml @@ -19,4 +19,6 @@ steps = [ { argv = ["vp", "pm", "list", "--find-by", "customFinder"], comment = "should use custom finder (pnpm-specific)", continue-on-failure = true }, { argv = ["vp", "pm", "list", "--recursive"], comment = "should list packages recursively in workspace", continue-on-failure = true }, { argv = ["vp", "pm", "list", "--", "--loglevel=warn"], comment = "should support pass through arguments", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@10.15.1"], snapshot = false }, + { argv = ["vp", "pm", "list", "--find-by", "customFinder"], comment = "Reject finders before pnpm 10.16.0.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots/command_list_pnpm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots/command_list_pnpm10.md index ad2ec991a5..75f3d6e9a3 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots/command_list_pnpm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_list_pnpm10/snapshots/command_list_pnpm10.md @@ -279,3 +279,16 @@ testnpm2 1.0.1 devDependencies: test-vite-plus-package 1.0.0 ``` + +## `vpt json-edit package.json packageManager pnpm@10.15.1` + + +## `vp pm list --find-by customFinder` + +Reject finders before pnpm 10.16.0. + +**Exit code:** 1 + +``` +pnpm < 10.16.0 does not support --find-by. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots.toml index 191e5e12db..10f080176b 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots.toml @@ -9,4 +9,8 @@ steps = [ { argv = ["vpt", "rm", "-rf", "./dist"], continue-on-failure = true }, { argv = ["vp", "pm", "pack", "--json", "--", "--loglevel=warn"], comment = "should support pass through arguments" }, { argv = ["vpt", "rm", "-f", "command-pack-npm10-1.0.0.tgz"], snapshot = false, continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@7.8.0"], snapshot = false }, + { argv = ["vp", "pm", "pack", "--filter", "app"], comment = "Reject workspace selection before npm 7.9.0.", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@7.17.0"], snapshot = false }, + { argv = ["vp", "pm", "pack", "--pack-destination", "dist"], comment = "Reject pack-destination before npm 7.18.0.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots/command_pack_npm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots/command_pack_npm10.md index 149406c4b6..266389c253 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots/command_pack_npm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_npm10/snapshots/command_pack_npm10.md @@ -94,3 +94,29 @@ should support pass through arguments ## `vpt rm -f command-pack-npm10-1.0.0.tgz` + +## `vpt json-edit package.json packageManager npm@7.8.0` + + +## `vp pm pack --filter app` + +Reject workspace selection before npm 7.9.0. + +**Exit code:** 1 + +``` +npm < 7.9.0 does not support --filter. +``` + +## `vpt json-edit package.json packageManager npm@7.17.0` + + +## `vp pm pack --pack-destination dist` + +Reject pack-destination before npm 7.18.0. + +**Exit code:** 1 + +``` +npm < 7.18.0 does not support --pack-destination. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots.toml index 2b493ddf64..66fa500bc1 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots.toml @@ -16,4 +16,6 @@ steps = [ { argv = ["vpt", "rm", "-f", "command-pack-pnpm10-1.0.0.tgz"], snapshot = false, continue-on-failure = true }, { argv = ["vp", "pm", "pack", "--", "--loglevel=warn"], comment = "should support pass through arguments" }, { argv = ["vpt", "rm", "-f", "command-pack-pnpm10-1.0.0.tgz"], snapshot = false, continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@10.10.0"], snapshot = false }, + { argv = ["vp", "pm", "pack", "--recursive"], comment = "Reject recursive pack before pnpm 10.11.0.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots/command_pack_pnpm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots/command_pack_pnpm10.md index ea912f13ab..f997f0cb06 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots/command_pack_pnpm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_pack_pnpm10/snapshots/command_pack_pnpm10.md @@ -129,3 +129,16 @@ command-pack-pnpm10-1.0.0.tgz ## `vpt rm -f command-pack-pnpm10-1.0.0.tgz` + +## `vpt json-edit package.json packageManager pnpm@10.10.0` + + +## `vp pm pack --recursive` + +Reject recursive pack before pnpm 10.11.0. + +**Exit code:** 1 + +``` +pnpm < 10.11.0 does not support --recursive. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots.toml index f2fd17bdf5..9c069bf4e3 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots.toml @@ -6,4 +6,9 @@ steps = [ { argv = ["vp", "pm", "publish", "--help"], comment = "should show help", continue-on-failure = true }, { argv = ["vp", "pm", "publish", "--dry-run", "--", "--loglevel", "error"], comment = "should preview publish without actually publishing (uses npm publish --dry-run)", continue-on-failure = true }, { argv = ["vp", "pm", "publish", "--dry-run", "--json", "--", "--ignore-scripts", "--loglevel", "error"], comment = "should preserve JSON output without publishing", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "private", "true"], snapshot = false }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@5.8.0"], snapshot = false }, + { argv = ["vp", "pm", "publish", "--dry-run"], comment = "Reject npm versions that publish despite dry-run. The package is private for safety.", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@9.4.2"], snapshot = false }, + { argv = ["vp", "pm", "publish", "--dry-run", "--provenance"], comment = "Reject provenance before npm 9.5.0.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots/command_publish_npm10.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots/command_publish_npm10.md index 7eeabb6e92..de92bf6d16 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots/command_publish_npm10.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_npm10/snapshots/command_publish_npm10.md @@ -66,3 +66,32 @@ should preserve JSON output without publishing "bundled": [] } ``` + +## `vpt json-edit package.json private true` + + +## `vpt json-edit package.json packageManager npm@5.8.0` + + +## `vp pm publish --dry-run` + +Reject npm versions that publish despite dry-run. The package is private for safety. + +**Exit code:** 1 + +``` +npm < 5.10.0 does not support --dry-run. +``` + +## `vpt json-edit package.json packageManager npm@9.4.2` + + +## `vp pm publish --dry-run --provenance` + +Reject provenance before npm 9.5.0. + +**Exit code:** 1 + +``` +npm < 9.5.0 does not support --provenance. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots.toml index b32d6965e8..96fae24da3 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots.toml @@ -4,4 +4,5 @@ vp = "global" steps = [ { argv = ["vp", "pm", "publish", "--help"], comment = "should show help", continue-on-failure = true }, { argv = ["vp", "pm", "publish", "--dry-run", "--", "--loglevel", "error"], comment = "should preview publish without actually publishing (uses pnpm publish --dry-run)", continue-on-failure = true }, + { argv = ["vp", "pm", "publish", "--dry-run", "--json"], comment = "Reject pnpm 11.0.6, which silently omitted JSON output.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots/command_publish_pnpm11.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots/command_publish_pnpm11.md index da143dac83..4439e77175 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots/command_publish_pnpm11.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_publish_pnpm11/snapshots/command_publish_pnpm11.md @@ -39,3 +39,13 @@ should preview publish without actually publishing (uses pnpm publish --dry-run) ``` ``` + +## `vp pm publish --dry-run --json` + +Reject pnpm 11.0.6, which silently omitted JSON output. + +**Exit code:** 1 + +``` +pnpm >= 11.0.0 && < 11.0.7 does not support --json. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots.toml index bd7ece4147..ebd374f6f1 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots.toml @@ -8,4 +8,11 @@ steps = [ { argv = ["vpt", "print-file", "package.json"], continue-on-failure = true }, { argv = ["vp", "up", "testnpm2", "--latest"], comment = "should update to absolute latest version" }, { argv = ["vpt", "print-file", "package.json"], continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "bun@1.3.14"], snapshot = false }, + { argv = ["vp", "update", "--prod"], comment = "Reject production dependency selection before Bun 1.4.", continue-on-failure = true }, + { argv = ["vp", "update", "--no-optional"], comment = "Reject optional dependency exclusion before Bun 1.4.", continue-on-failure = true }, + { argv = ["vp", "update", "--recursive"], comment = "Reject recursive updates before Bun 1.4.", continue-on-failure = true }, + { argv = ["vp", "update", "--filter", "app"], comment = "Reject filtered updates before Bun 1.4.", continue-on-failure = true }, + { argv = ["vp", "update", "--interactive", "--recursive"], comment = "Interactive updates use the same Bun version requirement.", continue-on-failure = true }, + { argv = ["vp", "update", "--interactive", "--filter", "app"], continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md index 5205d4bd40..705ae9d795 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_update_bun/snapshots/command_update_bun.md @@ -97,3 +97,64 @@ installed testnpm2@1.0.1 "packageManager": "bun@1.3.11" } ``` + +## `vpt json-edit package.json packageManager bun@1.3.14` + + +## `vp update --prod` + +Reject production dependency selection before Bun 1.4. + +**Exit code:** 1 + +``` +bun < 1.4 does not support --prod. +``` + +## `vp update --no-optional` + +Reject optional dependency exclusion before Bun 1.4. + +**Exit code:** 1 + +``` +bun < 1.4 does not support --no-optional. +``` + +## `vp update --recursive` + +Reject recursive updates before Bun 1.4. + +**Exit code:** 1 + +``` +bun < 1.4 does not support --recursive. +``` + +## `vp update --filter app` + +Reject filtered updates before Bun 1.4. + +**Exit code:** 1 + +``` +bun < 1.4 does not support --filter. +``` + +## `vp update --interactive --recursive` + +Interactive updates use the same Bun version requirement. + +**Exit code:** 1 + +``` +bun < 1.4 does not support --recursive. +``` + +## `vp update --interactive --filter app` + +**Exit code:** 1 + +``` +bun < 1.4 does not support --filter. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots.toml index f6a6e5eb4c..874784c34f 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots.toml @@ -18,4 +18,7 @@ steps = [ { argv = ["vp", "why", "test-vite-plus-package-optional", "--no-optional"], comment = "should exclude optional dependencies", continue-on-failure = true }, { argv = ["vp", "why", "testnpm2", "--find-by", "customFinder"], comment = "should support find-by option (pnpm-specific)", continue-on-failure = true }, { argv = ["vp", "why", "testnpm2", "--", "--reporter=silent"], comment = "should support pass through arguments", continue-on-failure = true }, + { argv = ["vp", "why", "--find-by", "customFinder"], comment = "Package names remain required even when a finder is supplied.", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "pnpm@10.15.1"], snapshot = false }, + { argv = ["vp", "why", "testnpm2", "--find-by", "customFinder"], comment = "Reject finders before pnpm 10.16.0.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.global.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.global.md index 98e7f1bb66..d67398c145 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.global.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.global.md @@ -221,3 +221,31 @@ command-why-pnpm10@1.0.0 dependencies: testnpm2 1.0.1 ``` + +## `vp why --find-by customFinder` + +Package names remain required even when a finder is supplied. + +**Exit code:** 2 + +``` +error: the following required arguments were not provided: + ... + +Usage: vp why --find-by ... [-- ...] + +For more information, try '--help'. +``` + +## `vpt json-edit package.json packageManager pnpm@10.15.1` + + +## `vp why testnpm2 --find-by customFinder` + +Reject finders before pnpm 10.16.0. + +**Exit code:** 1 + +``` +pnpm < 10.16.0 does not support --find-by. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.local.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.local.md index 640cac2508..f0e039cf1c 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.local.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_why_pnpm10/snapshots/command_why_pnpm10.local.md @@ -216,3 +216,31 @@ command-why-pnpm10@1.0.0 dependencies: testnpm2 1.0.1 ``` + +## `vp why --find-by customFinder` + +Package names remain required even when a finder is supplied. + +**Exit code:** 2 + +``` +error: the following required arguments were not provided: + ... + +Usage: vp why --find-by ... [-- ...] + +For more information, try '--help'. +``` + +## `vpt json-edit package.json packageManager pnpm@10.15.1` + + +## `vp why testnpm2 --find-by customFinder` + +Reject finders before pnpm 10.16.0. + +**Exit code:** 1 + +``` +pnpm < 10.16.0 does not support --find-by. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots.toml index 29ba0391a2..027b75ae75 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots.toml @@ -8,4 +8,8 @@ steps = [ { argv = ["vpt", "list-dir", "node_modules"], continue-on-failure = true }, { argv = ["vp", "run", "install"], comment = "install again hit cache", continue-on-failure = true }, { argv = ["vp", "run", "--last-details"], continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@7.13.0"], snapshot = false }, + { argv = ["vp", "install", "--filter", "app"], comment = "Reject workspace selection before npm 7.14.0.", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "npm@8.0.0"], snapshot = false }, + { argv = ["vp", "install", "--workspace-root"], comment = "Reject workspace root inclusion before npm 8.1.0.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md index 88393ea14b..e08a013060 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/npm_install_with_options/snapshots/npm_install_with_options.md @@ -25,7 +25,7 @@ Options: -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile - --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) + --fix-lockfile Fix broken lockfile entries (pnpm and yarn@4+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) --resolution-only Re-run resolution for peer dependency analysis (pnpm only) --silent Suppress output (silent mode) @@ -81,3 +81,29 @@ Task Details: → Cache disabled in task configuration ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ``` + +## `vpt json-edit package.json packageManager npm@7.13.0` + + +## `vp install --filter app` + +Reject workspace selection before npm 7.14.0. + +**Exit code:** 1 + +``` +npm < 7.14.0 does not support --filter. +``` + +## `vpt json-edit package.json packageManager npm@8.0.0` + + +## `vp install --workspace-root` + +Reject workspace root inclusion before npm 8.1.0. + +**Exit code:** 1 + +``` +npm < 8.1.0 does not support --workspace-root. +``` diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots.toml index 11a8ef123d..65d95c9c76 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots.toml @@ -8,4 +8,6 @@ steps = [ { argv = ["vp", "run", "install"], continue-on-failure = true }, { argv = ["vpt", "list-dir", "node_modules"], continue-on-failure = true }, { argv = ["vp", "run", "install"], comment = "install again hit cache", continue-on-failure = true }, + { argv = ["vpt", "json-edit", "package.json", "packageManager", "yarn@2.4.2"], snapshot = false }, + { argv = ["vp", "install", "--fix-lockfile"], comment = "Reject lockfile refresh before Yarn 4.", continue-on-failure = true }, ] diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md index 9bd3373a98..e8afc63b7c 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/yarn_install_with_options/snapshots/yarn_install_with_options.md @@ -25,7 +25,7 @@ Options: -f, --force Force reinstall all dependencies --ignore-scripts Do not run lifecycle scripts --no-lockfile Don't read or generate lockfile - --fix-lockfile Fix broken lockfile entries (pnpm and yarn@2+ only) + --fix-lockfile Fix broken lockfile entries (pnpm and yarn@4+ only) --shamefully-hoist Create flat `node_modules` (pnpm only) --resolution-only Re-run resolution for peer dependency analysis (pnpm only) --silent Suppress output (silent mode) @@ -75,3 +75,16 @@ success Already up-to-date. Done in . ``` + +## `vpt json-edit package.json packageManager yarn@2.4.2` + + +## `vp install --fix-lockfile` + +Reject lockfile refresh before Yarn 4. + +**Exit code:** 1 + +``` +yarn < 4 does not support --fix-lockfile. +``` diff --git a/crates/vp_pm_cli/src/resolution/commands/add.rs b/crates/vp_pm_cli/src/resolution/commands/add.rs index f2518be19d..5d77e989a4 100644 --- a/crates/vp_pm_cli/src/resolution/commands/add.rs +++ b/crates/vp_pm_cli/src/resolution/commands/add.rs @@ -16,19 +16,19 @@ pub struct AddArgs { pub(crate) save_exact: bool, /// Save the new dependency to the specified catalog name - #[arg(long, value_name = "CATALOG_NAME", not_supported(npm, yarn, bun < "1.4"))] + #[arg(long, value_name = "CATALOG_NAME", not_supported(npm, pnpm < "10.12.0", yarn, bun < "1.4"))] pub(crate) save_catalog_name: Option, /// Save the new dependency to the default catalog - #[arg(long, not_supported(npm, yarn, bun < "1.4"))] + #[arg(long, not_supported(npm, pnpm < "10.12.0", yarn, bun < "1.4"))] pub(crate) save_catalog: bool, /// A list of package names allowed to run postinstall - #[arg(long, value_name = "NAMES", not_supported(npm, yarn, bun))] + #[arg(long, value_name = "NAMES", not_supported(npm, pnpm < "10.4.0", yarn, bun))] pub(crate) allow_build: Option, /// Do not run lifecycle scripts - #[arg(long)] + #[arg(long, not_supported(yarn >= "2" && < "3"))] pub(crate) ignore_scripts: bool, /// Do not install optionalDependencies @@ -82,11 +82,11 @@ pub struct AddArgs { pub(crate) silent: bool, /// Filter packages in monorepo (can be used multiple times) - #[arg(long, value_name = "PATTERN", not_supported(yarn < "2", bun < "1.4"))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", yarn < "2", bun < "1.4"))] pub(crate) filter: Vec, /// Add to workspace root - #[arg(short = 'w', long, not_supported(yarn >= "2", bun))] + #[arg(short = 'w', long, not_supported(npm < "8.1.0", yarn >= "2", bun))] pub(crate) workspace_root: bool, /// Only add if package exists in workspace (pnpm-specific) @@ -293,7 +293,7 @@ impl Resolve for Yarn { } cmd.arg_if("--exact", args.save_exact); if self.is_berry() { - Self::apply_berry_install_mode(&mut cmd, args.lockfile_only, args.ignore_scripts, diag); + self.apply_berry_install_mode(&mut cmd, args.lockfile_only, args.ignore_scripts, diag); } else { cmd.arg_if("--frozen-lockfile", args.frozen_lockfile) .arg_if("--ignore-scripts", args.ignore_scripts) @@ -412,7 +412,7 @@ mod tests { let mut options = add_args(&["react"]); options.filter = vec!["app".to_string()]; options.save_catalog_name = Some("react18".to_string()); - let resolution = resolve(&pnpm("10.0.0"), options); + let resolution = resolve(&pnpm("10.12.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "pnpm"); @@ -427,7 +427,7 @@ mod tests { let mut options = add_args(&["react"]); options.filter = vec!["app".to_string()]; options.save_catalog_name = Some(String::new()); - let resolution = resolve(&pnpm("10.0.0"), options); + let resolution = resolve(&pnpm("10.12.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "pnpm"); @@ -439,7 +439,7 @@ mod tests { let mut options = add_args(&["react"]); options.filter = vec!["app".to_string()]; options.save_catalog = true; - let resolution = resolve(&pnpm("10.0.0"), options); + let resolution = resolve(&pnpm("10.12.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "pnpm"); @@ -653,7 +653,7 @@ mod tests { fn test_pnpm_add_with_allow_build() { let mut options = add_args(&["react"]); options.allow_build = Some("react,napi".to_string()); - let resolution = resolve(&pnpm("10.0.0"), options); + let resolution = resolve(&pnpm("10.4.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "pnpm"); diff --git a/crates/vp_pm_cli/src/resolution/commands/install.rs b/crates/vp_pm_cli/src/resolution/commands/install.rs index f2229b07be..bc9d5c7af3 100644 --- a/crates/vp_pm_cli/src/resolution/commands/install.rs +++ b/crates/vp_pm_cli/src/resolution/commands/install.rs @@ -4,8 +4,9 @@ use super::parse_positive_usize; use crate::{ Error, PackageManager, resolution::{ - AddArgs, Bun, CommandBuilder, CommandResolution, DiagnosticKind, Diagnostics, Npm, Pnpm, - Resolution, Resolve, SaveDependencyArgs, Yarn, resolve_for_manager, + AddArgs, Bun, CommandBuilder, CommandResolution, DiagnosticKind, Diagnostics, Npm, + PackageManagerDialect, Pnpm, Resolution, Resolve, SaveDependencyArgs, Yarn, + resolve_for_manager, }, }; @@ -51,15 +52,15 @@ pub struct InstallArgs { pub(crate) force: bool, /// Do not run lifecycle scripts - #[arg(long)] + #[arg(long, not_supported(yarn >= "2" && < "2.4.0"))] pub(crate) ignore_scripts: bool, /// Don't read or generate lockfile #[arg(long, not_supported(yarn >= "2", bun))] pub(crate) no_lockfile: bool, - /// Fix broken lockfile entries (pnpm and yarn@2+ only) - #[arg(long, not_supported(npm, bun, yarn < "2"))] + /// Fix broken lockfile entries (pnpm and yarn@4+ only) + #[arg(long, not_supported(npm, bun, yarn < "4"))] pub(crate) fix_lockfile: bool, /// Create flat `node_modules` (pnpm only) @@ -75,11 +76,11 @@ pub struct InstallArgs { pub(crate) silent: bool, /// Filter packages in monorepo (can be used multiple times) - #[arg(long, value_name = "PATTERN", not_supported(yarn < "2"))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", yarn < "2"))] pub(crate) filter: Vec, /// Install in workspace root only - #[arg(short = 'w', long, not_supported(yarn, bun))] + #[arg(short = 'w', long, not_supported(npm < "8.1.0", yarn, bun))] pub(crate) workspace_root: bool, /// Save exact version (only when adding packages) @@ -262,7 +263,7 @@ impl Resolve for Npm { impl Resolve for Yarn { fn resolve(&self, args: &InstallArgs, diag: &mut Diagnostics) -> CommandResolution { if self.is_berry() { - Yarn::resolve_berry_install(args, diag) + self.resolve_berry_install(args, diag) } else { Yarn::resolve_v1_install(args, diag) } @@ -291,7 +292,11 @@ impl Yarn { cmd.into() } - fn resolve_berry_install(args: &InstallArgs, diag: &mut Diagnostics) -> CommandResolution { + fn resolve_berry_install( + &self, + args: &InstallArgs, + diag: &mut Diagnostics, + ) -> CommandResolution { let mut cmd = CommandBuilder::new("yarn"); if !args.filter.is_empty() { cmd.arg("workspaces").arg("foreach").arg("-A"); @@ -303,7 +308,7 @@ impl Yarn { } else { cmd.arg_if("--immutable", args.frozen_lockfile); } - Self::apply_berry_install_mode(&mut cmd, args.lockfile_only, args.ignore_scripts, diag); + self.apply_berry_install_mode(&mut cmd, args.lockfile_only, args.ignore_scripts, diag); if args.prod { diag.warn( DiagnosticKind::BehaviorChange, @@ -315,6 +320,7 @@ impl Yarn { } pub(super) fn apply_berry_install_mode( + &self, cmd: &mut CommandBuilder, lockfile_only: bool, ignore_scripts: bool, @@ -329,7 +335,11 @@ impl Yarn { ); } } else if ignore_scripts { - cmd.arg("--mode").arg("skip-build"); + if self.version().is_some_and(|version| version.major == 2) { + cmd.arg("--skip-builds"); + } else { + cmd.arg("--mode").arg("skip-build"); + } } } } diff --git a/crates/vp_pm_cli/src/resolution/commands/list.rs b/crates/vp_pm_cli/src/resolution/commands/list.rs index 9bf6ddfe15..d2ca54016b 100644 --- a/crates/vp_pm_cli/src/resolution/commands/list.rs +++ b/crates/vp_pm_cli/src/resolution/commands/list.rs @@ -47,15 +47,15 @@ pub struct ListArgs { pub(crate) only_projects: bool, /// Use a finder function - #[arg(long, value_name = "FINDER_NAME", not_supported(npm, yarn, bun))] + #[arg(long, value_name = "FINDER_NAME", not_supported(npm, pnpm < "10.16.0", yarn, bun))] pub(crate) find_by: Option, /// List across all workspaces - #[arg(short = 'r', long, not_supported(yarn, bun))] + #[arg(short = 'r', long, not_supported(npm < "7.14.0", yarn, bun))] pub(crate) recursive: bool, /// Filter packages in monorepo - #[arg(long, value_name = "PATTERN", not_supported(yarn, bun))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", yarn, bun))] pub(crate) filter: Vec, /// List global packages @@ -550,7 +550,7 @@ mod tests { fn test_pnpm_list_find_by() { let command = expect_run( resolve( - &pnpm("10.0.0"), + &pnpm("10.16.0"), ListArgs { find_by: Some("customFinder".to_string()), ..Default::default() }, ) .outcome, diff --git a/crates/vp_pm_cli/src/resolution/commands/outdated.rs b/crates/vp_pm_cli/src/resolution/commands/outdated.rs index 304df51699..d5dc701f96 100644 --- a/crates/vp_pm_cli/src/resolution/commands/outdated.rs +++ b/crates/vp_pm_cli/src/resolution/commands/outdated.rs @@ -64,11 +64,11 @@ pub struct OutdatedArgs { pub(crate) recursive: bool, /// Filter packages in monorepo - #[arg(long, value_name = "PATTERN", not_supported(yarn))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", yarn))] pub(crate) filter: Vec, /// Include workspace root - #[arg(short = 'w', long, not_supported(yarn, bun))] + #[arg(short = 'w', long, not_supported(npm < "8.1.0", yarn, bun))] pub(crate) workspace_root: bool, /// Only production and optional dependencies diff --git a/crates/vp_pm_cli/src/resolution/commands/pack.rs b/crates/vp_pm_cli/src/resolution/commands/pack.rs index 2b0fd357b0..cb197165d1 100644 --- a/crates/vp_pm_cli/src/resolution/commands/pack.rs +++ b/crates/vp_pm_cli/src/resolution/commands/pack.rs @@ -8,11 +8,11 @@ use crate::resolution::{ #[derive(clap::Args, Clone, Debug, Default, PartialEq, Eq)] pub struct PackArgs { /// Pack all workspace packages - #[arg(short = 'r', long, not_supported(yarn < "2", bun))] + #[arg(short = 'r', long, not_supported(npm < "7.9.0", pnpm < "10.11.0", yarn < "2", bun))] pub(crate) recursive: bool, /// Filter packages to pack - #[arg(long, value_name = "PATTERN", not_supported(yarn < "2", bun))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.9.0", pnpm < "10.11.0", yarn < "2", bun))] pub(crate) filter: Vec, /// Output path for the tarball @@ -20,7 +20,7 @@ pub struct PackArgs { pub(crate) out: Option, /// Directory where the tarball will be saved - #[arg(long, not_supported(yarn))] + #[arg(long, not_supported(npm < "7.18.0", yarn))] pub(crate) pack_destination: Option, /// Gzip compression level (0-9) @@ -128,7 +128,7 @@ mod tests { #[test] fn test_pnpm_pack_recursive() { let command = expect_run( - resolve(&pnpm("10.0.0"), PackArgs { recursive: true, ..Default::default() }).outcome, + resolve(&pnpm("10.11.0"), PackArgs { recursive: true, ..Default::default() }).outcome, ); assert_eq!(command.args, vec!["pack", "--recursive"]); @@ -194,7 +194,7 @@ mod tests { fn test_pnpm_pack_with_filter() { let command = expect_run( resolve( - &pnpm("10.0.0"), + &pnpm("10.11.0"), PackArgs { filter: vec!["app".to_string()], ..Default::default() }, ) .outcome, @@ -207,7 +207,7 @@ mod tests { fn test_pnpm_pack_with_multiple_filters() { let command = expect_run( resolve( - &pnpm("10.0.0"), + &pnpm("10.11.0"), PackArgs { filter: vec!["app".to_string(), "web".to_string()], ..Default::default() diff --git a/crates/vp_pm_cli/src/resolution/commands/publish.rs b/crates/vp_pm_cli/src/resolution/commands/publish.rs index 5f1e4481bf..fb219115eb 100644 --- a/crates/vp_pm_cli/src/resolution/commands/publish.rs +++ b/crates/vp_pm_cli/src/resolution/commands/publish.rs @@ -1,7 +1,8 @@ use vp_pm_cli_macros::pm_args; use crate::resolution::{ - Bun, CommandBuilder, CommandResolution, Diagnostics, Npm, Pnpm, Resolve, Yarn, + Bun, CommandBuilder, CommandResolution, Diagnostics, Npm, PackageManagerDialect, Pnpm, Resolve, + Yarn, }; #[pm_args] @@ -12,7 +13,8 @@ pub struct PublishArgs { pub(crate) target: Option, /// Preview without publishing - #[arg(long, not_supported(yarn < "4.9.3"))] + // npm 5.8 ignores this flag and publishes; stable 5.10 supports previews. + #[arg(long, not_supported(npm < "5.10.0", yarn < "4.9.3"))] pub(crate) dry_run: bool, /// Publish tag @@ -40,7 +42,7 @@ pub struct PublishArgs { pub(crate) report_summary: bool, /// Publish with provenance - #[arg(long, not_supported(yarn < "4.9.0", bun))] + #[arg(long, not_supported(npm < "9.5.0", yarn < "4.9.0", bun))] pub(crate) provenance: bool, /// Force publish @@ -48,15 +50,17 @@ pub struct PublishArgs { pub(crate) force: bool, /// Output in JSON format - #[arg(long, not_supported(yarn >= "2" && < "4.9.3", bun))] + // pnpm 11's native publish dropped JSON output until 11.0.7 restored it. + // https://github.com/pnpm/pnpm/releases/tag/v11.0.7 + #[arg(long, not_supported(pnpm >= "11.0.0" && < "11.0.7", yarn >= "2" && < "4.9.3", bun))] pub(crate) json: bool, /// Publish all workspace packages - #[arg(short = 'r', long, not_supported(yarn, bun))] + #[arg(short = 'r', long, not_supported(npm < "7.13.0", yarn, bun))] pub(crate) recursive: bool, /// Filter packages in monorepo - #[arg(long, value_name = "PATTERN", not_supported(yarn, bun))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.13.0", yarn, bun))] pub(crate) filter: Option>, /// Additional arguments @@ -102,6 +106,11 @@ impl Npm { impl Resolve for Npm { fn resolve(&self, args: &PublishArgs, _diag: &mut Diagnostics) -> CommandResolution { + if self.version().is_none() && (args.dry_run || args.provenance) { + return CommandResolution::InvalidArgument( + "A known npm version is required for --dry-run and --provenance.".into(), + ); + } Self::resolve_publish(args) } } diff --git a/crates/vp_pm_cli/src/resolution/commands/remove.rs b/crates/vp_pm_cli/src/resolution/commands/remove.rs index 81f0ef8dfa..d55e6d2059 100644 --- a/crates/vp_pm_cli/src/resolution/commands/remove.rs +++ b/crates/vp_pm_cli/src/resolution/commands/remove.rs @@ -20,15 +20,15 @@ pub struct RemoveArgs { pub(crate) save_prod: bool, /// Filter packages in monorepo (can be used multiple times) - #[arg(long, value_name = "PATTERN", not_supported(bun < "1.4"))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", bun < "1.4"))] pub(crate) filter: Vec, /// Remove from workspace root - #[arg(short = 'w', long, not_supported(yarn, bun))] + #[arg(short = 'w', long, not_supported(npm < "8.1.0", yarn, bun))] pub(crate) workspace_root: bool, /// Remove recursively from all workspace packages - #[arg(short = 'r', long, not_supported(yarn < "2", bun))] + #[arg(short = 'r', long, not_supported(npm < "8.1.0", yarn < "2", bun))] pub(crate) recursive: bool, /// Remove global packages @@ -374,7 +374,7 @@ mod tests { fn test_npm_remove_with_workspace() { let mut options = remove_args(&["lodash"]); options.filter = vec!["app".to_string()]; - let resolution = resolve(&npm("1.0.0"), options); + let resolution = resolve(&npm("7.14.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "npm"); @@ -385,7 +385,7 @@ mod tests { fn test_npm_remove_workspace_root() { let mut options = remove_args(&["typescript"]); options.workspace_root = true; - let resolution = resolve(&npm("1.0.0"), options); + let resolution = resolve(&npm("8.1.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "npm"); @@ -396,7 +396,7 @@ mod tests { fn test_npm_remove_recursive() { let mut options = remove_args(&["lodash"]); options.recursive = true; - let resolution = resolve(&npm("1.0.0"), options); + let resolution = resolve(&npm("8.1.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "npm"); @@ -410,7 +410,7 @@ mod tests { fn test_npm_remove_multiple_workspaces() { let mut options = remove_args(&["lodash"]); options.filter = vec!["app".to_string(), "web".to_string()]; - let resolution = resolve(&npm("1.0.0"), options); + let resolution = resolve(&npm("7.14.0"), options); let command = expect_run(resolution.outcome); assert_eq!(command.program, "npm"); diff --git a/crates/vp_pm_cli/src/resolution/commands/unlink.rs b/crates/vp_pm_cli/src/resolution/commands/unlink.rs index 4573234db4..3ccc6aa2a8 100644 --- a/crates/vp_pm_cli/src/resolution/commands/unlink.rs +++ b/crates/vp_pm_cli/src/resolution/commands/unlink.rs @@ -14,7 +14,7 @@ pub struct UnlinkArgs { /// Unlink in every workspace package // Berry added unlink, including --all, in Yarn 3. Classic has no recursive unlink. // https://github.com/yarnpkg/berry/blob/01586a88806a2bebd7edb28d1bee3581b1fd3762/CHANGELOG.md#300 - #[arg(short = 'r', long, not_supported(yarn < "3", bun))] + #[arg(short = 'r', long, not_supported(npm < "8.1.0", yarn < "3", bun))] pub(crate) recursive: bool, /// Arguments to pass to package manager diff --git a/crates/vp_pm_cli/src/resolution/commands/update.rs b/crates/vp_pm_cli/src/resolution/commands/update.rs index 1aca6ee7ab..16104a71e0 100644 --- a/crates/vp_pm_cli/src/resolution/commands/update.rs +++ b/crates/vp_pm_cli/src/resolution/commands/update.rs @@ -29,15 +29,15 @@ pub struct UpdateArgs { pub(crate) ignore_node_mismatch: bool, /// Update recursively in all workspace packages - #[arg(short = 'r', long, not_supported(yarn < "2"))] + #[arg(short = 'r', long, not_supported(npm < "8.1.0", yarn < "2", bun < "1.4"))] pub(crate) recursive: bool, /// Filter packages in monorepo (can be used multiple times) - #[arg(long, value_name = "PATTERN", not_supported(bun < "1.4", yarn >= "2"))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", yarn >= "2", bun < "1.4"))] pub(crate) filter: Vec, /// Include workspace root - #[arg(short = 'w', long, not_supported(yarn, bun))] + #[arg(short = 'w', long, not_supported(npm < "8.1.0", yarn, bun))] pub(crate) workspace_root: bool, /// Update devDependencies @@ -45,7 +45,7 @@ pub struct UpdateArgs { pub(crate) dev: bool, /// Update dependencies (production) - #[arg(short = 'P', long, not_supported(yarn >= "2"))] + #[arg(short = 'P', long, not_supported(yarn >= "2", bun < "1.4"))] pub(crate) prod: bool, /// Interactive mode @@ -53,7 +53,7 @@ pub struct UpdateArgs { pub(crate) interactive: bool, /// Exclude optionalDependencies - #[arg(long, not_supported(yarn >= "2"))] + #[arg(long, not_supported(yarn >= "2", bun < "1.4"))] pub(crate) no_optional: bool, /// Update lockfile only, don't modify package.json @@ -169,14 +169,8 @@ impl Resolve for Bun { .arg_if("--dev", args.dev) .arg_if("--interactive", args.interactive) .arg_if("--production", args.prod); - if args.no_optional { - if self.supports_v1_4_commands() { - cmd.arg("--no-optional"); - } else { - cmd.arg("--omit").arg("optional"); - } - } - cmd.arg_if("--no-save", args.no_save) + cmd.arg_if("--no-optional", args.no_optional) + .arg_if("--no-save", args.no_save) .arg_if("--recursive", args.recursive) .extend(args.pass_through_args.iter()) .extend(args.packages.iter()); @@ -798,22 +792,19 @@ mod tests { "bun < 1.4 does not support --filter.", "bun does not support --workspace-root.", "bun < 1.4 does not support --dev.", + "bun < 1.4 does not support --prod.", + "bun < 1.4 does not support --no-optional.", ], ); } #[test] fn test_bun_update_prod_and_optional_selection() { - for version in ["1.3.14", "1.4.0-beta.1", "1.4.0"] { - let optional_flags = - if version == "1.4.0" { vec!["--no-optional"] } else { vec!["--omit", "optional"] }; + for version in ["1.4.0", "1.4.1"] { for (flags, expected) in [ (vec!["-P"], vec!["update", "--production"]), - (vec!["--no-optional"], [vec!["update"], optional_flags.clone()].concat()), - ( - vec!["-P", "--no-optional"], - [vec!["update", "--production"], optional_flags].concat(), - ), + (vec!["--no-optional"], vec!["update", "--no-optional"]), + (vec!["-P", "--no-optional"], vec!["update", "--production", "--no-optional"]), ] { let args = parse_args::(flags).unwrap(); let resolution = resolve(&bun(version), args); @@ -835,7 +826,7 @@ mod tests { #[test] fn test_bun_update_recursive() { - for version in ["1.3.11", "1.4.0"] { + for version in ["1.4.0", "1.4.1"] { let options = UpdateArgs { recursive: true, ..Default::default() }; let resolution = resolve(&bun(version), options); assert!(resolution.diagnostics.is_empty()); @@ -857,9 +848,18 @@ mod tests { } #[test] - fn test_bun_update_rejects_filter_before_1_4() { - let options = UpdateArgs { filter: vec!["web".to_string()], ..Default::default() }; - let resolution = resolve(&bun("1.3.11"), options); - expect_unsupported(resolution, &["bun < 1.4 does not support --filter."]); + fn test_bun_update_rejects_workspace_selection_before_1_4() { + for version in ["1.3.11", "1.3.14", "1.4.0-beta.1"] { + for interactive in [false, true] { + for (argv, message) in [ + (vec!["--recursive"], "bun < 1.4 does not support --recursive."), + (vec!["--filter", "web"], "bun < 1.4 does not support --filter."), + ] { + let mut args = parse_args::(argv).unwrap(); + args.interactive = interactive; + expect_unsupported(resolve(&bun(version), args), &[message]); + } + } + } } } diff --git a/crates/vp_pm_cli/src/resolution/commands/why.rs b/crates/vp_pm_cli/src/resolution/commands/why.rs index 8aab65f427..2b05107a90 100644 --- a/crates/vp_pm_cli/src/resolution/commands/why.rs +++ b/crates/vp_pm_cli/src/resolution/commands/why.rs @@ -24,11 +24,11 @@ pub struct WhyArgs { pub(crate) parseable: bool, /// Check recursively across all workspaces - #[arg(short = 'r', long, not_supported(yarn < "2", bun))] + #[arg(short = 'r', long, not_supported(npm < "7.14.0", yarn < "2", bun))] pub(crate) recursive: bool, /// Filter packages in monorepo - #[arg(long, value_name = "PATTERN", not_supported(yarn, bun))] + #[arg(long, value_name = "PATTERN", not_supported(npm < "7.14.0", yarn, bun))] pub(crate) filter: Vec, /// Check in workspace root @@ -56,7 +56,7 @@ pub struct WhyArgs { pub(crate) exclude_peers: bool, /// Use a finder function defined in .pnpmfile.cjs - #[arg(long, value_name = "FINDER_NAME", not_supported(npm, yarn, bun))] + #[arg(long, value_name = "FINDER_NAME", not_supported(npm, pnpm < "10.16.0", yarn, bun))] pub(crate) find_by: Option, /// Additional arguments to pass through to the package manager @@ -275,7 +275,7 @@ mod tests { fn test_pnpm_why_with_find_by() { let mut options = why_args(&["react"]); options.find_by = Some("customFinder".to_string()); - let command = expect_run(resolve(&pnpm("10.0.0"), options).outcome); + let command = expect_run(resolve(&pnpm("10.16.0"), options).outcome); assert_eq!(command.program, "pnpm"); assert_eq!(command.args, vec!["why", "--find-by", "customFinder", "react"]);