59

I am writing an internal tool which compares the version installed in a project and only allow certain version to be passed. For that I have to check the version which is resolved in the yarn.lock file, as package.json file has a semver range, not specific version and it doesn't tell you the dependency of the dependency anyway.

I tried using yarn list command, but it prints the semver range too and is very hard to parse (even with --json option). So yarn.lock seems like the only way. I know that yarn.lock may have separate versions of the same package and in that case I want only the version which is installed in. the node_nodules (must be just one of them). I have no idea how to parse the lockfile though.

Another way I could think of is actually going into node_modules folder and checking the version in the package.json of the package.

None of the above option looks clean to me. Is there any way I can know the resolved version of a specific package (provided I know the name of the package and I know that it's installed) easily and as cleanly as possible?

Update:
I actually wanted all the versions of the installed package (even if they're really deep in the dependency tree).

0xC0DED00D
  • 19,522
  • 20
  • 117
  • 184
  • Not quite sure If it helps but since you know the name of the package. `npm info [package_name] version` can be helpful to retrieve the package version. – Varit J Patel Feb 28 '20 at 15:16
  • @VaritJPatel It doesn't return the installed package version. It just fetches the information from the npm registry – 0xC0DED00D Feb 28 '20 at 15:19
  • Probably the best way is to use `require.resolve` to look up the location of the node module that will actually be included, and then read the `package.json`. https://nodejs.org/api/modules.html#modules_require_resolve_request_options – Gordon Burgett Feb 28 '20 at 19:36
  • 3
    It's a bit ridiculous that this isn't possible/easy. – pixelearth Dec 11 '20 at 01:46
  • Does this answer your question? [Find the version of an installed npm package](https://stackoverflow.com/questions/10972176/find-the-version-of-an-installed-npm-package) – Seeta Ram Yadav Jun 22 '22 at 09:13
  • @SeetaRamYadav This question is already answered a couple of years ago. Furthermore, I asked about yarn command, not npm. Also there's no correct answer which fixed my issue other than my own answer for this question. – 0xC0DED00D Jun 22 '22 at 12:41

7 Answers7

64

Since, you know the name of the package, do this:

yarn list --pattern <package_name>

The above command will get you all installed versions of a package at any depth. For example, I have different versions of camelcase library installed at various depths. On running the command : yarn list --pattern "camelcase", this is the output:

yarn list v1.22.5
├─ camelcase@6.2.0
└─ yargs-parser@13.1.2
   └─ camelcase@5.3.1
Binita Bharati
  • 5,239
  • 1
  • 43
  • 24
37

I found out that yarn whyis the best way to find out the currently installed version of a package (Thanks to one of my colleague who point out to me). This is how my test code looks in the JavaScript.

const { spawnSync } = require('child_process');
const packageName = 'micromatch';
const whyBuffer = spawnSync('yarn', ['why', packageName]);
const grepBuffer = spawnSync('grep', ['Found'], { input: whyBuffer.stdout });
const outputArray = grepBuffer.stdout.toString().split('\n');
console.log(outputArray); // ['info \r=> Found "micromatch@3.1.10"',    'info \r=> Found "fast-glob#micromatch@4.0.2"', ''  ]
const parsedOutputArray = outputArray.filter(output => output.length > 0).map((output) => output.split('@')[1].replace('"', ''))
console.log(parsedOutputArray); // [ '3.1.10', '4.0.2' ]
0xC0DED00D
  • 19,522
  • 20
  • 117
  • 184
  • 1
    The answer works for me but could be improved by handling scoped packages cases (when package name starts with `@`): ```output.split('@')[1]``` here use the last element of array but not the second. – ivandz Jun 15 '21 at 09:15
  • you want the fastest, why not `cat package.json | jq -r '.dependencies.pckname'` – Time Killer May 04 '22 at 06:36
  • 2
    @TimeKiller It doesn't tell you the exact version of installed package. Also it doesn't tell you anything about transitive dependencies. – 0xC0DED00D May 06 '22 at 09:39
6

For programmatic use, I like yarn list:

yarn list --pattern lodash --depth=0 --json --non-interactive --no-progress | jq -r '.data.trees[].name'
lodash@4.17.21
lodash.defaults@4.2.0
lodash.flatten@4.4.0
lodash.isarguments@3.1.0
lodash.memoize@3.0.4

For even better programmatic use: https://www.npmjs.com/package/@yarnpkg/lockfile

Jason Kohles
  • 597
  • 5
  • 12
3

You can check with

via yarn yarn list --depth=0 or via npm 'npm list --depth=0`

Seeta Ram Yadav
  • 847
  • 9
  • 16
  • btw it seems like a duplicate of https://stackoverflow.com/questions/10972176/find-the-version-of-an-installed-npm-package?rq=1 – Seeta Ram Yadav Jun 22 '22 at 09:12
2

npm list --depth=0 is 1000x faster than yarn why <each package>. It also tells you about extraneous dependencies, unmet peer deps, etc, but the output is very clean - still cleaner than yarn why

Devin Rhode
  • 23,026
  • 8
  • 58
  • 72
  • How can you be so sure that it's 1000x faster? Is there any benchmark? Moreover, I am not interested in depth 0 deps only. Moreover, I don't want to know about every package. I just wanna know if a given package is installed or not, if it is, what's the installed version. Parsing the entire list seems slower than just using `yarn why`. – 0xC0DED00D Oct 10 '21 at 21:49
  • One additional point is that I am using yarn as the package manager, not npm. When using `npm list` without `package-lock.json` I received a lot of errors for missing deps. – 0xC0DED00D Oct 10 '21 at 21:52
2

Since yarn list isn't yet implemented for newer versions of Yarn, and yarn why can be a bit hard to parse, yarn info is another option. It outputs the version resolved in yarn.lock.

$ yarn info sass -A
└─ sass@npm:1.41.0
   ├─ Version: 1.41.0
   │
   ├─ Exported Binaries
   │  └─ sass
   │
   └─ Dependencies
      └─ chokidar@npm:>=3.0.0 <4.0.0 → npm:3.5.2

Or, to just get the name and version:

$ yarn info sass -A --name-only
└─ sass@npm:1.41.0

And to get just the version, you can use the --json flag to output in a more machine readable format, and then parse it with jq:

$ yarn info sass -A --json | jq ".children.Version"
"1.41.0"
Noah Allen
  • 699
  • 5
  • 14
  • 1
    what '-A' is for? – Piotr Jan 20 '22 at 11:55
  • The -A flag stands for —all: “Print versions of a package from the whole project.” I believe this would help if you had a monorepo and just wanted to run yarn info from the root directory. – Noah Allen Jan 21 '22 at 20:00
  • 2
    Ever since `yarn` developers seem to have moved around pretty much every invocation in the CLI, most of the answers on the Internet on how to do something with `yarn` don't work any longer. Yours with `yarn info` was a welcoming change for someone that was just exposed to `yarn` in 2022 ;). – ikaerom Nov 09 '22 at 06:58
  • Thanks, I agree! I remember this being frustrating when I was trying to find the answer to this question myself :) – Noah Allen Dec 01 '22 at 21:17
0

Update to Noah Allen answer, for yarn 1.22.19, children is data and Version is lowercase.

Run this command in your terminal to see the currently installed version.

yarn info sass -A --json | jq ".data.version"
Ajay Kumar
  • 586
  • 5
  • 21
swasweng
  • 23
  • 1
  • 5