npm/npx

[FEATURE] Be able to execute a nested package

thiagodp opened this issue · 9 comments

What / Why

Major use case: Execute a package that is installed as a dependency of a dependency, inside its own node_modules folder.

There are some cases - e.g., local packages - in which NPM installs packages as nested dependencies. NPX is not yet able to execute them.

Example: When I install foo, it installs rimraf as a dependency (inside its own node_modules folder). Whether I run npx --no-install rimraf, then rimraf is not found. I would like to run it without having to install it explicitly.

node_modules/
┣ foo/          
┃ ┣ node_modules/
┃ ┃ ┗ rimraf/
┃ ┃   ┗ ...
┃ ┗ ...
┗ bar/

So, currently I can use npx --no-install to execute foo or bar but I cannot execute rimraf.

$ npx --no-install rimraf
  not found: rimraf

PROPOSAL

A flag such as --recursive to search for a nested package, since the search could take some time.

Example:

$ npx --no-install --recursive rimraf

When

  • n/a

Where

  • n/a

How

Current Behavior

  • NPX cannot run an application installed as a nested package.

Expected Behavior

$ npx --no-install --recursive my-nested-pkg

Who

  • n/a

References

  • n/a

It seems prone to failure to rely on being able to run packages that aren't even (necessarily) installed. Couldn't you fix your problem by making a formal dependency? E.g. just add "rimraf": "*" to your package.json.

Problem is that I need to run that exactly same version of rimraf inside foo. A different version can be incompatible with foo and have side effects.

Right but when you specify * the hoisting logic will look for a version of rimraf that satisfies as many semvers as possible. Since the * semver permits any version it will choose the exact version of rimraf that foo is using.

EDIT: And it will put that version in the root node_modules folder, where foo will find it by searching upwards through the directory tree.

@conartist6 Do you know if npm dedupe would do that without having to add the entry to package.json?

In the real-life case, the tool denoted here as rimraf is installed by a plug-in (denoted foo) and the application shouldn't depend on it (hence, adding it to its package.json), but the users (which are users lay in technology) need to execute rimraf in certain cases.

I don't know, no. All I can say for sure is: if you (or your users) circumvent the process of specifying the deps you (or they) really need in favor of making assumptions about skip level dependencies, here be dragons. And almost certainly no support in any official tooling like npx.

Right, the solution is providing them an easy way to execute the dependency without having to install it "again" since it is already installed. So by using npx to find it and execute it would solve the problem without having to use other tools.

You're still asking to be able to use something as a dependency that isn't a dependency.

Well, it's a transitive dependency.

@conartist6 I got your point. Thanks for the help. I'll see if npm dedupe can solve this problem and close this issue whether it can.