nacho4d
nacho4d

Reputation: 45088

Check package version at runtime in nodejs?

I have some of my entries in package.json defined as "*"

"dependencies": {
    "express": "4.*",
    "passport": "*",
    "body-parser": "*",
    "express-error-handler": "*"
},

I wan't to freeze those values to the current version. How can I know what version my packages are at run time? I don't mind checking one by one since I don't have many of them :)

BTW: I cannot do npm list --depth=0 because I cannot access the vm directly (PaaS restriction), just the logs.

Upvotes: 11

Views: 11171

Answers (4)

Antonio Terreno
Antonio Terreno

Reputation: 3065

I've 'modernised' a bit @laggingreflex answer, this works on ES6+, node 10, tested on a lambda running in aws. It's an endpoint from an express app.

const fs = require("fs");

module.exports.dependencies = async (_req, res) => {
  const dirs = fs.readdirSync("./node_modules");

  const modulesInfo = dirs.reduce((acc, dir) => {
    try {
      const file = `${dir}/package.json`;
      const { name, version } = require(file);
      return { ...acc, [name]: version };
    } catch (err) {}
  }, {});
  res.status(200).json(modulesInfo);
};

Upvotes: 1

NSjonas
NSjonas

Reputation: 12032

The accepted solution can be improved upon in both terms of performance and stability:

1: the package name IS THE directory. In typically cases where you are looking for a specific package, you do not need to load every module.

2: this code will not run on all os due to the way the paths are formed

3: using require means the path needs to be relative to the current file (this would only work if your file is located at the top of your project folder & along side node_modules). In most cases, using readFile or readFileSync is a easier approach.

const fs = require('fs');
const path = require('path');

const dirs = fs.readdirSync('node_modules');
const data = {};
//add ones you care about
const trackedPackages = ['express', 'passport', 'body-parser'];
dirs.forEach(function(dir) {

   if(trackedPackages.indexOf(dir) > -1){
      try{
        const json = JSON.parse(
          fs.readFileSync(path.join('node_modules', dir, 'package.json'), 'utf8')
        );
        data[dir] = json.version;
      }catch(e){
        console.log(`failed to read/parse package.json for ${dir}`, e);
      }
   }

});
console.debug(data['express']); //= 4.11.2

Upvotes: 0

laggingreflex
laggingreflex

Reputation: 34627

You can use the fs module to read the directories in the node_modules directory and then read package.json in each of them.

var fs = require('fs');
var dirs = fs.readdirSync('node_modules');
var data = {};
dirs.forEach(function(dir) {
    try{
    var file = 'node_modules/' + dir + '/package.json';
    var json = require(file);
    var name = json.name;
    var version = json.version;
    data[name] = version;
    }catch(err){}
});
console.debug(data['express']); //= 4.11.2

Upvotes: 10

Dinesh Pandiyan
Dinesh Pandiyan

Reputation: 6289

Just in case if you need the version on the front-end, there is an npm package just for this and it can be used both on client-side and server-side.

global-package-version

You can use it in your code like this

import globalPackageVersion from 'global-package-version';

// package name is 'lodash'
globalPackageVersion(require('lodash/package.json'));

// You can type 'packageVersion' in browser console to check lodash version
// => packageVersion = { lodash: '4.7.2'}

packageVersion becomes a global object when used in server side and becomes a window object when used on the client side. Works well with webpack and all other bundling tools.

Disclaimer: I am the author of this package :)

Upvotes: 1

Related Questions