base-generators
Advanced tools
Comparing version 0.1.19 to 0.2.0
802
index.js
@@ -12,12 +12,7 @@ /*! | ||
var async = require('async'); | ||
var util = require('generator-util'); | ||
var debug = require('debug')('base:generators'); | ||
var FragmentCache = require('./lib/fragment'); | ||
var plugins = require('./lib/plugins'); | ||
var search = require('./lib/search'); | ||
var debug = require('debug')('base:base-generators'); | ||
var createApp = require('./lib/app'); | ||
var tasks = require('./lib/tasks'); | ||
var cache = require('./lib/cache'); | ||
var utils = require('./lib/utils'); | ||
var env = require('./lib/env'); | ||
var answers = {}; | ||
var num = 0; | ||
@@ -28,93 +23,36 @@ /** | ||
module.exports = function generators(config) { | ||
module.exports = function(config) { | ||
config = config || {}; | ||
return function plugin(app) { | ||
if (this.isRegistered('base-generators')) return; | ||
if (!isValidInstance(this)) return; | ||
var cache = {}; | ||
this.fragment = new FragmentCache(); | ||
this.generators = this.generators || {}; | ||
/** | ||
* Add plugins necessary for running generators. | ||
* Plugins will only be registered once. | ||
*/ | ||
this.define('initGenerators', function() { | ||
this.options = utils.extend({}, this.options, config); | ||
if (!this.isGenerator) { | ||
this.isGenerator = true; | ||
this.define('firstGen', null); | ||
this.generators = {}; | ||
if (!this.task) this.use(plugins.task(this.options)); | ||
this.use(plugins.resolver('apps')); | ||
this.use(plugins.plugin(this.options)); | ||
this.use(plugins.cwd(this.options)); | ||
this.options.validatePlugin = function(app) { | ||
return app.isGenerator === true; | ||
}; | ||
this.use(tasks(this.options)); | ||
this.use(cache(this.options)); | ||
this.use(env(this.options)); | ||
// plugins | ||
this.use(utils.option()); | ||
this.use(utils.plugins()); | ||
this.use(utils.cwd()); | ||
this.use(utils.pkg()); | ||
this.use(utils.task()); | ||
this.use(utils.env()); | ||
this.apps.resolve('generate-*/{generator,index}.js'); | ||
this.apps.resolve('verb-*-generator/{generator,index}.js'); | ||
this.apps.resolve('./verbfile.js', {cwd: this.cwd}); | ||
}); | ||
// ensure this plugin is registered on generators | ||
this.fns.push(plugin); | ||
this.use(tasks()); | ||
this.num = num++; | ||
this.define('constructor', this.constructor); | ||
} | ||
/** | ||
* Attempts to find a generator with the given `name` and `options`. | ||
* Alias to `.setGenerator`. | ||
* | ||
* ```js | ||
* // resolve by generator "alias" | ||
* app.resolve('foo'); | ||
* | ||
* // resolve by generator name | ||
* app.resolve('generate-foo'); | ||
* | ||
* // resolve by filepath | ||
* app.resolve('./a/b/c/'); | ||
* ``` | ||
* @name .resolve | ||
* @param {String} `name` Can be a module name or filepath to a module that is locally or globally installed. | ||
* @param {Object} `options` | ||
* @return {Object} Returns the filepath to the generator, if found. | ||
* @api public | ||
*/ | ||
this.define('resolve', function(name, options) { | ||
var opts = util.extend({}, this.options, options); | ||
if (utils.isAbsolute(name)) { | ||
return this.resolveConfigpath(name, opts); | ||
} | ||
var generator = this.apps.get(name); | ||
if (generator) { | ||
return generator.path; | ||
} | ||
if (opts.cwd) { | ||
return this.resolveConfigpath(path.resolve(opts.cwd, name), opts); | ||
} | ||
}); | ||
/** | ||
* Register configfile with the given `name` and `options`. | ||
* | ||
* @param {String} `name` | ||
* @param {String} `configfile` | ||
* @param {Object} `options` | ||
* @return {object} | ||
* @api public | ||
*/ | ||
this.define('registerConfig', function(name, configfile, options) { | ||
var opts = util.extend({ cwd: this.cwd }, options); | ||
debug('registering configfile "%s", at cwd: "%s"', name, opts.cwd); | ||
this.createEnv('default', configfile, opts); | ||
var fn = util.configfile(configfile, opts); | ||
return this.register(name, fn); | ||
}); | ||
/** | ||
* Register generator `name` with the given `fn`. | ||
* | ||
* ```js | ||
* base.register('foo', function(app, base) { | ||
@@ -126,4 +64,5 @@ * // "app" is a private instance created for the generator | ||
* @name .register | ||
* @param {String} `name` | ||
* @param {Function} `fn` Generator function or instance | ||
* @param {String} `name` The generator's name | ||
* @param {Object|Function|String} `options` or generator | ||
* @param {Object|Function|String} `generator` Generator function, instance or filepath. | ||
* @return {Object} Returns the generator instance. | ||
@@ -133,23 +72,18 @@ * @api public | ||
this.define('register', function(name, fn, options) { | ||
var gen = this.generators.set(name, fn, this, options); | ||
var path = gen.env.path; | ||
if (path && this.apps.files.indexOf(path) === -1) { | ||
this.apps.files.push(path); | ||
} | ||
this.fragment.set('name', name, gen); | ||
return gen; | ||
this.define('register', function(name, options, generator) { | ||
return this.setGenerator.apply(this, arguments); | ||
}); | ||
/** | ||
* Register generator `name` with the given `fn`, or get generator `name` | ||
* if only one argument is passed. This method calls the `.getGenerator` method | ||
* but goes one step further: if `name` is not already registered, it will try | ||
* to resolve and register the generator before returning it (or `undefined` | ||
* if unsuccessful). | ||
* Get and invoke generator `name`, or register generator `name` with | ||
* the given `val` and `options`, then invoke and return the generator | ||
* instance. This method differs from `.register`, which lazily invokes | ||
* generator functions when `.generate` is called. | ||
* | ||
* ```js | ||
* base.generator('foo', function(app, base) { | ||
* // "app" is a private instance created for the generator | ||
* // "base" is a shared instance | ||
* base.generator('foo', function(app, base, env, options) { | ||
* // "app" - private instance created for generator "foo" | ||
* // "base" - instance shared by all generators | ||
* // "env" - environment object for the generator | ||
* // "options" - options passed to the generator | ||
* }); | ||
@@ -159,3 +93,3 @@ * ``` | ||
* @param {String} `name` | ||
* @param {Function|Object} `fn` Generator function or instance. When `fn` is defined, this method is just a proxy for the `.register` method. | ||
* @param {Function|Object} `fn` Generator function, instance or filepath. | ||
* @return {Object} Returns the generator instance or undefined if not resolved. | ||
@@ -165,8 +99,11 @@ * @api public | ||
this.define('generator', function(name, fn, options) { | ||
this.define('generator', function(name, val, options) { | ||
if (arguments.length === 1 && typeof name === 'string') { | ||
var generator = this.getGenerator(name); | ||
if (generator) return generator; | ||
if (generator) { | ||
return generator; | ||
} | ||
} | ||
this.register(name, fn, options); | ||
this.setGenerator(name, val, options); | ||
return this.getGenerator(name); | ||
@@ -176,30 +113,49 @@ }); | ||
/** | ||
* Return true if the given `name` exists on the `generators` | ||
* object. Dot-notation may be used to check for sub-generators. | ||
* Store a generator by file path or instance with the given | ||
* `name` and `options`. | ||
* | ||
* ```js | ||
* base.register('foo', function(app) { | ||
* app.register('bar', function() {}); | ||
* base.setGenerator('foo', function(app, base) { | ||
* // "app" - private instance created for generator "foo" | ||
* // "base" - instance shared by all generators | ||
* // "env" - environment object for the generator | ||
* // "options" - options passed to the generator | ||
* }); | ||
* | ||
* base.hasGenerator('foo'); | ||
* //=> true | ||
* base.hasGenerator('bar'); | ||
* //=> false | ||
* base.hasGenerator('foo.bar'); | ||
* //=> true | ||
* ``` | ||
* | ||
* @name .hasGenerator | ||
* @param {String} `name` | ||
* @return {Boolean} Returns true if the generator exists. | ||
* @name .setGenerator | ||
* @param {String} `name` The generator's name | ||
* @param {Object|Function|String} `options` or generator | ||
* @param {Object|Function|String} `generator` Generator function, instance or filepath. | ||
* @return {Object} Returns the generator instance. | ||
* @api public | ||
*/ | ||
this.define('hasGenerator', function(name) { | ||
var objectPath = util.toGeneratorPath(name); | ||
if (this.has(objectPath)) { | ||
return objectPath; | ||
this.define('setGenerator', function(name, val, options) { | ||
debug('setting generator "%s"', name); | ||
// ensure local sub-generator paths are resolved | ||
if (typeof val === 'string' && val.charAt(0) === '.' && this.env) { | ||
val = path.resolve(this.env.dirname, val); | ||
} | ||
return false; | ||
var Generator = this.constructor; | ||
var generator = new Generator(); | ||
createApp.setParent(generator, this); | ||
createApp.decorate(generator, generator); | ||
generator.createEnv(name, val, options, this); | ||
if (utils.isGenerator(generator.env.app)) { | ||
var app = generator.env.app; | ||
createApp.setParent(app, generator); | ||
createApp.decorate(app, generator); | ||
generator = app; | ||
} | ||
// cache the generator | ||
this.generators[generator.alias] = generator; | ||
this.generators[generator.name] = generator; | ||
this.emit('generator', generator.alias, generator); | ||
return generator; | ||
}); | ||
@@ -225,71 +181,75 @@ | ||
debug('getting generator "%s"', name); | ||
var opts = utils.merge({}, this.options, options); | ||
var app = this.findGenerator(name, opts); | ||
if (app) { | ||
if (app.isInvoked) { | ||
return app; | ||
} | ||
app.isInvoked = true; | ||
app.option(opts); | ||
this.run(app); | ||
app.invoke(opts); | ||
this.generators[name] = app; | ||
return app; | ||
} | ||
}); | ||
options = options || {}; | ||
var aliasFn = (options.toAlias || this.toAlias).bind(this); | ||
/** | ||
* Find generator `name`, by first searching the cache, | ||
* then searching the cache of the `base` generator. | ||
* | ||
* ```js | ||
* // search by "alias" | ||
* var foo = app.findGenerator('foo'); | ||
* | ||
* // search by "full name" | ||
* var foo = app.findGenerator('generate-foo'); | ||
* ``` | ||
* @name .findGenerator | ||
* @param {String} `name` | ||
* @param {Function} `options` Optionally supply a rename function on `options.toAlias` | ||
* @return {Object|undefined} Returns the generator instance if found, or undefined. | ||
* @api public | ||
*/ | ||
var fullname = this.toFullname(name); | ||
var alias = aliasFn(name); | ||
var self = this; | ||
var app = this; | ||
function get(key) { | ||
return self.generators.get(key) || self.base.generators.get(key); | ||
this.define('findGenerator', function(name, opts) { | ||
debug('finding generator "%s"', name); | ||
if (typeof name !== 'string') { | ||
return name; | ||
} | ||
function match(key) { | ||
return name === key || fullname === key || alias === key; | ||
if (cache[name]) return cache[name]; | ||
var app = this._findGenerator(name, opts); | ||
// if no app, check the `base` instance | ||
if (typeof app === 'undefined' && this.parent) { | ||
app = this.base._findGenerator(name, opts); | ||
} | ||
function cacheApp(app) { | ||
if (self && self.env) { | ||
self.fragment.set('name', name, self); | ||
} | ||
// if no app, check `node_modules` or the file system | ||
if (!app && utils.exists(name)) { | ||
app = this.register(name, opts); | ||
} | ||
var isSubgenerator = name.indexOf('.') !== -1; | ||
if (!isSubgenerator) { | ||
app = get(name) || get(alias) || get(fullname); | ||
if (typeof app === 'undefined') { | ||
app = this.apps.alias(name) | ||
|| this.apps.name(name) | ||
|| this.apps.alias(fullname) | ||
|| this.apps.name(fullname) | ||
|| this.apps.alias(alias) | ||
|| this.apps.name(alias) | ||
} | ||
} else { | ||
app = this.getSubGenerator(name, aliasFn); | ||
if (app) { | ||
cache[name] = app; | ||
return app; | ||
} | ||
}); | ||
if (app && app.path && !app.env) { | ||
this.register(name, app.path); | ||
app = this.generators[name]; | ||
this.invoke(app); | ||
} | ||
/** | ||
* Private method used by `.findGenerator` | ||
*/ | ||
cacheApp(app); | ||
if (app) return app; | ||
for (var key in this.generators) { | ||
if (match(key) || match(aliasFn(key)) || match(this.toFullname(key))) { | ||
app = this.getGenerator(key); | ||
break; | ||
} | ||
this.define('_findGenerator', function(name, options) { | ||
if (~name.indexOf('.')) { | ||
return this.getSubGenerator.apply(this, arguments); | ||
} | ||
cacheApp(app); | ||
if (app) return app; | ||
options = options || {}; | ||
var opts = utils.merge({}, this.options, options); | ||
for (var key in this.base.generators) { | ||
if (match(key) || match(aliasFn(key)) || match(this.toFullname(key))) { | ||
app = this.base.getGenerator(key); | ||
break; | ||
} | ||
if (typeof opts.lookup === 'function') { | ||
return this.lookupGenerator(name, opts, opts.lookup); | ||
} else { | ||
return this.generators[name] || this.matchGenerator(name); | ||
} | ||
cacheApp(app); | ||
if (app) return app; | ||
}); | ||
@@ -305,3 +265,3 @@ | ||
* @param {String} `name` The property-path of the generator to get | ||
* @param {Function} `aliasFn` | ||
* @param {Object} `options` | ||
* @api public | ||
@@ -311,14 +271,11 @@ */ | ||
this.define('getSubGenerator', function(name, options) { | ||
if (!~name.indexOf('.')) { | ||
return this.getGenerator.apply(this, arguments); | ||
} | ||
var props = name.split('.'); | ||
var len = props.length; | ||
debug('getting sub-generator "%s"', name); | ||
var segs = name.split('.'); | ||
var len = segs.length; | ||
var idx = -1; | ||
app = this; | ||
var app = this; | ||
while (++idx < len) { | ||
var key = props[idx]; | ||
app = app.findGenerator(key, options); | ||
var key = segs[idx]; | ||
app = app.getGenerator(key, options); | ||
if (!app) { | ||
@@ -328,118 +285,78 @@ break; | ||
} | ||
if (app && app.env) { | ||
this.fragment.set('name', name, app); | ||
return app; | ||
} | ||
return app; | ||
}); | ||
/** | ||
* Find generator `name`, by first searching the cache, | ||
* then searching the cache of the `base` generator, | ||
* and last searching for a globally installed generator. | ||
* Iterate over `app.generators` and call `generator.isMatch(name)` | ||
* on `name` until a match is found. | ||
* | ||
* @name .findGenerator | ||
* @param {String} `name` | ||
* @param {Function} `options` Optionally supply a rename function on `options.toAlias` | ||
* @return {Object|undefined} Returns the generator instance if found, or undefined. | ||
* @return {Object|undefined} Returns a generator object if a match is found. | ||
* @api public | ||
*/ | ||
this.define('findGenerator', function(name, options) { | ||
debug('finding generator "%s"', name); | ||
// if sub-generator, look for it on the first resolved generator | ||
if (this.firstGen && this.firstGen.generators[name]) { | ||
var sub = this.firstGen.getGenerator(name, options); | ||
if (sub) { | ||
return sub; | ||
this.define('matchGenerator', function(name) { | ||
debug('matching generator "%s"', name); | ||
for (var prop in this.generators) { | ||
var app = this.generators[prop]; | ||
if (app.isMatch(name)) { | ||
return app; | ||
} | ||
} | ||
// search for generator on the instance cache, then if not found | ||
// search for the generator on the base instance's cache | ||
var generator = this.generators.get(name, options) | ||
|| this.base.generators.get(name, options); | ||
// try searching in local and global node_modules | ||
if (!generator) { | ||
var fp = this.resolve(name); | ||
if (fp) { | ||
generator = this.generator(name, fp); | ||
} | ||
} | ||
if (!generator && name.indexOf(this.prefix) === -1) { | ||
var fullname = this.toFullname(name); | ||
if (name !== fullname) { | ||
generator = this.findGenerator(fullname, options); | ||
} | ||
} | ||
// if resolved, cache it | ||
if (generator) { | ||
if (!this.firstGen) this.firstGen = generator; | ||
return generator; | ||
} | ||
}); | ||
/** | ||
* Search for globally installed generator `name`. If found, then generator | ||
* is registered and returned, otherwise `undefined` is returned. | ||
* Tries to find a registered generator that matches `name` | ||
* by iterating over the `generators` object, and doing a strict | ||
* comparison of each name returned by the given lookup `fn`. | ||
* The lookup function receives `name` and must return an array | ||
* of names to use for the lookup. | ||
* | ||
* @name .globalGenerator | ||
* @param {String} `name` | ||
* @return {Object|undefined} | ||
* For example, if the lookup `name` is `foo`, the function might | ||
* return `["generator-foo", "foo"]`, to ensure that the lookup happens | ||
* in that order. | ||
* | ||
* @param {String} `name` Generator name to search for | ||
* @param {Object} `options` | ||
* @param {Function} `fn` Lookup function that must return an array of names. | ||
* @return {Object} | ||
* @api public | ||
*/ | ||
this.define('globalGenerator', function(name) { | ||
debug('getting global generator "%s"', name); | ||
this.define('lookupGenerator', function(name, options, fn) { | ||
if (typeof options === 'function') { | ||
fn = options; | ||
options = {}; | ||
} | ||
var filepath = this.resolve(name, {cwd: util.gm}); | ||
if (this.isGeneratorPath(filepath, this.prefix)) { | ||
var generator = this.getGenerator(name); | ||
if (generator) { | ||
return generator; | ||
} | ||
if (typeof fn !== 'function') { | ||
throw new TypeError('expected `fn` to be a lookup function'); | ||
} | ||
return util.tryResolve(name, { | ||
configfile: this.configfile | ||
}); | ||
}); | ||
/** | ||
* Invoke the given generator in the context of (`this`) the current | ||
* instance. | ||
* | ||
* ```js | ||
* base.invoke('foo'); | ||
* ``` | ||
* @name .invoke | ||
* @param {String|Object} `app` Generator name or instance. | ||
* @return {Object} Returns the instance for chaining. | ||
* @api public | ||
*/ | ||
options = options || {}; | ||
this.define('invoke', function(app) { | ||
if (Array.isArray(app)) { | ||
return app.forEach(this.invoke.bind(this)); | ||
} | ||
// remove `lookup` fn from options to prevent self-recursion | ||
delete this.options.lookup; | ||
delete options.lookup; | ||
var orig = app; | ||
if (typeof app === 'string') { | ||
app = this.generator(app); | ||
} | ||
var names = fn(name); | ||
debug('looking up generator "%s" with "%j"', name, names); | ||
if (typeof app === 'undefined') { | ||
throw new Error('cannot find generator "' + orig + '"'); | ||
var len = names.length; | ||
var idx = -1; | ||
while (++idx < len) { | ||
var gen = this.findGenerator(names[idx], options); | ||
if (gen) { | ||
this.options.lookup = fn; | ||
return gen; | ||
} | ||
} | ||
debug('invoking generator "%s"', app.namespace); | ||
return utils.invoke(app, this); | ||
this.options.lookup = fn; | ||
}); | ||
/** | ||
* Alias for `.invoke`, Extend the current generator instance with the settings of other | ||
* generators. | ||
* Extend the generator instance with settings and features | ||
* of another generator. | ||
* | ||
@@ -453,2 +370,4 @@ * ```js | ||
* base.extendWith(['foo', 'bar', 'baz']); | ||
* | ||
* app.extendWith(require('generate-defaults')); | ||
* ``` | ||
@@ -462,4 +381,26 @@ * | ||
this.define('extendWith', function(app) { | ||
this.invoke(app); | ||
this.define('extendWith', function(name, options) { | ||
if (typeof name === 'function') { | ||
this.use(name, options); | ||
return this; | ||
} | ||
if (Array.isArray(name)) { | ||
var len = name.length; | ||
var idx = -1; | ||
while (++idx < len) { | ||
this.extendWith(name[idx], options); | ||
} | ||
return this; | ||
} | ||
debug('extending "%s" with "%s"', this.env.alias, name); | ||
var app = this.findGenerator(name, options); | ||
if (!utils.isApp(app, 'Generator')) { | ||
throw new Error('cannot find generator ' + name); | ||
} | ||
app.run(this); | ||
app.invoke(options, this); | ||
return this; | ||
@@ -502,9 +443,3 @@ }); | ||
this.define('generate', function(name, tasks, cb) { | ||
if (typeof name === 'function') { | ||
cb = name; | ||
name = 'default'; | ||
tasks = ['default']; | ||
} | ||
if (Array.isArray(name)) { | ||
if (Array.isArray(name) && typeof tasks === 'function') { | ||
return this.generateEach(name, tasks); | ||
@@ -516,46 +451,54 @@ } | ||
if (typeof cb === 'function' && cb.name === 'finishRun') { | ||
if (typeof name === 'string' && !/\W/.test(name)) { | ||
var app = this.getGenerator(name); | ||
tasks = Array.isArray(tasks) ? tasks : ['default']; | ||
if (tasks[0] === 'default' && !app.hasTask('default')) { | ||
tasks = ['noop']; | ||
app.task('noop', function(next) { | ||
debug('running noop task'); | ||
delete app.tasks.noop; | ||
next(); | ||
}); | ||
} | ||
return app.build(tasks, build); | ||
if (typeof cb !== 'function') { | ||
throw new TypeError('expected a callback function'); | ||
} | ||
var resolved = this.resolveTasks.apply(this, args); | ||
if (cb.name === 'finishRun' && resolved.tasks.indexOf(name) !== -1) { | ||
var app = this.getGenerator(name); | ||
if (app) { | ||
return app.build('default', cb); | ||
} | ||
} | ||
var res = this.resolveTasks.apply(this, args); | ||
if (res.tasks === null) { | ||
debug('no default tasks defined'); | ||
return this.processTasks(name, resolved, cb); | ||
}); | ||
/** | ||
* Run generator or task `name` | ||
*/ | ||
this.define('processTasks', function(name, resolved, cb) { | ||
var generator = resolved.generator; | ||
var tasks = resolved.tasks; | ||
if (!tasks) { | ||
this.emit('error', new Error('no default task defined')); | ||
return cb(); | ||
} | ||
if (res.generator && res.generator.env) { | ||
debug('generating: "%s"', res.tasks.join(', ')); | ||
this.emit('generate', res.generator.env.alias, res.tasks); | ||
if (!generator) { | ||
this.emit('error', new Error(name + ' generator is not registered')); | ||
return cb(); | ||
} | ||
var config = this.base.cache.config || {}; | ||
var gen = res.generator; | ||
debug('generating: "%s"', tasks.join(', ')); | ||
this.emit('generate', generator.alias, tasks, generator); | ||
var config = this.get('cache.config') || {}; | ||
var self = this; | ||
if (typeof gen.config === 'undefined') { | ||
gen.build(res.tasks, build); | ||
if (typeof generator.config !== 'undefined' && !config.isNormalized) { | ||
generator.config.process(config, function(err, config) { | ||
if (err) return cb(err); | ||
self.set('cache.config', config); | ||
generator.build(tasks, build); | ||
}); | ||
return; | ||
} | ||
gen.config.process(config, function(err) { | ||
if (err) return cb(err); | ||
gen.build(res.tasks, build); | ||
}); | ||
generator.build(tasks, build); | ||
function build(err) { | ||
if (err) { | ||
generatorError(err, self, name, cb); | ||
utils.generatorError(err, self, name, cb); | ||
} else { | ||
@@ -585,26 +528,27 @@ cb(); | ||
this.define('generateEach', function(tasks, cb) { | ||
if (Array.isArray(tasks) && tasks.length === 0) { | ||
if (typeof tasks === 'function') { | ||
cb = tasks; | ||
tasks = ['default']; | ||
} | ||
if (typeof tasks === 'function') { | ||
return this.generateEach('default', tasks); | ||
if (typeof tasks === 'string') { | ||
tasks = [tasks]; | ||
} | ||
async.eachSeries(util.arrayify(tasks), function(task, next) { | ||
var args = task.split(':').concat(next); | ||
this.generate.apply(this, args); | ||
}.bind(this), cb); | ||
}); | ||
var len = tasks.length; | ||
var idx = -1; | ||
var arr = []; | ||
var app = this; | ||
while (++idx < len) { | ||
var val = tasks[idx]; | ||
arr.push({name: val, resolved: app.resolveTasks(val)}); | ||
if (this._lookup) { | ||
this.options.lookup = this._lookup; | ||
} | ||
} | ||
/** | ||
* Returns true if the given | ||
*/ | ||
this.define('isGeneratorPath', function(filepath) { | ||
if (typeof filepath !== 'string') { | ||
return false; | ||
} | ||
var basename = path.basename(path.dirname(filepath)); | ||
return basename.indexOf(this.prefix) !== -1; | ||
async.eachSeries(arr, function(obj, next) { | ||
app.processTasks(obj.name, obj.resolved, next); | ||
}, cb); | ||
}); | ||
@@ -623,180 +567,26 @@ | ||
this.define('toAlias', function(name, options) { | ||
var opts = util.extend({}, config, this.options, options); | ||
opts.prefix = opts.prefix || opts.modulename || this.prefix; | ||
var alias = util.toAlias(name, opts); | ||
debug('created alias "%s" for string "%s"', alias, name); | ||
return alias; | ||
}); | ||
/** | ||
* Create a generator's full name from the given `alias`. | ||
* | ||
* @name .fullname | ||
* @param {String} `alias` | ||
* @param {Object} `options` | ||
* @return {String} Returns the full name. | ||
* @api public | ||
*/ | ||
this.define('toFullname', function(alias, options) { | ||
var opts = util.extend({prefix: this.prefix}, config, this.options, options); | ||
var fullname = util.toFullname(alias, opts); | ||
debug('created fullname "%s" for alias "%s"', fullname, alias); | ||
return fullname; | ||
}); | ||
/** | ||
* Return the absolute filepath to a generator's main file. | ||
* | ||
* @name .resolveConfigpath | ||
* @param {String} `alias` | ||
* @param {Object} `options` | ||
* @return {String} Returns the full name. | ||
* @api public | ||
*/ | ||
this.define('resolveConfigpath', function(filepath, options) { | ||
var opts = util.extend({}, config, this.options, options); | ||
var file = this.apps.createEnv(filepath, opts); | ||
if (file) { | ||
this.fragment.set('name', file.name, file); | ||
debug('created configpath "%s" for generator "%s"', file.main, file.name); | ||
return file.main; | ||
if (typeof options === 'function') { | ||
return options(name); | ||
} | ||
}); | ||
/** | ||
* Getter/setter for defining the `configname` name to use for lookups. | ||
* By default `configname` is set to `generator.js`. | ||
* | ||
* @name .configname | ||
* @api public | ||
*/ | ||
Object.defineProperty(app, 'configname', { | ||
configurable: true, | ||
set: function(configname) { | ||
this.options.configname = configname; | ||
this.options.configfile = configname + '.js'; | ||
}, | ||
get: function() { | ||
if (this.options.configname) { | ||
return this.options.configname; | ||
} | ||
return (this.options.configname = utils.basename(this.configfile)); | ||
if (options && typeof options.toAlias === 'function') { | ||
return options.toAlias(name); | ||
} | ||
}); | ||
/** | ||
* Getter/setter for defining the `configfile` name to use for lookups. | ||
* By default `configfile` is set to `generator.js`. | ||
* | ||
* @name .configfile | ||
* @api public | ||
*/ | ||
Object.defineProperty(app, 'configfile', { | ||
configurable: true, | ||
set: function(configfile) { | ||
this.options.configfile = configfile; | ||
}, | ||
get: function() { | ||
return this.options.configfile || 'generator.js'; | ||
if (this && this.options && typeof this.options.toAlias === 'function') { | ||
return this.options.toAlias(name); | ||
} | ||
return name; | ||
}); | ||
/** | ||
* Getter/setter for defining the `configpath` name to use for lookups. | ||
* By default `configpath` is set to `generator.js`. | ||
* | ||
* @name .configpath | ||
* @api public | ||
*/ | ||
Object.defineProperty(app, 'configpath', { | ||
configurable: true, | ||
set: function(configpath) { | ||
this.options.configpath = path.resolve(configpath); | ||
}, | ||
get: function() { | ||
return this.options.configpath || path.resolve(this.cwd, this.configfile); | ||
} | ||
}); | ||
/** | ||
* Getter/setter for defining the `modulename` name to use for lookups. | ||
* By default `modulename` is set to `generate`. | ||
* | ||
* @name .modulename | ||
* @api public | ||
*/ | ||
Object.defineProperty(app, 'prefix', { | ||
configurable: true, | ||
set: function(prefix) { | ||
this.options.prefix = prefix; | ||
}, | ||
get: function() { | ||
return this.options.prefix || 'generate'; | ||
} | ||
}); | ||
/** | ||
* Getter/setter for the `base` (or shared) instance of `generate`. | ||
* | ||
* When a generator is registered, the current instance (`this`) is | ||
* passed as the "parent" instance to the generator. The `base` getter | ||
* ensures that the `base` instance is always the firstGen instance_. | ||
* | ||
* ```js | ||
* app.register('foo', function(app, base) { | ||
* // "app" is a private instance created for "foo" | ||
* // "base" is a shared instance, also accessible using `app.base` | ||
* }); | ||
* ``` | ||
* @name .base | ||
* @api public | ||
*/ | ||
Object.defineProperty(app, 'base', { | ||
configurable: true, | ||
get: function() { | ||
return this.parent ? this.parent.base : this; | ||
} | ||
}); | ||
// initialize base-generators | ||
this.initGenerators(); | ||
return plugin; | ||
}; | ||
}; | ||
/** | ||
* Handle generator errors | ||
*/ | ||
function generatorError(err, app, name, cb) { | ||
var match = /task "(.*?)" is not registered/.exec(err.message); | ||
if (!match) return cb(err); | ||
var taskName = match[1]; | ||
if (~name.indexOf(':')) { | ||
var segs = name.split(':'); | ||
taskName = segs[1]; | ||
name = segs[0]; | ||
function isValidInstance(app) { | ||
if (!app.isApp && !app.isGenerator) { | ||
return false; | ||
} | ||
var msg = 'Cannot find '; | ||
if (app.hasGenerator(name) && name !== taskName) { | ||
msg += 'task: "' + taskName + '" in generator'; | ||
} else if (app.hasGenerator(name) || app.hasConfigfile) { | ||
msg += 'task'; | ||
} else { | ||
msg += 'generator'; | ||
if (app.isRegistered('base-generators')) { | ||
return false; | ||
} | ||
msg += ': "' + name + '"'; | ||
var cwd = app.get('options.cwd'); | ||
if (cwd) msg += ' in "' + cwd + '/' + app.configfile + '"'; | ||
return cb(new Error(msg)); | ||
return true; | ||
} |
'use strict'; | ||
var debug = require('debug')('base:generators:tasks'); | ||
var utils = require('generator-util'); | ||
var utils = require('./utils'); | ||
@@ -18,14 +18,14 @@ module.exports = function(options) { | ||
this.mixin('resolveTasks', function(names, tasks) { | ||
this.define('resolveTasks', function(names, tasks) { | ||
var prop = this.stringifyTasks(names, tasks); | ||
var segs = prop.split(':'); | ||
var len = segs.length; | ||
var def = this.getGenerator('default'); | ||
var gen = this; | ||
debug('normalizing task args: "%s"', prop); | ||
var res = {}; | ||
res.generator = this; | ||
res.generator = gen; | ||
res.tasks = (segs[1] || segs[0]).split(','); | ||
var len = segs.length; | ||
var gen = this; | ||
var isDefault = res.tasks.length === 1 && res.tasks[0] === 'default'; | ||
@@ -45,17 +45,40 @@ function ensureDefault(res) { | ||
var fallback = gen.getGenerator('default'); | ||
if (fallback) { | ||
gen = fallback; | ||
} | ||
if (len > 1) { | ||
debug('default tasks "%s"', prop); | ||
if (def) { | ||
res.generator = def.getGenerator(segs[0]); | ||
if (res.generator) { | ||
if (isDefault) { | ||
ensureDefault(res); | ||
} | ||
return res; | ||
} | ||
} | ||
res.generator = gen.getGenerator(segs[0]); | ||
if (isDefault) { | ||
if (res.generator) { | ||
if (isDefault) { | ||
ensureDefault(res); | ||
} | ||
return res; | ||
} | ||
} | ||
if (def) { | ||
debug('default generator tasks "%s"', prop); | ||
if (def.hasTask(res.tasks[0])) { | ||
res.generator = def; | ||
return res; | ||
} | ||
res.generator = def.getGenerator(segs[0]); | ||
if (res.generator) { | ||
res.tasks = ['default']; | ||
ensureDefault(res); | ||
return res; | ||
} | ||
return res; | ||
} | ||
if (gen.hasTask(res.tasks[0])) { | ||
if (gen.hasTask(res.tasks[0]) && res.generator) { | ||
debug('tasks 1 "%s"', prop); | ||
res.generator = gen; | ||
@@ -67,2 +90,3 @@ return res; | ||
if (res.generator) { | ||
debug('tasks 2 "%s"', prop); | ||
res.tasks = ['default']; | ||
@@ -89,3 +113,3 @@ ensureDefault(res); | ||
this.mixin('hasTask', function(name) { | ||
this.define('hasTask', function(name) { | ||
return this.has(['tasks', name]); | ||
@@ -103,3 +127,3 @@ }); | ||
this.mixin('stringifyTasks', function(names, tasks) { | ||
this.define('stringifyTasks', function(names, tasks) { | ||
debug('stringifying tasks "%j"', arguments); | ||
@@ -106,0 +130,0 @@ if (typeof tasks === 'function') { |
143
lib/utils.js
'use strict'; | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var debug = require('debug')('base:generators:utils'); | ||
var utils = require('lazy-cache')(require); | ||
var fn = require; | ||
require = utils; // eslint-disable-line | ||
var existsCache = {}; | ||
@@ -13,87 +14,109 @@ /** | ||
require('ansi-bold', 'bold'); | ||
require('ansi-yellow', 'yellow'); | ||
require('ansi-magenta', 'magenta'); | ||
require('arr-union', 'union'); | ||
require('array-unique', 'unique'); | ||
require('base-cwd', 'cwd'); | ||
require('base-env', 'env'); | ||
require('base-option', 'option'); | ||
require('base-pkg', 'pkg'); | ||
require('base-plugins', 'plugins'); | ||
require('base-task', 'task'); | ||
require('define-property', 'define'); | ||
require('extend-shallow', 'extend'); | ||
require('get-value', 'get'); | ||
require('is-absolute'); | ||
require('global-modules', 'gm'); | ||
require('kind-of', 'typeOf'); | ||
require('mixin-deep', 'merge'); | ||
require('resolve'); | ||
require('vinyl', 'Vinyl'); | ||
require = fn; // eslint-disable-line | ||
utils.validate = function(file, opts) { | ||
if (!/^generate-/.test(file.name)) { | ||
return false; | ||
} | ||
var keys = file.pkg.keywords || []; | ||
return ~keys.indexOf('generator'); | ||
/** | ||
* Cast `val` to an array | ||
*/ | ||
utils.arrayify = function(val) { | ||
return val ? (Array.isArray(val) ? val : [val]) : []; | ||
}; | ||
/** | ||
* Invoke the generator `fn` on `app` in the given `context` | ||
* Returns true if `val` is an object | ||
*/ | ||
utils.invoke = function(app, context) { | ||
if (!context) { | ||
context = app; | ||
} | ||
utils.isObject = function(val) { | ||
return utils.typeOf(val) === 'object'; | ||
}; | ||
var isFunction = typeof app === 'function'; | ||
/** | ||
* Return true if `filepath` exists on the file system | ||
*/ | ||
var fn = isFunction ? app : (app.env && app.env.fn); | ||
utils.exists = function(name) { | ||
if (existsCache[name]) return true; | ||
// if app is not a function, it's already instantiated | ||
if (typeof fn !== 'function') { | ||
return app; | ||
function set(name, fp) { | ||
if (name) existsCache[name] = true; | ||
if (fp) existsCache[fp] = true; | ||
} | ||
var base = context.base; | ||
var env = context.env; | ||
try { | ||
fs.lstatSync(name); | ||
set(name); | ||
return true; | ||
} catch (err) {}; | ||
debug('invoking "%s"', env && env.alias); | ||
fn.call(context, context, base, env); | ||
return context; | ||
try { | ||
var fp = path.resolve('node_modules', name); | ||
if (existsCache[fp]) return true; | ||
fs.lstatSync(fp); | ||
set(name, fp); | ||
return true; | ||
} catch (err) {} | ||
try { | ||
fp = path.resolve(utils.gm, name); | ||
if (existsCache[fp]) return true; | ||
fs.lstatSync(fp); | ||
set(name, fp); | ||
return true; | ||
} catch (err) {} | ||
return false; | ||
}; | ||
/** | ||
* Return the given value as-is | ||
*/ | ||
utils.isGenerator = function(val) { | ||
return utils.isApp(val, 'Generator'); | ||
}; | ||
utils.identity = function(val) { | ||
return val; | ||
utils.isApp = function(val, ctorName) { | ||
return utils.isObject(val) && val['is' + ctorName] === true; | ||
}; | ||
/** | ||
* Get the basename of a filepath, excluding extension. | ||
* Handle generator errors | ||
*/ | ||
utils.basename = function(fp) { | ||
return path.basename(fp, path.extname(fp)); | ||
}; | ||
utils.generatorError = function generatorError(err, app, name, cb) { | ||
var match = /task "(.*?)" is not registered/.exec(err.message); | ||
if (!match) return cb(err); | ||
utils.formatAlias = function(file) { | ||
return utils.yellow(file.alias); | ||
} | ||
var taskName = match[1]; | ||
if (~name.indexOf(':')) { | ||
var segs = name.split(':'); | ||
taskName = segs[1]; | ||
name = segs[0]; | ||
} | ||
utils.formatPath = function(file) { | ||
var inspectType = file.inspectType || 'path'; | ||
var fp = file.path; | ||
if (!/\.\.\//.test(file.relative)) { | ||
fp = file.relative; | ||
var msg = 'Cannot find '; | ||
var gen = app.getGenerator(name); | ||
if (gen && name !== taskName) { | ||
msg += 'task: "' + taskName + '" in generator'; | ||
} else { | ||
// don't error when a `default` generator is not defined | ||
if (name === 'default') { | ||
cb(); | ||
return; | ||
} | ||
msg += 'generator'; | ||
} | ||
var name = path.dirname(fp); | ||
if (name === '.') { | ||
name = file.name; | ||
} | ||
var res = ' <' + utils.magenta(inspectType) + '>'; | ||
if (inspectType === 'function') { | ||
return res; | ||
} | ||
res += ' '; | ||
res += utils.yellow(utils.bold(name)); | ||
return res; | ||
msg += ': "' + name + '"'; | ||
var cwd = app.get('options.cwd'); | ||
if (cwd) msg += ' in "' + cwd + '"'; | ||
return cb(new Error(msg)); | ||
}; | ||
@@ -100,0 +123,0 @@ |
{ | ||
"name": "base-generators", | ||
"description": "Adds project-generator support to your `base` application.", | ||
"version": "0.1.19", | ||
"homepage": "https://github.com/jonschlinkert/base-generators", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/node-base/base-generators", | ||
"author": "Jon Schlinkert (https://github.com/jonschlinkert)", | ||
"repository": "jonschlinkert/base-generators", | ||
"repository": "node-base/base-generators", | ||
"bugs": { | ||
"url": "https://github.com/jonschlinkert/base-generators/issues" | ||
"url": "https://github.com/node-base/base-generators/issues" | ||
}, | ||
@@ -24,30 +24,23 @@ "license": "MIT", | ||
"dependencies": { | ||
"ansi-bold": "^0.1.1", | ||
"ansi-magenta": "^0.1.1", | ||
"ansi-yellow": "^0.1.1", | ||
"arr-union": "^3.1.0", | ||
"array-unique": "^0.2.1", | ||
"async": "^1.5.2", | ||
"base-cwd": "^0.1.3", | ||
"base-plugins": "^0.4.4", | ||
"base-resolver": "github:node-base/base-resolver#dev", | ||
"base-task": "^0.4.1", | ||
"async": "1.5.2", | ||
"base-cwd": "^0.1.6", | ||
"base-env": "^0.1.1", | ||
"base-option": "^0.7.0", | ||
"base-pkg": "^0.2.0", | ||
"base-plugins": "^0.4.10", | ||
"base-task": "^0.4.2", | ||
"debug": "^2.2.0", | ||
"define-property": "^0.2.5", | ||
"extend-shallow": "^2.0.1", | ||
"generator-util": "^0.2.7", | ||
"get-value": "^2.0.3", | ||
"is-absolute": "^0.2.3", | ||
"kind-of": "^3.0.2", | ||
"lazy-cache": "^1.0.3", | ||
"map-cache": "^0.2.0", | ||
"mixin-deep": "^1.1.3", | ||
"resolve": "^1.1.7", | ||
"vinyl": "^1.1.1" | ||
"mixin-deep": "^1.1.3" | ||
}, | ||
"devDependencies": { | ||
"base": "^0.7.9", | ||
"base-option": "^0.6.2", | ||
"base-runtimes": "^0.1.4", | ||
"assemble-core": "^0.16.1", | ||
"base": "^0.8.1", | ||
"base-config": "^0.5.2", | ||
"base-runtimes": "^0.1.5", | ||
"generate-foo": "^0.1.5", | ||
"global-modules": "^0.2.0", | ||
"generator-util": "^0.2.9", | ||
"global-modules": "^0.2.1", | ||
"gulp": "^3.9.1", | ||
@@ -58,2 +51,3 @@ "gulp-eslint": "^2.0.0", | ||
"gulp-mocha": "^2.2.0", | ||
"gulp-unused": "^0.1.2", | ||
"minimist": "^1.2.0", | ||
@@ -60,0 +54,0 @@ "mocha": "^2.4.5", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
12
1
1
0
43803
16
7
824
560
1
+ Addedbase-env@^0.1.1
+ Addedbase-option@^0.7.0
+ Addedbase-pkg@^0.2.0
+ Addedkind-of@^3.0.2
+ Addedansi-bgblack@0.1.1(transitive)
+ Addedansi-bgblue@0.1.1(transitive)
+ Addedansi-bgcyan@0.1.1(transitive)
+ Addedansi-bggreen@0.1.1(transitive)
+ Addedansi-bgmagenta@0.1.1(transitive)
+ Addedansi-bgred@0.1.1(transitive)
+ Addedansi-bgwhite@0.1.1(transitive)
+ Addedansi-bgyellow@0.1.1(transitive)
+ Addedansi-black@0.1.1(transitive)
+ Addedansi-blue@0.1.1(transitive)
+ Addedansi-colors@0.2.0(transitive)
+ Addedansi-cyan@0.1.1(transitive)
+ Addedansi-dim@0.1.1(transitive)
+ Addedansi-gray@0.1.1(transitive)
+ Addedansi-green@0.1.1(transitive)
+ Addedansi-grey@0.1.1(transitive)
+ Addedansi-hidden@0.1.1(transitive)
+ Addedansi-inverse@0.1.1(transitive)
+ Addedansi-italic@0.1.1(transitive)
+ Addedansi-red@0.1.1(transitive)
+ Addedansi-reset@0.1.1(transitive)
+ Addedansi-strikethrough@0.1.1(transitive)
+ Addedansi-underline@0.1.1(transitive)
+ Addedansi-white@0.1.1(transitive)
+ Addedarray-unique@0.3.2(transitive)
+ Addedassign-symbols@1.0.0(transitive)
+ Addedbase-env@0.1.7(transitive)
+ Addedbase-option@0.7.0(transitive)
+ Addedbase-pkg@0.2.5(transitive)
+ Addedcache-base@0.8.51.0.1(transitive)
+ Addedcall-bind-apply-helpers@1.0.2(transitive)
+ Addedcall-bound@1.0.4(transitive)
+ Addedcollection-visit@0.2.31.0.0(transitive)
+ Addedcwd@0.9.1(transitive)
+ Addeddefaults-deep@0.2.4(transitive)
+ Addeddefine-property@1.0.0(transitive)
+ Addeddunder-proto@1.0.1(transitive)
+ Addederror-symbol@0.1.0(transitive)
+ Addedes-define-property@1.0.1(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-object-atoms@1.1.1(transitive)
+ Addedexpand-pkg@0.1.9(transitive)
+ Addedexport-files@2.1.1(transitive)
+ Addedextend-shallow@3.0.2(transitive)
+ Addedfile-name@0.1.0(transitive)
+ Addedfind-file-up@0.1.3(transitive)
+ Addedfind-pkg@0.1.2(transitive)
+ Addedfs-exists-sync@0.1.0(transitive)
+ Addedget-intrinsic@1.3.0(transitive)
+ Addedget-proto@1.0.1(transitive)
+ Addedgit-config-path@1.0.1(transitive)
+ Addedgit-repo-name@0.6.0(transitive)
+ Addedgopd@1.2.0(transitive)
+ Addedhas-symbols@1.1.0(transitive)
+ Addedhas-tostringtag@1.0.2(transitive)
+ Addedhas-value@0.3.11.0.0(transitive)
+ Addedhas-values@0.1.41.0.0(transitive)
+ Addedinfo-symbol@0.1.0(transitive)
+ Addedis-arguments@1.2.0(transitive)
+ Addedis-descriptor@1.0.3(transitive)
+ Addedis-number@3.0.0(transitive)
+ Addedis-valid-app@0.3.0(transitive)
+ Addedis-valid-instance@0.3.0(transitive)
+ Addedkind-of@4.0.0(transitive)
+ Addedlazy-cache@0.2.7(transitive)
+ Addedload-pkg@3.0.1(transitive)
+ Addedlog-ok@0.1.1(transitive)
+ Addedlog-utils@0.2.1(transitive)
+ Addedlongest@1.0.1(transitive)
+ Addedmap-schema@0.2.4(transitive)
+ Addedmap-visit@0.1.51.0.0(transitive)
+ Addedmath-intrinsics@1.1.0(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addednormalize-pkg@0.3.20(transitive)
+ Addedobject-visit@0.3.41.0.1(transitive)
+ Addedobject.pick@1.3.0(transitive)
+ Addedomit-empty@0.4.1(transitive)
+ Addedoption-cache@3.5.0(transitive)
+ Addedpad-right@0.2.2(transitive)
+ Addedparse-author@1.0.0(transitive)
+ Addedparse-git-config@1.1.1(transitive)
+ Addedparse-github-url@0.3.2(transitive)
+ Addedpascalcase@0.1.1(transitive)
+ Addedpkg-store@0.2.2(transitive)
+ Addedproject-name@0.2.6(transitive)
+ Addedreduce-object@0.1.3(transitive)
+ Addedremote-origin-url@0.5.3(transitive)
+ Addedrepo-utils@0.3.7(transitive)
+ Addedsemver@5.7.2(transitive)
+ Addedset-value@0.3.30.4.32.0.1(transitive)
+ Addedsort-object-arrays@0.1.1(transitive)
+ Addedsplit-string@3.1.0(transitive)
+ Addedstringify-author@0.1.3(transitive)
+ Addedsuccess-symbol@0.1.0(transitive)
+ Addedtime-stamp@1.1.0(transitive)
+ Addedto-object-path@0.2.0(transitive)
+ Addedunion-value@0.2.41.0.1(transitive)
+ Addedunset-value@0.1.21.0.0(transitive)
+ Addedwarning-symbol@0.1.0(transitive)
+ Addedwrite@0.2.1(transitive)
+ Addedwrite-json@0.2.2(transitive)
- Removedansi-bold@^0.1.1
- Removedansi-magenta@^0.1.1
- Removedansi-yellow@^0.1.1
- Removedarr-union@^3.1.0
- Removedarray-unique@^0.2.1
- Removedextend-shallow@^2.0.1
- Removedgenerator-util@^0.2.7
- Removedget-value@^2.0.3
- Removedis-absolute@^0.2.3
- Removedmap-cache@^0.2.0
- Removedresolve@^1.1.7
- Removedvinyl@^1.1.1
- Removedclone@1.0.4(transitive)
- Removedclone-stats@0.0.1(transitive)
- Removedgenerator-util@0.2.9(transitive)
- Removedmap-cache@0.2.2(transitive)
- Removedreplace-ext@0.0.1(transitive)
- Removedtry-open@0.1.3(transitive)
- Removedvinyl@1.2.0(transitive)
Updatedasync@1.5.2
Updatedbase-cwd@^0.1.6
Updatedbase-plugins@^0.4.10
Updatedbase-task@^0.4.2