Specify the path to node when running executable npm moduels - node.js

I'm fairly new to node and npm so imagine this might be the way I'm trying to use it. My understanding so far and questions are as follows.
When installing modules with npm if they have executables they are created in node_moadules/.bin
For example npm install istanbul creates
node_moadules/.bin/istanbul.cmd with the following contents
#IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\istanbul\lib\cli.js" %*
) ELSE (
#SETLOCAL
#SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\istanbul\lib\cli.js" %*
)
This seems to be roughly similar for other npm modules installed.
1) When would there be a node.exe in the bin directory (%~dp0 is the path of the batch file - so node_moadules/.bin)? When using npm istanbul it will use the above script but I don't understand when it would use the IF block, it seems it would always go into the ELSE which uses node on the path to run it. This will work as intended when I have node installed and on my path. However this would seem to be a problem if you don't have it on your path or need to use a specific version in a project (different from the version on your path).
2) I can fix this by manually editing the above script to point to the specific node version but don't want to have to do this for all module executables installed with npm. Is there a way to configure this in npm so it uses a specific path to node when it generates these executable files?
A bit more background
We're using the gradle-node-plugin in our build so we don't have to manage node and npm on our build machines, this does it for us. However this means we don't have node on the path.
The plugin allows me to install npm modules but there is no clear way to then run the executables, using the version of node unpacked by the plugin, without manually editing the generated executable scripts as in 2), or instead of calling npm istanbul calling something like this:
<path_to>\node <path_to>\node_modules\istanbul\lib\cli.js
This also doesn't seem right as I'm hardcoding to the cli.js executable path within the module which could presumably change in future versions of that module.
If anyone could explain this, or tell me where the specific part of the docs that do are that would be helpful. I've tried to search but probably not using the right terms.

Related

NVM for windows - ability to specify specific version without switching

I've installed NVM for windows, so I can switch between different versions of node when I have to. However, I have a need to be able to call one version of node / npm WITHOUT having to switch
For example, right now I have 2 versions of node installed: 10.17.0 and 8.9.1. I can easily switch between them using nvm use 10.17.0 or nvm use 8.9.4, and after either of those commands, when I run node ./app.js or npm install package, it uses the expected version of node / npm to do what I'm asking
But I want to create a situation where I can avoid switching, and instead I can just type node10 ./app.js or npm10 install package, and it uses the version I specify
Now, I've done a bit of research myself about what it would take to do this, so I'll lay that out and hope that someone has some advice because they've done something similar.
First of all: nvm installs both versions of node in a specific place, and that place should stay static and unchanging. I can find the 8.9.1 versions of node and npm here: C:\Users\SamuelR\AppData\Roaming\nvm\v8.9.1
I can find the 10.17.0 versions here: C:\Users\SamuelR\AppData\Roaming\nvm\v10.17.0
When I use nvm use 10.17.0, what it does is it changes a symlink at C:\Program Files\nodejs, and it points it to whichver of those two folders I specify
So my idea to make node8 / node10 and npm8 / npm10 commands work was this:
In some folder in my PATH, I was going to create 4 .bat files, node8.bat npm8.bat node10.bat npm10.bat. For node8.bat, I was going to follow the example here:
C:\Users\SamuelR\AppData\Roaming\nvm\v8.9.1\node.exe %*, so that it always forwards all my command line arguments to the correct installation.
For npm, the file npm8.bat would have C:\Users\SamuelR\AppData\Roaming\nvm\v8.9.1\npm.cmd %*.
Maybe I'd do the same for npx. And then I'd repeat those steps for the node10.bat npm10.bat files.
Is this the right way to go about this? Does it even make sense?
Welp, nobody's giving any answers, but I've tried it myself and as far as I can tell, it works!
I'll just lay it out for total clarity here: once you have nvm working as you like, find the install directory, in my case it was C:\Users\SamuelR\AppData\Roaming\nvm
For each version of node in there that you want to make these shortcuts to, make the following files,
node{v}.bat (eg node10.bat)
npm{v}.bat (eg npm10.vat)
npx{v}.bat (eg npx10.vat)
Put them all in a file that is accessible in your PATH environment variable (I made a new folder called C:\Program Files\nodelinks and put it in my path myself)
inside node10.bat:
C:\Users\SamuelR\AppData\Roaming\nvm\v10.17.0\node.exe %*
inside npm10.bat:
C:\Users\SamuelR\AppData\Roaming\nvm\v10.17.0\npm %*
inside npx10.bat:
C:\Users\SamuelR\AppData\Roaming\nvm\v10.17.0\npx %*
As far as I can tell, it passes all arguments through as expected, there's no apparent permissions issue, it works exactly as expected.

