Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: CLI to run package.json scripts #12073

Closed
bmeck opened this issue Mar 27, 2017 · 20 comments
Closed

Feature Request: CLI to run package.json scripts #12073

bmeck opened this issue Mar 27, 2017 · 20 comments
Labels
cli Issues and PRs related to the Node.js command line interface. feature request Issues that request new features to be added to Node.js. module Issues and PRs related to the module subsystem.

Comments

@bmeck
Copy link
Member

bmeck commented Mar 27, 2017

Currently many people use npm run in order to start up applications. In environments without npm this functionality would be very useful I recommend we pull this functionality into core itself.

This has a few things to note/bikeshed:

Wrapper process when running a node child process:

  • extra pid, may cause oddities if trying to get the PID of the application
    • in *nix we can exec() in C to replace current process even if the child is not node
    • in WIN32 we cannot use the current process if the child is not node
  • mostly wasted CPU/mem
  • wraps stdio

Env variables:

  • npm sets up many environment variables.
    • PATH is mutated for the process to include a vendored node-gyp, I am unclear to what extent we want this.

Argv:

  • some things like --inspect are not properly propagated to child processes

I am not seeking to introduce a standards node --run-script build etc. that would run a compile toolchain, not am I seeking to introduce a standard node --run-script install. I would like those to completely delegate to the package.json.

This can somewhat be related to #11903 which would have some entry point with a package.json presumably. It also relates to #11997 which has an idea of process argv delegation.

@mscdex mscdex added cli Issues and PRs related to the Node.js command line interface. feature request Issues that request new features to be added to Node.js. module Issues and PRs related to the module subsystem. labels Mar 27, 2017
@michael-ciniawsky
Copy link

Maybe node --pkg index like (without the .noderc stuff) in the additional section #11907

In a nutshell if package.json and instead of some .noderc config when passsing a flag run npm i (NODE_ENV !== 'production') or npm i --production (NODE_ENV === 'production')

@bmeck
Copy link
Member Author

bmeck commented Mar 30, 2017

@michael-ciniawsky can you clarify what index in node --pkg index means?

@jasnell
Copy link
Member

jasnell commented Mar 30, 2017

I've found myself many times wanting to have generic node --run and node --test commands that would address the same basic need as npm run and npm test. Not necessarily as a replacement for those, however, and not necessarily with the same semantics. In fact, we can (and likely should) implement it in a way that is fairly independent and isolated from the normal package.json lifecycle scripts.

For instance,

package.json

{
  "name": "foo",
  "main" "index.js",
  "test": "test.js",
  "scripts": {
     "test": "..."
  }
}

Calling node --run would look specifically at main (in this example index.js) as being the entry point. In other words, node --run is exactly equivalent to calling node index.

If I am in a directory that contains multiple modules in node_modules, and I want to select which one I run... e.g.

root
  |-- node_modules
          |-- moduleA
          |         |-- package.json
          |         |-- index.js
          |-- moduleB
                    |--package.json
                    |--index.js

(sorry, missed a level in the diagram initially)

