npm / npx

npm package executor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG] npx stops traversing looking for match if directory has package.json file

jnardone opened this issue · comments

commented

What / Why

copied from zkat/npx#222

We hoist all our common deps to the top-level parent, as well as common utilities (jest, eslint, pm2, etc.)

However, many of the child folders have their own package.json for one reason or another. (version strings, main: declaration, etc.)

npx won't traverse past the current directory, but only if it has a package.json. (This was reported and then closed in #210)

/package.json
/node_modules
/node_modules/.bin/foo
/packages
/packages/bar
/packages/bar/package.json

I should be able to, in packages/bar, call npx foo and have it resolve. This is expected behavior. But it won't.

If packages/bar does NOT have a package.json, npx foo will resolve to the correct in 2 parents up.

Is there a way to tell npx to keep going up the directory hierarchy looking for matches?

Typically I'd expect all commands in a repo to only ever be used at the repo root; in a monorepo, that means not running commands directly inside packages/.

commented

Well not everyone does it the same way. We have commands in specific packages, but none of those packages defines its own dependencies, so we can manage them all in one place from release to release.

How about: if a package.json does not define dependencies or devDependencies, npx should traverse farther up the tree?

Agree this would be pretty great, and it would be at parity with how node_modules are resolved.

For modules that are shared across an entire monorepo (linters, prettier, etc) it is common to hoist or install these in the root domain. If a file deep inside the directory tree imports or requires this module it resolves fine. Yet, trying to run an npx command with a binary from one of these modules from a subdirectory fails because npx does not traverse up similar to module resolving.

To provide more insight on why I believe this is important...

Some insight: I have a mono repo. I have 1 rule, never install any packages globally. All packages, including CLI tools, are installed locally.

I am wanting to remove devDependencies from all packages as this is very frustrating to maintain. I am wanting to only add devDependencies to the root package.json file and this will allow the packages to use them (kinda pointless to have them in the packages in a mono repo). So far, this seems to work fine with Lerna when running commands from the root but the issue is when I want to run some CLI tools in the packages during development (lint and tests). I planned to use npx but this always installs the versions instead of using the packages that are in the mono repo root. So far, I can use npx but it wastes a lot of time by downloading packages that are already in the root node_modules directory. For now, I have gone back to going to the packages using relative pathing (../../node_modules/.bin/eslint) to get this working but it's just really ugly and hacky ( I also need to specify configs too...).

Again the entire purpose of this is DRY. The last thing I need is over 100 packages with the same devDependencies and configs that are already in the mono repo root. Not to mention, updating the version of these devDependencies is seriously optimized and takes only a couple seconds.

If we had a way to allow for it to traverse up to the parent root node_modules in npx, that is really the holy grail here. Especially if it could use the configs in the root too.