An open API service indexing awesome lists of open source software.

https://github.com/artdecocode/reloquent

Readline query with timeout for Node.js
https://github.com/artdecocode/reloquent

Last synced: 2 months ago
JSON representation

Readline query with timeout for Node.js

Awesome Lists containing this project

README

          

# reloquent

[![npm version](https://badge.fury.io/js/reloquent.svg)](https://www.npmjs.com/package/reloquent)
[![Build status](https://ci.appveyor.com/api/projects/status/9bkgy77h7arflx24?svg=true)](https://ci.appveyor.com/project/4r7d3c0/reloquent)

_Reloquent_ allows to ask users a question, a confirmation (y/n), or a series of questions via the read-line interface.

```sh
yarn add reloquent
npm i reloquent
```

## Table Of Contents

- [Table Of Contents](#table-of-contents)
- [API](#api)
- [`Question` Type](#question-type)
* [text*](#text)
* [validation](#validation)
* [postProcess](#postprocess)
* [defaultValue](#defaultvalue)
* [getDefault](#getdefault)
* [password](#password)
* [Question](#type-question)
- [`async askSingle(question: (string|!Question), timeout=: number): string`](#async-asksinglequestion-stringquestiontimeout-number-string)
- [`async askQuestions(questions: !Questions, timeout=: number): !Object`](#async-askquestionsquestions-questionstimeout-number-objectstring-string)
* [`Questions`](#type-questions)
- [`async confirm(question: (string|!Question), options=: !ConfirmOptions): boolean`](#async-confirmquestion-stringquestionoptions-confirmoptions-boolean)
* [`ConfirmOptions`](#type-confirmoptions)
- [Copyright](#copyright)



## API

There are 4 types of calls to the API:

- ask a single question as a string;
- ask a single question as an object;
- ask multiple questions.
- ask for a confirmation;

Their respective methods can be accessed via the `import` statement:

```js
import ask, { askSingle, confirm } from 'reloquent'
```



## `Question` Type

When asking a question which is not a string, the `question` object should have the following structure:



Property
Type
Description
Example




text*
string
Display text. Required.

```js
const q = {
text: 'What is your name',
}
```



validation
(async) function
A function which needs to throw an error if validation does not pass.

```js
const q = {
text: 'What is your name',
validate(v) {
if (!v.length) {
throw new Error('Name required.')
}
},
}
```



postProcess
(async) function
A function to transform the answer.

```js
const q = {
text: 'What is your name',
postProcess(v) {
return `${v.toLowerCase()}`
},
}
```



defaultValue
string

Default answer (shown to users in `[default]` brackets).

```js
const q = {
text: 'What is your name',
defaultValue: 'Visitor',
}
```



getDefault
(async) function
A function to execute to obtain the default value.

```js
const q = {
text: 'What is your name',
async getDefault() {
await git('config', 'user.name')
},
}
```



password
boolean
Hide the inputs behind * when typing the answer.

```js
const q = {
text: 'Please enter the password',
password: true,
}
```


If both `defaultValue` and `getDefault` are provided, the result of the `getDefault` takes precedence:

```js
const q = {
defaultValue: 'I desire it much',
getDefault() {
return 'I desire it much so'
},
}
```

![getDefault will get precedence](doc/precedence.gif)

When the `password` property is set to true, the answer will be hidden behind the `*` symbols.

```js
import { askSingle } from 'reloquent'

const Password = async () => {
const res = await askSingle({
text: 'Please enter the password',
password: true,
})
return res
}
```
```
Please enter the password: ********
```

Question extends readline.ReadLineOptions: A question.

| Name | Type | Description | Default |
| ------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------- | ------- |
| __text*__ | string | The text to show to the user. | - |
| defaultValue | string | The default answer to the question. | - |
| password | boolean | Hide the inputs behind `*` when typing the answer. | `false` |
| getDefault | () => (string \| !Promise<string>) | The function which will get the default value, possibly asynchronously. | - |
| validation | (answer: string) => void | The validation function which should throw on error. | - |
| postProcess | (answer: string) => (string \| !Promise<string>) | The transformation function for the answer. | - |



## async askSingle(
  `question: (string|!Question),`
  `timeout=: number,`
): string
Ask user a question via the CLI. Returns the answer to the question.
If a timeout is passed, the promise will expire after the specified
number of milliseconds if the answer was not given.

- question* (string \| !Question): The question to present to the user.
- timeout `number` (optional): How long to wait before rejecting the promise. Waits forever by default.

Questions can be asked as a simple string.

```js
import { askSingle } from 'reloquent'

(async () => {
try {
const answer = await askSingle('What brought you her', 10000)
console.log(`You've answered: ${answer}`)
} catch (err) {
console.log()
console.log(err)
console.log('Nevermind...')
}
})()
```

```fs
What brought you her: I guess Art is the cause.
```

```fs
You've answered: I guess Art is the cause.
```

Alternatively, _Reloquent_ can ask a question which is passed as an object of the `Question` type, and return a string.

```js
import { askSingle } from 'reloquent'

(async () => {
const answer = await askSingle({
text: 'Do you wish me to stay so long?',
validation(a) {
if (a.length < 5) {
throw new Error('The answer is too short')
}
},
defaultValue: 'I desire it much',
postProcess(a) {
return `${a}!`
},
async getDefault() {
return 'I desire it much so'
},
})
console.log(answer)
})()
```

```fs
Do you wish me to stay so long? [I desire it much]
```

```fs
I desire it much!
```



## async askQuestions(
  `questions: !Questions,`
  `timeout=: number,`
): !Object
Ask user a series of questions via CLI and transform them into answers.
Returns an object with keys as questions' texts and values as answers.

- questions* !Questions: A set of questions.
- timeout `number` (optional): How long to wait before rejecting the promise. Waits forever by default.

!Object<string, (string \| !Question)> __`Questions`__: A set of questions.

```js
import ask from 'reloquent'

const Ask = async () => {
const questions = {
title: {
text: 'Title',
validation(a) {
if (!a) throw new Error('Please enter the title.')
},
},
description: {
text: 'Description',
postProcess: s => s.trim(),
defaultValue: 'A test default value',
},
date: {
text: 'Date',
async getDefault() {
await new Promise(r => setTimeout(r, 200))
return new Date().toLocaleString()
},
},
}
const res = await ask(questions)
return res
}
```

If when provided with the following answers (leaving _Date_ as it is), the result will be returned as an object:

```
Title: hello
Description: [A test default value] world
Date: [2/22/2020, 21:37:04]

Result: {
"title": "hello",
"description": "world",
"date": "2/22/2020, 21:37:04"
}
```



## async confirm(
  `question: (string|!Question),`
  `options=: !ConfirmOptions,`
): boolean
Ask a yes/no question. Returns `true` when answer was `y` and `false` otherwise.

- question* (string \| !Question): The question, such as "Add default options", or "Continue to delete?".
The question mark can added automatically.
- options !ConfirmOptions (optional): Options for the confirmation question.

__`ConfirmOptions`__: Options for the confirmation question.

| Name | Type | Description | Default |
| ---------- | ---------------- | ------------------------------------------------------------------------ | ------- |
| defaultYes | boolean | Whether the default value is _yes_. | `true` |
| timeout | number | How long to wait before rejecting the promise. Waits forever by default. | - |

```js
import { confirm } from 'reloquent'

const Confirm = async (question) => {
const res = await confirm(question, {
defaultYes: false,
})
return res
}
```

```
Do you wish to continue (y/n): [n] y

Result: true
```



## Copyright




Art Deco


© Art Deco™ 2020