[BUG] peerDependencies of package behave like dependencies when package is locally installed
Is there an existing issue for this?
- [X] I have searched the existing issues
This issue exists in the latest npm version
- [X] I am using the latest npm
Current Behavior
You can find a lot of context for this question here: https://stackoverflow.com/questions/77829498/can-i-use-peer-dependencies-in-my-library-when-my-library-is-depended-on-with-a
This visual guide may help:
In summary, lib-package's peer dependency's of behave like regular dependencies when app-package depends on lib-package with a file://... URL.
- Here is a link to a branch that behaves as described above: https://github.com/DanKaplanSES/jsdom-sandbox/tree/lib-has-peer-dependency-and-lib-is-file-dependency-so
- app-package depends on lib-package via a
file://URL. cd app-package; npm run execthrows an error indicating that it is using**lib**-package\node_modules\jsdom\lib\api.js. It should be using**app**-package\node_modules\jsdom\lib\api.jsinstead, because jsdom is a peerDependency of lib-package.
- app-package depends on lib-package via a
- Here is a link to a branch that behaves as expected: https://github.com/DanKaplanSES/jsdom-sandbox/tree/lib-has-peer-dependency-and-lib-is-file-dependency-works-so
- app-package depends on lib-package via
"dankaplanses-lib-package": "^0.0.1",instead offile://. cd app-package; npm run execruns without throwing an error.- If
app-package\node_modules\jsdom\lib\api.jsis modified to add a log statement, you can confirm that app-package is using this file.
- app-package depends on lib-package via
Expected Behavior
I believe peerDependency's should behave the same way regardless of how lib is depended on.
When using a local file URL, I see an error because (I believe) lib-package is using a different jsdom dependency than app-package. When using lib-package as an npmjs.com dependency, lib-package does not have its own jsdom dependency to use. I believe the latter is correct behavior.
Steps To Reproduce
- git clone https://github.com/DanKaplanSES/jsdom-sandbox/tree/lib-has-peer-dependency-and-lib-is-file-dependency-so
- Follow the readme OR cd into each subproject and
npm install cd app-package; npm run exec
Environment
; "builtin" config from C:\Users\user\AppData\Roaming\npm\node_modules\npm\npmrc
prefix = "C:\\Users\\user\\AppData\\Roaming\\npm"
; "user" config from C:\cygwin64\home\user\.npmrc
//registry.npmjs.org/:_authToken = (protected)
registry = "https://registry.npmjs.org/"
script-shell = "C:\\cygwin64\\bin\\bash.exe"
; node bin location = C:\Program Files\nodejs\node.exe
; node version = v20.10.0
; npm local prefix = C:\my-projects\jsdom-sandbox\lib-package
; npm version = 10.3.0
; cwd = C:\my-projects\jsdom-sandbox\lib-package
; HOME = C:\cygwin64\home\user
; Run `npm config ls -l` to show all defaults.
I either found a workaround or a solution, honestly, I can't tell. I will inline the answer here:
By default,
npm installwill create symlinks forfile:protocol dependencies.npm install --install-linkswill install them as regular dependencies instead of links, solving the problem.I have a feeling there's more going on here than I realize:
- It feels kind of arbitrary that if my link is using a peer dependency, then I need
--install-linksto get the documented behavior of peerDependencies.- I'm developing on Windows and it does not have real symlinks. That might be playing a role here.
- Maybe Linux would have worked as expected in the original question.
- Even though my answer solves the problem, the original behavior could be a bug. I've created an issue here: #7143
Regardless, this is at least one of many ways to solve the problem, so I'm posting it as an answer.
I have some additional suggestions:
- Maybe depending on a package via
file:should give a warning if that package uses peerDependencies? - Maybe peerDependency documentation should mention
--install-linksto help developers if this comes up?
I think this is a dupe of https://github.com/npm/cli/issues/7171 but I'm hoping https://github.com/npm/cli/issues/7171 can be reopened.