detective-amd

Find all dependencies within a JavaScript file using AMD module syntax

Detective-AMD

Returns a list of dependencies for a given JavaScript file or AST using any of the AMD module syntaxes.

Inspired by substack/node-detective but built for AMD

npm install detective-amd

Let's say we have the following file definitions:

 
// a.js 
define(['./b', './c'], function (bc) {
  console.log(b, c);
});
 
// b.js 
define({
  name: 'foo'
});
 
// c.js 
define(function () {
  return 'bar';
});
 

Here's how you can grab the list of dependencies of a.js synchronously.

var getDependencies = require('detective-amd');
 
var srca = fs.readFileSync('a.js', 'utf8');
var srcb = fs.readFileSync('b.js', 'utf8');
var srcc = fs.readFileSync('c.js', 'utf8');
 
// Pass in the source code or an AST (if you've already parsed the file) 
console.log(getDependencies(srca)); // prints ['./b', './c'] 
console.log(getDependencies(srcb)); // prints [] 
console.log(getDependencies(srcc)); // prints [] 
 

Supports the 4 forms of AMD module syntax:

  • "named": define('name', [deps], func)
  • "dependency list": define([deps], func)
  • "factory": define(func(require))
  • "no dependencies": define({})

Also supports "driver script" syntax: require([deps], func)

Also handles REM form: define(function(require, exports, module) {}).

Also handles dynamically loaded dependencies (ex: inner requires).

Supports driver scripts

You can also find the dependencies from a script that has a top-level require (an app initialization/driver/entry-point script):

require([
  './a'
], function (a) {
  // My app will get booted up from here 
});

Expression-based requires

If there's a require call that doesn't have a string literal but an expression, a string (escodegen-generated) representation will be returned.

For example, if a.js was of the "factory" form and contained a dynamic module name:

// a.js 
 
define(function (require) {
  // Assume str is some variable that gets set to a string dynamically 
  // var str = ... 
 
  var b = require('./' + str),
      c = require('./c');
 
  console.log(b, c);
});

The dependency list will be: [ '\'./\' + str', './c' ]

  • Even though that string representation isn't incredibly useful, it's still added to the list to represent/count that dependency