| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 | var util = require('util');var path = require('path');var EE = require('events').EventEmitter;var extend = require('extend');var resolve = require('resolve');var flaggedRespawn = require('flagged-respawn');var isPlainObject = require('is-plain-object');var mapValues = require('object.map');var fined = require('fined');var findCwd = require('./lib/find_cwd');var findConfig = require('./lib/find_config');var fileSearch = require('./lib/file_search');var parseOptions = require('./lib/parse_options');var silentRequire = require('./lib/silent_require');var buildConfigName = require('./lib/build_config_name');var registerLoader = require('./lib/register_loader');var getNodeFlags = require('./lib/get_node_flags');function Liftoff(opts) {  EE.call(this);  extend(this, parseOptions(opts));}util.inherits(Liftoff, EE);Liftoff.prototype.requireLocal = function(module, basedir) {  try {    var result = require(resolve.sync(module, { basedir: basedir }));    this.emit('require', module, result);    return result;  } catch (e) {    this.emit('requireFail', module, e);  }};Liftoff.prototype.buildEnvironment = function(opts) {  opts = opts || {};  // get modules we want to preload  var preload = opts.require || [];  // ensure items to preload is an array  if (!Array.isArray(preload)) {    preload = [preload];  }  // make a copy of search paths that can be mutated for this run  var searchPaths = this.searchPaths.slice();  // calculate current cwd  var cwd = findCwd(opts);  // if cwd was provided explicitly, only use it for searching config  if (opts.cwd) {    searchPaths = [cwd];  } else {    // otherwise just search in cwd first    searchPaths.unshift(cwd);  }  // calculate the regex to use for finding the config file  var configNameSearch = buildConfigName({    configName: this.configName,    extensions: Object.keys(this.extensions),  });  // calculate configPath  var configPath = findConfig({    configNameSearch: configNameSearch,    searchPaths: searchPaths,    configPath: opts.configPath,  });  // if we have a config path, save the directory it resides in.  var configBase;  if (configPath) {    configBase = path.dirname(configPath);    // if cwd wasn't provided explicitly, it should match configBase    if (!opts.cwd) {      cwd = configBase;    }  }  // TODO: break this out into lib/  // locate local module and package next to config or explicitly provided cwd  /* eslint one-var: 0 */  var modulePath, modulePackage;  try {    var delim = path.delimiter;    var paths = (process.env.NODE_PATH ? process.env.NODE_PATH.split(delim) : []);    modulePath = resolve.sync(this.moduleName, { basedir: configBase || cwd, paths: paths });    modulePackage = silentRequire(fileSearch('package.json', [modulePath]));  } catch (e) {}  // if we have a configuration but we failed to find a local module, maybe  // we are developing against ourselves?  if (!modulePath && configPath) {    // check the package.json sibling to our config to see if its `name`    // matches the module we're looking for    var modulePackagePath = fileSearch('package.json', [configBase]);    modulePackage = silentRequire(modulePackagePath);    if (modulePackage && modulePackage.name === this.moduleName) {      // if it does, our module path is `main` inside package.json      modulePath = path.join(path.dirname(modulePackagePath), modulePackage.main || 'index.js');      cwd = configBase;    } else {      // clear if we just required a package for some other project      modulePackage = {};    }  }  var exts = this.extensions;  var eventEmitter = this;  var configFiles = {};  if (isPlainObject(this.configFiles)) {    var notfound = { path: null };    configFiles = mapValues(this.configFiles, function(prop, name) {      var defaultObj = { name: name, cwd: cwd, extensions: exts };      return mapValues(prop, function(pathObj) {        var found = fined(pathObj, defaultObj) || notfound;        if (isPlainObject(found.extension)) {          registerLoader(eventEmitter, found.extension, found.path, cwd);        }        return found.path;      });    });  }  return {    cwd: cwd,    require: preload,    configNameSearch: configNameSearch,    configPath: configPath,    configBase: configBase,    modulePath: modulePath,    modulePackage: modulePackage || {},    configFiles: configFiles,  };};Liftoff.prototype.handleFlags = function(cb) {  if (typeof this.v8flags === 'function') {    this.v8flags(function(err, flags) {      if (err) {        cb(err);      } else {        cb(null, flags);      }    });  } else {    process.nextTick(function() {      cb(null, this.v8flags);    }.bind(this));  }};Liftoff.prototype.prepare = function(opts, fn) {  if (typeof fn !== 'function') {    throw new Error('You must provide a callback function.');  }  process.title = this.processTitle;  var completion = opts.completion;  if (completion && this.completions) {    return this.completions(completion);  }  var env = this.buildEnvironment(opts);  fn.call(this, env);};Liftoff.prototype.execute = function(env, forcedFlags, fn) {  if (typeof forcedFlags === 'function') {    fn = forcedFlags;    forcedFlags = undefined;  }  if (typeof fn !== 'function') {    throw new Error('You must provide a callback function.');  }  this.handleFlags(function(err, flags) {    if (err) {      throw err;    }    flags = flags || [];    flaggedRespawn(flags, process.argv, forcedFlags, execute.bind(this));    function execute(ready, child, argv) {      if (child !== process) {        var execArgv = getNodeFlags.fromReorderedArgv(argv);        this.emit('respawn', execArgv, child);      }      if (ready) {        preloadModules(this, env);        registerLoader(this, this.extensions, env.configPath, env.cwd);        fn.call(this, env, argv);      }    }  }.bind(this));};Liftoff.prototype.launch = function(opts, fn) {  if (typeof fn !== 'function') {    throw new Error('You must provide a callback function.');  }  var self = this;  self.prepare(opts, function(env) {    var forcedFlags = getNodeFlags.arrayOrFunction(opts.forcedFlags, env);    self.execute(env, forcedFlags, fn);  });};function preloadModules(inst, env) {  var basedir = env.cwd;  env.require.filter(toUnique).forEach(function(module) {    inst.requireLocal(module, basedir);  });}function toUnique(elem, index, array) {  return array.indexOf(elem) === index;}module.exports = Liftoff;
 |