(name: string, itemDef: InputDefinition<T>, options?: ArrayDefOptions<T>)
| 62 | * @param options See definition of `ArrayDefOptions` for more details. |
| 63 | */ |
| 64 | export function arrayDef<T>(name: string, itemDef: InputDefinition<T>, options?: ArrayDefOptions<T>): InputDefinition<T[]> { |
| 65 | const minItems = options?.minItems ?? 1 |
| 66 | |
| 67 | const checkForDuplicate = (list: T[], value: T, index: number): boolean => { |
| 68 | if (!options?.allowDuplicates && list.includes(value) && (index === -1 || list[index] !== value)) { |
| 69 | console.log('Duplicate values are not allowed.') |
| 70 | return false |
| 71 | } |
| 72 | return true |
| 73 | } |
| 74 | |
| 75 | const itemSummary = (item: T): string => { |
| 76 | const summary = itemDef.summarizeForEdit(item) |
| 77 | if (summary === uneditable) { |
| 78 | throw Error('The itemDef used for an arrayDef must be editable.') |
| 79 | } |
| 80 | return summary |
| 81 | } |
| 82 | |
| 83 | const editItem = async (itemDef: InputDefinition<T>, list: T[], index: number, context: unknown[]): Promise<void> => { |
| 84 | const currentValue = itemSummary(list[index]) |
| 85 | const choices: Choice<T | symbol>[] = [editOption(currentValue)] |
| 86 | if (list.length > minItems) { |
| 87 | choices.push(deleteOption(currentValue)) |
| 88 | } |
| 89 | choices.push(cancelOption) |
| 90 | |
| 91 | const action = await select({ |
| 92 | message: `What do you want to do with ${currentValue}?`, |
| 93 | choices, |
| 94 | default: editAction, |
| 95 | }) |
| 96 | |
| 97 | if (action === editAction) { |
| 98 | const response = await itemDef.updateFromUserInput(list[index], context) |
| 99 | if (response !== cancelAction) { |
| 100 | if (checkForDuplicate(list, response, index)) { |
| 101 | list[index] = response |
| 102 | } |
| 103 | } |
| 104 | } else if (action === deleteAction) { |
| 105 | list.splice(index, 1) |
| 106 | } |
| 107 | // Nothing to do for cancelAction |
| 108 | } |
| 109 | |
| 110 | // Common code from build and edit |
| 111 | const editList = async (list: T[], context: unknown[]): Promise<FinishAction | CancelAction> => { |
| 112 | // eslint-disable-next-line no-constant-condition |
| 113 | while (true) { |
| 114 | const choices: (Choice<symbol | number>)[] = list.map((item, index) => ({ |
| 115 | name: `Edit ${itemSummary(item)}.`, |
| 116 | value: index, |
| 117 | })) |
| 118 | |
| 119 | if (choices.length > 0) { |
| 120 | choices.push(new Separator()) |
| 121 | } |
no test coverage detected