How can I get the exact latest npm version from a relative version?

早过忘川 提交于 2020-08-09 08:15:19

问题


I want to be able to get the latest released version of npm that matches a relative semantic version.

For example, I would like to run something like:

npm -v 6.12.x

then return the exact latest version that matches:

=> 6.12.1

I have explored some of the docs and the commands available or think this is possible with npm, but I haven't seen anything that works without installing another global dependency.


回答1:


Short answer: npm does not provide a built-in feature to meet your requirement exactly.

However, npm does provide the npm-view command. It's documentation states the following:

If a version range is provided, then data will be printed for every matching version of the package. This will show which version of jsdom was required by each matching version of yui3:

npm view yui3@'>0.5.4' dependencies.jsdom.

The two solutions given below demonstrate how the output of the npm view command can be parsed/manipulated to meet your requirement (without having to install another global dependency).


Solution A: *Nix platforms only (Linux/MacOS...)

Therefore, it's possible to achieve your requirement with the help of some additional Bash utilities to parse the output.

Consider running the following compound command:

npm view npm@'6.12.x' version | tail -n 1 | cut -d "'" -f2

Explanation

The following provides an explanation of the constituent parts in the aforementioned compound command:

  1. npm view npm@'6.12.x' version

    This part utilizes the npm view command to return all versions in the given range, i.e. 6.12.x.

    Running these parts standalone will print the following to your console:

    npm@6.12.0 '6.12.0'
    npm@6.12.1 '6.12.1'
    
  2. | tail -n 1

    The previously shown result is then piped to tail using the -n 1 option so that only the last line is printed.

    Running:

    npm view npm@'6.12.x' version | tail -n 1
    

    prints:

    npm@6.12.1 '6.12.1'

  3. | cut -d "'" -f2

    The previously shown result is then piped to cut using the -d option and specifying a single quote as the delimiter. The -f2 part then selects the second item.

    Running the full compound command:

    npm view npm@'6.12.x' version | tail -n 1 | cut -d "'" -f2
    

    prints your desired result:

    6.12.1

Semver tilde (~) and caret (^) ranges.

You can also specify tilde or caret ranges with the aforementioned compound command.

Examples:

  • Specifying a tilde range:

    npm view npm@'~4.0.0' version | tail -n 1 | cut -d "'" -f2
                  ^^^^^^
    

    prints:

    4.0.5

  • Specifying a caret range:

    npm view npm@'^4.0.0' version | tail -n 1 | cut -d "'" -f2
                  ^^^^^^
    

    prints:

    4.6.1

Simplified Usage:

If you intend to run the command often on *nix then I suggest:

  1. Running the following compound command:

    echo $'\n'"npmv() { npm view \"npm@\${1}\" version | tail -n 1 | cut -d \"'\" -f2; }" >> ~/.bash_profile
    

    This will add a shell function to the content of your .bash_profile file, i.e. it will add a new line that reads:

    npmv() { npm view "npm@${1}" version | tail -n 1 | cut -d "'" -f2; }

  2. Then when you create a new session (i.e. create new window, or relaunch terminal), in the future you can simply run:

    npmv 6.12.x
    

    It's terse and more akin to the example command given in your question.

Note: If you already have the npm package called npmv installed globally on your system then choose a different name for the shell function/command to avoid any conflict.


Solution B: Cross Platform (Windows/Linux/macOS...)

If you're using Windows, or are wanting a cross-platform solution, (i.e. one that runs successfully on Windows, Linux, and macOS...), you'll need to utilize nodejs to achieve your requirement.

Consider running the following compound command:

node -e "var res = require('child_process').execSync('npm view npm@"\"6.12.x\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"

Yes, I agree it's somewhat verbose compared to Solution A :)

Explanation

The following provides an explanation of the constituent parts in the aforementioned compound command:

  1. node -e "..."

    We invoke node and the nodejs command line option -e is utilized to evaluate the given inline JavaScript.

  2. var res = require('child_process').execSync('npm view npm@"\"6.12.x\"" version', {encoding: 'utf-8'})

    This part of the given node.js script (JavaScript) shells-out the the same npm view command as per Solution A, i.e. npm view npm@"\"6.12.x\"" version, using execSync().

  3. .split('\n').filter(Boolean);

    The result of the npm view command is converted from a String to an Array using the String's split() method - essentially each line of the result is split by the newline character \n so that each line of output becomes an element in a Array.

    The .filter(Boolean) part removes empty elements from the Array that are produced by the additional trailing empty lines that the npm view command prints.

  4. if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } ... }

    Here we utilize some conditional if..else statements to ensure we obtain the desired item from the Array.

  5. console.log(res.replace(/[']/g, ''));

    Finally we log the result to console and use the replace() method to remove the single quotes (') that encase the semver value.

Semver tilde (~) and caret (^) ranges.

As per Solution A, you can also specify tilde or caret ranges with the aforementioned compound command.

Examples:

  • Specifying a tilde range:

    node -e "var res = require('child_process').execSync('npm view npm@"\"~4.0.0\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"
                                                                          ^^^^^^
    

    prints:

    4.0.5

  • Specifying a caret range:

    node -e "var res = require('child_process').execSync('npm view npm@"\"^4.0.0\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"
                                                                          ^^^^^^
    

    prints:

    4.6.1



来源:https://stackoverflow.com/questions/58773187/how-can-i-get-the-exact-latest-npm-version-from-a-relative-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!