import assert from 'node:assert'; import filter from 'lodash/filter.js'; import map from 'lodash/map.js'; import Separator from './separator.js'; import Choice from './choice.js'; /** * Choices collection * Collection of multiple `choice` object */ export default class Choices { /** @param {Array} choices All `choice` to keep in the collection */ constructor(choices, answers) { this.choices = choices.map((val) => { if (val.type === 'separator') { if (!(val instanceof Separator)) { val = new Separator(val.line); } return val; } return new Choice(val, answers); }); this.realChoices = this.choices .filter(Separator.exclude) .filter((item) => !item.disabled); Object.defineProperty(this, 'length', { get() { return this.choices.length; }, set(val) { this.choices.length = val; }, }); Object.defineProperty(this, 'realLength', { get() { return this.realChoices.length; }, set() { throw new Error('Cannot set `realLength` of a Choices collection'); }, }); } /** * Get a valid choice from the collection * @param {Number} selector The selected choice index * @return {Choice|Undefined} Return the matched choice or undefined */ getChoice(selector) { assert(typeof selector === 'number'); return this.realChoices[selector]; } /** * Get a raw element from the collection * @param {Number} selector The selected index value * @return {Choice|Undefined} Return the matched choice or undefined */ get(selector) { assert(typeof selector === 'number'); return this.choices[selector]; } /** * Match the valid choices against a where clause * @param {Object} whereClause Lodash `where` clause * @return {Array} Matching choices or empty array */ where(whereClause) { return filter(this.realChoices, whereClause); } /** * Pluck a particular key from the choices * @param {String} propertyName Property name to select * @return {Array} Selected properties */ pluck(propertyName) { return map(this.realChoices, propertyName); } // Expose usual Array methods indexOf(...args) { return this.choices.indexOf(...args); } forEach(...args) { return this.choices.forEach(...args); } filter(...args) { return this.choices.filter(...args); } reduce(...args) { return this.choices.reduce(...args); } find(func) { return this.choices.find(func); } push(...args) { const objs = args.map((val) => new Choice(val)); this.choices.push(...objs); this.realChoices = this.choices .filter(Separator.exclude) .filter((item) => !item.disabled); return this.choices; } }