How to know the version of currently installed package from yarn.lock

Viewed 52334

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).

6 Answers

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

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' ]

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

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

You can check with

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

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"
Related