prompt-suggestion.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. 'use strict';
  2. const assert = require('assert');
  3. const _ = require('lodash');
  4. /**
  5. * @module promptSuggestion
  6. * @description Utilities to allow remembering answers to Inquirer.js prompts
  7. */
  8. const promptSuggestion = module.exports;
  9. /**
  10. * Returns the default value for a checkbox
  11. *
  12. * @param {Object} question Inquirer prompt item
  13. * @param {*} defaultValue The stored default value
  14. * @return {*} Default value to set
  15. * @private
  16. */
  17. const getCheckboxDefault = (question, defaultValue) => {
  18. // For simplicity we uncheck all boxes and use .default to set the active ones
  19. for (const choice of question.choices) {
  20. if (typeof choice === 'object') {
  21. choice.checked = false;
  22. }
  23. }
  24. return defaultValue;
  25. };
  26. /**
  27. * Returns the default value for a list
  28. *
  29. * @param {Object} question Inquirer prompt item
  30. * @param {*} defaultValue The stored default value
  31. * @return {*} Default value to set
  32. * @private
  33. */
  34. const getListDefault = (question, defaultValue) => {
  35. const choiceValues = question.choices.map(choice => typeof choice === 'object' ? choice.value : choice);
  36. return choiceValues.indexOf(defaultValue);
  37. };
  38. /**
  39. * Return true if the answer should be store in
  40. * the global store, otherwise false
  41. *
  42. * @param {Object} question Inquirer prompt item
  43. * @param {String|Array} answer The inquirer answer
  44. * @param {Boolean} storeAll Should store default values
  45. * @return {Boolean} Answer to be stored
  46. * @private
  47. */
  48. const storeListAnswer = (question, answer, storeAll) => {
  49. const choiceValues = question.choices.map(choice => {
  50. if (Object.prototype.hasOwnProperty.call(choice, 'value')) {
  51. return choice.value;
  52. }
  53. return choice;
  54. });
  55. const choiceIndex = choiceValues.indexOf(answer);
  56. // Check if answer is not equal to default value
  57. if (storeAll || question.default !== choiceIndex) {
  58. return true;
  59. }
  60. return false;
  61. };
  62. /**
  63. * Return true if the answer should be store in
  64. * the global store, otherwise false
  65. *
  66. * @param {Object} question Inquirer prompt item
  67. * @param {String|Array} answer The inquirer answer
  68. * @param {Boolean} storeAll Should store default values
  69. * @return {Boolean} Answer to be stored
  70. * @private
  71. */
  72. const storeAnswer = (question, answer, storeAll) => {
  73. // Check if answer is not equal to default value or is undefined
  74. if (answer !== undefined && (storeAll || question.default !== answer)) {
  75. return true;
  76. }
  77. return false;
  78. };
  79. /**
  80. * Prefill the defaults with values from the global store
  81. *
  82. * @param {Store} store `.yo-rc-global` global config
  83. * @param {Array|Object} questions Original prompt questions
  84. * @return {Array} Prompt questions array with prefilled values.
  85. */
  86. promptSuggestion.prefillQuestions = (store, questions) => {
  87. assert(store, 'A store parameter is required');
  88. assert(questions, 'A questions parameter is required');
  89. const promptValues = store.get('promptValues') || {};
  90. if (!Array.isArray(questions)) {
  91. questions = [questions];
  92. }
  93. questions = questions.map(_.clone);
  94. // Write user defaults back to prompt
  95. return questions.map(question => {
  96. if (question.store !== true) {
  97. return question;
  98. }
  99. const storedValue = promptValues[question.name];
  100. if ((storedValue === undefined) || _.isFunction(question.choices)) {
  101. // Do not override prompt default when question.choices is a function,
  102. // since can't guarantee that the `storedValue` will even be in the returned choices
  103. return question;
  104. }
  105. // Override prompt default with the user's default
  106. switch (question.type) {
  107. case 'rawlist':
  108. case 'expand':
  109. question.default = getListDefault(question, storedValue);
  110. break;
  111. case 'checkbox':
  112. question.default = getCheckboxDefault(question, storedValue);
  113. break;
  114. default:
  115. question.default = storedValue;
  116. break;
  117. }
  118. return question;
  119. });
  120. };
  121. /**
  122. * Store the answers in the global store
  123. *
  124. * @param {Store} store `.yo-rc-global` global config
  125. * @param {Array|Object} questions Original prompt questions
  126. * @param {Object} answers The inquirer answers
  127. * @param {Boolean} storeAll Should store default values
  128. */
  129. promptSuggestion.storeAnswers = (store, questions, answers, storeAll) => {
  130. assert(store, 'A store parameter is required');
  131. assert(answers, 'A answers parameter is required');
  132. assert(questions, 'A questions parameter is required');
  133. assert.ok(_.isObject(answers), 'answers must be a object');
  134. storeAll = storeAll || false;
  135. const promptValues = store.get('promptValues') || {};
  136. if (!Array.isArray(questions)) {
  137. questions = [questions];
  138. }
  139. _.each(questions, question => {
  140. if (question.store !== true) {
  141. return;
  142. }
  143. let saveAnswer;
  144. const key = question.name;
  145. const answer = answers[key];
  146. switch (question.type) {
  147. case 'rawlist':
  148. case 'expand':
  149. saveAnswer = storeListAnswer(question, answer, storeAll);
  150. break;
  151. default:
  152. saveAnswer = storeAnswer(question, answer, storeAll);
  153. break;
  154. }
  155. if (saveAnswer) {
  156. promptValues[key] = answer;
  157. }
  158. });
  159. if (Object.keys(promptValues).length > 0) {
  160. store.set('promptValues', promptValues);
  161. }
  162. };