Description
Is there an existing issue for this?
- I have searched the existing issues
This issue exists in the latest npm version
- I am using the latest npm
Current Behavior
Having a package (peer) both as transitive peerOptional dependency and as dev dependency leads to it being installed for production as well.
Scenario:
optional-peer-test@0.0.1
├─┬ direct@1.0.0 (dependency)
│ └── peer@1.0.0 (peerOptional dependency)
└── peer@1.0.0 (dev dependency)
$ npm i --omit=dev
$ npm explain peer
peer@1.0.0
node_modules/peer
dev peer@"file:../deps/peer/peer-1.0.0.tgz" from the root project
peerOptional peer@"file:../peer/peer-1.0.0.tgz" from direct@1.0.0
node_modules/direct
direct@"file:../deps/direct/direct-1.0.0.tgz" from the root project
Expected Behavior
The peerOptional dependency is not auto installed for npm i --omit=dev
.
Steps To Reproduce
Reproduction repo: https://github.com/Akatuoro/optional-peer-test
For a real world scenario, use the package.json
{
"name": "optional-peer-test",
"version": "0.0.1",
"description": "Testing npm behavior for installing optional peer dependencies",
"scripts": {
"test": "npm i --omit=dev && npm ls @sap/hana-client",
"clean": "rm -Rdf node_modules && rm package-lock.json"
},
"dependencies": {
"@sap/hdi": "4.5.2"
},
"devDependencies": {
"@sap/hana-client": "2.21.31"
}
}
and run
npm i --omit=dev
resulting in
$ npm ls @sap/hana-client
optional-peer-test@0.0.1
├── @sap/hana-client@2.21.31
└─┬ @sap/hdi@4.5.2
└── @sap/hana-client@2.21.31 deduped
$ npm explain @sap/hana-client
@sap/hana-client@2.21.31
node_modules/@sap/hana-client
dev @sap/hana-client@"2.21.31" from the root project
peerOptional @sap/hana-client@"^2 >= 2.5" from @sap/hdi@4.5.2
node_modules/@sap/hdi
@sap/hdi@"4.5.2" from the root project
Also note that in the package-lock.json, the @sap/hana-client
is now marked as devOptional
, while it was never included under optionalDependencies
. When a npm-shrinkwrap.json is then generated and the package is published, the consumer also auto installs the peerOptional dependency.
This seems to be due to arborist not really differentiating between optional dependencies and optional peer dependencies, as e.g. discussed here: #4859 (comment) .
Environment
- npm: 10.8.3
- Node.js: v22.7.0