1

I am trying to get some of the NPM functionality into my Node.js programs. In particular, I would like to be able to analyze the available node modules on my system. "Module" here means "module identifier", thus either an identifier like "fd", or a file path; in other words, anything that can be put into a require() call and does load a module. This question is split into three sub-problems: 1) Get a list of all core modules 2) Get a list of all loaded modules 3) Get a list of all installed and available modules.

Question 1 is answered by zeke's node-core-module-names list. Loading another module to find the core modules list is not elegant and it may outdate itself, but it is an option and does work. The (ordered) list is thus ['assert', 'buffer', 'child_process', ..., 'zlib'].

The 2. question can be answered by a call of Object.keys(require.cache), which returns a list of file paths.

What I cannot elegantly solve by now is the 3. question. There is the shell command npm ls which returns a tree graph. But is there anything usable and better?

Thank's for listening! Tom

martin
  • 93,354
  • 25
  • 191
  • 226

2 Answers2

1

Here is something I have found tinkering around and I think this should be valid.

The V8 code has a standard set of bindings which you have seen in Node. They include but are not limited to:

  • fs
  • path
  • http
  • etc.

Also, there is a global variable by name of process. This exposes process level information and functionality, but also lets you get your hands on some V8 code through a function inside of the process variable called bindings.

The bindings(...) functions allows you to interface into exposed C++ libraries created by Node or you can create your own NodeJS modules by following the V8 developer guide (beyond the scope of this answer, read more here).

A funny little line I saw in the Node.cc file included a static check for checking for bindings for a keyword natives. This returns, it seems, a list of system level modules that you are looking for, and then some.

So that being said, I went into Node REPL and plugged in two lines (which I am sure can be shortened in a more elegant, expressive manner). Also note that I am pruning out anything starting with an underscore (_) so to preserve private functions or bindings:

var natives = process.binding('natives'); for (var key in natives) {if (key.indexOf('_') !== 0) {console.log(key);}}

Tom Pennetta
  • 482
  • 7
  • 25
  • This is implementation-dependent, which means that if chakra or gecko are behind it or if this undocumented behavior changes, this will not work. – fregante Mar 01 '16 at 15:23
  • Thank you, Tom! What you teach me there is new for me and definitely worth exploring. My problem is solved. Thank you very much! – user2527816 Mar 01 '16 at 16:54
  • Valid point regarding flavor of engine implementation. Glad it provided some insight into some native bindings. :) – Tom Pennetta Mar 03 '16 at 00:56
1

npm list has various output options/flags, including json and parseable (which outputs a list of paths)

Try this:

var exec = require('child_process').exec;
var cmd = 'npm ls --json';

exec(cmd, function(error, stdout, stderr) {
  var treeObject = JSON.parse(stdout);
});

The above requires no external packages but might need more code to work around the buffer limit: https://github.com/nodejs/node/issues/4236

Alternatively npm can also be used programmatically, perhaps through global-npm:

var npm = require('global-npm');
npm.load({}, function (err) {
  npm.commands.list(null, function(err, treeObject) {
    var firstLevelDependenciesArray = Object.keys(treeObject.dependencies);
  });
});
fregante
  • 29,050
  • 14
  • 119
  • 159
  • Thank you very much! I think I go with the `npm ls --parseable`, which solves my problem, and which I oversaw in my research. Thank's a lot, this was a great help! – user2527816 Mar 01 '16 at 16:51