Socket
Socket
Sign inDemoInstall

promptly

Package Overview
Dependencies
4
Maintainers
2
Versions
16
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.2.0 to 3.0.0

CHANGELOG.md

207

index.js
'use strict';
var read = require('read');
var promptly = module.exports;
const prompt = require('./lib/prompt');
const getOptions = require('./lib/getOptions');
function prompt(message, opts, fn) {
// Setup read's options
var readOpts = {
prompt: message,
input: opts.input || process.stdin,
output: opts.output || process.stdout,
silent: opts.silent,
replace: opts.replace || ''
};
const promptly = module.exports;
// Use readline question
read(readOpts, function (err, data) {
// Ignore the error attribute
// It is set on SIGINT or if timeout reached (we are not using timeout)
if (err) {
return;
}
promptly.prompt = (message, options) => {
options = getOptions(options);
// Trim?
if (opts.trim) {
data = data.trim();
}
return prompt(message, options);
};
// Mandatory?
if (opts['default'] == null && !data) {
return promptly.prompt(message, opts, fn);
} else {
data = data || opts['default'];
}
// Validator verification
if (opts.validator) {
if (!Array.isArray(opts.validator)) {
opts.validator = [opts.validator];
}
var x;
var length = opts.validator.length;
for (x = 0; x < length; x += 1) {
try {
data = opts.validator[x](data);
} catch (e) {
// Retry automatically if the retry option is enabled
if (opts.retry) {
if (e.message) {
readOpts.output.write(e.message + '\n');
}
return promptly.prompt(message, opts, fn);
}
e.retry = promptly.prompt.bind(promptly, message, opts, fn);
return fn(e);
}
}
}
// Everything ok
fn(null, data);
promptly.password = (message, options) => {
options = getOptions({
silent: true, // Hide password chars
trim: false, // Do not trim so that spaces can be part of the password
default: '', // Allow empty passwords
...options,
});
}
promptly.prompt = function (message, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else if (!opts) {
opts = {};
}
return prompt(message, options);
};
if (opts.trim === undefined) {
opts.trim = true;
}
if (opts.retry === undefined) {
opts.retry = true;
}
if (fn) {
return prompt(message, opts, fn);
}
return new Promise(function (resolve, reject) {
prompt(message, opts, function (err, result) {
if (err) {
return reject(err);
}
resolve(result);
});
promptly.confirm = (message, options) => {
options = getOptions({
trim: false, // Do not trim so that only exact matches pass the validator
...options,
});
};
promptly.password = function (message, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else {
opts = opts || {};
}
// Unshift the validator that will coerse boolean values
options.validator.unshift((value) => {
value = value.toLowerCase();
// Set default options
if (opts.silent === undefined) {
opts.silent = true;
}
if (opts.trim === undefined) {
opts.trim = false;
}
if (opts['default'] === undefined) {
opts['default'] = '';
}
// Use prompt()
return promptly.prompt(message, opts, fn);
};
promptly.confirm = function (message, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else if (!opts) {
opts = {};
}
opts.validator = opts.validator || [];
if (!Array.isArray(opts.validator)) {
opts.validator = [opts.validator];
}
// Push the validator that will coerse boolean values
var validator = function (value) {
if (typeof value === 'string') {
value = value.toLowerCase();
}
switch (value) {

@@ -149,3 +39,2 @@ case 'y':

case '1':
case true:
return true;

@@ -155,45 +44,31 @@ case 'n':

case '0':
case false:
return false;
default:
throw new Error(`Invalid choice: ${value}`);
}
});
throw new Error();
};
opts.validator.push(validator);
// Use choose() with true, false
return promptly.choose(message, [true, false], opts, fn);
return prompt(message, options);
};
promptly.choose = function (message, choices, opts, fn) {
// Arguments parsing
if (typeof opts === 'function') {
fn = opts;
opts = {};
} else if (!opts) {
opts = {};
}
promptly.choose = (message, choices, options) => {
options = getOptions({
trim: false, // Do not trim so that only exact matches pass the validator
...options,
});
opts.validator = opts.validator || [];
if (!Array.isArray(opts.validator)) {
opts.validator = [opts.validator];
}
// Unshift the validator that will validate the data against the choices
options.validator.unshift((value) => {
// Check if the value exists by comparing values loosely
// Additionally, use the coorced value
const index = choices.findIndex((choice) => value == choice); // eslint-disable-line eqeqeq
// Push the choice validator
var nrChoices = choices.length;
var validator = function (value) {
var x;
for (x = 0; x < nrChoices; x++) {
if (choices[x] == value) {
return choices[x];
}
if (index === -1) {
throw new Error(`Invalid choice: ${value}`);
}
throw new Error('Invalid choice: ' + value);
};
opts.validator.push(validator);
return choices[index];
});
// Use prompt()
return promptly.prompt(message, opts, fn);
return prompt(message, options);
};
{
"name": "promptly",
"version": "2.2.0",
"version": "3.0.0",
"description": "Simple command line prompting utility",
"main": "index.js",
"dependencies": {
"read": "^1.0.4"
},
"devDependencies": {
"async": "^2.0.0",
"expect.js": "^0.3.1",
"mocha": "^3.0.2"
},
"scripts": {
"test": "mocha --bail"
},
"repository": {
"type": "git",
"url": "git://github.com/IndigoUnited/node-promptly"
},
"bugs": {
"url": "http://github.com/IndigoUnited/node-promptly/issues"
},
"keywords": [

@@ -32,4 +13,52 @@ "prompt",

],
"author": "IndigoUnited <hello@indigounited.com> (http://indigounited.com)",
"license": "MIT"
"author": "André Cruz <andre@moxy.studio>",
"homepage": "https://github.com/moxystudio/node-promptly",
"repository": {
"type": "git",
"url": "git@github.com:moxystudio/node-promptly.git"
},
"license": "MIT",
"main": "index.js",
"files": [
"lib"
],
"scripts": {
"lint": "eslint .",
"test": "jest --env node --coverage --runInBand",
"prerelease": "npm t && npm run lint",
"release": "standard-version",
"precommit": "lint-staged",
"commitmsg": "commitlint -e $GIT_PARAMS"
},
"standard-version": {
"scripts": {
"posttag": "git push --follow-tags origin master && npm publish"
}
},
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"dependencies": {
"read": "^1.0.4",
"strip-ansi": "^4.0.0"
},
"devDependencies": {
"@commitlint/cli": "^6.0.0",
"@commitlint/config-conventional": "^6.0.2",
"eslint": "^4.3.0",
"eslint-config-moxy": "^4.1.0",
"husky": "^0.14.3",
"jest": "^22.0.0",
"lint-staged": "^6.0.0",
"p-series": "^1.0.0",
"standard-version": "^4.2.0"
}
}
# promptly
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][codecov-image]][codecov-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url] [![Greenkeeper badge][greenkeeper-image]][greenkeeper-url]

@@ -8,8 +8,12 @@ [npm-url]:https://npmjs.org/package/promptly

[npm-image]:http://img.shields.io/npm/v/promptly.svg
[travis-url]:https://travis-ci.org/IndigoUnited/node-promptly
[travis-image]:http://img.shields.io/travis/IndigoUnited/node-promptly/master.svg
[david-dm-url]:https://david-dm.org/IndigoUnited/node-promptly
[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-promptly.svg
[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-promptly#info=devDependencies
[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-promptly.svg
[travis-url]:https://travis-ci.org/moxystudio/node-promptly
[travis-image]:http://img.shields.io/travis/moxystudio/node-promptly/master.svg
[codecov-url]:https://codecov.io/gh/moxystudio/node-promptly
[codecov-image]:https://img.shields.io/codecov/c/github/moxystudio/node-ppromptly/master.svg
[david-dm-url]:https://david-dm.org/moxystudio/node-promptly
[david-dm-image]:https://img.shields.io/david/moxystudio/node-promptly.svg
[david-dm-dev-url]:https://david-dm.org/moxystudio/node-promptly?type=dev
[david-dm-dev-image]:https://img.shields.io/david/dev/moxystudio/node-promptly.svg
[greenkeeper-image]:https://badges.greenkeeper.io/moxystudio/node-promptly.svg
[greenkeeper-url]:https://greenkeeper.io/

@@ -26,155 +30,152 @@ Simple command line prompting utility.

### .prompt(message, [opts], [fn])
### .prompt(message, [options])
Prompts for a value, printing the `message` and waiting for the input.
When done, calls `fn` with `error` and `value` or returns a `Promise` if no `fn` is provided.
Returns a promise that resolves with the input.
Default options:
```js
{
// The default value. If not supplied, the input is mandatory
'default': null,
// Automatically trim the input
'trim': true,
// A validator or an array of validators.
'validator': null,
// Automatically retry if a validator fails
'retry': true,
// Do not print what the user types
'silent': false,
// Replace each character with the specified string when 'silent' is true
'replace': '',
// Input and output streams to read and write to
'input': process.stdin,
'output': process.stdout
}
```
Available options:
The validators have two purposes:
| Name | Description | Type | Default |
| ------ | ------------- | -------- | ------- |
| default | The default value to use if the user provided an empty input | string | undefined |
| trim | Trims the user input | boolean | true |
| validator | A validator or an array of validators | Function/Array | undefined |
| retry | Retry if any of the validators fail | boolean | true |
| silent | Do not print what the user types | boolean | false |
| replace | Replace each character with the specified string when `silent` is true | string | '' |
| input | Input stream to read from | [Stream](https://nodejs.org/api/process.html#process_process_stdin) | process.stdin |
| output | Output stream to write to | [Stream](https://nodejs.org/api/process.html#process_process_stdout) | process.stdout |
```js
function (value) {
// Validation example, throwing an error when invalid
if (value.length !== 2) {
throw new Error('Length must be 2');
}
The same **options** are available to **all functions** but with different default values.
// Parse the value, modifying it
return value.replace('aa', 'bb');
}
```
#### Examples
Example usages
- Ask for a name:
Ask for a name:
```js
const name = await promptly.prompt('Name: ');
```js
promptly.prompt('Name: ', function (err, value) {
// err is always null in this case, because no validators are set
console.log(value);
});
```
console.log(name);
```
Using Promise:
- Ask for a name with a constraint (non-empty value and length > 2):
```js
promptly.prompt('Name: ')
.then(function (value) {
// no need for catch in this case, because no validators are set
console.log(value);
});
```
```js
const validator = function (value) {
if (value.length < 2) {
throw new Error('Min length of 2');
}
Ask for a name with a constraint (non-empty value and length > 2):
return value;
};
```js
var validator = function (value) {
if (value.length < 2) {
throw new Error('Min length of 2');
}
const name = await promptly.prompt('Name: ', { validator });
return value;
};
promptly.prompt('Name: ', { validator: validator }, function (err, value) {
// Since retry is true by default, err is always null
// because promptly will be prompting for a name until it validates
// Since retry is true by default, promptly will keep asking for a name until it is valid
// Between each prompt, the error message from the validator will be printed
console.log('Name is:', value);
});
```
```
Same as above but do not retry automatically:
- Same as above but do not retry automatically:
```js
var validator = function (value) {
if (value.length < 2) {
throw new Error('Min length of 2');
```js
var validator = function (value) {
if (value.length < 2) {
throw new Error('Min length of 2');
}
return value;
};
try {
const name = promptly.prompt('Name: ', { validator, retry: false });
console.log('Name is:', value);
} catch (err) {
console.error('Invalid name:')
console.error(`- ${err.message}`);
}
```
return value;
};
#### Validators
promptly.prompt('Name: ', { validator: validator, retry: false }, function (err, value) {
if (err) {
console.error('Invalid name:', err.message);
// Manually call retry
// The passed error has a retry method to easily prompt again.
return err.retry();
The validators have two purposes: to validate and to transform input.
```js
(value) => {
// Validation example, throwing an error when invalid
if (value.length !== 2) {
throw new Error('Length must be 2');
}
console.log('Name is:', value);
});
// Parse the value, modifying it
return value.replace('aa', 'bb');
}
```
### .confirm(message, [opts], fn)
### .confirm(message, [options])
Ask the user to confirm something.
Calls `fn` with `error` and `value` (true or false).
Ask the user for confirmation, printing the `message` and waiting for the input.
Returns a promise that resolves with the answer.
Truthy values are: `y`, `yes` and `1`.
Falsy values are `n`, `no`, and `0`.
Truthy values are: `y`, `yes` and `1`. Falsy values are `n`, `no`, and `0`.
Comparison is made in a case insensitive way.
Example usage:
The same options from [prompt](#promptmessage-options) are available.
```js
promptly.confirm('Are you sure? ', function (err, value) {
console.log('Answer:', value);
});
```
#### Examples
- Ask to confirm something important:
### .choose(message, choices, [opts], fn)
```js
const answer = await promptly.confirm('Are you really sure? ');
Ask the user to choose between multiple `choices` (array of choices).
Calls `fn` with `error` and `value`.
console.log('Answer:', answer);
```
Example usage:
### .choose(message, choices, [options])
```js
promptly.choose('Do you want an apple or an orange? ', ['apple', 'orange'], function (err, value) {
console.log('Answer:', value);
});
```
Ask the user to choose between multiple `choices` (array of choices), printing the `message` and waiting for the input.
Returns a promise that resolves with the choice.
The same options from [prompt](#promptmessage-options) are available.
### .password(message, [opts], fn)
#### Examples
- Ask to choose between:
```js
const choice = promptly.choose('Do you want an apple or an orange? ', ['apple', 'orange']);
console.log('Choice:', choice);
```
### .password(message, [options])
Prompts for a password, printing the `message` and waiting for the input.
When available, calls `fn` with `error` and `value`.
Returns a promise that resolves with the password.
The available options are the same, except that `trim` and `silent` default to `false` and `default` is an empty string (to allow empty passwords).
The same options from [prompt](#promptmessage-options) are available, except that `trim` and `silent` default to `false` and `default` is an empty string to allow empty passwords.
Example usage:
#### Examples
```js
promptly.password('Type a password: ', { replace: '*' }, function (err, value) {
console.log('Password is:', value);
});
```
- Ask for a password:
```js
const password = promptly.password('Type a password: ');
console.log('Password:', password);
```
- Ask for a password but mask the input with `*`:
```js
const password = promptly.password('Type a password: ', { replace: '*' });
console.log('Password:', password);
```
## License
Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc