yeoman-generator
Advanced tools
Comparing version 0.11.4 to 0.12.0
@@ -80,6 +80,7 @@ var logger = process.logging || require('./utils/log'); | ||
this.checkForCollision(destination, body, function (err, status) { | ||
this.checkForCollision(destination, body, function (err, config) { | ||
var stats; | ||
if (err) { | ||
config.callback(err); | ||
return this.emit('error', err); | ||
@@ -90,4 +91,4 @@ } | ||
// actual write | ||
if (!(/force|create/.test(status))) { | ||
return; | ||
if (!(/force|create/.test(config.status))) { | ||
return config.callback(); | ||
} | ||
@@ -106,2 +107,4 @@ | ||
} | ||
config.callback(); | ||
}.bind(this)); | ||
@@ -139,4 +142,5 @@ | ||
actions.write = function write(filepath, content) { | ||
this.checkForCollision(filepath, content, function (err, status) { | ||
this.checkForCollision(filepath, content, function (err, config) { | ||
if (err) { | ||
config.callback(err); | ||
return this.emit('error', err); | ||
@@ -147,6 +151,8 @@ } | ||
// actual write | ||
if (/force|create/.test(status)) { | ||
if (/force|create/.test(config.status)) { | ||
mkdirp.sync(path.dirname(filepath)); | ||
fs.writeFileSync(filepath, content); | ||
} | ||
config.callback(); | ||
}); | ||
@@ -153,0 +159,0 @@ return this; |
'use strict'; | ||
var prompt_ = require('prompt'); | ||
var _ = require('lodash'); | ||
var validate = require('revalidator').validate; | ||
var inquirer = require('inquirer'); | ||
function evaluatePrompts(prompt) { | ||
if (_.isFunction(prompt.default)) { | ||
prompt.default = prompt.default(); | ||
} else if (typeof prompt.default === 'boolean') { | ||
// Handle boolean defaults as confirmation prompts. | ||
var defaultMsg = prompt.default ? 'Y/n' : 'y/N'; | ||
prompt.default = defaultMsg; | ||
prompt.validator = function (value) { | ||
return value.match(/^([yYnN]|(y\/N)|(Y\/n))$/); | ||
}; | ||
prompt.required = true; | ||
prompt.before = function (val) { | ||
if (val === 'Y/n' || val.toLowerCase() === 'y') { | ||
return true; | ||
} else if (val === 'y/N' || val.toLowerCase() === 'n') { | ||
return false; | ||
} | ||
return val; | ||
}; | ||
} | ||
return prompt; | ||
} | ||
// Monkey-patching prompt._performValidation to get rid of the overly verbose | ||
// error message. | ||
// | ||
// Arguments: | ||
// - name {Object} Variable name | ||
// - prop {Object|string} Variable to get input for. | ||
// - against {Object} Input | ||
// - schema {Object} Validation schema | ||
// - line {String|Boolean} Input line | ||
// - callback {function} Continuation to pass control to when complete. | ||
// | ||
// Perfoms user input validation, print errors if needed and returns value | ||
// according to validation | ||
// | ||
prompt_._performValidation = function (name, prop, against, schema, line, callback) { | ||
var numericInput, valid, msg; | ||
try { | ||
valid = validate(against, schema); | ||
} catch (err) { | ||
return (line !== -1) ? callback(err) : false; | ||
} | ||
if (!valid.valid) { | ||
msg = 'Invalid input'; | ||
if (prompt_.colors) { | ||
prompt_.logger.error(msg); | ||
} else { | ||
prompt_.logger.error(msg); | ||
} | ||
if (prop.schema.message) { | ||
prompt_.logger.error(prop.schema.message); | ||
} | ||
prompt_.emit('invalid', prop, line); | ||
} | ||
return valid.valid; | ||
}; | ||
// Prompt for user input based on the given Array of `prompts` to perform in | ||
// series, and call `done` callback on completion. `prompts` can be a single | ||
// Hash of options in which case a single prompt is performed. | ||
// series, and call `done` callback on completion. | ||
// | ||
// Options can be any prompt's option: https://npmjs.org/package/prompt | ||
// Options can be any prompt's option: https://github.com/SBoudrias/Inquirer.js | ||
// | ||
// - prompts - A single or an Array of Hash options. | ||
// - prompts - an Array of Hash options. | ||
// - done - Callback to call on error or on completion. | ||
// | ||
// Returns the generator instance. | ||
module.exports = function prompt(prompts, done) { | ||
prompts = Array.isArray(prompts) ? prompts : [prompts]; | ||
prompts = prompts.map(evaluatePrompts); | ||
prompt_.colors = false; | ||
prompt_.message = '[' + '?'.green + ']'; | ||
prompt_.delimiter = ' '; | ||
prompt_.start(); | ||
var results = {}; | ||
(function next(prompt) { | ||
function handleResult(err, value) { | ||
if (err) { | ||
return done(err); | ||
} | ||
results[prompt.name] = value[prompt.name]; | ||
next(prompts.shift()); | ||
} | ||
if (!prompt) { | ||
return done(null, results); | ||
} | ||
prompt_.get(prompt, handleResult); | ||
})(prompts.shift()); | ||
module.exports = function prompt() { | ||
inquirer.prompt.apply(inquirer, arguments); | ||
return this; | ||
}; |
@@ -91,2 +91,3 @@ var fs = require('fs'); | ||
_.extend(Base.prototype, require('./actions/wiring')); | ||
_.extend(Base.prototype, require('./util/common')); | ||
Base.prototype.prompt = require('./actions/prompt'); | ||
@@ -258,4 +259,5 @@ Base.prototype.invoke = require('./actions/invoke'); | ||
} | ||
next(); | ||
}); | ||
next(); | ||
}; | ||
@@ -262,0 +264,0 @@ |
@@ -123,3 +123,3 @@ var fs = require('fs'); | ||
generator.prompt = function (prompts, done) { | ||
done(null, answers); | ||
done(answers); | ||
}; | ||
@@ -126,0 +126,0 @@ generator.origPrompt = origPrompt; |
@@ -9,2 +9,3 @@ var logger = process.logging || require('./log'); | ||
var log = logger('conflicter'); | ||
var async = require('async'); | ||
@@ -49,18 +50,26 @@ var conflicter = module.exports = Object.create(events.EventEmitter.prototype); | ||
conflicter.resolve = function resolve(cb) { | ||
var conflicts = this.conflicts; | ||
(function next(conflict) { | ||
if (!conflict) { | ||
return cb(); | ||
} | ||
conflicter.collision(conflict.file, conflict.content, function (err, status) { | ||
if (err) { | ||
return cb(err); | ||
var resolveConflicts = function (conflict) { | ||
return function (next) { | ||
if (!conflict) { | ||
return next(); | ||
} | ||
conflicter.emit('resolved:' + conflict.file, status); | ||
next(conflicts.shift()); | ||
}); | ||
conflicter.collision(conflict.file, conflict.content, function (status) { | ||
conflicter.emit('resolved:' + conflict.file, { | ||
status: status, | ||
callback: next | ||
}); | ||
}); | ||
}; | ||
}; | ||
})(conflicts.shift()); | ||
async.series(this.conflicts.map(resolveConflicts), function (err) { | ||
if (err) { | ||
cb(); | ||
return self.emit('error', err); | ||
} | ||
conflicter.reset(); | ||
cb(); | ||
}.bind(this)); | ||
}; | ||
@@ -73,63 +82,48 @@ | ||
var self = this; | ||
var menu = [ | ||
' ' + 'Y'.bold + ' yes overwrite', | ||
' ' + 'n'.bold + ' no do not overwrite', | ||
' ' + 'a'.bold + ' all overwrite this and all others', | ||
' ' + 'q'.bold + ' quit abort', | ||
' ' + 'd'.bold + ' diff show the differences between the old and the new', | ||
' ' + 'h'.bold + ' help show help' | ||
].join('\n'); | ||
var config = { | ||
message: ('Overwrite ' + filepath + '? (enter "h" for help) [Ynaqdh]?'), | ||
name: 'overwrite', | ||
default: 'h' | ||
}; | ||
process.nextTick(function () { | ||
self.emit('prompt', config); | ||
self.emit('conflict', filepath); | ||
}); | ||
prompt(config, function (err, result) { | ||
if (err) { | ||
return cb(err); | ||
} | ||
var answer = result.overwrite; | ||
var ok = 'Yynaqdh'.split('').some(function (valid) { | ||
return valid === answer; | ||
}); | ||
if (answer === 'h' || !ok) { | ||
console.log(menu); | ||
return self._ask(filepath, content, cb); | ||
} | ||
if (answer === 'n') { | ||
log.skip(filepath); | ||
return cb(null, 'skip'); | ||
} | ||
if (answer === 'q') { | ||
log.writeln('Aborting...'); | ||
return process.exit(0); | ||
} | ||
if (/Y|a/i.test(answer)) { | ||
log.force(filepath); | ||
if (answer === 'a') { | ||
var config = [{ | ||
type: 'list', | ||
message: 'Overwrite ' + filepath + '?', | ||
choices: [{ | ||
name: 'Overwrite', | ||
value: function () { | ||
log.force(filepath); | ||
return cb('force'); | ||
} | ||
}, { | ||
name: 'do not overwrite', | ||
value: function () { | ||
log.skip(filepath); | ||
return cb('skip'); | ||
} | ||
}, { | ||
name: 'overwrite this and all others', | ||
value: function () { | ||
log.force(filepath); | ||
self.force = true; | ||
return cb('force'); | ||
} | ||
return cb(null, 'force'); | ||
} | ||
}, { | ||
name: 'abort', | ||
value: function () { | ||
log.writeln('Aborting ...'); | ||
return process.exit(0); | ||
} | ||
}, { | ||
name: 'show the differences between the old and the new', | ||
value: function () { | ||
console.log(conflicter.diff(fs.readFileSync(filepath, 'utf8'), content)); | ||
return self._ask(filepath, content, cb); | ||
} | ||
}], | ||
name: 'overwrite' | ||
}]; | ||
if (answer === 'd') { | ||
console.log(conflicter.diff(fs.readFileSync(filepath, 'utf8'), content)); | ||
return self._ask(filepath, content, cb); | ||
} | ||
process.nextTick(function () { | ||
this.emit('prompt', config); | ||
this.emit('conflict', filepath); | ||
}.bind(this)); | ||
// default, even though we should have handled every possible value | ||
return cb(); | ||
prompt(config, function (result) { | ||
cb(result.overwrite()); | ||
}); | ||
@@ -143,3 +137,3 @@ }; | ||
log.create(filepath); | ||
return cb(null, 'create'); | ||
return cb('create'); | ||
} | ||
@@ -152,3 +146,3 @@ | ||
log.identical(filepath); | ||
return cb(null, 'identical'); | ||
return cb('identical'); | ||
} | ||
@@ -158,3 +152,3 @@ | ||
log.force(filepath); | ||
return cb(null, 'force'); | ||
return cb('force'); | ||
} | ||
@@ -161,0 +155,0 @@ |
{ | ||
"name": "yeoman-generator", | ||
"version": "0.11.4", | ||
"version": "0.12.0", | ||
"description": "Rails-inspired generator system that provides scaffolding for your apps", | ||
@@ -42,11 +42,10 @@ "keywords": [ | ||
"isbinaryfile": "~0.1.8", | ||
"prompt": "~0.2.9", | ||
"revalidator": "~0.1.5", | ||
"dargs": "~0.1.0", | ||
"async": "~0.2.8" | ||
"async": "~0.2.8", | ||
"inquirer": "~0.1.3" | ||
}, | ||
"devDependencies": { | ||
"mocha": "~1.9.0", | ||
"mocha": "~1.10.0", | ||
"proxyquire": "~0.4.0" | ||
} | ||
} |
@@ -20,3 +20,3 @@ # Generator [![Build Status](https://secure.travis-ci.org/yeoman/generator.png?branch=master)](http://travis-ci.org/yeoman/generator) | ||
There is currently no formal infrastructure for testing generators, however you may find our [mocha generator](https://github.com/yeoman/yeoman/wiki/Testing-generators) for custom generators useful. | ||
There is currently no formal infrastructure for testing generators, however you may find our [mocha generator](https://github.com/yeoman/generator-mocha) for custom generators useful. | ||
@@ -23,0 +23,0 @@ ## Officially maintained generators |
@@ -35,3 +35,5 @@ /*global describe, before, it, afterEach, beforeEach */ | ||
it('generator.prompt(defaults, prompts, cb)', function (done) { | ||
this.dummy.prompt([], done); | ||
this.dummy.prompt([], function () { | ||
done(); | ||
}); | ||
}); | ||
@@ -38,0 +40,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*global describe, before, it */ | ||
/*global describe, before, beforeEach, it */ | ||
var fs = require('fs'); | ||
@@ -8,2 +8,3 @@ var path = require('path'); | ||
var generators = require('..'); | ||
var helpers = require('../lib/test/helpers'); | ||
@@ -69,2 +70,29 @@ | ||
describe('generator.run(args, cb) regression', function () { | ||
beforeEach(function () { | ||
var Unicorn = function () { | ||
generators.Base.apply(this, arguments); | ||
}; | ||
util.inherits(Unicorn, generators.Base); | ||
Unicorn.prototype.test1 = function () { | ||
this.async()(); | ||
}; | ||
Unicorn.prototype.test2 = function () { | ||
// Nothing | ||
}; | ||
this.unicorn = helpers.createGenerator('unicorn:app', [ | ||
[Unicorn, 'unicorn:app'] | ||
]); | ||
}); | ||
it('should call `done` only once', function (done) { | ||
// Mocha will fail if done was called more than once. | ||
this.unicorn.run({}, done); | ||
}); | ||
}); | ||
describe('generator.runHooks(cb)', function () { | ||
@@ -71,0 +99,0 @@ it('should go through all registered hooks, and invoke them in series', function (done) { |
@@ -42,3 +42,6 @@ /*global describe, before, it */ | ||
it('with at least one', function (done) { | ||
it('with at least one, without async callback handling', function (done) { | ||
var conflicts = 0; | ||
var callbackExecuted = false; | ||
conflicter.add(__filename); | ||
@@ -50,4 +53,45 @@ conflicter.add({ | ||
conflicter.resolve(done); | ||
// called. | ||
conflicter.once('resolved:' + __filename, function (config) { | ||
conflicts++; | ||
}); | ||
// not called. | ||
conflicter.once('resolved:foo.js', function (config) { | ||
conflicts++; | ||
}); | ||
conflicter.resolve(function(){ | ||
callbackExecuted = true; | ||
}); | ||
assert(conflicts, 1); | ||
assert(!callbackExecuted); | ||
done(); | ||
}); | ||
it('with at least one, with async callback handling', function (done) { | ||
var called = 0; | ||
conflicter.add(__filename); | ||
conflicter.add({ | ||
file: 'foo.js', | ||
content: 'var foo = "foo";\n' | ||
}); | ||
conflicter.once('resolved:' + __filename, function (config) { | ||
called++; | ||
config.callback(); | ||
}); | ||
conflicter.once('resolved:foo.js', function (config) { | ||
called++; | ||
config.callback(); | ||
}); | ||
conflicter.resolve(function(){ | ||
assert(called, 2); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -59,3 +103,3 @@ | ||
it('identical status', function(done) { | ||
conflicter.collision(__filename, me, function (err, status) { | ||
conflicter.collision(__filename, me, function (status) { | ||
assert.equal(status, 'identical'); | ||
@@ -67,3 +111,3 @@ done(); | ||
it('create status', function (done) { | ||
conflicter.collision('foo.js', '', function (err, status) { | ||
conflicter.collision('foo.js', '', function (status) { | ||
assert.equal(status, 'create'); | ||
@@ -75,3 +119,3 @@ done(); | ||
it('conflict status', function (done) { | ||
conflicter.collision(__filename, '', function (err, status) { | ||
conflicter.collision(__filename, '', function (status) { | ||
assert.equal(status, 'force'); | ||
@@ -91,3 +135,3 @@ done(); | ||
prompt: function (config, cb) { | ||
cb(this.err, { overwrite: this.answer }); | ||
cb({ overwrite: this.answer }); | ||
}, | ||
@@ -104,21 +148,11 @@ err: null, | ||
it('skips on "n answer"', function (done) { | ||
promptMock.answer = 'n'; | ||
this.conflicter._ask('/tmp/file', 'my file contents', function (err, result) { | ||
assert.strictEqual(err, null); | ||
assert(result, 'skip'); | ||
it('Calls answer related function', function (done) { | ||
var callCount = 0; | ||
promptMock.answer = function () { callCount++; }; | ||
this.conflicter._ask('/tmp/file', 'my file contents', function (result) { | ||
assert(callCount, 1); | ||
done(); | ||
}); | ||
}); | ||
it('enables force on "a" answer', function (done) { | ||
promptMock.answer = 'a'; | ||
this.conflicter._ask('/tmp/file', 'my file contents', function (err, result) { | ||
assert.strictEqual(err, null); | ||
assert(result, 'force'); | ||
assert(this.conflicter.force); | ||
done(); | ||
}.bind(this)); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
Found 1 instance in 1 package
17
282461
58
7851
1
+ Addedinquirer@~0.1.3
+ Addedcli-color@0.2.3(transitive)
+ Addedes5-ext@0.9.2(transitive)
+ Addedevent-emitter@0.2.2(transitive)
+ Addedinquirer@0.1.12(transitive)
+ Addedlodash@1.2.1(transitive)
+ Addedmemoizee@0.2.6(transitive)
+ Addedmute-stream@0.0.3(transitive)
+ Addednext-tick@0.1.0(transitive)
- Removedprompt@~0.2.9
- Removedrevalidator@~0.1.5
- Removedarray-buffer-byte-length@1.0.1(transitive)
- Removedavailable-typed-arrays@1.0.7(transitive)
- Removedcall-bind@1.0.7(transitive)
- Removedcolors@0.6.2(transitive)
- Removedcycle@1.0.3(transitive)
- Removeddeep-equal@2.2.3(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddefine-properties@1.2.1(transitive)
- Removedes-define-property@1.0.0(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedes-get-iterator@1.1.3(transitive)
- Removedeyes@0.1.8(transitive)
- Removedfor-each@0.3.3(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedfunctions-have-names@1.2.3(transitive)
- Removedget-intrinsic@1.2.4(transitive)
- Removedgopd@1.0.1(transitive)
- Removedhas-bigints@1.0.2(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-proto@1.0.3(transitive)
- Removedhas-symbols@1.0.3(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedi@0.3.7(transitive)
- Removedinternal-slot@1.0.7(transitive)
- Removedis-arguments@1.1.1(transitive)
- Removedis-array-buffer@3.0.4(transitive)
- Removedis-bigint@1.0.4(transitive)
- Removedis-boolean-object@1.1.2(transitive)
- Removedis-callable@1.2.7(transitive)
- Removedis-date-object@1.0.5(transitive)
- Removedis-map@2.0.3(transitive)
- Removedis-number-object@1.0.7(transitive)
- Removedis-regex@1.1.4(transitive)
- Removedis-set@2.0.3(transitive)
- Removedis-shared-array-buffer@1.0.3(transitive)
- Removedis-string@1.0.7(transitive)
- Removedis-symbol@1.0.4(transitive)
- Removedis-weakmap@2.0.2(transitive)
- Removedis-weakset@2.0.3(transitive)
- Removedisarray@2.0.5(transitive)
- Removedisstream@0.1.2(transitive)
- Removedmute-stream@0.0.8(transitive)
- Removedncp@0.4.2(transitive)
- Removedobject-inspect@1.13.3(transitive)
- Removedobject-is@1.1.6(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedobject.assign@4.1.5(transitive)
- Removedpkginfo@0.3.10.4.1(transitive)
- Removedpossible-typed-array-names@1.0.0(transitive)
- Removedprompt@0.2.14(transitive)
- Removedread@1.0.7(transitive)
- Removedregexp.prototype.flags@1.5.3(transitive)
- Removedrevalidator@0.1.8(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedset-function-name@2.0.2(transitive)
- Removedside-channel@1.0.6(transitive)
- Removedstack-trace@0.0.10(transitive)
- Removedstop-iteration-iterator@1.0.0(transitive)
- Removedutile@0.2.1(transitive)
- Removedwhich-boxed-primitive@1.0.2(transitive)
- Removedwhich-collection@1.0.2(transitive)
- Removedwhich-typed-array@1.1.15(transitive)
- Removedwinston@0.8.3(transitive)