'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 });