import type { Command } from "commander"; import type { NamedCommandDescriptor } from "./command-group-descriptors.js"; export type CommandDescriptorLike = Pick; export type CommandDescriptorCatalog = { descriptors: readonly TDescriptor[]; getDescriptors: () => readonly TDescriptor[]; getNames: () => string[]; getCommandsWithSubcommands: () => string[]; }; export function getCommandDescriptorNames( descriptors: readonly TDescriptor[], ): string[] { return descriptors.map((descriptor) => descriptor.name); } export function getCommandsWithSubcommands( descriptors: readonly TDescriptor[], ): string[] { return descriptors .filter((descriptor) => descriptor.hasSubcommands) .map((descriptor) => descriptor.name); } export function collectUniqueCommandDescriptors( descriptorGroups: readonly (readonly TDescriptor[])[], ): TDescriptor[] { const seen = new Set(); const descriptors: TDescriptor[] = []; for (const group of descriptorGroups) { for (const descriptor of group) { if (seen.has(descriptor.name)) { continue; } seen.add(descriptor.name); descriptors.push(descriptor); } } return descriptors; } export function defineCommandDescriptorCatalog( descriptors: readonly TDescriptor[], ): CommandDescriptorCatalog { return { descriptors, getDescriptors: () => descriptors, getNames: () => getCommandDescriptorNames(descriptors), getCommandsWithSubcommands: () => getCommandsWithSubcommands(descriptors), }; } export function addCommandDescriptorsToProgram( program: Command, descriptors: readonly TDescriptor[], existingCommands: Set = new Set(), ): Set { for (const descriptor of descriptors) { if (existingCommands.has(descriptor.name)) { continue; } program.command(descriptor.name).description(descriptor.description); existingCommands.add(descriptor.name); } return existingCommands; }