NodeJS unexpected strict mode reserved word "let" when installing ejs (not my code)

I'm getting this output when trying to install a node application using npm install:
$ npm install
> ejs#2.7.4 postinstall /home/dh_8u42k7/quotegoodeair.com/node_modules/ejs
> node ./postinstall.js
/home/dh_8u42k7/quotegoodeair.com/node_modules/ejs/postinstall.js:9
let envDisable = isTrue(process.env.DISABLE_OPENCOLLECTIVE) || isTrue(process.
^^^
SyntaxError: Unexpected strict mode reserved word
I have already found this question which contains a workaround. However, this isn't my own code, so I can't just remove "let", it seems to be a problem with ejs itself.
For another thing, the file postinstall.js doesn't even exist, even the ejs folder doesn't exist, so I can't just go in and edit the file.
Is there something wrong with my node application, or with ejs, or maybe with npm or Node itself? Why does Node install components which aren't supported by Node? Why does Node tell me there's an error in a file which doesn't exist?
It may be that your version of node does not support the features in the application you are trying to install.
One solution may be to find out what the version of node the application that you are trying to install originally used.
I believe you can check the engine field in your package.json file.
If you local node version is different, and you need to change it, here is a link to a question providing that information: How can I specify the required Node.js version in package.json?
I also found this post interesting: https://github.com/tj/n/issues/472
It's for a different application but they received the same error message. The issue was conflicting npm folders. It's possible that the program that you are trying to install is conflicting with your existing npm setup if you have other nom folders in the directory you are installing the application in.
Ultimately, given the information you provided, I think your best bet it to look in the package.json file of the application you're trying to install and see if your local setup is conflicting with how the program is trying to be installed or run.

I’d like to install and require “fs”, ”path”, and “js-yaml” in Windows 10 but only “js-yaml” led to "Error cannot find module "

 Nice to meet you. I'm a beginner in computer and these days have enjoyed your sophisticated Q&As here. This is my first question in StackOverFlow. Please forgive me when I use not common notations and unnatural English.
 I trid for several hours to install external modules in Node-Red (Node.js ?).
I’d like to install three---“fs”, ”path”, and “js-yaml”--- in Windows 10 but my trouble is that only “js-yaml” resulted in failure although the others can be successfully installed and used.
 I tried the following command…
C:\windows\system32>npm –g install js-yaml
C:\windows\system32>npm –g install fs
C:\windows\system32>npm –g install path
These commands created the modules, but only js-yaml behaved differently from the other two. After adding appropriate keys and properties such as “ fs: require(‘fs’)” to functionGlobalContext in (C:~~~/.node-red/) setting.js, I tried to start Node-Red.
When I commanded
C:\windows\system32> node-red
it returned the following errors only on js-yaml and node-red did not open. It ran successfully when I removed the term “jsyaml: require(‘js-yaml’)” from setting.js.
Error loading C:~~~/.node-red/setteing.js
Error cannot find module “js-yaml”
I’ll list reports which may be related with my problem.
*The other two (fs, path) created the folders only in the directory “C:~~~/npm/node-modules”, but js-yaml created another js-yaml file apart from there in “C:~~~/npm”.
*Perhaps I tried “npm link” command in each directory before install command. And npm link [module name] in C:~~~/.node-red directory.
*I downloaded external module (node-red-contrib-postgres) from github, which may have fs.js and path.js??
*It did not change the result to add “js-yaml” term into “dependency” in (C:~~~/.node-red/) package.json.
*I add C:~~~/npm.node_modules(got by "npm -g bin"command) to enviroment variable "PATH"
I would suggest you install them locally, not globally.
When you install npm modules globally using -g, they are stored under %APPDATA%\npm, which is user-specific, and to which Node Red may not have access, depending on how it's being run.
Have a look at Running on Windows under "Sharing Node-RED between Users" and npm-folders for further info.
Alternatively, you can also put the actual path in functionGlobalContext, which may work for you. Along the lines of:
js-yaml: require(‘/the/path/to/js-yaml’)

How to include the path for the node binary npm was executed with

Windows, VSC, Running npm start got this
npm WARN lifecycle The node binary used for scripts is C:\Program
Files\nodejs\node.exe but npm is using
C:\somewhere\AppData\Roaming\npm\node_modules\node\bin\node.exe
itself. Use the --scripts-prepend-node-path option to include the
path for the node binary npm was executed with.
I understand it means my local version is diff from the one in the PATH variable (C:\Program Files...). How do proceed to tell it to use --scripts-prepend-node-path?
I played a trick by replacing the C:\Program Files\nodejs with C:\somewhere\AppData\Roaming\npm\node_modules\node\bin in PATH variable, it does pick up that new node.exe got but there is no node binary in the current PATH. Again recommend to use the --scrip
ts-prepend-node-path option to include the path for the node binary npm was executed with
Like I said, replacing the actual path in PATH system variable didn't fix the problem completely, it still complained about binary is missing. Found this solved the there is no node binary in the current PATH problem. So I restored the original PATH, then:
Simply create a file at the root folder of the app, called .npmrc,
place this line into it:
scripts-prepend-node-path=true
Here's another way that works: npm config set scripts-prepend-node-path auto
Conflict between your node binary and your npm
In case the error looks something like:
npm is trying to use the same node as the one it use to run itself.
resolve this conflict by adding the node directory to your PATH:
npm config set scripts-prepend-node-path true
From the npm documentation:
npm run sets the NODE environment variable to the node executable with
which npm is executed. Also, if the --scripts-prepend-node-path is
passed, the directory within which node resides is added to the PATH
Having this issue in Visual Studio 2017, I instead told VS to always use the NodeJS that I had installed from nodejs.org rather than the frozen-in-time one that ships with Visual Studio. (The one that shipped with VS2015 is so ancient it doesn't really work anymore.)
In Visual Studio, go to TOOLS > OPTIONS > search for EXTERNAL WEB TOOLS > and ensure "C:\Program Files\nodejs" (or wherever nodejs.org installed it) is first in the list of paths, adding it if necessary.
For WebStorm, invalidating caches and restarting worked for me.

Can I assume `node` is always in the $PATH setup by NPM?

So I have have been using NPM as a simple build tool for a few years where I can assume that every CLI tool installed through package.json is available in the PATH, as NPM adds the ./node_modules/.bin path to it.
But as I was about to write a small Node script to do some house cleanup chores I got a bit wary if NPM actually has the node executable in the PATH it gives to users. This might seems stupid, as all the scripts in ./node_modules/.bin rely on node being there for the wrapper scripts on Unix to be able to find it, but I thought there might be some magic going on in Windows. Perhaps they use some other magic of their own. Or something. Does not matter, really, I just want to be able to assert:
Is the node executable always on the PATH given to npm scripts by NPM? On all platforms? And is it always the same Node as NPM runs on?
This might seem too basic to almost be asked, but better safe than sorry.
Note: not a definitive answer, but too lengthy for a comment
If you look at the documentation on default values that are set up for scripts:
npm will default some script values based on package contents.
"start": "node server.js":
If there is a server.js file in the root of your package, then npm
will default the start command to node server.js.
Although this isn't a definitive answer to your question, npm uses node as a default in case there's no npm start defined. This is a clear indicator npm relies on node to be present under all circumstances.
On Windows, you can safely make the assumption that npm requires node to be in the PATH, or in the same folder as npm. This is from npm.cmd (the script that is called when you type npm):
SET "NODE_EXE=%~dp0\node.exe"
IF NOT EXIST "%NODE_EXE%" (
SET "NODE_EXE=node"
)

Resources