OS independent access to variables in package.json - node.js

To access a variable in npm scripts you would do something like this in your package.json:
"scripts": {
"preinstall": "echo ${npm_package_name}"
}
The problem is that works only in Unix, not Windows, where you have to use %npm_package_name%.
Is there a way to do this OS independent? It will be good if npm could do such a variable expansion, before invoking the command.

To make it cross-platform, use cross-var:
"scripts": {
"preinstall": "cross-var echo ${npm_package_name}"
}

There's no known way to do this that's OS independent.
A good workaround is to execute the command within a node script:
First, change the preinstall command to execute a node script:
"scripts": {
"preinstall": "node nameEcho.js"
}
Then you define the command in the nameEcho.js file:
// require the package.json file
var pjson = require('./package.json');
// echo the package's name
console.log(pjson.name);

Related

Can I run a command from package.json bin script?

Is it possible to run a command from a bin script in a package.json ? I know it expects a path to file and trying to run a command there results in an error upon installation (after publishing to npm). Is it possible to run a command like it is in an npm start ?
Examples:
{
"name": "myscript",
"version": "1.0.3",
"bin": {
"myscript": "app/main.js"
}
}
This will create a symlink from the app/main.js script to /usr/local/bin/myscript
Instead, this is what I want to achieve:
{
"name": "myscript",
"version": "1.0.3",
"bin": {
"myscript": "echo hello world"
}
}
Possible workarounds are also appreciated.
This answer is updated since the old answer was a bit dated and ultimately incorrect. You can now do:
npx myscript
Have you tried running npm link https://docs.npmjs.com/cli/link which would create a link to your binary, then you can just run your script on the command line as myscript.

'standard' is not recognized as an internal or external command

I want to integrate some kind of code linting for node.js in webstorm so I installed standard to my node.js project using:
npm instal standard --save-dev
It was installed and listed in the "devDependencies" section of package.json but when I run the command:
standard
in the console I get
'standard' is not recognized as an internal or external command
if you want to use it locally you have to include it in you scripts first in package.json
"scripts": {
"standard": "standard",
"standard::fix": "standard --fix"
}
and use npm run standard to run it. or if you are using yarn type yarn standard
The scripts are in node_modules\.bin.
So, either:
Add this to PATH before running standard, e.g.:
set PATH=%PATH%;node_modules\.bin
Run it in using node_modules\.bin\standard
Use #tarek's approach using package.json: https://stackoverflow.com/a/49026837/122441
"scripts": {
"test": "standard middlewares/validations.js"
}
Add above lines in package.json.
Here middlewares/validations.js is the path of the file to check.
Run -> npm test
If this file have any error you will get.

local node js module not executing script

I am trying to create a simple node js plugin. Here is what I have done till now.
package.json
{
"name": "testcli",
"version": "0.0.1",
"description": "Test CLI Tool",
"main": "index.js",
"author": "BJ",
"license": "ISC",
"bin": {
"testx": "index.js"
}
}
Beside the package.json I have a file index.js that has a single line console.log('Hi!')
now when I install the package with npm install -g (from the same directory) and then run the command testx it gives me the following error
.../AppData/Roaming/npm/testx: line 1: /node_modules/testcli/index.js: No such file or directory
How can I solve this?
You need to add a shebang to tell the shell how to invoke this script.
Try adding #! /usr/bin/env node at the beginning of your script.
A lot of packages have one or more executable files that they'd like to install into the PATH. npm makes this pretty easy (in fact, it uses this feature to install the "npm" executable.)
To use this, supply a bin field in your package.json which is a map of command name to local file name. On install, npm will symlink that file into prefix/bin for global installs, or ./node_modules/.bin/ for local installs.
For example, myapp could have this:
{ "bin" : { "myapp" : "./cli.js" } }
So, when you install myapp, it'll create a symlink from the cli.js script to /usr/local/bin/myapp.
If you have a single executable, and its name should be the name of the package, then you can just supply it as a string. For example:
{ "name": "my-program"
, "version": "1.2.5"
, "bin": "./path/to/program" }
would be the same as this:
{ "name": "my-program"
, "version": "1.2.5"
, "bin" : { "my-program" : "./path/to/program" } }
Please make sure that your file(s) referenced in bin starts with #!/usr/bin/env node, otherwise the scripts are started without the node executable!

Node Environmental variable on Windows

I noticed this strange behavior which is not a big deal, but bugging the heck out of me.
In my package.json file, under the "scripts" section, I have a "start" entry. It looks like this:
"scripts": {
"start": "APPLICATION_ENV=development nodemon app.js"
}
typing npm start on a Mac terminal works fine, and nodemon runs the app with the correct APPLICATION_ENV variable as expected. When I try the same on a Windows environment, I get the following error:
"'APPLICATION_ENV' is not recognized as an internal or external command, operable program or batch file."
I have tried the git-bash shell and the normal Win CMD prompt, same deal.
I find this odd, because typing the command directly into the terminal (not going through the package.json script via npm start) works fine.
Has anyone else seen this and found a solution? Thanks!!
For cross-platform usage of environment variables in your scripts install and utilize cross-env.
"scripts": {
"start": "cross-env APPLICATION_ENV=development nodemon app.js"
}
The issue is explained well at the link provided to cross-env. It reads:
Most Windows command prompts will choke when you set environment variables with NODE_ENV=production like that. (The exception is Bash on Windows, which uses native Bash.) Similarly, there's a difference in how windows and POSIX commands utilize environment variables. With POSIX, you use: $ENV_VAR and on windows you use %ENV_VAR%.
I ended up using the dotenv package based on the 2nd answer here:
Node.js: Setting Environment Variables
I like this because it allows me to setup environmental variables without having to inject extra text into my npm script lines. Instead, they are using a .env file (which should be placed on each environment and ommitted from version control).
You should use "set" command to set environment variables in Windows.
"scripts": {
"start": "set APPLICATION_ENV=development && nodemon app.js"
}
Something like this.

Inject argument into npm script command

I have an npm script that looks like:
"scripts": {
"example": "webpack-dev-server --content-base examples/embeddable/"
},
I'd like to form the --content-base argument dynamically based on whatever's passed when calling the npm script, like:
npm run example -- embeddable
I know the -- syntax works for making args available to process.argv, but I'm not calling a Node script here so I'm not sure how to access them when forming the command. Does anyone else know of a good, cross-platform way to do this? (Must work on Windows 7, i.e. without bash capabilities.)
This should work ($1 is replaced by whatever you add as first parameter):
"scripts": {
"example": "webpack-dev-server --content-base examples/${1}/"
},
Run it like this:
npm run example -- embeddable

Resources