Socket
Socket
Sign inDemoInstall

prompt

Package Overview
Dependencies
Maintainers
2
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prompt - npm Package Compare versions

Comparing version 0.1.12 to 0.2.0

.npmignore

4

examples/add-properties.js
/*
* 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);
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc