'Suddenly, NPM script variables no longer work

I use package.json variables like this in NPM scripts:

// package.json
{
  "version": "0.12.1",
  "scripts": {
    "get-version": "echo %npm_package_version%"
  }
}

npm run get-version currently echoes %npm_package_version% instead of 0.12.1. In the past, the scripts worked without any problems. Suddenly only the variable name comes back. With multiple repositories. I run Windows 10 2004 and NodeJS v15.4.0.

Was there a change for NPM scripts in Node.js 15? Is it a bug or a feature?



Solution 1:[1]

UPDATE: Failure to expand environment variables on Windows appears to be a recent high-priority known bug in the npm CLI.

Because this is npm@7 specific, until a fix is released, you can downgrade to npm@6.

ORIGINAL ANSWER:

The easiest solution for the specific case in this question is to use node.

    "get-version": "node -p process.env.npm_package_version"

This will work on every platform that Node.js supports.

If you need a more general solution and don't want to rewrite a bunch of scripts to use node, you can try cross-var as mentioned by @RobC in the comments.

As for the source of the problem, perhaps you are running under the Windows bash shell, in which case you can use this:

    "get-version": "echo $npm_package_version"

That won't work for non-bash Windows environments though.

Solution 2:[2]

I found simple hack which is working perfect in my case,

Specifically in your use case

// package.json
{
  "version": "0.12.1",
  "scripts": {
    "get-version": "node -e \"console.log(process.env.npm_package_version)\""
  }
}

Usage

npm run get-version

However you want to pass arguments.

// package.json
{
  "scripts": {
    "get-argument": "node -e \"console.log('your argument:',  process.argv[1] )\"",
  }
}

Test example

npm run get-argument hello_world

Solution 3:[3]

Default values are a great way to handle undefined values. We use a predefined value instead. Inside our NPM script we can achieve that by using the following syntax;

{
  "version": "0.12.1",
  "scripts": {
    "get-version": "echo ${npm_package_version:0.99}"
  }
}

And of course, running npm from a bash prompt might help. I guess running from a Cmd/Powershell "could work" but I would be careful about that.

Solution 4:[4]

FYI - A related change in Version 7 if you are using the Package config variables: The variable name changed from npm_package_config_customFooVar in V6 to npm_config_customFooVar in V7 Delineate these appropriate (as below) to the environment (Windows bash linux etc) being used. or Use lib like cross-var.

Package.json

{
  "config": {
    "customFooVar": "bar",
    "env": "development"
   },
  "scripts": {
    "get-var": "echo using env1 $npm_config_customFooVar OR env2 %npm_config_customFooVar%"
    "build": "npm config set myAppName:env"
    "postbuild": "cross-var ng build --configuration=$npm_config_env && cross-var node myOtherBuildSript.js $npm_config_env"
  }
} 

e.g. npm-cli call (note space after --) as this is passed to the script. Not to npm itself.

npm run build -- production

Solution 5:[5]

pass args from package.json to cli echo %npm_package_version%

Solution 6:[6]

This solution allowed me to use the npm_package_version variable in both Windows and Unix: Install run-script-os as a dev dependency. Then in your package.json the variable can be used:

"scripts": {
    ...
    "postversion": "yarn postversion-wrapper",
    "postversion-wrapper": "run-script-os",
    "postversion-wrapper:windows": "echo %npm_package_version%",
    "postversion-wrapper:nix": "echo $npm_package_version"
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 djangofan
Solution 4 redevill
Solution 5 Роман Зыков
Solution 6 jrsmolley