Then I could do node --run moduleA. Essentially, the argument for --run is a module name that is resolved with the same semantics as require('...'), with the entry point defined by the main property in package.json. (note that if I were in node_modules, calling node moduleA would already just work, so we're really quite close already)

node --test would work the same, but using a top level test property instead of either main or scripts.test .

There would be no environment variables, no need to keep it semantically the same as npm lifecycle scripts, as the node --run and node --test would simply ignore anything under the scripts property in package.json.

@bmeck
Copy link
Member Author

bmeck commented Mar 30, 2017

@jasnell people use runners in node_modules/.bin I think that behavior needs to be preserved still.

@jasnell
Copy link
Member

jasnell commented Mar 30, 2017

ok. so perhaps ... node --run {name} would first try to resolve name as a runner in node_modules/.bin, and failing that, would treat it as a module looking for the appropriate package.json entry point? Would there even be a need for a separate node --test then? I could simply throw my test running into node_modules/.bin and have node --run test Just Work.

@thebergamo
Copy link
Contributor

I really like the idea and few days before I wanted something like that. We already have a lot of forms to run a script in development systems. We've make, npm scripts, gulp, grunt and many others. Porting some of this to the node binary is not an unnecessary overhead?

@jasnell
Copy link
Member

jasnell commented Mar 30, 2017

The scripts would not necessarily need to be ported to the binary. Runner scripts located in node_modules/.bin would just end up being child processes spawned by node at startup, and could be written to use any tool. Essentially the flow would be:

$ node --run foo
  1. Look for ./node_modules/.bin/foo, if it exists, spawn it a a child process, and exit the node binary
  2. If it does not, resolve foo as a module, look for the package.json index entry point and load/run it.

@bmeck
Copy link
Member Author

bmeck commented Mar 30, 2017

I think we have differing ideas on what this should do, for example webpack, doesn't use main in this manner. Also, some people have bins with different names than their modules so routing could get weird. I am not sure I want foo to ever resolve to the foo package. Then again, I am not wanting to access node_modules/ except to get .bin setup.

@jasnell
Copy link
Member

jasnell commented Mar 30, 2017

Ok, that's fair. Perhaps describe a bit more about what you're looking for?

@bmeck
Copy link
Member Author

bmeck commented Mar 30, 2017

I was wanting to just run the package.json#scripts of the "current package" (core has not defined this term). In doing so, avoiding the double PID problem of the current npm behavior, setting up the PATH properly for node_modules/.bin, and properly passing argv if a child process is needed like #12028 does.

@bmeck
Copy link
Member Author

bmeck commented Mar 30, 2017

of note: --require should be well defined for any behavior we think this should take. I think it should generally be loaded after starting up any target script.

@michael-ciniawsky
Copy link

@bmeck index is the entry :) index.js which has external dependencies and therefore requires node_modules to run. With a --pkg || --install flag node 'knows' that it needs to install deps/check if node_modules exists first, before it actually runs index.js. The goal is to make it easier to run node e.g in containers with a simple NODE_ENV='...' node --flag entry.js command and the rest is up to node. "Node Package Mode"

@bmeck
Copy link
Member Author

bmeck commented Mar 30, 2017

@michael-ciniawsky this is not intended to be used for any form of package management/installation. That was discussed in https://github.com/nodejs/node/issues/11835

@michael-ciniawsky
Copy link

Following the discussion node --run package => node start && node start package (index || node_module)

@ljharb
Copy link
Member

ljharb commented Mar 30, 2017

I very much want this to only look at "scripts", and not a new top level key - there should only be one place in my package.json where I define how to run my tests.

@Trott
Copy link
Member

Trott commented Jul 31, 2017

Discussion on this has gone quiet for a few months. Is there something resembling consensus on how this feature should work? Doesn't look like it to me, but if so, maybe we can add a help wanted label.

If there isn't consensus, maybe the thing to do is close. People can still submit pull requests with proof-of-concept implementations for any approach they feel strongly about.

@TimothyGu
Copy link
Member

Agreed. To consolidate the many ideas floating around, people could file an EP at https://github.com/nodejs/node-eps, which is what we usually do for a big feature like this.

@ghost
Copy link

ghost commented Feb 23, 2019

For anyone who really wants this badly, there is a little cli app called ipt that creates a dropdown menu from any list you pipe to it.
so cat package.json | jq '.scripts' | ipt | xargs npm run would probably do the trick.

But it looks like there is even a 'workflow' to run npm scripts if you're not a fan of shell aliases.

@ljharb
Copy link
Member

ljharb commented Feb 23, 2019

Having to have jq installed, and an npm package, seems a lot heavier weight than just having npm itself installed and using npm run.

@bnoordhuis
Copy link
Member

Since #11835 is undead... several people have remarked that the number 1 reason for broken node installs (observe nodejs/help) is in fact npm. Notably, doing an in-place upgrade or downgrade sometimes leaves npm in a broken state.

Node itself is immune to that because it's a single binary. node --pkg install would be immune for the same reason.

(FWIW, I was not in favor of this proposal back in 2017 but the more I think about it, the more it starts to make sense.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cli Issues and PRs related to the Node.js command line interface. feature request Issues that request new features to be added to Node.js. module Issues and PRs related to the module subsystem.
Projects
None yet
Development

No branches or pull requests

9 participants