New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

base-generators

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

base-generators - npm Package Compare versions

Comparing version 0.1.19 to 0.2.0

lib/app.js

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') {

'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",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc