TheSoul
TheSoul

Reputation: 5376

Node.js command line tool opens in Notepad instead of being executed

I try to create a simple Node.js command line tool to get around this concept. I am following this tutorial. Using npm init, I have created a project named lb-model-discovery. This is the content of the package.json:

{
  "name": "lb-model-discovery",
  "version": "1.0.0",
  "description": "loopback model discovery command line tool",
  "main": "index.js",
  "bin" :{
      "lb-discover":"./index.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "seya obey",
  "license": "ISC"
}

And this is the (very simple) content of the index.js at the root of the project:

console.log('hello world');

After that I executed this command from within the folder (as suggested by the above tutorial):

npm install -g

This correctly install my tool as a global Node command line module. Going into the global repository of node_modules/ in my system (Windows), I can see that this is the file created in the npm folder: lb-discover.cmd. And here is its content:

@"%~dp0\node_modules\lb-model-discovery\index.js"   %*

But now when I run my new tool from the command line prompt:

$ lb-discover

instead of displaying a "Hello world" message in the console, it opens Notepad instead and merely displays the content of the index.js file.

What am I doing wrong? How can I execute my custom Node.js command line?

Upvotes: 4

Views: 3008

Answers (4)

jonrsharpe
jonrsharpe

Reputation: 122169

I had this issue, and looking in "$(npm config get cache)\_npm\<hash>\node_modules\.bin" showed that all of the auto-generated scripts (<pkg> for Bash, <pkg>.cmd for Command Prompt, and <pkg>.ps1 for PowerShell) were present and correct - executing these directly in the appropriate shell worked fine.

This was for a simple package with a single script:

{
  "name": "<pkg>",
  "version": "<version>",
  "bin": "lib/cli.js",
  "...": "..."
}

lib/cli.js was executable and started with:

#!/usr/bin/env node

However, the Bash version was still opened in Notepad when I tried to run the package with npx <pkg>.

The issue seems to be that packages with . in the name don't work correctly on Windows - switching from pkg.name to pkg-name or a scoped @pkg/name worked fine across all platforms (tested on macOS, Ubuntu, Windows).

This is despite the documentation suggesting that only starting an unscoped package's name with a . should be a problem:

  • The names of scoped packages can begin with a dot or an underscore. This is not permitted without a scope.

Upvotes: -3

JupiterPi
JupiterPi

Reputation: 23

For anyone who thinks they've put the #!/usr/bin/env node at the start of the script, check again! Some tutorials have an incorrect additional space.

Wrong!: # !/usr/bin/env node
Correct: #!/usr/bin/env node

Upvotes: 0

Marcos
Marcos

Reputation: 3323

Add #!/usr/bin/env node to the first line of lb-model-discovery/index.js. Then install the package again.

This script will be generated

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\lb-model-discovery\index.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\node_modules\lb-model-discovery\index.js" %*
)

instead of

@"%~dp0\node_modules\lb-model-discovery\index.js"   %*

Source: https://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm

Upvotes: 5

TheSoul
TheSoul

Reputation: 5376

I was able to fix this issue by modifying the content of the lb-discover.cmd from this :

@"%~dp0\node_modules\lb-model-discovery\index.js"   %*

to this:

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\lb-model-discovery\index.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\node_modules\lb-model-discovery\index.js" %*
)

My question is why executing npm install -g in the first place, generated the wrong script?

Upvotes: 0

Related Questions