UNPKG

@zowe/imperative

Version:
297 lines 15.4 kB
"use strict"; /* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 * * Copyright Contributors to the Zowe Project. * */ Object.defineProperty(exports, "__esModule", { value: true }); exports.YargsConfigurer = void 0; const util_1 = require("util"); const logger_1 = require("../../../logger"); const constants_1 = require("../../../constants"); const AbstractCommandYargs_1 = require("./AbstractCommandYargs"); const CommandProcessor_1 = require("../CommandProcessor"); const CommandUtils_1 = require("../utils/CommandUtils"); const utilities_1 = require("../../../utilities"); const fastest_levenshtein_1 = require("fastest-levenshtein"); /** * Before invoking commands, this class configures some settings and callbacks in Yargs, * including what happens on syntax failures. */ class YargsConfigurer { constructor(rootCommand, yargs, commandRespParms, helpGeneratorFactory, experimentalCommandDescription, rootCommandName, commandLine, envVariablePrefix, promptPhrase) { this.rootCommand = rootCommand; this.yargs = yargs; this.commandRespParms = commandRespParms; this.helpGeneratorFactory = helpGeneratorFactory; this.experimentalCommandDescription = experimentalCommandDescription; this.rootCommandName = rootCommandName; this.commandLine = commandLine; this.envVariablePrefix = envVariablePrefix; this.promptPhrase = promptPhrase; } configure() { /** * Add the command definitions to yargs */ const logger = logger_1.Logger.getImperativeLogger(); this.yargs.help(false); this.yargs.version(false); this.yargs.showHelpOnFail(false); this.yargs.parserConfiguration(YargsConfigurer.yargsConfiguration); // finally, catch any undefined commands this.yargs.command({ command: "*", description: "Unknown group", handler: (argv) => { const attemptedCommand = argv._.join(" "); if (attemptedCommand.trim().length === 0) { if (argv.V) { argv.version = true; } // Allocate a help generator from the factory const rootHelpGenerator = this.helpGeneratorFactory.getHelpGenerator({ commandDefinition: this.rootCommand, fullCommandTree: this.rootCommand, experimentalCommandsDescription: this.experimentalCommandDescription }); new CommandProcessor_1.CommandProcessor({ definition: this.rootCommand, fullDefinition: this.rootCommand, helpGenerator: rootHelpGenerator, rootCommandName: this.rootCommandName, commandLine: this.commandLine, envVariablePrefix: this.envVariablePrefix, promptPhrase: this.promptPhrase, }).invoke({ arguments: argv, silent: false, responseFormat: this.getResponseFormat(argv) }) .then((_response) => { logger_1.Logger.getImperativeLogger().debug("Root help complete."); }) .catch((rejected) => { var _a; const daemonStream = (_a = utilities_1.ImperativeConfig.instance.daemonContext) === null || _a === void 0 ? void 0 : _a.stream; if (daemonStream) { daemonStream.write(utilities_1.DaemonRequest.create({ stderr: `Internal Imperative Error: Root command help ` + `error occurred: ${rejected.message}\n` })); } else { process.stderr.write("Internal Imperative Error: Root command help error occurred: " + rejected.message + "\n"); } logger_1.Logger.getImperativeLogger().error(`Root unexpected help error: ${(0, util_1.inspect)(rejected)}`); }); } else { // unknown command, not successful process.exitCode = constants_1.Constants.ERROR_EXIT_CODE; const closestCommand = this.getClosestCommand(attemptedCommand); argv.failureMessage = this.buildFailureMessage(closestCommand); const failedCommandDefinition = this.buildFailedCommandDefinition(); // Allocate a help generator from the factory const rootHelpGenerator = this.helpGeneratorFactory.getHelpGenerator({ commandDefinition: failedCommandDefinition, fullCommandTree: failedCommandDefinition, experimentalCommandsDescription: this.experimentalCommandDescription }); // Create the command processor for the fail command const failCommand = new CommandProcessor_1.CommandProcessor({ definition: failedCommandDefinition, fullDefinition: failedCommandDefinition, helpGenerator: rootHelpGenerator, rootCommandName: this.rootCommandName, commandLine: utilities_1.ImperativeConfig.instance.commandLine, envVariablePrefix: this.envVariablePrefix, promptPhrase: this.promptPhrase }); // Invoke the fail command failCommand.invoke({ arguments: argv, silent: false, responseFormat: this.getResponseFormat(argv) }) .then((_failedCommandResponse) => { logger.debug("Finished invoking the 'FailedCommand' handler"); }).catch((err) => { logger.error("%s", err.msg); }); } } }); this.yargs.fail((msg, error, _failedYargs) => { process.exitCode = constants_1.Constants.ERROR_EXIT_CODE; AbstractCommandYargs_1.AbstractCommandYargs.STOP_YARGS = true; // todo: figure out a better way error = error || new Error(msg); const failedCommandDefinition = this.buildFailedCommandDefinition(); // Allocate a help generator from the factory const failHelpGenerator = this.helpGeneratorFactory.getHelpGenerator({ commandDefinition: failedCommandDefinition, fullCommandTree: failedCommandDefinition, experimentalCommandsDescription: this.experimentalCommandDescription }); // Create the command processor for the fail command const failCommand = new CommandProcessor_1.CommandProcessor({ definition: failedCommandDefinition, fullDefinition: failedCommandDefinition, helpGenerator: failHelpGenerator, rootCommandName: this.rootCommandName, commandLine: this.commandLine, envVariablePrefix: this.envVariablePrefix, promptPhrase: this.promptPhrase, daemonContext: utilities_1.ImperativeConfig.instance.daemonContext }); const failureMessage = this.buildFailureMessage(); // Construct the fail command arguments const argv = { failureMessage, error, _: [], $0: constants_1.Constants.PRIMARY_COMMAND }; // Invoke the fail command failCommand.invoke({ arguments: argv, silent: false, responseFormat: this.getResponseFormat(argv) }) .then((_failedCommandResponse) => { logger.debug("Finished invoking the 'FailedCommand' handler"); }).catch((err) => { logger.error("%s", err.msg); }); }); process.on("uncaughtException", (error) => { process.exitCode = constants_1.Constants.ERROR_EXIT_CODE; const failedCommandDefinition = this.buildFailedCommandDefinition(); // Allocate a help generator from the factory const failHelpGenerator = this.helpGeneratorFactory.getHelpGenerator({ commandDefinition: failedCommandDefinition, fullCommandTree: failedCommandDefinition, experimentalCommandsDescription: this.experimentalCommandDescription }); // Create the command processor for failure let failureMessage = "Imperative encountered an unexpected exception"; const failCommand = new CommandProcessor_1.CommandProcessor({ definition: failedCommandDefinition, fullDefinition: failedCommandDefinition, helpGenerator: failHelpGenerator, rootCommandName: this.rootCommandName, commandLine: utilities_1.ImperativeConfig.instance.commandLine, envVariablePrefix: this.envVariablePrefix, promptPhrase: this.promptPhrase }); failureMessage += `\nCommand entered: "${this.rootCommandName} ${utilities_1.ImperativeConfig.instance.commandLine}"`; const groupValues = utilities_1.ImperativeConfig.instance.commandLine.split(" ", 2); failureMessage += `\nUse "${this.rootCommandName} ${groupValues[0]} ${groupValues[1]} --help" to view groups, commands, and options.`; // Construct the arguments const argv = { failureMessage, error, _: [], $0: constants_1.Constants.PRIMARY_COMMAND }; // Invoke the fail command processor failCommand.invoke({ arguments: argv, silent: false, responseFormat: this.getResponseFormat(argv) }) .then((_failedCommandResponse) => { logger.debug("Finished invoking the 'FailedCommand' handler"); }).catch((err) => { logger.error("%s", err.msg); }); }); } /** * Builds the failure message that is passed to the failedCommand handler * @return {string} - Returns the failure message */ buildFailureMessage(closestCommand) { const three = 3; let commands = ""; let groups = " "; // default to " " for proper spacing in message let delimiter = ""; // used to delimit between possible 'command' values const groupValues = utilities_1.ImperativeConfig.instance.commandLine.split(" ", three); const commandToCheck = groupValues.join(" "); const nearestCommand = closestCommand || this.getClosestCommand(commandToCheck); let failureMessage = "Command failed due to improper syntax"; if (closestCommand != null) { failureMessage += (0, util_1.format)("\nUnknown group: %s", groupValues[0]); } if (closestCommand != null || !commandToCheck.includes(nearestCommand)) { failureMessage += (0, util_1.format)("\nDid you mean: %s?\n", nearestCommand); } failureMessage += `\nCommand entered: "${utilities_1.ImperativeConfig.instance.commandLine}"`; // limit to three to include two levels of group and command value, if present // loop through the top level groups for (const group of this.rootCommand.children) { if (group.name.trim() === groupValues[0] || group.aliases[0] === groupValues[0]) { groups += groupValues[0] + " "; // found the top level group so loop to see if second level group valid for (const group2 of group.children) { if (group2.name.trim() === groupValues[1] || group2.aliases[0] === groupValues[1]) { groups += groupValues[1] + " "; // second level group valid so command provided is invalid, retrieve the valid command(s) for (let i = 0; i < group2.children.length; i++) { if (i > 0) { delimiter = ", "; } commands += delimiter + group2.children[i].name; } break; } } break; } } if (commands.length > 0) { failureMessage += `\nAvailable commands are "${commands}".`; } failureMessage += `\nUse "${this.rootCommandName}${groups}--help" to view groups, commands, and options.`; return failureMessage; } /** * Define failed command with the current command line arguments. * @returns Failed command definition object */ buildFailedCommandDefinition() { return { name: this.rootCommandName + " " + utilities_1.ImperativeConfig.instance.commandLine, handler: __dirname + "/../handlers/FailedCommandHandler", type: "command", description: "The command you tried to invoke failed" }; } // /** // * Constructs the response object for invoking help and error command handlers. // * @param {boolean} silent - Enable silent mode // * @param {boolean} printJsonResponse - Print a JSON response if requested. // * @return {CommandResponse} - Returns the constructed command response object // */ // private buildResponseObject(silent = false, printJsonResponse = false): CommandResponse { // return new CommandResponse({ // log: this.commandRespParms.log, // silent: silent, // printJsonOnResponse: printJsonResponse, // primaryTextColor: this.commandRespParms.primaryTextColor, // progressBarSpinner: this.commandRespParms.progressBarSpinner, // progressBarPollFrequency: this.commandRespParms.progressBarPollFrequency // }); // } getClosestCommand(attemptedCommand) { const commandTree = CommandUtils_1.CommandUtils.flattenCommandTree(this.rootCommand, true); const commands = []; for (const commandEntry of commandTree) { if (commandEntry.fullName.trim().length === 0) { continue; } commands.push(commandEntry.fullName); } return (0, fastest_levenshtein_1.closest)(attemptedCommand, commands); } /** * Get the command response format based on whether `--rfj` is set. * @param argv Yargs arguments object */ getResponseFormat(argv) { return argv[constants_1.Constants.JSON_OPTION] ? "json" : "default"; } } exports.YargsConfigurer = YargsConfigurer; YargsConfigurer.yargsConfiguration = { "parse-numbers": false, "parse-positional-numbers": false }; //# sourceMappingURL=YargsConfigurer.js.map