Comparing version 0.1.12 to 0.2.0
/* | ||
* add-properties.js: Example of how to add properties to an object using prompt. | ||
* add-properties.js: Example of how to add properties to an object using prompt. | ||
* | ||
@@ -7,3 +7,3 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var prompt = require('../lib/prompt'); | ||
@@ -10,0 +10,0 @@ |
/* | ||
* existing-properties.js: Example of using prompt with predefined properties. | ||
* existing-properties.js: Example of using prompt with predefined properties. | ||
* | ||
@@ -7,3 +7,3 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var prompt = require('../lib/prompt'); | ||
@@ -13,8 +13,6 @@ | ||
email: { | ||
name: 'email', | ||
validator: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, | ||
warning: 'Must be a valid email address' | ||
format: 'email', | ||
message: 'Must be a valid email address' | ||
}, | ||
password: { | ||
name: 'password', | ||
hidden: true | ||
@@ -39,2 +37,2 @@ } | ||
console.log(' password: ' + result.password); | ||
}); | ||
}); |
/* | ||
* history.js: Example of using the prompt history capabilities. | ||
* history.js: Example of using the prompt history capabilities. | ||
* | ||
@@ -7,3 +7,3 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var prompt = require('../lib/prompt'); | ||
@@ -16,20 +16,20 @@ | ||
var properties = [ | ||
{ | ||
name: 'animal', | ||
description: 'Enter an animal', | ||
default: 'dog', | ||
validator: /dog|cat/ | ||
}, | ||
{ | ||
name: 'sound', | ||
description: 'What sound does this animal make?', | ||
validator: function (value) { | ||
var animal = prompt.history(0).value; | ||
return animal === 'dog' && value === 'woof' | ||
|| animal === 'cat' && value === 'meow'; | ||
var properties = { | ||
properties: { | ||
animal: { | ||
description: 'Enter an animal', | ||
default: 'dog', | ||
pattern: /dog|cat/ | ||
}, | ||
sound: { | ||
description: 'What sound does this animal make?', | ||
conform: function (value) { | ||
var animal = prompt.history(0).value; | ||
return animal === 'dog' && value === 'woof' | ||
|| animal === 'cat' && value === 'meow'; | ||
} | ||
} | ||
} | ||
] | ||
} | ||
@@ -46,2 +46,2 @@ // | ||
console.log(' sound: ' + result.sound); | ||
}); | ||
}); |
/* | ||
* simple-prompt.js: Simple example of using prompt. | ||
* password.js: Simple example of using prompt. | ||
* | ||
@@ -18,7 +18,10 @@ * (C) 2010, Nodejitsu Inc. | ||
// | ||
prompt.get([{ | ||
name:'password', | ||
hidden: true, | ||
validator: function (value, next) { | ||
setTimeout(next, 200); | ||
prompt.get([{ | ||
name: 'username', | ||
required: true | ||
}, { | ||
name: 'password', | ||
hidden: true, | ||
conform: function (value) { | ||
return true; | ||
} | ||
@@ -30,3 +33,4 @@ }], function (err, result) { | ||
console.log('Command-line input received:'); | ||
console.log(' username: ' + result.username); | ||
console.log(' password: ' + result.password); | ||
}); |
/* | ||
* property-prompt.js: Example of using prompt with complex properties. | ||
* property-prompt.js: Example of using prompt with complex properties. | ||
* | ||
@@ -7,23 +7,23 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var prompt = require('../lib/prompt'); | ||
var properties = [ | ||
{ | ||
name: 'name', | ||
validator: /^[a-zA-Z\s-]+$/, | ||
warning: 'Name must be only letters, spaces, or dashes', | ||
empty: false | ||
}, | ||
{ | ||
name: 'email', | ||
validator: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, | ||
warning: 'Must be a valid email address' | ||
}, | ||
{ | ||
name: 'password', | ||
empty: false, | ||
hidden: true | ||
var schema = { | ||
properties: { | ||
name: { | ||
pattern: /^[a-zA-Z\s-]+$/, | ||
message: 'Name must be only letters, spaces, or dashes', | ||
required: true | ||
}, | ||
email: { | ||
name: 'email', | ||
format: 'email', | ||
message: 'Must be a valid email address' | ||
}, | ||
password: { | ||
required: true, | ||
hidden: true | ||
} | ||
} | ||
]; | ||
}; | ||
@@ -38,3 +38,3 @@ // | ||
// | ||
prompt.get(properties, function (err, result) { | ||
prompt.get(schema, function (err, result) { | ||
// | ||
@@ -41,0 +41,0 @@ // Log the results. |
/* | ||
* simple-prompt.js: Simple example of using prompt. | ||
* simple-prompt.js: Simple example of using prompt. | ||
* | ||
@@ -7,3 +7,3 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var prompt = require('../lib/prompt'); | ||
@@ -10,0 +10,0 @@ |
@@ -9,17 +9,11 @@ /* | ||
var events = require('events'), | ||
async = require('async'), | ||
utile = require('utile'), | ||
async = utile.async, | ||
capitalize = utile.inflect.capitalize, | ||
colors = require('colors'), | ||
winston = require('winston'), | ||
validate = require('revalidator').validate, | ||
tty = require('tty'); | ||
// | ||
// ### @private function capitalize (str) | ||
// #### str {string} String to capitalize | ||
// Capitalizes the string supplied. | ||
// | ||
function capitalize(str) { | ||
return str.charAt(0).toUpperCase() + str.slice(1); | ||
} | ||
// | ||
// Expose version using `pkginfo` | ||
@@ -66,7 +60,9 @@ // | ||
options = options || {}; | ||
stdin = options.stdin || process.openStdin(); | ||
stdin = options.stdin || process.stdin; | ||
stdout = options.stdout || process.stdout; | ||
stdin.resume && stdin.resume(); | ||
// | ||
// By default: Remeber the last `10` prompt property / | ||
// By default: Remember the last `10` prompt property / | ||
// answer pairs and don't allow empty responses globally. | ||
@@ -84,3 +80,3 @@ // | ||
process.exit(1); | ||
}); | ||
}); | ||
} | ||
@@ -152,3 +148,40 @@ | ||
// | ||
// ### function get (msg, [validator,] callback) | ||
// ### function convert (schema) | ||
// #### @schema {Object} Schema for a property | ||
// Converts the schema into new format if it is in old format | ||
// | ||
var convert = function (schema) { | ||
var newSchema = false, | ||
newProps = Object.keys(validate.messages); | ||
newProps = newProps.concat(['description','dependencies']); | ||
for (var key in schema) { | ||
if (newProps.indexOf(key) > 0) { | ||
newSchema = true; | ||
break; | ||
} | ||
} | ||
if (!newSchema || schema.validator || | ||
schema.warning || schema.empty != null | ||
) { | ||
schema.description = schema.message; | ||
schema.message = schema.warning; | ||
schema.pattern = schema.validator; | ||
if (schema.empty != null) { | ||
schema.required = !(schema.empty); | ||
} | ||
delete schema.warning; | ||
delete schema.validator; | ||
delete schema.empty; | ||
} | ||
return schema; | ||
}; | ||
// | ||
// ### function get (msg, callback) | ||
// #### @msg {Array|Object|string} Set of variables to get input for. | ||
@@ -158,15 +191,8 @@ // #### @callback {function} Continuation to pass control to when complete. | ||
// | ||
prompt.get = function (msg, callback) { | ||
var vars = !Array.isArray(msg) ? [msg] : msg, | ||
result = {}; | ||
prompt.get = function (schema, callback) { | ||
vars = vars.map(function (v) { | ||
if (typeof v === 'string') { | ||
v = v.toLowerCase(); | ||
} | ||
iterate(schema, function get(target, next) { | ||
var path = target.path, | ||
schema = target.schema; | ||
return prompt.properties[v] || v; | ||
}); | ||
function get(target, next) { | ||
prompt.getInput(target, function (err, line) { | ||
@@ -176,19 +202,176 @@ if (err) { | ||
} | ||
next(null, line); | ||
}); | ||
}, callback); | ||
var name = target.name || target; | ||
result[name] = line; | ||
next(); | ||
return prompt; | ||
// iterate over the values in the schema, | ||
// represented as legit single-property object sub-schemas. | ||
function iterate(schema, get, cb) { | ||
var iterator = []; | ||
// We can iterate over a single string, ... | ||
if (typeof schema == 'string') { | ||
iterator.push({ | ||
path: [ schema ], | ||
schema: {} | ||
}); | ||
} // ..an array of strings and/or single-prop schema and/or no-prop schema... | ||
else if (Array.isArray(schema)) { | ||
iterator = schema.map(function (element) { | ||
if (typeof element == 'string') { | ||
return { | ||
path: [ element ], | ||
schema: prompt.properties[element.toLowerCase()] || {} | ||
} | ||
} | ||
else if (element.properties) { | ||
return { | ||
path: [ Object.keys(element.properties)[0] ], | ||
schema: element.properties[Object.keys(element.properties)[0]] | ||
}; | ||
} | ||
else if (element.path && element.schema) { | ||
return element; | ||
} | ||
else { | ||
return { | ||
path: [ element.name || 'question' ], | ||
schema: element | ||
}; | ||
} | ||
}); | ||
} //..or a complete schema... | ||
else if (schema.properties) { | ||
// `untangle` is defined later. | ||
iterator = untangle(schema); | ||
} //...or a partial schema and path. TODO: Evaluate need for this option. | ||
else { | ||
iterator = [{ | ||
schema: schema.schema ? schema.schema : schema, | ||
path: schema.path || [ 'question' ] | ||
}]; | ||
} | ||
var result = {}; | ||
// Now, iterate and assemble the result. | ||
async.forEachSeries(iterator, function (branch, next) { | ||
get(branch, function assembler(err, line) { | ||
if (err) { | ||
return next(err); | ||
} | ||
result = attach(result, build(branch.path, line)); | ||
next(); | ||
function build(path, line) { | ||
var o = {}; | ||
if (path.length) { | ||
o[path[0]] = build(path.slice(1), line); | ||
return o; | ||
} | ||
else { | ||
return line; | ||
} | ||
} | ||
function attach(obj, attr) { | ||
var keys; | ||
if (attr instanceof Object) { | ||
keys = Object.keys(attr); | ||
if (keys.length) { | ||
if (!obj[keys[0]]) { | ||
obj[keys[0]] = {}; | ||
} | ||
obj[keys[0]] = attach(obj[keys[0]], attr[keys[0]]); | ||
} | ||
return obj; | ||
} | ||
return attr; | ||
} | ||
}); | ||
}, function (err) { | ||
return err ? cb(err) : cb(null, result); | ||
}); | ||
// Transforms a full JSON-schema into an array describing path and sub-schemas. | ||
// Used for iteration purposes. | ||
function untangle(schema, path) { | ||
var results = []; | ||
path = path || []; | ||
if (schema.properties) { | ||
// Iterate over the properties in the schema and use recursion | ||
// to process sub-properties. | ||
Object.keys(schema.properties).forEach(function (k) { | ||
var o = {}; | ||
o[k] = schema.properties[k]; | ||
// Concat a sub-untangling to the results. | ||
results = results.concat(untangle(o[k], path.concat(k))); | ||
}); | ||
// Return the results. | ||
return results; | ||
} | ||
else { | ||
// This is a schema "leaf." | ||
return { | ||
path: path, | ||
schema: schema | ||
}; | ||
} | ||
} | ||
} | ||
}; | ||
async.forEachSeries(vars, get, function (err) { | ||
return err ? callback(err) : callback(null, result); | ||
// | ||
// ### function confirm (msg, callback) | ||
// #### @msg {Array|Object|string} set of message to confirm | ||
// #### @callback {function} Continuation to pass control to when complete. | ||
// Confirms a single or series of messages by prompting the user for a Y/N response. | ||
// Returns `true` if ALL messages are answered in the affirmative, otherwise `false` | ||
// | ||
// `msg` can be a string, or object (or array of strings/objects). | ||
// An object may have the following properties: | ||
// { | ||
// description: 'yes/no' // message to prompt user | ||
// pattern: /^[yntf]{1}/i // optional - regex defining acceptable responses | ||
// yes: /^[yt]{1}/i // optional - regex defining `affirmative` responses | ||
// message: 'yes/no' // optional - message to display for invalid responses | ||
// } | ||
// | ||
prompt.confirm = function (msg, callback) { | ||
var vars = !Array.isArray(msg) ? [msg] : msg, | ||
RX_Y = /^[yt]{1}/i, | ||
RX_YN = /^[yntf]{1}/i; | ||
function confirm(target, next) { | ||
var yes = target.yes || RX_Y, | ||
options = { | ||
description: typeof target === 'string' ? target : target.description||'yes/no', | ||
pattern: target.pattern || RX_YN, | ||
name: 'confirm', | ||
message: target.message || 'yes/no' | ||
}; | ||
prompt.get([options], function (err, result) { | ||
next(err ? false : yes.test(result[options.name])); | ||
}); | ||
} | ||
async.rejectSeries(vars, confirm, function(result) { | ||
callback(null, result.length===0); | ||
}); | ||
return prompt; | ||
}; | ||
// | ||
// ### function getInput (msg, validator, callback) | ||
// #### @msg {Object|string} Variable to get input for. | ||
// ### function getInput (prop, callback) | ||
// #### @prop {Object|string} Variable to get input for. | ||
// #### @callback {function} Continuation to pass control to when complete. | ||
@@ -198,9 +381,29 @@ // Gets input from the user via stdin for the specified message `msg`. | ||
prompt.getInput = function (prop, callback) { | ||
var name = prop.message || prop.name || prop, | ||
propName = prop.name || prop, | ||
delim = prompt.delimiter, | ||
raw = [prompt.message, delim + name.grey, delim.grey], | ||
read = prop.hidden ? prompt.readLineHidden : prompt.readLine, | ||
length, msg; | ||
var schema = prop.schema || prop, | ||
propName = prop.path && prop.path.join(':') || prop, | ||
storedSchema = prompt.properties[propName.toLowerCase()], | ||
delim = prompt.delimiter, raw, | ||
name, read, defaultLine, length, msg, valid, against; | ||
if ( | ||
schema instanceof Object && !Object.keys(schema).length && | ||
typeof storedSchema !== 'undefined' | ||
) { | ||
schema = storedSchema; | ||
} | ||
schema = convert(schema); | ||
name = prop.description || schema.description || propName; | ||
read = (schema.hidden ? prompt.readLineHidden : prompt.readLine); | ||
raw = [prompt.message, delim + name.grey, delim.grey]; | ||
defaultLine = schema.default; | ||
prop = { | ||
schema: schema, | ||
path: propName.split(':') | ||
}; | ||
// Handle overrides here. | ||
// TODO: Make overrides nestable | ||
if (prompt.override && prompt.override[propName]) { | ||
@@ -210,6 +413,25 @@ return callback (null, prompt.override[propName]) | ||
if (prop.default) { | ||
raw.splice(2, -1, ' (' + prop.default + ')'); | ||
// Build a proper validation schema if we just have a string | ||
if (typeof prop == 'string') { | ||
schema = {}; | ||
} | ||
// TODO: Isn't this broken? Maybe? | ||
if (!schema.properties) { | ||
schema = (function () { | ||
var o = { | ||
properties: {} | ||
}; | ||
o.properties[propName] = schema; | ||
return o; | ||
})(); | ||
} | ||
// Show the default in the prompt (this is correct) | ||
if (defaultLine) { | ||
raw.splice(2, -1, ' (' + defaultLine + ')'); | ||
} | ||
// Calculate the raw length and colorize the prompt | ||
@@ -220,4 +442,4 @@ length = raw.join('').length; | ||
if (prop.help) { | ||
prop.help.forEach(function (line) { | ||
if (schema.help) { | ||
schema.help.forEach(function (line) { | ||
logger.help(line); | ||
@@ -227,5 +449,8 @@ }); | ||
// Write the message, emit a "prompting" event | ||
// TODO: Find prompt.on's | ||
stdout.write(msg); | ||
prompt.emit('prompt', prop); | ||
prompt.emit('prompt', schema); | ||
// Make the actual read | ||
read.call(null, function (err, line) { | ||
@@ -236,64 +461,41 @@ if (err) { | ||
var valid, | ||
against = {}; | ||
// Apply defaults. This is cool. | ||
if (!line || line === '') { | ||
line = prop.default || line; | ||
line = defaultLine || line; | ||
} | ||
if (!prop.validator && prop.empty !== false) { | ||
logger.input(line.yellow); | ||
return callback(null, line); | ||
if (line && !(line === '')) { | ||
against[propName] = line; | ||
} | ||
var valid = true, | ||
validator = prop.validator; | ||
// Validate. | ||
try { | ||
valid = validate(against, schema); | ||
} | ||
catch (err) { | ||
return callback(err); | ||
} | ||
function next(valid) { | ||
if (arguments.length < 1) { | ||
valid = true; | ||
if (!valid.valid) { | ||
logger.error('Invalid input for ' + name.grey); | ||
if (prop.schema.message) { | ||
logger.error(prop.schema.message); | ||
} | ||
if (prop.empty === false && valid) { | ||
valid = line.length > 0; | ||
if (!valid) { | ||
prop.warning = prop.warning || 'You must supply a value.'; | ||
} | ||
} | ||
if (!valid) { | ||
logger.error('Invalid input for ' + name.grey); | ||
if (prop.warning) { | ||
logger.error(prop.warning); | ||
} | ||
prompt.emit('invalid', prop, line); | ||
return prompt.getInput(prop, callback); | ||
} | ||
// | ||
// Log the resulting line, append this `property:value` | ||
// pair to the history for `prompt` and respond to | ||
// the callback. | ||
// | ||
logger.input(line.yellow); | ||
prompt._remember(prop, line); | ||
callback(null, line); | ||
prompt.emit('invalid', prop, line); | ||
return prompt.getInput(prop, callback); | ||
} | ||
if (validator) { | ||
if (validator.test) { | ||
valid = validator.test(line) | ||
} | ||
else if (typeof validator === 'function') { | ||
return validator.length < 2 | ||
? next(validator(line)) | ||
: validator(line, next); | ||
} | ||
else { | ||
return callback(new Error('Invalid valiator: ' + typeof validator)); | ||
} | ||
} | ||
next(valid); | ||
// | ||
// Log the resulting line, append this `property:value` | ||
// pair to the history for `prompt` and respond to | ||
// the callback. | ||
// | ||
logger.input(line.yellow); | ||
prompt._remember(propName, line); | ||
callback(null, line); | ||
}); | ||
return prompt; | ||
}; | ||
@@ -390,3 +592,8 @@ | ||
var value = ''; | ||
function raw(mode) { | ||
var setRawMode = stdin.setRawMode || tty.setRawMode; | ||
setRawMode.call(stdin, mode); | ||
} | ||
// | ||
@@ -396,5 +603,5 @@ // Ignore errors from `.setRawMode()` so that `prompt` can | ||
// | ||
try { tty.setRawMode(true) } | ||
try { raw(true) } | ||
catch (ex) { } | ||
prompt.resume(); | ||
@@ -405,6 +612,6 @@ stdin.on('error', callback); | ||
for(var i = 0; i < line.length; i++) { | ||
c = line[i]; | ||
var c = line[i]; | ||
switch (c) { | ||
case '\n': case '\r': case '\r\n': case '\u0004': | ||
try { tty.setRawMode(false) } | ||
try { raw(false) } | ||
catch (ex) { } | ||
@@ -411,0 +618,0 @@ stdin.removeListener('data', data); |
{ | ||
"name": "prompt", | ||
"description": "A beautiful command-line prompt for node.js", | ||
"version": "0.1.12", | ||
"version": "0.2.0", | ||
"author": "Nodejitsu Inc. <info@nodejitsu.com>", | ||
"contributors": [ | ||
{ "name": "Charlie Robbins", "email": "charlie@nodejitsu.com" }, | ||
{ "name": "Joshua Holbrook", "email": "josh.holbrook@gmail.com" }, | ||
{ "name": "Bradley Meck", "email": "bradley.meck@gmail.com" }, | ||
{ "name": "Maciej Malecki", "email": "maciej@nodejitsu.com" } | ||
"maintainers": [ | ||
"indexzero <charlie@nodejitsu.com>", | ||
"jesusabdullah <josh@nodejitsu.com>" | ||
], | ||
@@ -17,6 +15,7 @@ "repository": { | ||
"dependencies": { | ||
"async": "0.1.x", | ||
"utile": "0.1.x", | ||
"colors": "0.x.x", | ||
"pkginfo": "0.x.x", | ||
"winston": "0.5.x" | ||
"winston": "0.5.x", | ||
"revalidator": "0.1.x" | ||
}, | ||
@@ -35,1 +34,2 @@ "devDependencies": { | ||
} | ||
@@ -65,14 +65,14 @@ # prompt [![Build Status](https://secure.travis-ci.org/flatiron/prompt.png)](http://travis-ci.org/flatiron/prompt) | ||
``` js | ||
var properties = [ | ||
{ | ||
name: 'name', | ||
validator: /^[a-zA-Z\s\-]+$/, | ||
warning: 'Name must be only letters, spaces, or dashes', | ||
empty: false | ||
}, | ||
{ | ||
name: 'password', | ||
hidden: true | ||
var schema = { | ||
properties: { | ||
name: { | ||
pattern: /^[a-zA-Z\s\-]+$/, | ||
message: 'Name must be only letters, spaces, or dashes', | ||
required: true | ||
}, | ||
password: { | ||
hidden: true | ||
} | ||
} | ||
]; | ||
}; | ||
@@ -87,3 +87,3 @@ // | ||
// | ||
prompt.get(properties, function (err, result) { | ||
prompt.get(schema, function (err, result) { | ||
// | ||
@@ -113,19 +113,59 @@ // Log the results. | ||
## Valid Property Settings | ||
`prompt` uses a simple property system for performing a couple of basic validation operations against input received from the command-line. The motivations here were speed and simplicity of implementation to integration of pseudo-standards like JSON-Schema were not feasible. | ||
`prompt` understands JSON-schema with a few extra parameters and uses [revalidator](https://github.com/flatiron/revalidator) for validation. | ||
Lets examine the anatomy of a prompt property: | ||
Here's an overview of the properties that may be used for validation and prompting controls: | ||
``` js | ||
{ | ||
message: 'Enter your password', // Prompt displayed to the user. If not supplied name will be used. | ||
name: 'password' // Key in the JSON object returned from `.get()`. | ||
validator: /^\w+$/ // Regular expression that input must be valid against. | ||
warning: 'Password must be letters' // Warning message to display if validation fails. | ||
hidden: true // If true, characters entered will not be output to console. | ||
default: 'lamepassword' // Default value to use if no value is entered. | ||
empty: false // If false, value entered must be non-empty. | ||
description: 'Enter your password', // Prompt displayed to the user. If not supplied name will be used. | ||
pattern: /^\w+$/, // Regular expression that input must be valid against. | ||
message: 'Password must be letters', // Warning message to display if validation fails. | ||
hidden: true, // If true, characters entered will not be output to console. | ||
default: 'lamepassword', // Default value to use if no value is entered. | ||
required: true // If true, value entered must be non-empty. | ||
} | ||
``` | ||
### skipping prompts | ||
Alternatives to `pattern` include `format` and `conform`, as documented in [revalidator](https://github.com/flatiron/revalidator). | ||
### Alternate Validation API: | ||
Prompt, in addition to iterating over JSON-Schema properties, will also happily iterate over an array of validation objects given an extra 'name' property: | ||
```js | ||
var prompt = require('../lib/prompt'); | ||
// | ||
// Start the prompt | ||
// | ||
prompt.start(); | ||
// | ||
// Get two properties from the user: username and password | ||
// | ||
prompt.get([{ | ||
name: 'username', | ||
required: true | ||
}, { | ||
name: 'password', | ||
hidden: true, | ||
conform: function (value) { | ||
return true; | ||
} | ||
}], function (err, result) { | ||
// | ||
// Log the results. | ||
// | ||
console.log('Command-line input received:'); | ||
console.log(' username: ' + result.username); | ||
console.log(' password: ' + result.password); | ||
}); | ||
``` | ||
### Backward Compatibility | ||
Note that, while this structure is similar to that used by prompt 0.1.x, that the object properties use the same names as in JSON-Schema. prompt 0.2.x is backward compatible with prompt 0.1.x except for asynchronous validation. | ||
### Skipping Prompts | ||
Sometimes power users may wish to skip promts and specify all data as command line options. | ||
@@ -136,3 +176,3 @@ if a value is set as a property of `prompt.override` prompt will use that instead of | ||
``` js | ||
//prompt-everride.js | ||
//prompt-override.js | ||
@@ -164,3 +204,3 @@ var prompt = require('prompt'), | ||
//: node prompt-everride.js --username USER --email EMAIL | ||
//: node prompt-override.js --username USER --email EMAIL | ||
@@ -229,4 +269,9 @@ ``` | ||
prompt.get([{ name: "name", | ||
message: "What is your name?".magenta }], function (err, result) { | ||
prompt.get({ | ||
properties: { | ||
name: { | ||
description: "What is your name?".magenta | ||
} | ||
} | ||
}, function (err, result) { | ||
console.log("You said your name is: ".cyan + result.name.cyan); | ||
@@ -233,0 +278,0 @@ }); |
/* | ||
* helpers.js: Test helpers for the prompt tests. | ||
* helpers.js: test helpers for the prompt tests. | ||
* | ||
@@ -33,3 +33,3 @@ * (C) 2010, Nodejitsu Inc. | ||
// Create some mock streams for asserting against | ||
// in our prompt tests. | ||
// in our prompt teSts. | ||
// | ||
@@ -48,57 +48,61 @@ helpers.stdin = new MockReadWriteStream(); | ||
helpers.properties = { | ||
riffwabbles: { | ||
name: 'riffwabbles', | ||
validator: /^[\w|\-]+$/, | ||
warning: 'riffwabbles can only be letters, numbers, and dashes', | ||
default: 'foobizzles' | ||
}, | ||
username: { | ||
name: 'username', | ||
validator: /^[\w|\-]+$/, | ||
warning: 'Username can only be letters, numbers, and dashes' | ||
}, | ||
notblank: { | ||
name: 'notblank', | ||
empty: false | ||
}, | ||
password: { | ||
name: 'password', | ||
hidden: true, | ||
empty: false | ||
}, | ||
badValidator: { | ||
name: 'bad-validator', | ||
validator: ['cant', 'use', 'array'] | ||
}, | ||
animal: { | ||
name: 'animal', | ||
description: 'Enter an animal', | ||
default: 'dog', | ||
validator: /dog|cat/ | ||
}, | ||
sound: { | ||
name: 'sound', | ||
description: 'What sound does this animal make?', | ||
validator: function (value) { | ||
var animal = prompt.history(0).value; | ||
return animal === 'dog' && value === 'woof' | ||
|| animal === 'cat' && value === 'meow'; | ||
} | ||
}, | ||
fnvalidator: { | ||
name: 'fnvalidator', | ||
validator: function (line) { | ||
return line.slice(0,2) == 'fn'; | ||
// 1) .properties | ||
// 2) warning --> message | ||
// 3) Name --> description || key | ||
// 4) validator --> conform (fxns), pattern (regexp), format (built-in) | ||
// 5) empty --> required | ||
helpers.schema = { | ||
properties: { | ||
oldschema: { | ||
message: 'Enter your username', | ||
validator: /^[\w|\-]+$/, | ||
warning: 'username can only be letters, numbers, and dashes', | ||
empty: false | ||
}, | ||
warning: 'fnvalidator must start with "fn"' | ||
}, | ||
cbvalidator: { | ||
name: 'cbvalidator', | ||
validator: function (line, next) { | ||
next(line.slice(0,2) == 'cb'); | ||
riffwabbles: { | ||
pattern: /^[\w|\-]+$/, | ||
message: 'riffwabbles can only be letters, numbers, and dashes', | ||
default: 'foobizzles' | ||
}, | ||
warning: 'cbvalidator must start with "cb"' | ||
username: { | ||
pattern: /^[\w|\-]+$/, | ||
message: 'Username can only be letters, numbers, and dashes' | ||
}, | ||
notblank: { | ||
required: true | ||
}, | ||
password: { | ||
hidden: true, | ||
required: true | ||
}, | ||
badValidator: { | ||
pattern: ['cant', 'use', 'array'] | ||
}, | ||
animal: { | ||
description: 'Enter an animal', | ||
default: 'dog', | ||
pattern: /dog|cat/ | ||
}, | ||
sound: { | ||
description: 'What sound does this animal make?', | ||
conform: function (value) { | ||
var animal = prompt.history(0).value; | ||
return animal === 'dog' && value === 'woof' | ||
|| animal === 'cat' && value === 'meow'; | ||
} | ||
}, | ||
fnvalidator: { | ||
conform: function (line) { | ||
return line.slice(0,2) == 'fn'; | ||
}, | ||
message: 'fnvalidator must start with "fn"' | ||
}/*, | ||
cbvalidator: { | ||
conform: function (line, next) { | ||
next(line.slice(0,2) == 'cb'); | ||
}, | ||
message: 'cbvalidator must start with "cb"' | ||
}*/ | ||
} | ||
}; |
/* | ||
* prompt-test.js: Tests for prompt. | ||
* prompt-test.js: Tests for prompt. | ||
* | ||
@@ -7,3 +7,3 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var assert = require('assert'), | ||
@@ -31,3 +31,3 @@ vows = require('vows'), | ||
winston.info('When prompted, enter: 12345 [backspace] [backspace] [enter]'); | ||
prompt.getInput(helpers.properties.password, this.callback); | ||
prompt.getInput({ path: ['password'], schema: helpers.schema.properties.password}, this.callback); | ||
}, | ||
@@ -41,2 +41,2 @@ "should respond with `123`": function (err, result) { | ||
} | ||
}).export(module); | ||
}).export(module); |
@@ -11,4 +11,19 @@ /* | ||
prompt = require('../lib/prompt'), | ||
helpers = require('./helpers'); | ||
helpers = require('./helpers'), | ||
schema = helpers.schema; | ||
// A helper to pass fragments of our schema into prompt as full schemas. | ||
function grab () { | ||
var names = [].slice.call(arguments), | ||
complete = { | ||
schema: {} | ||
}; | ||
names.forEach(function (name) { | ||
complete.path = [ name ], | ||
complete.schema = schema.properties[name]; | ||
}); | ||
return complete; | ||
}; | ||
vows.describe('prompt').addBatch({ | ||
@@ -89,3 +104,3 @@ "When using prompt": { | ||
prompt.getInput(helpers.properties.notblank, function () {}); | ||
prompt.getInput(grab('notblank'), function () {}); | ||
prompt.once('invalid', this.callback.bind(null, null)) | ||
@@ -132,3 +147,3 @@ helpers.stdin.write('\n'); | ||
prompt.getInput(helpers.properties.password, function () {}); | ||
prompt.getInput(grab('password'), function () {} ); | ||
prompt.once('invalid', this.callback.bind(null, null)) | ||
@@ -153,3 +168,3 @@ helpers.stdin.write('\n'); | ||
prompt.getInput(helpers.properties.username, this.callback); | ||
prompt.getInput(grab('username'), this.callback); | ||
helpers.stdin.write('some-user\n'); | ||
@@ -174,3 +189,3 @@ }, | ||
prompt.getInput(helpers.properties.username, this.callback); | ||
prompt.getInput(grab('username'), this.callback); | ||
@@ -196,3 +211,3 @@ prompt.once('invalid', function () { | ||
topic: function () { | ||
prompt.getInput(helpers.properties.badValidator, this.callback); | ||
prompt.getInput(grab('badValidator'), this.callback); | ||
}, | ||
@@ -233,3 +248,3 @@ "should respond with an error": function (err, ign) { | ||
prompt.properties['riffwabbles'] = helpers.properties['riffwabbles']; | ||
prompt.properties.riffwabbles = schema.properties.riffwabbles; | ||
prompt.get('riffwabbles', this.callback); | ||
@@ -243,3 +258,3 @@ helpers.stdin.write('\n'); | ||
assert.include(result, 'riffwabbles'); | ||
assert.equal(result['riffwabbles'], helpers.properties['riffwabbles'].default); | ||
assert.equal(result['riffwabbles'], schema.properties['riffwabbles'].default); | ||
} | ||
@@ -255,3 +270,3 @@ }, | ||
prompt.get(helpers.properties.fnvalidator, this.callback); | ||
prompt.get(grab('fnvalidator'), this.callback); | ||
helpers.stdin.write('fn123\n'); | ||
@@ -263,3 +278,3 @@ }, | ||
} | ||
}, | ||
}/*, // Does not work with revalidator | ||
"with a callback validator": { | ||
@@ -273,3 +288,3 @@ topic: function () { | ||
prompt.get(helpers.properties.cbvalidator, this.callback); | ||
prompt.get(grab('cbvalidator'), this.callback); | ||
helpers.stdin.write('cb123\n'); | ||
@@ -281,3 +296,3 @@ }, | ||
} | ||
} | ||
}*/ | ||
} | ||
@@ -288,4 +303,4 @@ }, | ||
prompt.override = { coconihet: 'whatever' } | ||
prompt.get('coconihet', this.callback); | ||
}, | ||
prompt.get('coconihet', this.callback); | ||
}, | ||
"skips prompt and uses overide": function (err, results) { | ||
@@ -312,2 +327,40 @@ assert.equal(results.coconihet, 'whatever') | ||
"When using prompt": { | ||
topic: function () { | ||
// | ||
// Reset the prompt for mock testing | ||
// | ||
prompt.started = false; | ||
prompt.start({ | ||
stdin: helpers.stdin, | ||
stdout: helpers.stdout | ||
}); | ||
return null; | ||
}, | ||
"the get() method": { | ||
"with old schema": { | ||
topic: function () { | ||
var that = this; | ||
helpers.stdout.once('data', function (msg) { | ||
that.msg = msg; | ||
}); | ||
prompt.properties.username = schema.properties.oldschema; | ||
prompt.get('username', this.callback); | ||
helpers.stdin.write('\n'); | ||
helpers.stdin.write('hell$\n'); | ||
helpers.stdin.write('hello\n'); | ||
}, | ||
"should prompt to stdout and respond with the default value": function (err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(this.msg.indexOf('username') !== -1); | ||
assert.include(result, 'username'); | ||
assert.equal(result.username, 'hello'); | ||
} | ||
} | ||
} | ||
} | ||
}).addBatch({ | ||
"When using prompt": { | ||
"the history() method": { | ||
@@ -317,3 +370,3 @@ "when used inside of a complex property": { | ||
topic: function () { | ||
prompt.get([helpers.properties.animal, helpers.properties.sound], this.callback); | ||
prompt.get([ grab('animal'), grab('sound')], this.callback); | ||
helpers.stdin.write('dog\n'); | ||
@@ -330,3 +383,3 @@ helpers.stdin.write('woof\n'); | ||
topic: function () { | ||
prompt.get([helpers.properties.animal, helpers.properties.sound], function () {}); | ||
prompt.get([ grab('animal'), grab('sound') ], function () {}); | ||
prompt.once('invalid', this.callback.bind(null, null)); | ||
@@ -337,3 +390,3 @@ helpers.stdin.write('dog\n'); | ||
"should prompt for the error": function (ign, property, line) { | ||
assert.equal(property.name, 'sound'); | ||
assert.equal(property.path.join(''), 'sound'); | ||
assert.equal(line, 'meow'); | ||
@@ -388,11 +441,14 @@ } | ||
prompt.override = { UVW: 5423, DEF: 64235 } | ||
prompt.get([{ | ||
name:'UVW', | ||
message: 'a custom message', | ||
default: 6 | ||
},{ | ||
name:'DEF', | ||
message: 'a custom message', | ||
default: 6 | ||
}], this.callback); | ||
prompt.get({ | ||
properties: { | ||
'UVW': { | ||
description: 'a custom message', | ||
default: 6 | ||
}, | ||
'DEF': { | ||
description: 'a custom message', | ||
default: 6 | ||
} | ||
} | ||
}, this.callback); | ||
}, | ||
@@ -406,4 +462,244 @@ "should respond with overrides": function (err, results) { | ||
} | ||
}).addBatch({ | ||
"when using prompt": { | ||
topic: function () { | ||
// | ||
// Reset the prompt for mock testing | ||
// | ||
prompt.started = false; | ||
prompt.start({ | ||
stdin: helpers.stdin, | ||
stdout: helpers.stdout | ||
}); | ||
return null; | ||
}, | ||
"the confirm() method": { | ||
"with a string message" : { | ||
"responding with Y" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('Y\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding with N" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('N\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
}, | ||
"responding with YES" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('YES\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding with NO" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('NO\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
}, | ||
"responding with T" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('T\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding with F" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('F\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
}, | ||
"responding with TRUE" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('TRUE\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding with FALSE" : { | ||
topic: function () { | ||
prompt.confirm('test', this.callback); | ||
helpers.stdin.write('FALSE\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
} | ||
}, | ||
"with an object" : { | ||
"and description set" : { | ||
topic: function() { | ||
prompt.confirm({description:'a custom message'}, this.callback); | ||
helpers.stdin.write('Y\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"and they forgot the description" : { | ||
topic: function() { | ||
prompt.confirm({}, this.callback); | ||
helpers.stdin.write('Y\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"and custom validators" : { | ||
"responding node" : { | ||
topic : function() { | ||
prompt.confirm({ | ||
description: 'node or jitsu?', | ||
pattern: /^(node|jitsu)/i, | ||
yes: /^node/i | ||
}, this.callback); | ||
helpers.stdin.write('node\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding jitsu" : { | ||
topic : function() { | ||
prompt.confirm({ | ||
description: 'node or jitsu?', | ||
pattern: /^(node|jitsu)/i, | ||
yes: /^node/i | ||
}, this.callback); | ||
helpers.stdin.write('jitsu\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
"with multiple strings" : { | ||
"responding with yesses" : { | ||
topic : function() { | ||
prompt.confirm(["test", "test2", "test3"], this.callback); | ||
helpers.stdin.write('Y\n'); | ||
helpers.stdin.write('y\n'); | ||
helpers.stdin.write('YES\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding with one no" : { | ||
topic : function() { | ||
prompt.confirm(["test", "test2", "test3"], this.callback); | ||
helpers.stdin.write('Y\n'); | ||
helpers.stdin.write('N\n'); | ||
helpers.stdin.write('YES\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
}, | ||
"responding with all noes" : { | ||
topic : function() { | ||
prompt.confirm(["test", "test2", "test3"], this.callback); | ||
helpers.stdin.write('n\n'); | ||
helpers.stdin.write('NO\n'); | ||
helpers.stdin.write('N\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
} | ||
}, | ||
"with multiple objects" : { | ||
"responding with yesses" : { | ||
topic : function() { | ||
prompt.confirm( | ||
[ | ||
{message:"test"}, | ||
{message:"test2"} | ||
], | ||
this.callback | ||
); | ||
helpers.stdin.write('y\n'); | ||
helpers.stdin.write('y\n'); | ||
}, | ||
"should respond with true" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isTrue(result); | ||
} | ||
}, | ||
"responding with noes" : { | ||
topic : function() { | ||
prompt.confirm( | ||
[ | ||
{message:"test"}, | ||
{message:"test2"} | ||
], | ||
this.callback | ||
); | ||
helpers.stdin.write('n\n'); | ||
helpers.stdin.write('n\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
}, | ||
"responding with yes and no" : { | ||
topic : function() { | ||
prompt.confirm( | ||
[ | ||
{message:"test"}, | ||
{message:"test2"} | ||
], | ||
this.callback | ||
); | ||
helpers.stdin.write('n\n'); | ||
helpers.stdin.write('y\n'); | ||
}, | ||
"should respond with false" : function(err, result) { | ||
assert.isNull(err); | ||
assert.isFalse(result); | ||
} | ||
} | ||
} | ||
} | ||
}).export(module); | ||
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
109650
21
1851
284
5
+ Addedrevalidator@0.1.x
+ Addedutile@0.1.x
+ Addedarray-buffer-byte-length@1.0.1(transitive)
+ Addedavailable-typed-arrays@1.0.7(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addeddeep-equal@2.2.3(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddefine-properties@1.2.1(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-get-iterator@1.1.3(transitive)
+ Addedfor-each@0.3.3(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedfunctions-have-names@1.2.3(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedhas-bigints@1.0.2(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhas-tostringtag@1.0.2(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedi@0.3.7(transitive)
+ Addedinternal-slot@1.0.7(transitive)
+ Addedis-arguments@1.1.1(transitive)
+ Addedis-array-buffer@3.0.4(transitive)
+ Addedis-bigint@1.0.4(transitive)
+ Addedis-boolean-object@1.1.2(transitive)
+ Addedis-callable@1.2.7(transitive)
+ Addedis-date-object@1.0.5(transitive)
+ Addedis-map@2.0.3(transitive)
+ Addedis-number-object@1.0.7(transitive)
+ Addedis-regex@1.1.4(transitive)
+ Addedis-set@2.0.3(transitive)
+ Addedis-shared-array-buffer@1.0.3(transitive)
+ Addedis-string@1.0.7(transitive)
+ Addedis-symbol@1.0.4(transitive)
+ Addedis-weakmap@2.0.2(transitive)
+ Addedis-weakset@2.0.3(transitive)
+ Addedisarray@2.0.5(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedncp@0.2.7(transitive)
+ Addedobject-inspect@1.13.2(transitive)
+ Addedobject-is@1.1.6(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedobject.assign@4.1.5(transitive)
+ Addedpossible-typed-array-names@1.0.0(transitive)
+ Addedregexp.prototype.flags@1.5.3(transitive)
+ Addedrevalidator@0.1.8(transitive)
+ Addedrimraf@1.0.9(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedset-function-name@2.0.2(transitive)
+ Addedside-channel@1.0.6(transitive)
+ Addedstop-iteration-iterator@1.0.0(transitive)
+ Addedutile@0.1.7(transitive)
+ Addedwhich-boxed-primitive@1.0.2(transitive)
+ Addedwhich-collection@1.0.2(transitive)
+ Addedwhich-typed-array@1.1.15(transitive)
- Removedasync@0.1.x