import { Component, ILogger, IConfigReader, Json, IInjector } from "merapi"; import { ICommandList, ICommandDescriptor, ICommand } from "interfaces/main"; const commander = require("commander"); export default class Main extends Component { constructor( private config : IConfigReader, private injector : IInjector ) { super(); } public async start(argv : string[]) { const commands = this.config.get("commands"); commander.version(`Merapi CLI version ${this.config.default("version", "1.0.0")}`); await this.compile(commands, commander); commander.parse(argv); const validCommands = commander.commands.map((x : any) => x.name()); if (argv.length === 2 || validCommands.indexOf(argv[2]) === -1) { commander.parse([argv[0], argv[1], "-h"]); } } public async compile(commands : ICommandList, program : ICommand, currKey : string = "") { if (commands) { for (const key in commands) { if (key) { const command = commands[key]; if (command.type === "group") { await this.compileGroup(`${currKey}${key}`, command, program); } else if (command.type === "alias") { this.compileAlias(key, command, program); } else { await this.compileCommand(`${currKey}${key}`, command, program); } } } } } public async compileGroup(key : string, command : ICommandDescriptor, program : ICommand) { await this.compile(command.subcommands, program, `${key}-`); } public compileAlias(key : string, command : ICommandDescriptor, program : ICommand) { program.command(key).action((self) => { const args = self._args; commander.parse(command.alias.split(/\s+/).concat(args)); }); } public async compileCommand(key : string, command : ICommandDescriptor, program : ICommand) { let subcommand; const commandKey = command.alias ? command.alias : key; if (command.args) { subcommand = program.command(`${commandKey} ${command.args}`); } else { subcommand = program.command(commandKey); } if (command.params) { for (const i in command.params) { if (i) { const param = command.params[i]; const flag = param.short ? `-${param.short}, --${i}` : `--${i}`; if (param.value !== undefined) { subcommand.option(`${flag} `, param.desc || "", param.value); } else if (param.bool) { subcommand.option(flag, param.desc || ""); } else { subcommand.option(`${flag} [value]`, param.desc || ""); } } } } subcommand.action(await this.createAction(command.handler, command.middleware)); } public async createAction(handler : string, middleware : string[] = []) : Promise<(...args : any[]) => void> { const methods : any[] = []; for (const md of middleware) { methods.push(await this.injector.resolveMethod(md)); } const handlerMethod = await this.injector.resolveMethod(handler); return (...args : any[]) => { for (const method of methods) { args = method(...args); } handlerMethod(...args); }; } }