123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- 'use strict';
- /**
- * Base prompt implementation
- * Should be extended by prompt types.
- */
-
- var _ = require('lodash');
- var chalk = require('chalk');
- var runAsync = require('run-async');
- var { filter, flatMap, share, take, takeUntil } = require('rxjs/operators');
- var Choices = require('../objects/choices');
- var ScreenManager = require('../utils/screen-manager');
-
- class Prompt {
- constructor(question, rl, answers) {
- // Setup instance defaults property
- _.assign(this, {
- answers: answers,
- status: 'pending'
- });
-
- // Set defaults prompt options
- this.opt = _.defaults(_.clone(question), {
- validate: () => true,
- filter: val => val,
- when: () => true,
- suffix: '',
- prefix: chalk.green('?')
- });
-
- // Make sure name is present
- if (!this.opt.name) {
- this.throwParamError('name');
- }
-
- // Set default message if no message defined
- if (!this.opt.message) {
- this.opt.message = this.opt.name + ':';
- }
-
- // Normalize choices
- if (Array.isArray(this.opt.choices)) {
- this.opt.choices = new Choices(this.opt.choices, answers);
- }
-
- this.rl = rl;
- this.screen = new ScreenManager(this.rl);
- }
-
- /**
- * Start the Inquiry session and manage output value filtering
- * @return {Promise}
- */
-
- run() {
- return new Promise(resolve => {
- this._run(value => resolve(value));
- });
- }
-
- // Default noop (this one should be overwritten in prompts)
- _run(cb) {
- cb();
- }
-
- /**
- * Throw an error telling a required parameter is missing
- * @param {String} name Name of the missing param
- * @return {Throw Error}
- */
-
- throwParamError(name) {
- throw new Error('You must provide a `' + name + '` parameter');
- }
-
- /**
- * Called when the UI closes. Override to do any specific cleanup necessary
- */
- close() {
- this.screen.releaseCursor();
- }
-
- /**
- * Run the provided validation method each time a submit event occur.
- * @param {Rx.Observable} submit - submit event flow
- * @return {Object} Object containing two observables: `success` and `error`
- */
- handleSubmitEvents(submit) {
- var self = this;
- var validate = runAsync(this.opt.validate);
- var asyncFilter = runAsync(this.opt.filter);
- var validation = submit.pipe(
- flatMap(value =>
- asyncFilter(value, self.answers).then(
- filteredValue =>
- validate(filteredValue, self.answers).then(
- isValid => ({ isValid: isValid, value: filteredValue }),
- err => ({ isValid: err })
- ),
- err => ({ isValid: err })
- )
- ),
- share()
- );
-
- var success = validation.pipe(
- filter(state => state.isValid === true),
- take(1)
- );
- var error = validation.pipe(
- filter(state => state.isValid !== true),
- takeUntil(success)
- );
-
- return {
- success: success,
- error: error
- };
- }
-
- /**
- * Generate the prompt question string
- * @return {String} prompt question string
- */
-
- getQuestion() {
- var message =
- this.opt.prefix +
- ' ' +
- chalk.bold(this.opt.message) +
- this.opt.suffix +
- chalk.reset(' ');
-
- // Append the default if available, and if question isn't answered
- if (this.opt.default != null && this.status !== 'answered') {
- // If default password is supplied, hide it
- if (this.opt.type === 'password') {
- message += chalk.italic.dim('[hidden] ');
- } else {
- message += chalk.dim('(' + this.opt.default + ') ');
- }
- }
-
- return message;
- }
- }
-
- module.exports = Prompt;
|