Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

prompts

Package Overview
Dependencies
Maintainers
1
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prompts - npm Package Compare versions

Comparing version 0.1.4 to 0.1.5

2

lib/elements/autocomplete.js

@@ -129,3 +129,3 @@ 'use strict';

? this.suggestions[this.cursor].title
: this.transform(this.input)
: this.transform.render(this.input)
].join(' ');

@@ -132,0 +132,0 @@

@@ -19,3 +19,5 @@ 'use strict';

this.maxChoices = max;
this.value = choices.map(v => Object.assign({}, { selected: false }, v));
this.value = choices.map(v => {
return Object.assign({ title: v.value, selected: false }, v);
});
this.clear = clear('');

@@ -22,0 +24,0 @@ this.render(true);

@@ -11,3 +11,3 @@ const color = require('clorox');

class NumberPrompt extends Prompt {
constructor({ message, initial = null, min, max, style = 'default' }) {
constructor({ message, initial = '', min, max, style = 'default' }) {
super();

@@ -94,3 +94,3 @@

render() {
let value = this.transform(this.value !== null ? this.value : '');
let value = this.transform.render(this.value !== null ? this.value : '');
if (!this.done) value = color.cyan.underline(value);

@@ -97,0 +97,0 @@

@@ -16,3 +16,3 @@ 'use strict';

this.msg = message;
this.cursor = cursor;
this.cursor = initial || cursor;

@@ -19,0 +19,0 @@ this.values = choices;

@@ -15,5 +15,6 @@ const color = require('clorox');

this.transform = stl.render(style);
this.scale = this.transform.scale;
this.rendered = this.transform(this.value);
this.cursor = cursor || this.rendered.length;
this.rendered = this.transform.render(this.value);
this.cursor = cursor*this.scale || this.rendered.length;

@@ -26,4 +27,3 @@ this.clear = clear('');

this.value = v;
this.rendered = this.transform(v);
this.cursor = Math.min(this.rendered.length, this.cursor);
this.rendered = this.transform.render(v);
this.fire();

@@ -56,4 +56,6 @@ }

_(c, key) {
this.setValue(this.value + c);
this.cursor = this.rendered.length;
let s1 = this.value.slice(0, this.cursor);
let s2 = this.value.slice(this.cursor);
this.cursor++;
this.setValue(`${s1}${c}${s2}`);
this.render();

@@ -63,4 +65,7 @@ }

delete() {
if (this.value.length == 0) return this.bell();
this.setValue(this.value.slice(0, -1));
if (this.value.length === 0) return this.bell();
this.cursor--;
let s1 = this.value.slice(0, this.cursor);
let s2 = this.value.slice(this.cursor+1);
this.setValue(`${s1}${s2}`);
this.render();

@@ -86,3 +91,3 @@ }

right() {
if (this.cursor >= this.rendered.length) return this.bell();
if (this.cursor*this.scale >= this.rendered.length) return this.bell();
this.cursor++;

@@ -101,3 +106,3 @@ this.render();

this.out.write(this.clear + prompt);
this.out.write(cursor.move(-this.rendered.length + this.cursor));
this.out.write(cursor.move(-this.rendered.length + this.cursor*this.scale));

@@ -104,0 +109,0 @@ this.clear = clear(prompt);

@@ -5,4 +5,3 @@ 'use strict';

const toArray = val => (Array.isArray(val) ? val : val == null ? [] : [val]);
const ignore = ['suggest', 'format'];
const ignore = ['suggest', 'format', 'onState'];
const noop = () => {};

@@ -17,8 +16,8 @@

const answers = {};
questions = toArray(questions);
let answer, question, quit, name, key;
questions = [].concat(questions);
let answer, question, quit, name, type, key;
let MAP = prompt._map || {};
for (question of questions) {
name = question.name;
({ name, type } = question);

@@ -31,2 +30,6 @@ if (MAP[name] !== void 0) {

if (typeof question.message !== 'string') {
throw new Error('prompt message is required');
}
// if property is a function, invoke it unless it's ignored

@@ -40,14 +43,14 @@ for (key in question) {

// skip if type is a falsy value
if (!question.type) continue;
if (!type) continue;
if (!prompts.hasOwnProperty(question.type)) {
throw new Error(`prompt type ${question.type} not defined`);
if (prompts[type] === void 0) {
throw new Error(`prompt type (${type}) is not defined`);
}
try {
answer = await prompts[question.type](question);
answers[name] = answer = question.format ? question.format(answer, answers) : answer;
answer = await prompts[type](question);
answers[name] = answer = question.format ? await question.format(answer, answers) : answer;
quit = onSubmit(question, answer);
} catch (err) {
quit = onCancel(question);
quit = !onCancel(question);
}

@@ -54,0 +57,0 @@

'use strict';
const $ = exports;
const el = require('./elements');
const noop = v => v;
function toPrompt(type, args, opts={}) {
return new Promise((res, rej) => {
const p = new el[type](args);
const onAbort = opts.onAbort || noop;
const onSubmit = opts.onSubmit || noop;
p.on('state', args.onState || noop);
p.on('submit', x => res(onSubmit(x)));
p.on('abort', x => rej(onAbort(x)));
});
}
/**
* Text prompt
* @param {string} message Prompt message to display
* @param {string} [initial] Default string value
* @param {string} [style="default"] Render style ('default', 'password', 'invisible')
* @param {string} args.message Prompt message to display
* @param {string} [args.initial] Default string value
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function text({ message, initial, style }) {
if (typeof message !== 'string') throw new Error('message is required');
return new Promise((resolve, reject) => {
const p = new el.TextPrompt({ message, initial, style });
p.on('submit', resolve);
p.on('abort', reject);
});
}
$.text = args => toPrompt('TextPrompt', args);
/**
* Password prompt with masked input
* @param {string} message Prompt message to display
* @param {string} [initial] Default string value
* @param {string} args.message Prompt message to display
* @param {string} [args.initial] Default string value
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*
*/
const password = ({ message, initial }) => text({ message, initial, style: 'password' });
$.password = args => {
args.style = 'password';
return $.text(args);
};
/**
* Prompt where input is invisible, like sudo
* @param {string} message Prompt message to display
* @param {string} [initial] Default string value
* @param {string} args.message Prompt message to display
* @param {string} [args.initial] Default string value
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
const invisible = ({ message, initial }) => text({ message, initial, style: 'invisible' });
$.invisible = args => {
args.style = 'invisible';
return $.text(args);
};
/**
* Number prompt
* @param {string} message Prompt message to display
* @param {number} initial Default number value
* @param {number} [max] Max value
* @param {number} [min] Min value
* @param {string} [style="default"] Render style ('default', 'password', 'invisible')
* @param {string} args.message Prompt message to display
* @param {number} args.initial Default number value
* @param {number} [args.max] Max value
* @param {number} [args.min] Min value
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function number({ message, initial, max, min, style }) {
if (typeof message !== 'string') throw new Error('message is required');
return new Promise((resolve, reject) => {
const p = new el.NumberPrompt({ message, initial, max, min, style });
p.on('submit', resolve);
p.on('abort', reject);
});
}
$.number = args => toPrompt('NumberPrompt', args);
/**
* Classic yes/no prompt
* @param {string} message Prompt message to display
* @param {boolean} [initial=false] Default value
* @param {string} args.message Prompt message to display
* @param {boolean} [args.initial=false] Default value
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function confirm({ message, initial }) {
if (typeof message !== 'string') throw new Error('message is required');
return new Promise((resolve, reject) => {
const p = new el.ConfirmPrompt({ message, initial });
p.on('submit', resolve);
p.on('abort', reject);
});
}
$.confirm = args => toPrompt('ConfirmPrompt', args);
/**
* List prompt, split intput string by `seperator`
* @param {string} message Prompt message to display
* @param {string} [initial] Default string value
* @param {string} [style="default"] Render style ('default', 'password', 'invisible')
* @param {string} [separator] String separator
* @param {string} args.message Prompt message to display
* @param {string} [args.initial] Default string value
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
* @param {string} [args.separator] String separator
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input, in form of an `Array`
*/
function list({ message, initial, style, separator = ',' }) {
if (typeof message !== 'string') throw new Error('message is required');
return new Promise((resolve, reject) => {
const p = new el.TextPrompt({ message, initial, style });
p.on('submit', str => resolve(str.split(separator).map(s => s.trim())));
p.on('abort', reject);
$.list = args => {
const sep = args.separator || ',';
return toPrompt('TextPrompt', args, {
onSubmit: str => str.split(sep).map(s => s.trim())
});
}
};
/**
* Toggle/switch prompt
* @param {string} message Prompt message to display
* @param {boolean} [initial=false] Default value
* @param {string} [active="on"] Text for `active` state
* @param {string} [inactive="off"] Text for `inactive` state
* @param {string} args.message Prompt message to display
* @param {boolean} [args.initial=false] Default value
* @param {string} [args.active="on"] Text for `active` state
* @param {string} [args.inactive="off"] Text for `inactive` state
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function toggle({ message, initial, active, inactive }) {
if (typeof message !== 'string') throw new Error('message is required');
return new Promise((resolve, reject) => {
const p = new el.TogglePrompt({ message, initial, active, inactive });
p.on('submit', resolve);
p.on('abort', reject);
});
}
$.toggle = args => toPrompt('TogglePrompt', args);
/**
* Interactive select prompt
* @param {string} message Prompt message to display
* @param {Array} choices Array of choices objects `[{ title, value }, ...]`
* @param {number} [initial] Index of default value
* @param {string} arr.message Prompt message to display
* @param {Array} arr.choices Array of choices objects `[{ title, value }, ...]`
* @param {number} [arr.initial] Index of default value
* @param {function} [arr.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function select({ message, choices, initial }) {
if (typeof message !== 'string') throw new Error('message is required');
return new Promise((resolve, reject) => {
const p = new el.SelectPrompt({ message, choices, initial });
p.on('submit', resolve);
p.on('abort', reject);
});
}
$.select = args => toPrompt('SelectPrompt', args);
/**
* Interactive multi-select prompt
* @param {string} message Prompt message to display
* @param {Array} choices Array of choices objects `[{ title, value, [selected] }, ...]`
* @param {number} [max] Max select
* @param {string} [hint] Hint to display user
* @param {string} args.message Prompt message to display
* @param {Array} args.choices Array of choices objects `[{ title, value, [selected] }, ...]`
* @param {number} [args.max] Max select
* @param {string} [args.hint] Hint to display user
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function multiselect({ message, choices, max, hint }) {
if (typeof message !== 'string') throw new Error('message is required');
if (!Array.isArray(choices)) throw new Error('choices array is required');
return new Promise((resolve, reject) => {
const p = new el.MultiselectPrompt({ message, choices, max, hint });
const selected = items => items.filter(item => item.selected).map(item => item.value);
p.on('submit', items => resolve(selected(items)));
p.on('abort', items => reject(selected(items)));
$.multiselect = args => {
args.choices = [].concat(args.choices || []);
const toSelected = items => items.filter(item => item.selected).map(item => item.value);
return toPrompt('MultiselectPrompt', args, {
onAbort: toSelected,
onSubmit: toSelected
});
}
};
const byTitle = (input, choices) => Promise.resolve(
choices.filter(item => item.title.slice(0, input.length).toLowerCase() === input.toLowerCase())
);
/**
* Interactive multi-select prompt
* @param {string} message Prompt message to display
* @param {Array} choices Array of auto-complete choices objects `[{ title, value }, ...]`
* @param {Function} [suggest] Function to filter results based on user input. Defaults to stort by `title`
* @param {number} [limit=10] Max number of results to show
* @param {string} [style="default"] Render style ('default', 'password', 'invisible')
* @param {string} args.message Prompt message to display
* @param {Array} args.choices Array of auto-complete choices objects `[{ title, value }, ...]`
* @param {Function} [args.suggest] Function to filter results based on user input. Defaults to sort by `title`
* @param {number} [args.limit=10] Max number of results to show
* @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
* @param {function} [args.onState] On state change callback
* @returns {Promise} Promise with user input
*/
function autocomplete({ message, choices, suggest, limit, style }) {
if (typeof message !== 'string') throw new Error('message is required');
if (!Array.isArray(choices)) throw new Error('choices array is required');
const suggestByTitle = (input, choices) =>
Promise.resolve(
choices.filter(
item => item.title.slice(0, input.length).toLowerCase() === input.toLowerCase()
)
);
suggest = suggest ? suggest : suggestByTitle;
return new Promise((resolve, reject) => {
const p = new el.AutocompletePrompt({ message, choices, suggest, limit, style });
p.on('submit', resolve);
p.on('abort', reject);
});
}
module.exports = {
text,
password,
invisible,
number,
confirm,
list,
toggle,
select,
multiselect,
autocomplete
$.autocomplete = args => {
args.suggest = args.suggest || byTitle;
args.choices = [].concat(args.choices || []);
return toPrompt('AutocompletePrompt', args);
};

@@ -8,5 +8,6 @@ 'use strict';

const styles = Object.freeze({
password: input => '*'.repeat(input.length),
invisible: input => '',
default: input => `${input}`
password: { scale: 1, render: input => '*'.repeat(input.length) },
emoji: { scale: 2, render: input => '😃'.repeat(input.length) },
invisible: { scale: 0, render: input => '' },
default: { scale: 1, render: input => `${input}` }
});

@@ -13,0 +14,0 @@ const render = type => styles[type] || styles.default;

{
"name": "prompts",
"version": "0.1.4",
"version": "0.1.5",
"description": "Lightweight, beautiful and user-friendly prompts",

@@ -36,3 +36,6 @@ "homepage": "https://github.com/terkelg/prompts",

"tape": "^4.8.0"
},
"engines": {
"node": ">= 8"
}
}

@@ -26,3 +26,3 @@ <p align="center">

* **Simple**: prompts has no big dependencies nor is it broken into a dozen tiny modules that only work well together.
* **Simple**: prompts has [no big dependencies](http://npm.anvaka.com/#/view/2d/prompts) nor is it broken into a [dozen](http://npm.anvaka.com/#/view/2d/inquirer) tiny modules that only work well together.
* **User friendly**: prompt uses layout and colors to create beautiful cli interfaces.

@@ -32,2 +32,3 @@ * **Promised**: uses promises and `async`/`await`. No callback hell.

* **Testable**: provides a way to submit answers programmatically.
* **Unified**: consistent experience across all prompts.

@@ -64,3 +65,5 @@

> Examples are meant to be illustrative. `await` calls need to be run within an async function. See [`example.js`](https://github.com/terkelg/prompts/blob/master/example.js).
![split](https://github.com/terkelg/prompts/raw/master/media/split.png)

@@ -93,3 +96,3 @@

```js
const prompt = require('prompts');
const prompts = require('prompts');

@@ -110,3 +113,3 @@ let questions = [

name: 'about',
message: 'Tell somethign about yourself',
message: 'Tell something about yourself',
initial: 'Why should I?'

@@ -193,3 +196,4 @@ }

Return `true` to quit the prompt loop and return all collected responses so far, otherwise continue to iterate prompt objects.
Return `true` to continue and prevent the prompt loop from aborting.
On cancel responses collected so far are returned.

@@ -200,3 +204,3 @@ **Example:**

let onCancel = prompt => {
console.log('Lets stop prompting');
console.log('Never stop prompting!');
return true;

@@ -208,2 +212,34 @@ }

### inject(values)
Type: `Function`<br>
Programmatically inject responses. This enables you to prepare the responses ahead of time.
If any injected values are found the prompt is immediately resolved with the injected value.
This feature is intended for testing only.
#### values
Type: `Object`
Object with key/values to inject. Resolved values are deleted from the internel inject object.
**Example:**
```js
const prompts = require('prompts');
prompts.inject({ q1: 'a1', q2: 'q2' });
let response = await prompts({
type: 'text',
name: 'q1',
message: 'Question 1'
});
// => { q1: 'a1' }
```
> When `q1` resolves it's wiped. `q2` doesn't resolve and is left untouched.
![split](https://github.com/terkelg/prompts/raw/master/media/split.png)

@@ -223,3 +259,4 @@

initial: String || Function || Async Function
format: Function
format: Function || Async Function,
onState: Function
}

@@ -246,2 +283,4 @@ ```

Type: `String|Function`
Defines the type of prompt to display. See the list of [prompt types](#-types) for valid values.

@@ -260,2 +299,4 @@

Type: `String|Function`
The response will be saved under this key/property in the returned response object.

@@ -268,2 +309,4 @@ In case you have multiple prompts with the same name only the latest response will be stored.

Type: `String|Function`
The message to be displayed to the user.

@@ -273,6 +316,10 @@

Optional default prompt value.
Type: `String|Function`
Optional default prompt value. Async functions are suported too.
### format
Type: `Function`
Receive the user input and return the formatted value to be used inside the program.

@@ -294,3 +341,11 @@ The value returned will be added to the response object.

### onState
Type: `Function`
Callback for when the state of the current prompt changes.
The function signature is `(state)` where `state` is an object with a snapshot of the current state.
The state object have two properties `value` and `aborted`. E.g `{ value: 'This is ', aborted: false }`
![split](https://github.com/terkelg/prompts/raw/master/media/split.png)

@@ -324,2 +379,3 @@

| format | <code>function</code> | | Receive user input. The returned value will be added to the response object |
| onState | <code>function</code> | | On state change callback |

@@ -350,2 +406,3 @@

| format | <code>function</code> | Receive user input. The returned value will be added to the response object |
| onState | <code>function</code> | On state change callback |

@@ -377,2 +434,3 @@

| format | <code>function</code> | Receive user input. The returned value will be added to the response object |
| onState | <code>function</code> | On state change callback |

@@ -383,4 +441,3 @@

You can use `up`/`down` to increase/decrease the value.
Only numbers are allowed as input. Default resolve value is `null`.
You can type in numbers and use <kbd>up</kbd>/<kbd>down</kbd> to increase/decrease the value. Only numbers are allowed as input.

@@ -411,8 +468,8 @@ #### Example

| style | <code>string</code> | <code>'default'</code> | Render style (`default`, `password`, `invisible`) |
| onState | <code>function</code> | | On state change callback |
### confirm(message, [initial])
> Classic yes/no prompt.
Hit `y` or `n` to confirm/reject.
Hit <kbd>y</kbd> or <kbd>n</kbd> to confirm/reject.

@@ -438,4 +495,4 @@ #### Example

| format | <code>function</code> | | Receive user input. The returned value will be added to the response object |
| onState | <code>function</code> | | On state change callback |
### list(message, [initial])

@@ -466,2 +523,3 @@ > List prompt that return an array.

| seperator | <code>string</code> | <code>','</code> | String seperator. Will trim all white-spaces from start and end of string |
| onState | <code>function</code> | | On state change callback |

@@ -472,3 +530,3 @@

Use tab or arrow keys to switch between options.
Use tab or <kbd>arrow keys</kbd>/<kbd>tab</kbd>/<kbd>space</kbd> to switch between options.

@@ -497,8 +555,8 @@ #### Example

| inactive | <code>string</code> | <code>'off'</code> | Text for `inactive` state |
| onState | <code>function</code> | | On state change callback |
### select(message, choices, [initial])
> Interactive select prompt.
Use space to select/unselect and arrow keys to navigate the list.
Use <kbd>up</kbd>/<kbd>down</kbd> to navigate. Use <kbd>tab</kbd> to cycle the list.

@@ -529,2 +587,3 @@ #### Example

| choices | <code>Array</code> | Array of choices objects `[{ title, value }, ...]` |
| onState | <code>function</code> | On state change callback |

@@ -535,3 +594,3 @@

Use space to select/unselect and arrow keys to navigate the list.
Use <kbd>space</kbd> to toggle select/unselect and <kbd>up</kbd>/<kbd>down</kbd> to navigate. Use <kbd>tab</kbd> to cycle the list. You can also use <kbd>right</kbd> to select and <kbd>left</kbd> to deselect.
By default this prompt returns an `array` containing the **values** of the selected items - not their display title.

@@ -566,2 +625,3 @@

| hint | <code>string</code> | Hint to display user |
| onState | <code>function</code> | On state change callback |

@@ -575,3 +635,4 @@ This is one of the few prompts that don't take a initial value.

The prompt will list options based on user input.
The prompt will list options based on user input. Type to filter the list.
Use <kbd>up</kbd>/<kbd>down</kbd> to navigate. Use <kbd>tab</kbd> to cycle the result. Hit <kbd>enter</kbd> to select the highlighted item below the prompt.

@@ -605,7 +666,7 @@ The default suggests function is sorting based on the `title` property of the choices.

| choices | <code>Array</code> | | Array of auto-complete choices objects `[{ title, value }, ...]` |
| suggest | <code>function</code> | By `title` string | Filter function. Defaults to stort by `title` property. Suggest should always return a promise |
| suggest | <code>function</code> | By `title` string | Filter function. Defaults to stort by `title` property. `suggest` should always return a promise |
| limit | <code>number</code> | <code>10</code> | Max number of results to show |
| style | <code>string</code> | `'default'` | Render style (`default`, `password`, `invisible`) |
| onState | <code>function</code> | | On state change callback |
Example on what a `suggest` function might look like:

@@ -612,0 +673,0 @@ ```js

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