cli icon indicating copy to clipboard operation
cli copied to clipboard

[BUG] npm does not setup child workspace’s bin or use parent’s bin

Open jlarmstrongiv opened this issue 2 years ago • 4 comments

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

  1. Create an npm workspace with multiple packages
  2. 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",
  },
}
  1. 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",
  },
}
  1. Be sure you have installed all dependencies with npm install
  2. Attempt to run the script npm run port
  3. 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.

jlarmstrongiv avatar Mar 20 '22 09:03 jlarmstrongiv

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.

ShusenLiu avatar Apr 27 '22 22:04 ShusenLiu

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.

cackerman-qumulo avatar Jan 20 '23 23:01 cackerman-qumulo

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.

apples avatar May 15 '23 22:05 apples

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:

  1. compiled from typescript and builds its binary,
  2. and then npm rebuild step correctly sees that there is a binary this time in it and adds missing symlink to it in the node_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.

carecki avatar Feb 23 '24 22:02 carecki