71 lines
1.8 KiB
JavaScript
71 lines
1.8 KiB
JavaScript
'use strict';
|
|
|
|
const prompts = require('./prompts');
|
|
|
|
const ignore = ['suggest', 'format', 'onState'];
|
|
const noop = () => {};
|
|
|
|
/**
|
|
* Prompt for a series of questions
|
|
* @param {Array|Object} questions Single question object or Array of question objects
|
|
* @returns {Object} Object with values from user input
|
|
*/
|
|
async function prompt(questions=[], { onSubmit=noop, onCancel=noop }={}) {
|
|
const answers = {};
|
|
questions = [].concat(questions);
|
|
let answer, question, quit, name, type;
|
|
let MAP = prompt._map || {};
|
|
|
|
for (question of questions) {
|
|
({ name, type } = question);
|
|
|
|
if (MAP[name] !== void 0) {
|
|
answers[name] = MAP[name];
|
|
delete MAP[name];
|
|
continue; // take val & run
|
|
}
|
|
|
|
// if property is a function, invoke it unless it's ignored
|
|
for (let key in question) {
|
|
if (ignore.includes(key)) continue;
|
|
let value = question[key];
|
|
question[key] = typeof value === 'function' ? await value(answer, { ...answers }, question) : value;
|
|
}
|
|
|
|
if (typeof question.message !== 'string') {
|
|
throw new Error('prompt message is required');
|
|
}
|
|
|
|
// update vars in case they changed
|
|
({ name, type } = question);
|
|
|
|
// skip if type is a falsy value
|
|
if (!type) continue;
|
|
|
|
if (prompts[type] === void 0) {
|
|
throw new Error(`prompt type (${type}) is not defined`);
|
|
}
|
|
|
|
try {
|
|
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);
|
|
}
|
|
|
|
if (quit) return answers;
|
|
}
|
|
|
|
return answers;
|
|
}
|
|
|
|
function inject(obj) {
|
|
prompt._map = prompt._map || {};
|
|
for (let k in obj) {
|
|
prompt._map[k] = obj[k];
|
|
}
|
|
}
|
|
|
|
module.exports = Object.assign(prompt, { prompt, prompts, inject });
|