yeoman-environment
Advanced tools
Comparing version 1.6.6 to 2.0.0
'use strict'; | ||
const _ = require('lodash'); | ||
const inquirer = require('inquirer'); | ||
const diff = require('diff'); | ||
const chalk = require('chalk'); | ||
const logger = require('./util/log'); | ||
var _ = require('lodash'); | ||
var inquirer = require('inquirer'); | ||
var diff = require('diff'); | ||
var chalk = require('chalk'); | ||
var logger = require('./util/log'); | ||
/** | ||
@@ -17,60 +16,70 @@ * `TerminalAdapter` is the default implementation of `Adapter`, an abstraction | ||
*/ | ||
var TerminalAdapter = module.exports = function TerminalAdapter() { | ||
this.promptModule = inquirer.createPromptModule(); | ||
}; | ||
class TerminalAdapter { | ||
constructor() { | ||
this.promptModule = inquirer.createPromptModule(); | ||
} | ||
TerminalAdapter.prototype._colorDiffAdded = chalk.black.bgGreen; | ||
TerminalAdapter.prototype._colorDiffRemoved = chalk.bgRed; | ||
TerminalAdapter.prototype._colorLines = function colorLines(name, str) { | ||
return str.split('\n').map(function (line) { | ||
return this['_colorDiff' + name](line); | ||
}, this).join('\n'); | ||
}; | ||
get _colorDiffAdded() { | ||
return chalk.black.bgGreen; | ||
} | ||
/** | ||
* Prompt a user for one or more questions and pass | ||
* the answer(s) to the provided callback. | ||
* | ||
* It shares its interface with `Base.prompt` | ||
* | ||
* (Defined inside the constructor to keep interfaces separated between | ||
* instances) | ||
* | ||
* @param {Array} questions | ||
* @param {Function} callback | ||
*/ | ||
TerminalAdapter.prototype.prompt = function () {}; | ||
get _colorDiffRemoved() { | ||
return chalk.bgRed; | ||
} | ||
/** | ||
* Shows a color-based diff of two strings | ||
* | ||
* @param {string} actual | ||
* @param {string} expected | ||
*/ | ||
TerminalAdapter.prototype.diff = function _diff(actual, expected) { | ||
var msg = diff.diffLines(actual, expected).map(function (str) { | ||
if (str.added) { | ||
return this._colorLines('Added', str.value); | ||
} | ||
_colorLines(name, str) { | ||
return str.split('\n').map(line => this[`_colorDiff${name}`](line)).join('\n'); | ||
} | ||
if (str.removed) { | ||
return this._colorLines('Removed', str.value); | ||
} | ||
/** | ||
* Prompt a user for one or more questions and pass | ||
* the answer(s) to the provided callback. | ||
* | ||
* It shares its interface with `Base.prompt` | ||
* | ||
* (Defined inside the constructor to keep interfaces separated between | ||
* instances) | ||
* | ||
* @param {Array} questions | ||
* @param {Function} callback | ||
*/ | ||
prompt(questions, cb) { | ||
const promise = this.promptModule(questions); | ||
promise.then(cb || _.noop); | ||
return promise; | ||
} | ||
return str.value; | ||
}, this).join(''); | ||
/** | ||
* Shows a color-based diff of two strings | ||
* | ||
* @param {string} actual | ||
* @param {string} expected | ||
*/ | ||
diff(actual, expected) { | ||
let msg = diff.diffLines(actual, expected).map(str => { | ||
if (str.added) { | ||
return this._colorLines('Added', str.value); | ||
} | ||
// legend | ||
msg = '\n' + | ||
this._colorDiffRemoved('removed') + | ||
' ' + | ||
this._colorDiffAdded('added') + | ||
'\n\n' + | ||
msg + | ||
'\n'; | ||
if (str.removed) { | ||
return this._colorLines('Removed', str.value); | ||
} | ||
console.log(msg); | ||
return msg; | ||
}; | ||
return str.value; | ||
}).join(''); | ||
// Legend | ||
msg = '\n' + | ||
this._colorDiffRemoved('removed') + | ||
' ' + | ||
this._colorDiffAdded('added') + | ||
'\n\n' + | ||
msg + | ||
'\n'; | ||
console.log(msg); | ||
return msg; | ||
} | ||
} | ||
/** | ||
@@ -82,6 +91,2 @@ * Logging utility | ||
TerminalAdapter.prototype.prompt = function (questions, cb) { | ||
var promise = this.promptModule(questions); | ||
promise.then(cb || _.noop); | ||
return promise; | ||
}; | ||
module.exports = TerminalAdapter; |
'use strict'; | ||
var util = require('util'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var events = require('events'); | ||
var chalk = require('chalk'); | ||
var _ = require('lodash'); | ||
var GroupedQueue = require('grouped-queue'); | ||
var escapeStrRe = require('escape-string-regexp'); | ||
var untildify = require('untildify'); | ||
var memFs = require('mem-fs'); | ||
var debug = require('debug')('yeoman:environment'); | ||
var Store = require('./store'); | ||
var resolver = require('./resolver'); | ||
var TerminalAdapter = require('./adapter'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const EventEmitter = require('events'); | ||
const chalk = require('chalk'); | ||
const _ = require('lodash'); | ||
const GroupedQueue = require('grouped-queue'); | ||
const escapeStrRe = require('escape-string-regexp'); | ||
const untildify = require('untildify'); | ||
const memFs = require('mem-fs'); | ||
const debug = require('debug')('yeoman:environment'); | ||
const isScoped = require('is-scoped'); | ||
const Store = require('./store'); | ||
const resolver = require('./resolver'); | ||
const TerminalAdapter = require('./adapter'); | ||
@@ -39,488 +39,482 @@ /** | ||
*/ | ||
class Environment extends EventEmitter { | ||
static get queues() { | ||
return [ | ||
'initializing', | ||
'prompting', | ||
'configuring', | ||
'default', | ||
'writing', | ||
'conflicts', | ||
'install', | ||
'end' | ||
]; | ||
} | ||
var Environment = module.exports = function Environment(args, opts, adapter) { | ||
events.EventEmitter.call(this); | ||
/** | ||
* Make sure the Environment present expected methods if an old version is | ||
* passed to a Generator. | ||
* @param {Environment} env | ||
* @return {Environment} The updated env | ||
*/ | ||
static enforceUpdate(env) { | ||
if (!env.adapter) { | ||
env.adapter = new TerminalAdapter(); | ||
} | ||
args = args || []; | ||
this.arguments = Array.isArray(args) ? args : args.split(' '); | ||
this.options = opts || {}; | ||
this.adapter = adapter || new TerminalAdapter(); | ||
this.cwd = this.options.cwd || process.cwd(); | ||
this.store = new Store(); | ||
if (!env.runLoop) { | ||
env.runLoop = new GroupedQueue([ | ||
'initializing', | ||
'prompting', | ||
'configuring', | ||
'default', | ||
'writing', | ||
'conflicts', | ||
'install', | ||
'end' | ||
]); | ||
} | ||
this.runLoop = new GroupedQueue(Environment.queues); | ||
this.sharedFs = memFs.create(); | ||
if (!env.sharedFs) { | ||
env.sharedFs = memFs.create(); | ||
} | ||
// Each composed generator might set listeners on these shared resources. Let's make sure | ||
// Node won't complain about event listeners leaks. | ||
this.runLoop.setMaxListeners(0); | ||
this.sharedFs.setMaxListeners(0); | ||
return env; | ||
} | ||
this.lookups = ['.', 'generators', 'lib/generators']; | ||
this.aliases = []; | ||
/** | ||
* Factory method to create an environment instance. Take same parameters as the | ||
* Environment constructor. | ||
* | ||
* @see This method take the same arguments as {@link Environment} constructor | ||
* | ||
* @return {Environment} a new Environment instance | ||
*/ | ||
static createEnv(args, opts, adapter) { | ||
return new Environment(args, opts, adapter); | ||
} | ||
this.alias(/^([^:]+)$/, '$1:app'); | ||
}; | ||
/** | ||
* Convert a generators namespace to its name | ||
* | ||
* @param {String} namespace | ||
* @return {String} | ||
*/ | ||
static namespaceToName(namespace) { | ||
return namespace.split(':')[0]; | ||
} | ||
util.inherits(Environment, events.EventEmitter); | ||
_.extend(Environment.prototype, resolver); | ||
constructor(args, opts, adapter) { | ||
super(); | ||
Environment.queues = [ | ||
'initializing', | ||
'prompting', | ||
'configuring', | ||
'default', | ||
'writing', | ||
'conflicts', | ||
'install', | ||
'end' | ||
]; | ||
args = args || []; | ||
this.arguments = Array.isArray(args) ? args : args.split(' '); | ||
this.options = opts || {}; | ||
this.adapter = adapter || new TerminalAdapter(); | ||
this.cwd = this.options.cwd || process.cwd(); | ||
this.store = new Store(); | ||
/** | ||
* Error handler taking `err` instance of Error. | ||
* | ||
* The `error` event is emitted with the error object, if no `error` listener | ||
* is registered, then we throw the error. | ||
* | ||
* @param {Object} err | ||
* @return {Error} err | ||
*/ | ||
this.runLoop = new GroupedQueue(Environment.queues); | ||
this.sharedFs = memFs.create(); | ||
Environment.prototype.error = function error(err) { | ||
err = err instanceof Error ? err : new Error(err); | ||
// Each composed generator might set listeners on these shared resources. Let's make sure | ||
// Node won't complain about event listeners leaks. | ||
this.runLoop.setMaxListeners(0); | ||
this.sharedFs.setMaxListeners(0); | ||
if (!this.emit('error', err)) { | ||
throw err; | ||
this.lookups = ['.', 'generators', 'lib/generators']; | ||
this.aliases = []; | ||
this.alias(/^([^:]+)$/, '$1:app'); | ||
} | ||
return err; | ||
}; | ||
/** | ||
* Error handler taking `err` instance of Error. | ||
* | ||
* The `error` event is emitted with the error object, if no `error` listener | ||
* is registered, then we throw the error. | ||
* | ||
* @param {Object} err | ||
* @return {Error} err | ||
*/ | ||
error(err) { | ||
err = err instanceof Error ? err : new Error(err); | ||
/** | ||
* Outputs the general help and usage. Optionally, if generators have been | ||
* registered, the list of available generators is also displayed. | ||
* | ||
* @param {String} name | ||
*/ | ||
if (!this.emit('error', err)) { | ||
throw err; | ||
} | ||
Environment.prototype.help = function help(name) { | ||
name = name || 'init'; | ||
return err; | ||
} | ||
var out = [ | ||
'Usage: :binary: GENERATOR [args] [options]', | ||
'', | ||
'General options:', | ||
' --help # Print generator\'s options and usage', | ||
' -f, --force # Overwrite files that already exist', | ||
'', | ||
'Please choose a generator below.', | ||
'' | ||
]; | ||
/** | ||
* Outputs the general help and usage. Optionally, if generators have been | ||
* registered, the list of available generators is also displayed. | ||
* | ||
* @param {String} name | ||
*/ | ||
help(name) { | ||
name = name || 'init'; | ||
var ns = this.namespaces(); | ||
const out = [ | ||
'Usage: :binary: GENERATOR [args] [options]', | ||
'', | ||
'General options:', | ||
' --help # Print generator\'s options and usage', | ||
' -f, --force # Overwrite files that already exist', | ||
'', | ||
'Please choose a generator below.', | ||
'' | ||
]; | ||
var groups = {}; | ||
ns.forEach(function (namespace) { | ||
var base = namespace.split(':')[0]; | ||
const ns = this.namespaces(); | ||
if (!groups[base]) { | ||
groups[base] = []; | ||
const groups = {}; | ||
for (const namespace of ns) { | ||
const base = namespace.split(':')[0]; | ||
if (!groups[base]) { | ||
groups[base] = []; | ||
} | ||
groups[base].push(namespace); | ||
} | ||
groups[base].push(namespace); | ||
}); | ||
for (const key of Object.keys(groups).sort()) { | ||
const group = groups[key]; | ||
Object.keys(groups).sort().forEach(function (key) { | ||
var group = groups[key]; | ||
if (group.length >= 1) { | ||
out.push('', key.charAt(0).toUpperCase() + key.slice(1)); | ||
} | ||
if (group.length >= 1) { | ||
out.push('', key.charAt(0).toUpperCase() + key.slice(1)); | ||
for (const ns of groups[key]) { | ||
out.push(` ${ns}`); | ||
} | ||
} | ||
groups[key].forEach(function (ns) { | ||
out.push(' ' + ns); | ||
}); | ||
}); | ||
return out.join('\n').replace(/:binary:/g, name); | ||
} | ||
return out.join('\n').replace(/:binary:/g, name); | ||
}; | ||
/** | ||
* Registers a specific `generator` to this environment. This generator is stored under | ||
* provided namespace, or a default namespace format if none if available. | ||
* | ||
* @param {String} name - Filepath to the a generator or a npm package name | ||
* @param {String} namespace - Namespace under which register the generator (optional) | ||
* @return {String} namespace - Namespace assigned to the registered generator | ||
*/ | ||
register(name, namespace) { | ||
if (typeof name !== 'string') { | ||
return this.error(new Error('You must provide a generator name to register.')); | ||
} | ||
/** | ||
* Registers a specific `generator` to this environment. This generator is stored under | ||
* provided namespace, or a default namespace format if none if available. | ||
* | ||
* @param {String} name - Filepath to the a generator or a npm package name | ||
* @param {String} namespace - Namespace under which register the generator (optional) | ||
* @return {String} namespace - Namespace assigned to the registered generator | ||
*/ | ||
const modulePath = this.resolveModulePath(name); | ||
namespace = namespace || this.namespace(modulePath); | ||
Environment.prototype.register = function register(name, namespace) { | ||
if (!_.isString(name)) { | ||
return this.error(new Error('You must provide a generator name to register.')); | ||
} | ||
if (!namespace) { | ||
return this.error(new Error('Unable to determine namespace.')); | ||
} | ||
var modulePath = this.resolveModulePath(name); | ||
namespace = namespace || this.namespace(modulePath); | ||
this.store.add(namespace, modulePath); | ||
if (!namespace) { | ||
return this.error(new Error('Unable to determine namespace.')); | ||
debug('Registered %s (%s)', namespace, modulePath); | ||
return this; | ||
} | ||
this.store.add(namespace, modulePath); | ||
/** | ||
* Register a stubbed generator to this environment. This method allow to register raw | ||
* functions under the provided namespace. `registerStub` will enforce the function passed | ||
* to extend the Base generator automatically. | ||
* | ||
* @param {Function} Generator - A Generator constructor or a simple function | ||
* @param {String} namespace - Namespace under which register the generator | ||
* @return {this} | ||
*/ | ||
registerStub(Generator, namespace) { | ||
if (typeof Generator !== 'function') { | ||
return this.error(new Error('You must provide a stub function to register.')); | ||
} | ||
debug('Registered %s (%s)', namespace, modulePath); | ||
return this; | ||
}; | ||
if (typeof namespace !== 'string') { | ||
return this.error(new Error('You must provide a namespace to register.')); | ||
} | ||
/** | ||
* Register a stubbed generator to this environment. This method allow to register raw | ||
* functions under the provided namespace. `registerStub` will enforce the function passed | ||
* to extend the Base generator automatically. | ||
* | ||
* @param {Function} Generator - A Generator constructor or a simple function | ||
* @param {String} namespace - Namespace under which register the generator | ||
* @return {this} | ||
*/ | ||
this.store.add(namespace, Generator); | ||
Environment.prototype.registerStub = function registerStub(Generator, namespace) { | ||
if (!_.isFunction(Generator)) { | ||
return this.error(new Error('You must provide a stub function to register.')); | ||
return this; | ||
} | ||
if (!_.isString(namespace)) { | ||
return this.error(new Error('You must provide a namespace to register.')); | ||
/** | ||
* Returns the list of registered namespace. | ||
* @return {Array} | ||
*/ | ||
namespaces() { | ||
return this.store.namespaces(); | ||
} | ||
this.store.add(namespace, Generator); | ||
/** | ||
* Returns stored generators meta | ||
* @return {Object} | ||
*/ | ||
getGeneratorsMeta() { | ||
return this.store.getGeneratorsMeta(); | ||
} | ||
return this; | ||
}; | ||
/** | ||
* Get registered generators names | ||
* | ||
* @return {Array} | ||
*/ | ||
getGeneratorNames() { | ||
return _.uniq(Object.keys(this.getGeneratorsMeta()).map(Environment.namespaceToName)); | ||
} | ||
/** | ||
* Returns the list of registered namespace. | ||
* @return {Array} | ||
*/ | ||
/** | ||
* Get a single generator from the registered list of generators. The lookup is | ||
* based on generator's namespace, "walking up" the namespaces until a matching | ||
* is found. Eg. if an `angular:common` namespace is registered, and we try to | ||
* get `angular:common:all` then we get `angular:common` as a fallback (unless | ||
* an `angular:common:all` generator is registered). | ||
* | ||
* @param {String} namespaceOrPath | ||
* @return {Generator|null} - the generator registered under the namespace | ||
*/ | ||
get(namespaceOrPath) { | ||
// Stop the recursive search if nothing is left | ||
if (!namespaceOrPath) { | ||
return; | ||
} | ||
Environment.prototype.namespaces = function namespaces() { | ||
return this.store.namespaces(); | ||
}; | ||
let namespace = namespaceOrPath; | ||
/** | ||
* Returns stored generators meta | ||
* @return {Object} | ||
*/ | ||
// Legacy yeoman-generator `#hookFor()` function is passing the generator path as part | ||
// of the namespace. If we find a path delimiter in the namespace, then ignore the | ||
// last part of the namespace. | ||
const parts = namespaceOrPath.split(':'); | ||
const maybePath = _.last(parts); | ||
if (parts.length > 1 && /[/\\]/.test(maybePath)) { | ||
parts.pop(); | ||
Environment.prototype.getGeneratorsMeta = function getGeneratorsMeta() { | ||
return this.store.getGeneratorsMeta(); | ||
}; | ||
// We also want to remove the drive letter on windows | ||
if (maybePath.indexOf('\\') >= 0 && _.last(parts).length === 1) { | ||
parts.pop(); | ||
} | ||
/** | ||
* Get registered generators names | ||
* | ||
* @return {Array} | ||
*/ | ||
namespace = parts.join(':'); | ||
} | ||
Environment.prototype.getGeneratorNames = function getGeneratorNames() { | ||
return _.uniq(Object.keys(this.getGeneratorsMeta()).map(Environment.namespaceToName)); | ||
}; | ||
/** | ||
* Get a single generator from the registered list of generators. The lookup is | ||
* based on generator's namespace, "walking up" the namespaces until a matching | ||
* is found. Eg. if an `angular:common` namespace is registered, and we try to | ||
* get `angular:common:all` then we get `angular:common` as a fallback (unless | ||
* an `angular:common:all` generator is registered). | ||
* | ||
* @param {String} namespaceOrPath | ||
* @return {Generator|null} - the generator registered under the namespace | ||
*/ | ||
Environment.prototype.get = function get(namespaceOrPath) { | ||
// Stop the recursive search if nothing is left | ||
if (!namespaceOrPath) { | ||
return; | ||
return this.store.get(namespace) || | ||
this.store.get(this.alias(namespace)) || | ||
// Namespace is empty if namespaceOrPath contains a win32 absolute path of the form 'C:\path\to\generator'. | ||
// for this reason we pass namespaceOrPath to the getByPath function. | ||
this.getByPath(namespaceOrPath); | ||
} | ||
var namespace = namespaceOrPath; | ||
/** | ||
* Get a generator by path instead of namespace. | ||
* @param {String} path | ||
* @return {Generator|null} - the generator found at the location | ||
*/ | ||
getByPath(path) { | ||
if (fs.existsSync(path)) { | ||
const namespace = this.namespace(path); | ||
this.register(path, namespace); | ||
// Legacy yeoman-generator `#hookFor()` function is passing the generator path as part | ||
// of the namespace. If we find a path delimiter in the namespace, then ignore the | ||
// last part of the namespace. | ||
var parts = namespaceOrPath.split(':'); | ||
var maybePath = _.last(parts); | ||
if (parts.length > 1 && /[\/\\]/.test(maybePath)) { | ||
parts.pop(); | ||
// We also want to remove the drive letter on windows | ||
if (maybePath.indexOf('\\') >= 0 && _.last(parts).length === 1) { | ||
parts.pop(); | ||
return this.get(namespace); | ||
} | ||
namespace = parts.join(':'); | ||
} | ||
return this.store.get(namespace) || | ||
this.store.get(this.alias(namespace)) || | ||
// namespace is empty if namespaceOrPath contains a win32 absolute path of the form 'C:\path\to\generator'. | ||
// for this reason we pass namespaceOrPath to the getByPath function. | ||
this.getByPath(namespaceOrPath); | ||
}; | ||
/** | ||
* Create is the Generator factory. It takes a namespace to lookup and optional | ||
* hash of options, that lets you define `arguments` and `options` to | ||
* instantiate the generator with. | ||
* | ||
* An error is raised on invalid namespace. | ||
* | ||
* @param {String} namespace | ||
* @param {Object} options | ||
*/ | ||
create(namespace, options) { | ||
options = options || {}; | ||
/** | ||
* Get a generator by path instead of namespace. | ||
* @param {String} path | ||
* @return {Generator|null} - the generator found at the location | ||
*/ | ||
Environment.prototype.getByPath = function (path) { | ||
if (fs.existsSync(path)) { | ||
var namespace = this.namespace(path); | ||
this.register(path, namespace); | ||
const Generator = this.get(namespace); | ||
return this.get(namespace); | ||
} | ||
}; | ||
if (typeof Generator !== 'function') { | ||
let generatorHint = ''; | ||
if (isScoped(namespace)) { | ||
const splitName = namespace.split('/'); | ||
generatorHint = `${splitName[0]}/generator-${splitName[1]}`; | ||
} else { | ||
generatorHint = `generator-${namespace}`; | ||
} | ||
/** | ||
* Create is the Generator factory. It takes a namespace to lookup and optional | ||
* hash of options, that lets you define `arguments` and `options` to | ||
* instantiate the generator with. | ||
* | ||
* An error is raised on invalid namespace. | ||
* | ||
* @param {String} namespace | ||
* @param {Object} options | ||
*/ | ||
return this.error( | ||
new Error( | ||
chalk.red('You don\'t seem to have a generator with the name “' + namespace + '” installed.') + '\n' + | ||
'But help is on the way:\n\n' + | ||
'You can see available generators via ' + | ||
chalk.yellow('npm search yeoman-generator') + ' or via ' + chalk.yellow('http://yeoman.io/generators/') + '. \n' + | ||
'Install them with ' + chalk.yellow(`npm install ${generatorHint}`) + '.\n\n' + | ||
'To see all your installed generators run ' + chalk.yellow('yo') + ' without any arguments. ' + | ||
'Adding the ' + chalk.yellow('--help') + ' option will also show subgenerators. \n\n' + | ||
'If ' + chalk.yellow('yo') + ' cannot find the generator, run ' + chalk.yellow('yo doctor') + ' to troubleshoot your system.' | ||
) | ||
); | ||
} | ||
Environment.prototype.create = function create(namespace, options) { | ||
options = options || {}; | ||
var Generator = this.get(namespace); | ||
if (!_.isFunction(Generator)) { | ||
return this.error( | ||
new Error( | ||
chalk.red('You don\’t seem to have a generator with the name “' + namespace + '” installed.') + '\n' + | ||
'But help is on the way:\n\n' + | ||
'You can see available generators via ' + | ||
chalk.yellow('npm search yeoman-generator') + ' or via ' + chalk.yellow('http://yeoman.io/generators/') + '. \n' + | ||
'Install them with ' + chalk.yellow('npm install generator-' + namespace) + '.\n\n' + | ||
'To see all your installed generators run ' + chalk.yellow('yo') + ' without any arguments. ' + | ||
'Adding the ' + chalk.yellow('--help') + ' option will also show subgenerators. \n\n' + | ||
'If ' + chalk.yellow('yo') + ' cannot find the generator, run ' + chalk.yellow('yo doctor') + ' to troubleshoot your system.' | ||
) | ||
); | ||
return this.instantiate(Generator, options); | ||
} | ||
return this.instantiate(Generator, options); | ||
}; | ||
/** | ||
* Instantiate a Generator with metadatas | ||
* | ||
* @param {String} namespace | ||
* @param {Object} options | ||
* @param {Array|String} options.arguments Arguments to pass the instance | ||
* @param {Object} options.options Options to pass the instance | ||
*/ | ||
instantiate(Generator, options) { | ||
options = options || {}; | ||
/** | ||
* Instantiate a Generator with metadatas | ||
* | ||
* @param {String} namespace | ||
* @param {Object} options | ||
* @param {Array|String} options.arguments Arguments to pass the instance | ||
* @param {Object} options.options Options to pass the instance | ||
*/ | ||
let args = options.arguments || options.args || _.clone(this.arguments); | ||
args = Array.isArray(args) ? args : args.split(' '); | ||
Environment.prototype.instantiate = function instantiate(Generator, options) { | ||
options = options || {}; | ||
const opts = options.options || _.clone(this.options); | ||
var args = options.arguments || options.args || _.clone(this.arguments); | ||
args = Array.isArray(args) ? args : args.split(' '); | ||
var opts = options.options || _.clone(this.options); | ||
opts.env = this; | ||
opts.resolved = Generator.resolved || 'unknown'; | ||
opts.namespace = Generator.namespace; | ||
return new Generator(args, opts); | ||
}; | ||
/** | ||
* Tries to locate and run a specific generator. The lookup is done depending | ||
* on the provided arguments, options and the list of registered generators. | ||
* | ||
* When the environment was unable to resolve a generator, an error is raised. | ||
* | ||
* @param {String|Array} args | ||
* @param {Object} options | ||
* @param {Function} done | ||
*/ | ||
Environment.prototype.run = function run(args, options, done) { | ||
args = args || this.arguments; | ||
if (typeof options === 'function') { | ||
done = options; | ||
options = this.options; | ||
opts.env = this; | ||
opts.resolved = Generator.resolved || 'unknown'; | ||
opts.namespace = Generator.namespace; | ||
return new Generator(args, opts); | ||
} | ||
if (typeof args === 'function') { | ||
done = args; | ||
options = this.options; | ||
args = this.arguments; | ||
} | ||
/** | ||
* Tries to locate and run a specific generator. The lookup is done depending | ||
* on the provided arguments, options and the list of registered generators. | ||
* | ||
* When the environment was unable to resolve a generator, an error is raised. | ||
* | ||
* @param {String|Array} args | ||
* @param {Object} options | ||
* @param {Function} done | ||
*/ | ||
run(args, options, done) { | ||
args = args || this.arguments; | ||
args = Array.isArray(args) ? args : args.split(' '); | ||
options = options || this.options; | ||
if (typeof options === 'function') { | ||
done = options; | ||
options = this.options; | ||
} | ||
var name = args.shift(); | ||
if (!name) { | ||
return this.error(new Error('Must provide at least one argument, the generator namespace to invoke.')); | ||
} | ||
if (typeof args === 'function') { | ||
done = args; | ||
options = this.options; | ||
args = this.arguments; | ||
} | ||
var generator = this.create(name, { | ||
args: args, | ||
options: options | ||
}); | ||
args = Array.isArray(args) ? args : args.split(' '); | ||
options = options || this.options; | ||
if (generator instanceof Error) { | ||
return generator; | ||
} | ||
const name = args.shift(); | ||
if (!name) { | ||
return this.error(new Error('Must provide at least one argument, the generator namespace to invoke.')); | ||
} | ||
if (options.help) { | ||
return console.log(generator.help()); | ||
} | ||
const generator = this.create(name, { | ||
args, | ||
options | ||
}); | ||
return generator.run(done); | ||
}; | ||
if (generator instanceof Error) { | ||
return generator; | ||
} | ||
/** | ||
* Given a String `filepath`, tries to figure out the relative namespace. | ||
* | ||
* ### Examples: | ||
* | ||
* this.namespace('backbone/all/index.js'); | ||
* // => backbone:all | ||
* | ||
* this.namespace('generator-backbone/model'); | ||
* // => backbone:model | ||
* | ||
* this.namespace('backbone.js'); | ||
* // => backbone | ||
* | ||
* this.namespace('generator-mocha/backbone/model/index.js'); | ||
* // => mocha:backbone:model | ||
* | ||
* @param {String} filepath | ||
*/ | ||
if (options.help) { | ||
return console.log(generator.help()); | ||
} | ||
Environment.prototype.namespace = function namespace(filepath) { | ||
if (!filepath) { | ||
throw new Error('Missing namespace'); | ||
return generator.run(done); | ||
} | ||
// cleanup extension and normalize path for differents OS | ||
var ns = path.normalize(filepath.replace(new RegExp(escapeStrRe(path.extname(filepath)) + '$'), '')); | ||
/** | ||
* Given a String `filepath`, tries to figure out the relative namespace. | ||
* | ||
* ### Examples: | ||
* | ||
* this.namespace('backbone/all/index.js'); | ||
* // => backbone:all | ||
* | ||
* this.namespace('generator-backbone/model'); | ||
* // => backbone:model | ||
* | ||
* this.namespace('backbone.js'); | ||
* // => backbone | ||
* | ||
* this.namespace('generator-mocha/backbone/model/index.js'); | ||
* // => mocha:backbone:model | ||
* | ||
* @param {String} filepath | ||
*/ | ||
namespace(filepath) { | ||
if (!filepath) { | ||
throw new Error('Missing namespace'); | ||
} | ||
// Sort lookups by length so biggest are removed first | ||
var lookups = _(this.lookups.concat(['..'])).map(path.normalize).sortBy('length').value().reverse(); | ||
// Cleanup extension and normalize path for differents OS | ||
let ns = path.normalize(filepath.replace(new RegExp(escapeStrRe(path.extname(filepath)) + '$'), '')); | ||
// if `ns` contains a lookup dir in its path, remove it. | ||
ns = lookups.reduce(function (ns, lookup) { | ||
// only match full directory (begin with leading slash or start of input, end with trailing slash) | ||
lookup = new RegExp('(?:\\\\|/|^)' + escapeStrRe(lookup) + '(?=\\\\|/)', 'g'); | ||
return ns.replace(lookup, ''); | ||
}, ns); | ||
// Sort lookups by length so biggest are removed first | ||
const lookups = _(this.lookups.concat(['..'])).map(path.normalize).sortBy('length').value().reverse(); | ||
var folders = ns.split(path.sep); | ||
var scope = _.findLast(folders, function (folder) { | ||
return folder.indexOf('@') === 0; | ||
}); | ||
// If `ns` contains a lookup dir in its path, remove it. | ||
ns = lookups.reduce((ns, lookup) => { | ||
// Only match full directory (begin with leading slash or start of input, end with trailing slash) | ||
lookup = new RegExp(`(?:\\\\|/|^)${escapeStrRe(lookup)}(?=\\\\|/)`, 'g'); | ||
return ns.replace(lookup, ''); | ||
}, ns); | ||
// cleanup `ns` from unwanted parts and then normalize slashes to `:` | ||
ns = ns | ||
.replace(/(.*generator-)/, '') // remove before `generator-` | ||
.replace(/[\/\\](index|main)$/, '') // remove `/index` or `/main` | ||
.replace(/^[\/\\]+/, '') // remove leading `/` | ||
.replace(/[\/\\]+/g, ':'); // replace slashes by `:` | ||
const folders = ns.split(path.sep); | ||
const scope = _.findLast(folders, folder => folder.indexOf('@') === 0); | ||
if (scope) { | ||
ns = scope + '/' + ns; | ||
} | ||
// Cleanup `ns` from unwanted parts and then normalize slashes to `:` | ||
ns = ns | ||
.replace(/(.*generator-)/, '') // Remove before `generator-` | ||
.replace(/[/\\](index|main)$/, '') // Remove `/index` or `/main` | ||
.replace(/^[/\\]+/, '') // Remove leading `/` | ||
.replace(/[/\\]+/g, ':'); // Replace slashes by `:` | ||
debug('Resolve namespaces for %s: %s', filepath, ns); | ||
if (scope) { | ||
ns = `${scope}/${ns}`; | ||
} | ||
return ns; | ||
}; | ||
debug('Resolve namespaces for %s: %s', filepath, ns); | ||
/** | ||
* Resolve a module path | ||
* @param {String} moduleId - Filepath or module name | ||
* @return {String} - The resolved path leading to the module | ||
*/ | ||
Environment.prototype.resolveModulePath = function resolveModulePath(moduleId) { | ||
if (moduleId[0] === '.') { | ||
moduleId = path.resolve(moduleId); | ||
return ns; | ||
} | ||
if (path.extname(moduleId) === '') { | ||
moduleId += path.sep; | ||
} | ||
return require.resolve(untildify(moduleId)); | ||
}; | ||
/** | ||
* Resolve a module path | ||
* @param {String} moduleId - Filepath or module name | ||
* @return {String} - The resolved path leading to the module | ||
*/ | ||
resolveModulePath(moduleId) { | ||
if (moduleId[0] === '.') { | ||
moduleId = path.resolve(moduleId); | ||
} | ||
/** | ||
* Make sure the Environment present expected methods if an old version is | ||
* passed to a Generator. | ||
* @param {Environment} env | ||
* @return {Environment} The updated env | ||
*/ | ||
if (path.extname(moduleId) === '') { | ||
moduleId += path.sep; | ||
} | ||
Environment.enforceUpdate = function (env) { | ||
if (!env.adapter) { | ||
env.adapter = new TerminalAdapter(); | ||
return require.resolve(untildify(moduleId)); | ||
} | ||
} | ||
if (!env.runLoop) { | ||
env.runLoop = new GroupedQueue([ | ||
'initializing', | ||
'prompting', | ||
'configuring', | ||
'default', | ||
'writing', | ||
'conflicts', | ||
'install', | ||
'end' | ||
]); | ||
} | ||
Object.assign(Environment.prototype, resolver); | ||
if (!env.sharedFs) { | ||
env.sharedFs = memFs.create(); | ||
} | ||
return env; | ||
}; | ||
/** | ||
* Factory method to create an environment instance. Take same parameters as the | ||
* Environment constructor. | ||
* | ||
* @see This method take the same arguments as {@link Environment} constructor | ||
* | ||
* @return {Environment} a new Environment instance | ||
*/ | ||
Environment.createEnv = function (args, opts, adapter) { | ||
return new Environment(args, opts, adapter); | ||
}; | ||
/** | ||
* Convert a generators namespace to its name | ||
* | ||
* @param {String} namespace | ||
* @return {String} | ||
*/ | ||
Environment.namespaceToName = function (namespace) { | ||
return namespace.split(':')[0]; | ||
}; | ||
/** | ||
* Expose the utilities on the module | ||
* @see {@link env/util} | ||
*/ | ||
Environment.util = require('./util/util'); | ||
Environment.util = require('./util/util'); | ||
module.exports = Environment; |
'use strict'; | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var _ = require('lodash'); | ||
var globby = require('globby'); | ||
var debug = require('debug')('yeoman:environment'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const _ = require('lodash'); | ||
const globby = require('globby'); | ||
const debug = require('debug')('yeoman:environment'); | ||
var win32 = process.platform === 'win32'; | ||
const win32 = process.platform === 'win32'; | ||
@@ -14,3 +14,3 @@ /** | ||
*/ | ||
var resolver = module.exports; | ||
const resolver = module.exports; | ||
@@ -33,20 +33,19 @@ /** | ||
*/ | ||
resolver.lookup = function (cb) { | ||
var generatorsModules = this.findGeneratorsIn(this.getNpmPaths()); | ||
var patterns = []; | ||
const generatorsModules = this.findGeneratorsIn(this.getNpmPaths()); | ||
const patterns = []; | ||
this.lookups.forEach(function (lookup) { | ||
generatorsModules.forEach(function (modulePath) { | ||
for (const lookup of this.lookups) { | ||
for (const modulePath of generatorsModules) { | ||
patterns.push(path.join(modulePath, lookup)); | ||
}); | ||
}); | ||
} | ||
} | ||
patterns.forEach(function (pattern) { | ||
globby.sync('*/index.js', { cwd: pattern }).forEach(function (filename) { | ||
for (const pattern of patterns) { | ||
for (const filename of globby.sync('*/index.js', {cwd: pattern})) { | ||
this._tryRegistering(path.join(pattern, filename)); | ||
}, this); | ||
}, this); | ||
} | ||
} | ||
if (_.isFunction(cb)) { | ||
if (typeof cb === 'function') { | ||
return cb(null); | ||
@@ -64,7 +63,6 @@ } | ||
*/ | ||
resolver.findGeneratorsIn = function (searchPaths) { | ||
var modules = []; | ||
let modules = []; | ||
searchPaths.forEach(function (root) { | ||
for (const root of searchPaths) { | ||
if (!root) { | ||
@@ -77,6 +75,6 @@ return; | ||
'@*/generator-*' | ||
], { cwd: root }).map(function (match) { | ||
return path.join(root, match); | ||
}).concat(modules); | ||
}); | ||
], {cwd: root}) | ||
.map(match => path.join(root, match)) | ||
.concat(modules); | ||
} | ||
@@ -91,6 +89,5 @@ return modules; | ||
*/ | ||
resolver._tryRegistering = function (generatorReference) { | ||
var namespace; | ||
var realPath = fs.realpathSync(generatorReference); | ||
let namespace; | ||
const realPath = fs.realpathSync(generatorReference); | ||
@@ -105,4 +102,4 @@ try { | ||
this.register(realPath, namespace); | ||
} catch (e) { | ||
console.error('Unable to register %s (Error: %s)', generatorReference, e.message); | ||
} catch (err) { | ||
console.error('Unable to register %s (Error: %s)', generatorReference, err.message); | ||
} | ||
@@ -116,3 +113,3 @@ }; | ||
resolver.getNpmPaths = function () { | ||
var paths = []; | ||
let paths = []; | ||
@@ -136,3 +133,3 @@ // Add NVM prefix directory | ||
// adds support for generator resolving when yeoman-generator has been linked | ||
// Adds support for generator resolving when yeoman-generator has been linked | ||
if (process.argv[1]) { | ||
@@ -151,7 +148,7 @@ paths.push(path.join(path.dirname(process.argv[1]), '../..')); | ||
// Walk up the CWD and add `node_modules/` folder lookup on each level | ||
process.cwd().split(path.sep).forEach(function (part, i, parts) { | ||
var lookup = path.join.apply(path, parts.slice(0, i + 1).concat(['node_modules'])); | ||
process.cwd().split(path.sep).forEach((part, i, parts) => { | ||
let lookup = path.join.apply(path, parts.slice(0, i + 1).concat(['node_modules'])); | ||
if (!win32) { | ||
lookup = '/' + lookup; | ||
lookup = `/${lookup}`; | ||
} | ||
@@ -194,8 +191,7 @@ | ||
*/ | ||
resolver.alias = function alias(match, value) { | ||
resolver.alias = function (match, value) { | ||
if (match && value) { | ||
this.aliases.push({ | ||
match: match instanceof RegExp ? match : new RegExp('^' + match + '$'), | ||
value: value | ||
match: match instanceof RegExp ? match : new RegExp(`^${match}$`), | ||
value | ||
}); | ||
@@ -205,5 +201,5 @@ return this; | ||
var aliases = this.aliases.slice(0).reverse(); | ||
const aliases = this.aliases.slice(0).reverse(); | ||
return aliases.reduce(function (res, alias) { | ||
return aliases.reduce((res, alias) => { | ||
if (!alias.match.test(res)) { | ||
@@ -210,0 +206,0 @@ return res; |
130
lib/store.js
'use strict'; | ||
var _ = require('lodash'); | ||
@@ -11,80 +10,79 @@ /** | ||
*/ | ||
class Store { | ||
constructor() { | ||
this._generators = {}; | ||
this._meta = {}; | ||
} | ||
var Store = module.exports = function Store() { | ||
this._generators = {}; | ||
this._meta = {}; | ||
}; | ||
/** | ||
* Store a module under the namespace key | ||
* @param {String} namespace - The key under which the generator can be retrieved | ||
* @param {String|Function} generator - A generator module or a module path | ||
*/ | ||
add(namespace, generator) { | ||
if (typeof generator === 'string') { | ||
this._storeAsPath(namespace, generator); | ||
return; | ||
} | ||
/** | ||
* Store a module under the namespace key | ||
* @param {String} namespace - The key under which the generator can be retrieved | ||
* @param {String|Function} generator - A generator module or a module path | ||
*/ | ||
Store.prototype.add = function add(namespace, generator) { | ||
if (_.isString(generator)) { | ||
this._storeAsPath(namespace, generator); | ||
return; | ||
this._storeAsModule(namespace, generator); | ||
} | ||
this._storeAsModule(namespace, generator); | ||
}; | ||
_storeAsPath(namespace, path) { | ||
this._meta[namespace] = { | ||
resolved: path, | ||
namespace | ||
}; | ||
Store.prototype._storeAsPath = function _storeAsPath(namespace, path) { | ||
this._meta[namespace] = { | ||
resolved: path, | ||
namespace: namespace | ||
}; | ||
Object.defineProperty(this._generators, namespace, { | ||
get() { | ||
const Generator = require(path); | ||
return Generator; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
} | ||
Object.defineProperty(this._generators, namespace, { | ||
get: function () { | ||
var Generator = require(path); | ||
return Generator; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
}; | ||
_storeAsModule(namespace, Generator) { | ||
this._meta[namespace] = { | ||
resolved: 'unknown', | ||
namespace | ||
}; | ||
Store.prototype._storeAsModule = function _storeAsModule(namespace, Generator) { | ||
this._meta[namespace] = { | ||
resolved: 'unknown', | ||
namespace: namespace | ||
}; | ||
this._generators[namespace] = Generator; | ||
} | ||
this._generators[namespace] = Generator; | ||
}; | ||
/** | ||
* Get the module registered under the given namespace | ||
* @param {String} namespace | ||
* @return {Module} | ||
*/ | ||
get(namespace) { | ||
const Generator = this._generators[namespace]; | ||
/** | ||
* Get the module registered under the given namespace | ||
* @param {String} namespace | ||
* @return {Module} | ||
*/ | ||
if (!Generator) { | ||
return; | ||
} | ||
Store.prototype.get = function get(namespace) { | ||
var Generator = this._generators[namespace]; | ||
return Object.assign(Generator, this._meta[namespace]); | ||
} | ||
if (!Generator) { | ||
return; | ||
/** | ||
* Returns the list of registered namespace. | ||
* @return {Array} Namespaces array | ||
*/ | ||
namespaces() { | ||
return Object.keys(this._generators); | ||
} | ||
return _.extend(Generator, this._meta[namespace]); | ||
}; | ||
/** | ||
* Get the stored generators meta data | ||
* @return {Object} Generators metadata | ||
*/ | ||
getGeneratorsMeta() { | ||
return this._meta; | ||
} | ||
} | ||
/** | ||
* Returns the list of registered namespace. | ||
* @return {Array} Namespaces array | ||
*/ | ||
Store.prototype.namespaces = function namespaces() { | ||
return Object.keys(this._generators); | ||
}; | ||
/** | ||
* Get the stored generators meta data | ||
* @return {Object} Generators metadata | ||
*/ | ||
Store.prototype.getGeneratorsMeta = function getGeneratorsMeta() { | ||
return this._meta; | ||
}; | ||
module.exports = Store; |
/** @module env/log */ | ||
'use strict'; | ||
const util = require('util'); | ||
const EventEmitter = require('events'); | ||
const _ = require('lodash'); | ||
const table = require('text-table'); | ||
const chalk = require('chalk'); | ||
const logSymbols = require('log-symbols'); | ||
var util = require('util'); | ||
var events = require('events'); | ||
var _ = require('lodash'); | ||
var table = require('text-table'); | ||
var chalk = require('chalk'); | ||
var logSymbols = require('log-symbols'); | ||
// Padding step | ||
const step = ' '; | ||
let padding = ' '; | ||
// padding step | ||
var step = ' '; | ||
var padding = ' '; | ||
// color -> status mappings | ||
var colors = { | ||
// Color -> status mappings | ||
const colors = { | ||
skip: 'yellow', | ||
@@ -27,12 +26,12 @@ force: 'yellow', | ||
function pad(status) { | ||
var max = 'identical'.length; | ||
var delta = max - status.length; | ||
return delta ? new Array(delta + 1).join(' ') + status : status; | ||
const max = 'identical'.length; | ||
const delta = max - status.length; | ||
return delta ? ' '.repeat(delta) + status : status; | ||
} | ||
// borrowed from https://github.com/mikeal/logref/blob/master/main.js#L6-15 | ||
// Borrowed from https://github.com/mikeal/logref/blob/master/main.js#L6-15 | ||
function formatter(msg, ctx) { | ||
while (msg.indexOf('%') !== -1) { | ||
var start = msg.indexOf('%'); | ||
var end = msg.indexOf(' ', start); | ||
const start = msg.indexOf('%'); | ||
let end = msg.indexOf(' ', start); | ||
@@ -49,3 +48,3 @@ if (end === -1) { | ||
module.exports = function logger() { | ||
module.exports = () => { | ||
// `this.log` is a [logref](https://github.com/mikeal/logref) | ||
@@ -80,3 +79,3 @@ // compatible logger, with an enhanced API. | ||
_.extend(log, events.EventEmitter.prototype); | ||
_.extend(log, EventEmitter.prototype); | ||
@@ -111,11 +110,13 @@ // A simple write method, with formatted message. | ||
log.on('up', function () { | ||
padding = padding + step; | ||
log.on('up', () => { | ||
padding += step; | ||
}); | ||
log.on('down', function () { | ||
log.on('down', () => { | ||
padding = padding.replace(step, ''); | ||
}); | ||
Object.keys(colors).forEach(function (status) { | ||
/* eslint-disable no-loop-func */ | ||
// TODO: Fix this ESLint warning | ||
for (const status of Object.keys(colors)) { | ||
// Each predefined status has its logging method utility, handling | ||
@@ -146,3 +147,3 @@ // status color and padding before the usual `.write()` | ||
log[status] = function () { | ||
var color = colors[status]; | ||
const color = colors[status]; | ||
this.write(chalk[color](pad(status))).write(padding); | ||
@@ -152,3 +153,4 @@ this.write(util.format.apply(util, arguments) + '\n'); | ||
}; | ||
}); | ||
} | ||
/* eslint-enable no-loop-func */ | ||
@@ -163,11 +165,11 @@ // A basic wrapper around `cli-table` package, resetting any single | ||
// Returns the table reprensetation | ||
log.table = function (opts) { | ||
var tableData = []; | ||
log.table = opts => { | ||
const tableData = []; | ||
opts = Array.isArray(opts) ? { rows: opts } : opts; | ||
opts = Array.isArray(opts) ? {rows: opts} : opts; | ||
opts.rows = opts.rows || []; | ||
opts.rows.forEach(function (row) { | ||
for (const row of opts.rows) { | ||
tableData.push(row); | ||
}); | ||
} | ||
@@ -174,0 +176,0 @@ return table(tableData); |
/** @module env/util */ | ||
'use strict'; | ||
const GroupedQueue = require('grouped-queue'); | ||
var GroupedQueue = require('grouped-queue'); | ||
/** | ||
@@ -16,7 +15,6 @@ * Create a "sloppy" copy of an initial Environment object. The focus of this method is on | ||
*/ | ||
exports.duplicateEnv = function (initialEnv) { | ||
var queues = require('../environment').queues; | ||
// Hack: create a clone of the environment with a new instance of runLoop | ||
var env = Object.create(initialEnv); | ||
exports.duplicateEnv = initialEnv => { | ||
const queues = require('../environment').queues; | ||
// Hack: Create a clone of the environment with a new instance of `runLoop` | ||
const env = Object.create(initialEnv); | ||
env.runLoop = new GroupedQueue(queues); | ||
@@ -23,0 +21,0 @@ return env; |
{ | ||
"name": "yeoman-environment", | ||
"version": "1.6.6", | ||
"version": "2.0.0", | ||
"description": "Handles the lifecyle and bootstrapping of generators in a specific environment", | ||
@@ -27,3 +27,3 @@ "homepage": "http://yeoman.io", | ||
"scripts": { | ||
"test": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", | ||
"test": "xo && gulp", | ||
"doc": "jsdoc -c ./jsdoc.json ./readme.md", | ||
@@ -36,7 +36,8 @@ "benchmark": "matcha benchmark/**", | ||
"debug": "^2.0.0", | ||
"diff": "^2.1.2", | ||
"diff": "^3.2.0", | ||
"escape-string-regexp": "^1.0.2", | ||
"globby": "^4.0.0", | ||
"globby": "^6.1.0", | ||
"grouped-queue": "^0.3.0", | ||
"inquirer": "^1.0.2", | ||
"inquirer": "^3.0.1", | ||
"is-scoped": "^1.0.0", | ||
"lodash": "^4.11.1", | ||
@@ -46,3 +47,3 @@ "log-symbols": "^1.0.1", | ||
"text-table": "^0.2.0", | ||
"untildify": "^2.0.0" | ||
"untildify": "^3.0.2" | ||
}, | ||
@@ -53,7 +54,4 @@ "devDependencies": { | ||
"gulp-coveralls": "^0.1.0", | ||
"gulp-eslint": "^2.0.0", | ||
"gulp-exclude-gitignore": "^1.0.0", | ||
"gulp-istanbul": "^0.10.3", | ||
"gulp-jscs": "^3.0.0", | ||
"gulp-mocha": "^2.0.0", | ||
"gulp-istanbul": "^1.1.1", | ||
"gulp-mocha": "^3.0.1", | ||
"gulp-nsp": "^2.1.0", | ||
@@ -64,8 +62,20 @@ "gulp-plumber": "^1.0.0", | ||
"matcha": "^0.7.0", | ||
"mocha": "^2.3.4", | ||
"mocha": "^3.2.0", | ||
"shelljs": "^0.7.0", | ||
"sinon": "^1.9.1", | ||
"yeoman-assert": "^2.1.1", | ||
"yeoman-generator": "^0.22.1" | ||
"sinon": "^2.1.0", | ||
"sinon-test": "^1.0.1", | ||
"xo": "^0.18.1", | ||
"yeoman-assert": "^3.0.0", | ||
"yeoman-generator": "^1.1.0" | ||
}, | ||
"xo": { | ||
"space": true, | ||
"envs": [ | ||
"node", | ||
"mocha" | ||
], | ||
"rules": { | ||
"import/no-dynamic-require": "off" | ||
} | ||
} | ||
} |
@@ -9,2 +9,3 @@ # Yeoman Environment | ||
## Install | ||
@@ -19,12 +20,12 @@ | ||
Full documentation available at http://yeoman.io/authoring/integrating-yeoman.html | ||
Full documentation available [here](http://yeoman.io/authoring/integrating-yeoman.html). | ||
```js | ||
var yeoman = require('yeoman-environment'); | ||
var env = yeoman.createEnv(); | ||
const yeoman = require('yeoman-environment'); | ||
const env = yeoman.createEnv(); | ||
// The #lookup() method will search the user computer for installed generators. | ||
// The search if done from the current working directory. | ||
env.lookup(function () { | ||
env.run('angular', {'skip-install': true}, function (err) { | ||
// The #lookup() method will search the user computer for installed generators | ||
// The search if done from the current working directory | ||
env.lookup(() => { | ||
env.run('angular', {'skip-install': true}, err => { | ||
console.log('done'); | ||
@@ -40,2 +41,2 @@ }); | ||
BSD © Yeoman | ||
BSD-2-Clause © Yeoman |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33137
17
939
40
13
+ Addedis-scoped@^1.0.0
+ Addedansi-escapes@3.2.0(transitive)
+ Addedansi-regex@3.0.1(transitive)
+ Addedansi-styles@3.2.1(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedchardet@0.4.2(transitive)
+ Addedcli-cursor@2.1.0(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addeddiff@3.5.0(transitive)
+ Addedexternal-editor@2.2.0(transitive)
+ Addedfigures@2.0.0(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedglobby@6.1.0(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedinquirer@3.3.0(transitive)
+ Addedis-fullwidth-code-point@2.0.0(transitive)
+ Addedis-scoped@1.0.0(transitive)
+ Addedmimic-fn@1.2.0(transitive)
+ Addedmute-stream@0.0.7(transitive)
+ Addedonetime@2.0.1(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedrestore-cursor@2.0.0(transitive)
+ Addedrx-lite@4.0.8(transitive)
+ Addedrx-lite-aggregates@4.0.8(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedscoped-regex@1.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstring-width@2.1.1(transitive)
+ Addedstring_decoder@1.3.0(transitive)
+ Addedstrip-ansi@4.0.0(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedtmp@0.0.33(transitive)
+ Addeduntildify@3.0.3(transitive)
- Removedansi-escapes@1.4.0(transitive)
- Removedarrify@1.0.1(transitive)
- Removedbuffer-from@1.1.2(transitive)
- Removedcli-cursor@1.0.2(transitive)
- Removedcode-point-at@1.1.0(transitive)
- Removedconcat-stream@1.6.2(transitive)
- Removeddiff@2.2.3(transitive)
- Removedexit-hook@1.1.1(transitive)
- Removedextend@3.0.2(transitive)
- Removedexternal-editor@1.1.1(transitive)
- Removedfigures@1.7.0(transitive)
- Removedglob@6.0.4(transitive)
- Removedglobby@4.1.0(transitive)
- Removedinquirer@1.2.3(transitive)
- Removedis-fullwidth-code-point@1.0.0(transitive)
- Removedmute-stream@0.0.6(transitive)
- Removednumber-is-nan@1.0.1(transitive)
- Removedonetime@1.1.0(transitive)
- Removedos-homedir@1.0.2(transitive)
- Removedos-shim@0.1.3(transitive)
- Removedrestore-cursor@1.0.1(transitive)
- Removedrx@4.1.0(transitive)
- Removedspawn-sync@1.0.15(transitive)
- Removedstring-width@1.0.2(transitive)
- Removedtmp@0.0.29(transitive)
- Removedtypedarray@0.0.6(transitive)
- Removeduntildify@2.1.0(transitive)
Updateddiff@^3.2.0
Updatedglobby@^6.1.0
Updatedinquirer@^3.0.1
Updateduntildify@^3.0.2