cli
cli copied to clipboard
[BUG] npm does not setup child workspace’s bin or use parent’s bin
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
I cannot run unpublished npx package scripts in child workspaces
Expected Behavior
When using npm, whether from:
- npm install
- npm rebuild
- npx
I expect to find the node_modules/.bin
folder for my package.json
scripts in the child workspaces, not just parent. I expect npm to link the bin folder in my child package.
Or, I expect npm to fallback to/include the parent’s bin, so that unpublished npx commands can still be found.
Steps To Reproduce
- Create an npm workspace with multiple packages
- Have one package set the bin property in the package.json
{
"name": "@clis/port",
"version": "1.0.0",
"private": true,
"type": "module",
"exports": {
"require": "./dist/index.cjs",
"default": "./dist/index.js"
},
"main": "dist/index.cjs",
"module": "dist/index.js",
"source": "src/index.ts",
"types": "dist/index.d.ts",
"bin": "./dist/cli.js",
},
}
- Have another package depend on that first package
{
"name": "@keystonejs/example",
"version": "1.0.0",
"private": true,
"scripts": {
"port": "npx @clis/port",
},
"devDependencies": {
"@clis/port": "file:../../../clis/port",
},
}
- Be sure you have installed all dependencies with
npm install
- Attempt to run the script
npm run port
- Watch npm crash as it tries to find the private package published in npm, rather than find the private package locally
Other notes:
These script work fine in the parent package.json, as the node_modules/.bin
folder exists. However, it will crash in all child workspaces by trying to find a published version on npm.
Other notes:
Related issues:
- https://github.com/npm/cli/issues/2826
- https://github.com/npm/cli/issues/3520
Environment
- npm: 8.1.0
- Node.js: v14.18.1
- OS Name: MacOS 10.15.7
- System Model Name: MacBook Pro
- npm config:
; "user" config from /Users/username/.npmrc
//registry.npmjs.org/:_authToken = (protected)
init-author-name = (protected)
scripts-prepend-node-path = "auto"
; "env" config from environment
prefix = "/Users/username/.asdf/installs/nodejs/14.18.1/.npm"
; node bin location = /Users/username/.asdf/installs/nodejs/14.18.1/bin/node
; cwd = /Users/username/Desktop/monorepos/turbo-monorepo
; HOME = /Users/username
; Run `npm config ls -l` to show all defaults.
I encounter the same issue. as a workaround, i need to:
npm i
npm run build -ws `package-with-binary`
npm i
npm run `package-with-binary`
and I observe that in the second npm i
, it actually produce these logs:
44 silly reify mark retired [
44 silly reify 'path/node_modules/cli',
44 silly reify ]
45 silly reify moves {
45 silly reify 'path/node_modules/cli': 'path/node_modules/cli-FzlzzC2M',
45 silly reify }
this is really annoying for us, hope this could be prioritize and fixed soon.
Ran into this as well. Running the following caused an error.
npm ci
npx lerna run build
npx <workspace-name>
The solution I found was to add an npm update
after building.
npm ci
npx lerna run build
npm update <workspace-name>
npx <workspace-name>
That seems to work for me, without having to run a full "install" again.
I believe I'm running into a related issue here.
I've got two git repos: monorepo-1
and monorepo-2
. Both are using npm workspaces.
Inside of monorepo-1
is a package A
, and inside of monorepo-2
are packages B
and C
.
A
depends on B
via a git+ssh
url.
B
depends on C
via local workspace.
C
has bin
script which B
requires in its prepare
/build
script.
When I try to install within monorepo-2
by itself, it fails because the bin
scripts from C
are apparently not properly installed. Workarounds are easy, however, and I'm able to get monorepo-2
installing correctly with some convincing.
But when installing monorepo-1
, it git clones monorepo-2
to some temp dir, fails the install because of missing bin
scripts, and then cleans up the git clone directory. So there's no chance of a workaround here.
What I've done was instead npm install
or npm update
I've used more dedicated command for it - npm rebuild
. And put it in the postinstall
script after building my package containing binary (named code-gen). So whole postinstall
looks like this:
"postinstall": "npm run build -w packages/code-gen && npm rebuild --ignore-scripts @my-product/code-gen"
This way, straight after installing modules, my code-gen
package is:
- compiled from typescript and builds its binary,
- and then
npm rebuild
step correctly sees that there is a binary this time in it and adds missing symlink to it in thenode_modules/.bin
. I've added--ignore-scripts
to avoid running scrips unrelated to binary registration.
This way after whole npm install
the binary from @my-product/code-gen
package is ready to be used by other packages in the workspaces.