2

I'm trying to get what version i am creating in a npm preversion script.

As in:

{
    "scripts": {
        "preversion": "echo $version"
    }        
}

But i can't find what to write instead of $version.

I want to get the version i am creating when i do npm version <something>. For exemple, if i do npm version 1.0.1, i want to get the 1.0.1. But if i do npm version minor when i'm at version 1.0.0, i want to get 1.1.0.

Magus
  • 14,796
  • 3
  • 36
  • 51
  • I'm not sure what you are asking for. Could you please clarify? What version are you trying to get: `"version"` entry of package.json or sth else? @NaorLevi's answer seemed to be correct from what I understood but it seems like it's not what you are looking for. So please explain – Sebastian Kaczmarek Feb 06 '20 at 10:12

3 Answers3

7

Redefine your preversion script as follows:

"scripts": {
  "preversion": "echo $npm_package_version"
}

Explanation:

This accesses the package.json vars. The npm_package_version variable is one of the many environment variables that npm creates.

On *nix platforms npm runs package.json scripts by utilizing sh by default. Therefore you reference the environment variables inside npm scripts using the $ prefix, i.e. $npm_package_version.

However, on Windows npm runs scripts by using cmd by default. In which case you'll need to reference the environment variables inside npm scripts using the %...% syntax. For example:

"preversion": "echo %npm_package_version%"

If cross-platform support is necessary you can avoid the differences in syntax, i.e. the $ prefix v's %...%, by utilizing cross-var. In which case you will need to redefine your preversion script as follows:

"scripts": {
  "preversion": "cross-var echo $npm_package_version"
}

Tip: If you cd to your project directory and run npm run env it will list all the npm_* prefixed environment variables that npm creates.

RobC
  • 22,977
  • 20
  • 73
  • 80
  • It appears that `npm` is not actually setting an env var, but just doing some kind of internal interpolation. I did the above in git bash on Windows and it fails when I use "$", but works with the "%" (as shown). – Allen Nov 23 '21 at 18:33
  • @Allen - on Windows npm utilizes _cmd.exe_ as the default shell for running npm scripts. If you run `npm config get script-shell` to obtain the current [script-shell](https://docs.npmjs.com/cli/v8/using-npm/config#script-shell) setting it probably returns `cmd`. – RobC Nov 23 '21 at 20:58
  • ah, so you're saying that it doesn't execute the script in the current shell, but instead uses its configured `script-shell` to run the script and that's why it behaved the way I described. I just around for references about changing the `script-shell`, but couldn't find much. Can I just change that setting to use git bash instead? – Allen Nov 23 '21 at 22:26
  • I just tried it and it seems to work fine. – Allen Nov 23 '21 at 22:45
  • @Allen - yes that’s it. Refer to [this post](https://stackoverflow.com/questions/54423213/pass-argument-to-npm-script-command-by-inserting-it-not-appending/54429568#54429568) regarding how to configure npm to utilise the _git bash_ shell when running npm scripts. However be mindful that most consumers of your package will be using the default shell, i.e. either _cmd.exe_ (on _Windows_) or _sh_ (on _*nix_). For portability cross-platforms consider using the `cross-var` package as suggested in my answer above - that way you can use the `$` prefix syntax to reference the var. – RobC Nov 24 '21 at 20:00
  • This sadly seems to [no longer be the case](https://stackoverflow.com/questions/60092316/get-version-in-npm-preversion-script#comment120101463_60093346) with NPM 7. – El Yobo Jul 21 '22 at 12:32
0

From the docs:

The exact order of execution is as follows:

[...]

  1. Run the preversion script. These scripts have access to the old version in package.json.

So it's not possible to easily get the future version in the preversion script since it's being run before the version actually changes. You could come up with some hacky solution, for example like this:

"preversion": "mkdir ../ver && node -e \"const p = require('./package.json'); delete p.scripts.preversion; require('fs').writeFileSync('../ver/package.json', JSON.stringify(p), 'utf8')\" && cd ../ver && npm version minor && node -e \"console.log('new version is gonna be',require('./package.json').version);\" && cd -"

Which basically copies the package.json file to another dir, runs npm version minor and prints the new version. The problem is hardcoded npm version minor which will not give you the right result when you run for example npm version 1.0.1 and there's no way to get the same command which triggered this script (at least I don't know any way to do that) and run it again before it's finished.

I don't know your requirements but I would go with the version or postversion scripts in order to easily get the new version. Or you could create some custom script which does the same but generates the new version before all the scripts are started and the new version can be accessed.

Sebastian Kaczmarek
  • 8,120
  • 4
  • 20
  • 38
  • 2
    It's true that the docs say the preversion script has access to the old version. However, given this `package.json`: { "name": "test", "version": "1.0.0", "scripts": { "preversion": "cross-var echo \"preversion $npm_package_version\"", "version": "cross-var echo \"version $npm_package_version\"", "postversion": "cross-var echo \"postversion $npm_package_version\"" }, "devDependencies": { "cross-var": "^1.1.0" } } when running `npm version patch`, all three `echo` commands show `1.0.1`. – Blade1336 Apr 27 '21 at 12:25
  • 1
    @Blade1336 That behavior is seemingly changed in NPM 7; `preversion` now reports 1.0.0. – Kagami Sascha Rosylight Jun 12 '21 at 14:27
  • Annoying, easy to get the old version from package.json before but now impossible to get the new version (and potentially block execution). – El Yobo Jul 21 '22 at 12:26
0

If you are looking for the previous version this will help:

{
    "scripts": {
        "preversion": "node -p 'JSON.parse(fs.readFileSync(`package.json`)).version'"
    }        
}

Other ways will just get you the new version.

Nicolae Iotu
  • 399
  • 3
  • 7