ZenMaster
ZenMaster

Reputation: 12742

Passing parameters to node when invoked via executable (.bin) npm scripts

I've defined an npm CLI command as a mycommand module:

{
  ...
  "name": "mycommand",
  "bin": {
    "mycommand": "bin/mycommand.js"
  },
  ...
}

where mycommand.js looks like this:

#!/usr/bin/env node --harmony

console.log('...')

I'd like to be able to run it in the following manner, installed in another module:

{
  ..
  "scripts": {
    "mycommand": "mycommand --require ./bootstrap"
  }
  ...      
}

where bootstrap is a module that I expect to be require-ed before mycommand. The --require argument is supposed to be passed to Node running mycommand.

Results & Attempts

  1. Unfortunately, the bootstrap is never required. There are no errors or other indication of incorrect path resolution or some such.

  2. If I define mycommand script in a different manner:

    {
      ...
      "scripts": {
        "mycommand": "node --require ./bootstrap ./some-random-js-file"
      }
      ...      
    }
    

bootstrap is required as expected, proving that bootstrap exists and --require works.

  1. If I require the bootstrap module directly in mycommand (which I can't really do -- so just for the sake of the test):

    #!/usr/bin/env node --harmony
    require('../../../bootstrap');
    console.log('...')
    

bootstrap is required as expected. Note that ../../../ is there to compensate for the placement of mycommand.js within node_modules.

Assumption

I assume that --require is never actually passed to Node executing mycommand.

Question

How can this be done?

Upvotes: 1

Views: 720

Answers (1)

Grisha Levit
Grisha Levit

Reputation: 8617

Your assumption that --require is never passed to node is correct:

  • When you run node --require … path/to/mycommand.js you are passing arguments to node.

  • When you run mycommand --require … you are passing arguments to mycommand.

(And you could parse command line options in mycommand.js and require() as needed, if that fits your use case)

I'm assuming you don't want to use the node … mycommand.js method because you need to specify the path to the script, thus loosing the whole point of creating the bin field in the first place.

However, since you've provided a bin field, you will already have a known path to mycommand:

{
  ..
  "scripts": {
      "mycommand": "node --require ./bootstrap ./node_bin/mycommand"
  }
  ...      
}

Or could instead be … $(npm bin)/mycommand.

Upvotes: 1

Related Questions