ionic
Version:
A tool for creating and developing Ionic Framework mobile apps.
147 lines (124 loc) • 4.34 kB
JavaScript
const util = require('util');
const path = require('path');
const EE = require('events').EventEmitter;
const extend = require('extend');
const resolve = require('resolve');
const findCwd = require('./lib/find_cwd');
const findConfig = require('./lib/find_config');
const fileSearch = require('./lib/file_search');
const parseOptions = require('./lib/parse_options');
const silentRequire = require('./lib/silent_require');
const buildConfigName = require('./lib/build_config_name');
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
var modulePath, modulePackage;
try {
modulePath = resolve.sync(this.moduleName, {basedir: configBase || cwd});
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
modulePackage = silentRequire(fileSearch('package.json', [configBase]));
if (modulePackage && modulePackage.name === this.moduleName) {
// if it does, our module path is `main` inside package.json
modulePath = path.join(configBase, modulePackage.main||'index.js');
cwd = configBase;
} else {
// clear if we just required a package for some other project
modulePackage = {};
}
}
// get extension of config name, taking anything after the -first- dot
var configExtension = /(\.[^\/]*)?$/.exec(configPath)[0];
// preload module needed for config if any has been specified.
var requireForExtension = this.extensions[configExtension];
if (requireForExtension) {
preload.push(requireForExtension);
}
// preload modules, if any
if (preload.length) {
// unique results first
preload.filter(function (value, index, self) {
return self.indexOf(value) === index;
}).forEach(function (dep) {
this.requireLocal(dep, findCwd(opts));
}, this);
}
return {
cwd: cwd,
require: preload,
configNameSearch: configNameSearch,
configPath: configPath,
configBase: configBase,
modulePath: modulePath,
modulePackage: modulePackage||{}
};
};
Liftoff.prototype.launch = 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);
}
fn.call(this, this.buildEnvironment(opts));
};
module.exports = Liftoff;