UNPKG

commanding

Version:

A simple yet practical command-Line application framework, written in TypeScript.

190 lines (189 loc) 7.41 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = __importDefault(require("lodash")); const parser_1 = require("./helpers/parser"); const not_fancy_1 = require("./loggers/not-fancy"); const constant_1 = require("./loggers/constant"); const awesome_1 = require("./presenters/awesome"); const MissingArgument_1 = require("./errors/MissingArgument"); const MissingOption_1 = require("./errors/MissingOption"); const SanitizationError_1 = require("./errors/SanitizationError"); const CommandNotFound_1 = require("./errors/CommandNotFound"); const GLOBAL_OPTION_REQUIREMENTS = [ { sign: '-h, --help', shorthand: '-h', longhand: '--help', description: 'Display help', required: false, repeatable: false, csv: false, }, { sign: '-V, --version', shorthand: '-V', longhand: '--version', description: 'Display version', required: false, repeatable: false, csv: false, }, { sign: '--no-color', longhand: '--no-color', description: 'Disable colors', required: false, repeatable: false, csv: false, }, { sign: '--quiet', longhand: '--quiet', description: 'Quiet mode - only displays `warn` and `error` level messages', required: false, repeatable: false, csv: false, }, { sign: '-v, --verbose', longhand: '--verbose', description: 'Verbose mode - displays `debug` level messages', required: false, repeatable: false, csv: false, }, ]; class Application { constructor(name, description, version, commands, defaultCommand) { this.name = name; this.description = description; this.version = version; this.commands = commands; this.defaultCommand = defaultCommand; this.commandMap = lodash_1.default.keyBy(commands, command => command.getName()); } hasSubCommand() { return this.commands.length !== 0; } hasDefaultCommand() { return this.defaultCommand !== undefined; } matchCommand(name) { return this.commandMap[name]; } getGlobalOptionRequirements() { return GLOBAL_OPTION_REQUIREMENTS; } makeDefaultPresenter(colorEnabled = true, output = process.stdout) { return new awesome_1.AwesomePresenter(colorEnabled, output); } makeDefaultLogger(level = constant_1.LogLevel.INFO, colorEnabled = true, standardOutput = process.stdout, errorOutput = process.stderr) { return new not_fancy_1.NotFancyLogger(level, colorEnabled, standardOutput, errorOutput); } getGlobalOptions(parsedOptions) { return parser_1.mapOptions(parsedOptions, this.getGlobalOptionRequirements()); } containHelpCommand(parsedArgs) { if (parsedArgs.length !== 2) { return false; } const [instruction, commandName] = parsedArgs; if (instruction !== 'help') { return false; } return this.matchCommand(commandName) !== undefined; } async execute(executable, parsedArgs, parsedOptions, presenter, logger) { const globalOptions = this.getGlobalOptions(parsedOptions); if (globalOptions['--verbose']) { logger.setLevel(constant_1.LogLevel.DEBUG); } if (globalOptions['--quiet']) { logger.setLevel(constant_1.LogLevel.WARN); } if (globalOptions['--no-color']) { presenter.setColor(false); } // Matching sub-command first. if (this.hasSubCommand() && parsedArgs.length > 0) { if (this.containHelpCommand(parsedArgs)) { const command = this.matchCommand(parsedArgs[1]); return this.showCommandHelp(executable, command, presenter); } const commandName = lodash_1.default.first(parsedArgs); const command = this.matchCommand(commandName); if (command !== undefined) { if (this.shouldShowCommandHelp(parsedArgs.slice(1), globalOptions)) { return this.showCommandHelp(executable, command, presenter); } return await command.execute(parsedArgs.slice(1), parsedOptions, presenter, logger); } // If Application do not have a default Command, It means user typed wrong // Command name. if (!this.defaultCommand) { throw new CommandNotFound_1.CommandNotFound(commandName); } } // Global help, version if (parsedArgs.length === 0) { if (globalOptions['--version']) { return this.showVersion(presenter); } if (globalOptions['--help']) { return this.showHelp(executable, presenter); } } // Default Command if (this.defaultCommand) { return await this.defaultCommand.execute(parsedArgs, parsedOptions, presenter, logger); } return this.showHelp(executable, presenter); } async parse(argv, customPresenter, customLogger) { const presenter = customPresenter ? customPresenter : this.makeDefaultPresenter(); const logger = customLogger ? customLogger : this.makeDefaultLogger(); const executable = parser_1.extractExecutableNameFromArgv(argv); try { const [parsedArgs, parsedOptions] = parser_1.parseArgv(argv.slice(2)); return await this.execute(executable, parsedArgs, parsedOptions, presenter, logger); } catch (err) { presenter.renderError(err instanceof Error ? err.message : `${err}`); if (err instanceof MissingArgument_1.MissingArgument || err instanceof MissingOption_1.MissingOption || err instanceof SanitizationError_1.SanitizationError || err instanceof CommandNotFound_1.CommandNotFound) { this.showHelp(executable, presenter); } } } renderApplicationInfo(executable, presenter) { presenter.renderApplicationInfo(executable, this.name, this.description, this.version); } shouldShowCommandHelp(parsedArgs, globalOptions) { if (parsedArgs.length > 0) { return false; } return globalOptions['--help'] == true; } showHelp(executable, presenter) { this.renderApplicationInfo(executable, presenter); presenter.renderApplicationUsage(executable, this.commands, this.defaultCommand); presenter.renderCommandList(this.commands); presenter.renderGlobalOptions(this.getGlobalOptionRequirements()); presenter.renderEnding(); } showCommandHelp(executable, command, presenter) { this.renderApplicationInfo(executable, presenter); command.showHelp(executable, presenter); presenter.renderGlobalOptions(this.getGlobalOptionRequirements()); } showVersion(presenter) { presenter.renderVersion(lodash_1.default.defaultTo(this.version, '')); presenter.renderEnding(); } } exports.Application = Application;