docs: function ModuleGraph(moduleData) {
    var self = this;
    var modules = {};
    var moduleNameList = [];
    moduleData.forEach(function(info) {
      var m = new Module(info);
      modules[info.name] = m;
      moduleNameList.push(info.name);
    });
  
    /**
     * Get a list of all module names.
     * @return {Array.<string>} List of module names.
     */
    this.getAllModules = function() {
      return moduleNameList;
    };
  
    /**
     * Get transitive dependencies for a given module
     * @param {string} name Name of the module.
     * @return {Array.<string>} List of module names.
     */
    this.getTransitiveDependencies = function(name) {
      var m = getModule(name);
      return m.transitiveDeps || [];
    };
  
    function getModule(name) {
      var m = modules[name];
      if (!m) {
        throw new self.NotFoundException(name);
      }
      return m;
    }
  
    /**
     * Error object used when a requested module cannot be found.
     * @constructor
     */
    this.NotFoundException = function(name) {
      var msg = 'Unknown module: ' + name;
      this.name = name;
      this.message = msg;
      Error.call(this, msg);
    };
    this.NotFoundException.prototype = new Error();
    this.NotFoundException.prototype.statusCode = 404;
  
    /**
     * Gets the requested module names and their transitive deps minus the
     * transitive deps (and the) of the optional excluded names.
     * @param {Array.<string>} moduleNames List of module names.
     * @apram {Array.<string>} opt_excludeNames List of module names to exclude.
     * @return {Array.<string>} List of module names.
     */
    this.getModules = function(moduleNames, opt_excludeNames) {
      var list = [];
      var seen = {};
      var exclude = {};
  
      if (opt_excludeNames) {
        opt_excludeNames.forEach(function(name) {
          exclude[name] = true;
          var m = getModule(name);
          m.transitiveDeps.forEach(function(name) {
            exclude[name] = true;
          });
        });
      }
  
      function addModule(name) {
        if (!seen[name] && !exclude[name]) {
          seen[name] = true;
          list.push(name)
        }
      }
      moduleNames.forEach(function(name) {
        var m = getModule(name);
        m.transitiveDeps.forEach(addModule);
        addModule(m.name);
      });
      return list;
    };
  }