UNPKG

4.14 kBJavaScriptView Raw
1/*!
2 * question-store <https://github.com/jonschlinkert/question-store>
3 *
4 * Copyright (c) 2015, Jon Schlinkert.
5 * Licensed under the MIT License.
6 */
7
8'use strict';
9
10var util = require('util');
11var debug = require('debug')('questions:question');
12var utils = require('./utils');
13
14/**
15 * Create new `Question` store `name`, with the given `options`.
16 *
17 * ```js
18 * var question = new Question(name, options);
19 * ```
20 * @param {String} `name` The question property name.
21 * @param {Object} `options` Store options
22 * @api public
23 */
24
25function Question(name, message, options) {
26 if (utils.isObject(name)) {
27 options = utils.merge({}, message, name);
28 message = options.message;
29 name = options.name;
30 }
31
32 if (utils.isObject(message)) {
33 options = utils.merge({}, options, message);
34 message = options.message;
35 }
36
37 utils.define(this, 'isQuestion', true);
38 utils.define(this, 'cache', {});
39
40 this.options = options || {};
41 this.type = this.options.type || 'input';
42 this.message = message || this.options.message;
43 this.name = name || this.options.name;
44
45 if (!this.message) {
46 this.message = this.name;
47 }
48
49 utils.merge(this, this.options);
50 createNext(this);
51}
52
53/**
54 * Create the next question to ask, if `next` is passed on the
55 * options.
56 *
57 * @param {Object} `app` question instance
58 */
59
60function createNext(question) {
61 if (!question.options.next) return;
62
63 if (typeof question.options.next === 'function') {
64 question.next = function() {
65 question.options.next.apply(question, arguments);
66 };
67 return;
68 }
69
70 if (typeof question.options.next === 'string') {
71 question.type = 'confirm';
72 question.next = function(answer, questions, answers, next) {
73 if (answer === true) {
74 questions.ask(question.options.next, next);
75 } else {
76 next(null, answers);
77 }
78 };
79 }
80}
81
82/**
83 * Optionally define the next question to ask by setting a custom `next`
84 * function on the question object.
85 *
86 * ```js
87 * questions.choice('deps', 'Where?')
88 * questions.set('install', 'Want to install?', {
89 * type: 'confirm',
90 * next: function(answer, questions, answers, cb) {
91 * if (answer === true) {
92 * questions.ask('config.other', cb);
93 * } else {
94 * cb(null, answers);
95 * }
96 * }
97 * });
98 * ```
99 *
100 * @param {Object} `answer`
101 * @param {Object} `questions`
102 * @param {Object} `answers`
103 * @param {Function} `next`
104 * @return {Function}
105 * @api public
106 */
107
108Question.prototype.next = function(answer, questions, answers, next) {
109 next(null, answers);
110};
111
112/**
113 * Merge the given `options` object with `questions.options` and expose
114 * `get`, `set` and `enabled` properties to simplify checking for options values.
115 *
116 * @param {Object} options
117 * @return {Object}
118 */
119
120Question.prototype.opts = function(options) {
121 var args = [].slice.call(arguments);
122 options = [].concat.apply([], args);
123
124 var opts = utils.omitEmpty(utils.merge.apply(utils.merge, [{}].concat(options)));
125 utils.decorate(opts);
126
127 if (typeof opts.default !== 'undefined') {
128 this.default = opts.default;
129 }
130 if (opts.persist === false) {
131 opts.global = false;
132 opts.hint = false;
133 opts.save = false;
134 }
135 if (opts.save === false) {
136 opts.force = true;
137 }
138 return opts;
139};
140
141Question.prototype.setAnswer = function(val) {
142 this.answer = val;
143 return this;
144};
145
146/**
147 * Resolve the answer for the question from the given data sources, then
148 * set the question's `default` value with any stored hints or answers
149 * if not already defined.
150 *
151 * ```js
152 * question.answer(answers, data, store, hints);
153 * ```
154 * @param {Object} `answers`
155 * @param {Object} `data`
156 * @param {Object} `store`
157 * @param {Object} `hints`
158 * @return {Object}
159 * @api public
160 */
161
162Question.prototype.getAnswer = function(answers, data) {
163 return utils.get(answers, this.name) || utils.get(data, this.name);
164};
165
166/**
167 * Force the question to be asked.
168 *
169 * ```js
170 * question.force();
171 * ```
172 * @return {undefined}
173 * @api public
174 */
175
176Question.prototype.force = function() {
177 this.options.force = true;
178 return this;
179};
180
181/**
182 * Expose `Question`
183 */
184
185module.exports = Question;