choices.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import assert from 'node:assert';
  2. import _ from 'lodash';
  3. import Separator from './separator.js';
  4. import Choice from './choice.js';
  5. /**
  6. * Choices collection
  7. * Collection of multiple `choice` object
  8. */
  9. export default class Choices {
  10. /** @param {Array} choices All `choice` to keep in the collection */
  11. constructor(choices, answers) {
  12. this.choices = choices.map((val) => {
  13. if (val.type === 'separator') {
  14. if (!(val instanceof Separator)) {
  15. val = new Separator(val.line);
  16. }
  17. return val;
  18. }
  19. return new Choice(val, answers);
  20. });
  21. this.realChoices = this.choices
  22. .filter(Separator.exclude)
  23. .filter((item) => !item.disabled);
  24. Object.defineProperty(this, 'length', {
  25. get() {
  26. return this.choices.length;
  27. },
  28. set(val) {
  29. this.choices.length = val;
  30. },
  31. });
  32. Object.defineProperty(this, 'realLength', {
  33. get() {
  34. return this.realChoices.length;
  35. },
  36. set() {
  37. throw new Error('Cannot set `realLength` of a Choices collection');
  38. },
  39. });
  40. }
  41. /**
  42. * Get a valid choice from the collection
  43. * @param {Number} selector The selected choice index
  44. * @return {Choice|Undefined} Return the matched choice or undefined
  45. */
  46. getChoice(selector) {
  47. assert(typeof selector === 'number');
  48. return this.realChoices[selector];
  49. }
  50. /**
  51. * Get a raw element from the collection
  52. * @param {Number} selector The selected index value
  53. * @return {Choice|Undefined} Return the matched choice or undefined
  54. */
  55. get(selector) {
  56. assert(typeof selector === 'number');
  57. return this.choices[selector];
  58. }
  59. /**
  60. * Match the valid choices against a where clause
  61. * @param {Object} whereClause Lodash `where` clause
  62. * @return {Array} Matching choices or empty array
  63. */
  64. where(whereClause) {
  65. return _.filter(this.realChoices, whereClause);
  66. }
  67. /**
  68. * Pluck a particular key from the choices
  69. * @param {String} propertyName Property name to select
  70. * @return {Array} Selected properties
  71. */
  72. pluck(propertyName) {
  73. return _.map(this.realChoices, propertyName);
  74. }
  75. // Expose usual Array methods
  76. indexOf(...args) {
  77. return this.choices.indexOf(...args);
  78. }
  79. forEach(...args) {
  80. return this.choices.forEach(...args);
  81. }
  82. filter(...args) {
  83. return this.choices.filter(...args);
  84. }
  85. reduce(...args) {
  86. return this.choices.reduce(...args);
  87. }
  88. find(func) {
  89. return this.choices.find(func);
  90. }
  91. push(...args) {
  92. const objs = args.map((val) => new Choice(val));
  93. this.choices.push(...objs);
  94. this.realChoices = this.choices
  95. .filter(Separator.exclude)
  96. .filter((item) => !item.disabled);
  97. return this.choices;
  98. }
  99. }