import commander from "commander" ; import { enableVerboseLogging , logger } from "../logger" ; /**
 * General interface to encapsulate a sub-command.
 * The `name` and `description` are used to give information about the
 * sub-command to the root command.
 *
 * Warning: Avoid implementing this interface directly; use Command() function
 * to generate concrete implementations.
 */ interface Command { name : string ; description : string ; command : commander . Command ; subCommands : Command [ ] ; } param c const linkSubCommands = ( c ) : Command => { const { command , subCommands } = c ; for ( const subCommand of subCommands ) { linkSubCommands ( subCommand ) ; command . command ( subCommand . command . name ( ) ) . description ( subCommand . command . description ( ) ) ; } return c ; } ; param name param description param decorators param subCommands export const Command = ( name , description , decorators = [ ] , subCommands = [ ] ) : Command => { const cmd = new commander . Command ( ) ; cmd . name ( name . toLowerCase ( ) ) . description ( description ) . option ( "-v, --verbose" , "Enable verbose logging" ) . on ( "option:verbose" , ( ) => { enableVerboseLogging ( ) ; } ) ; for ( const decorator of decorators ) { decorator ( cmd ) ; } cmd . on ( "command:*" , ( calledCmd ) => { logger . error ( `Unknown command "${ calledCmd }"` ) ; cmd . outputHelp ( ) ; } ) ; cmd . on ( "option:*" , ( unknownOption ) => { logger . error ( `Unknown option "${ unknownOption }"` ) ; } ) ; return linkSubCommands ( { command : cmd , description , name : name . toLowerCase ( ) , subCommands , } ) ; } ; param argv const decrementArgv = ( argv ) : string [ ] => { const decremented = [ ... argv . slice ( 0 , 2 ) , ... argv . slice ( 3 ) ] ; return decremented ; } ; param cmd param argv export const executeCommand = ( cmd , argv ) : void => { const targetCommandName = argv . slice ( 2 , 3 ) [ 0 ] ; const targetCommand = cmd . subCommands . find ( ( sc ) => sc . name === targetCommandName ) ; if ( targetCommandName && targetCommand ) { executeCommand ( targetCommand , decrementArgv ( argv ) ) ; } else { try { argv . length <= 2 ? cmd . command . outputHelp ( ) : cmd . command . parse ( argv ) ; } catch ( err ) { logger . error ( err ) ; process . exit ( 1 ) ; } } } ;