UNPKG

@zowe/imperative

Version:
277 lines 14.8 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. * */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CommandYargs = void 0; const util_1 = require("util"); const constants_1 = require("../../../constants"); const AbstractCommandYargs_1 = require("./AbstractCommandYargs"); const CommandProcessor_1 = require("../CommandProcessor"); const CommandResponse_1 = require("../response/CommandResponse"); const utilities_1 = require("../../../utilities"); /** * Define an Imperative Command to Yargs. A command implies that an implementation is present (differs from a "group") * and it does not have children. */ class CommandYargs extends AbstractCommandYargs_1.AbstractCommandYargs { /** * Define the options to Yargs. * @param {yargs.Argv} yargsInstance: The instance of yargs to define the options. * @param {ICommandOptionDefinition[]} zoweOptions: The option definition document array. */ static defineOptionsToYargs(yargsInstance, zoweOptions) { if (zoweOptions != null) { for (const option of zoweOptions) { const definition = { alias: option.aliases, description: option.description }; if (!(option.type == null)) { // don't let yargs handle any types that we are validating ourselves // and don't use custom types as the yargs type since yargs won't understand if (option.type === "json" || option.type === "number") { definition.type = "string"; } else { definition.type = option.type; } } // If this is a boolean type option, default it to undefined so that we can distinguish // between the user not specifying the option at all and them specifying =false if (option.type === "boolean") { definition.default = undefined; } yargsInstance.option(option.name, definition); } } } /** * Define the Imperative JSON command definition to Yargs. Once the command is defined, Yargs will parse and * invoke its 'handler' (below). The handler can then invoke the potential "chain" of handlers in sequence and * is notified when they complete via a promise. * @param {YargsCommandCompleted} commandExecuted - Callback invoked when a command execution is complete. */ defineCommandToYargs(commandExecuted) { // TODO: Fix this when we re-implement Experimental Features - always enabled for now // if (!this.definition.experimental || (ExperimentalFeatures.ENABLED)) { // console.log("experimental? " + this.definition.experimental) this.log.debug("Defining command: " + this.definition.name); /** * Define the command to Yargs. */ this.yargs.command( /** * Define the command name, plus and positional arguments and aliases. */ [this.definition.name + this.buildPositionalString()].concat(this.definition.aliases), /** * Define the description to yargs. */ this.definition.description, /** * Define the options to Yargs. * @param {yargs.Argv} argsForBuilder: The yargs instance to define the options * @return {yargs.Argv}: The populated instance. */ (argsForBuilder) => { this.log.debug("Defining command builder for: " + this.definition.name); argsForBuilder.strict(); CommandYargs.defineOptionsToYargs(argsForBuilder, this.definition.options); return argsForBuilder; }, /** * Define the handler for the command. Invoked when Yargs matches the input command to this definition. * If help is present, then we will invoke the help handler for the command definition. * @param {yargs.Argv} argsForHandler: The yargs instance with the specified command line options. */ (argsForHandler) => __awaiter(this, void 0, void 0, function* () { this.log.debug("Handler invoked for: " + this.definition.name); /** * If help is present, invoke the help for this command definition. */ if (argsForHandler[constants_1.Constants.HELP_OPTION] || argsForHandler[constants_1.Constants.HELP_EXAMPLES]) { this.log.debug("Executing help: " + this.definition.name); this.executeHelp(argsForHandler, commandExecuted); } else if (argsForHandler[constants_1.Constants.HELP_WEB_OPTION]) { this.log.debug("Executing web help: " + this.definition.name); this.executeWebHelp(argsForHandler, commandExecuted); } else { this.log.debug("Executing Handlers: " + this.definition.name); /** * Before invoking the "command" we will build the complete set of handlers for the command. * In some cases, "providers" may be present along the chain of definitions and must be invoked * in sequence. */ const handlerDefinition = []; for (const parent of this.parents) { const definition = parent.definition; if (!(definition.handler == null)) { handlerDefinition.push(definition); } } handlerDefinition.push(this.definition); /** * If handlers are present, invoke the set in sequence OR fail with an error - the "command" */ if (handlerDefinition.length > 0) { this.log.debug("Executing Handlers (%s total)", handlerDefinition.length); const responses = []; /** * Invoke all handlers and collect all responses. */ this.invokeHandlers(handlerDefinition, 0, argsForHandler, responses) .then((successResponses) => { commandExecuted(argsForHandler, this.getZoweYargsResponse(true, `${successResponses.length} command handlers invoked.`, "command handler invoked", successResponses)); }) .catch((errorResponses) => { const response = this.getZoweYargsResponse(false, `Error in command ${this.definition.name}`, "command handler invoked", errorResponses); this.log.error(`Error in command ${this.definition.name}`); this.log.error((0, util_1.inspect)(errorResponses, { depth: null })); commandExecuted(argsForHandler, response); }); } else { /** * No handlers were present - Respond with an error - this condition should not occur if the * definition was validated against the schema. */ const response = this.getZoweYargsResponse(false, `No handlers provided for ${this.definition.name}`, "command handler invoked"); commandExecuted(argsForHandler, response); } } })); // } else { // this.log.debug("Experimental command %s disabled due to user settings", this.definition.name); // } } /** * Construct the positional argument string for Yargs. The positional arguments are always constructed as * "optional" to yargs. This prevents yargs from "throwing errors" if the user requests --help and the positional * parameters are not specified. * @return {string}: The positional argument string used in the Yargs command definition. */ buildPositionalString() { if (this.definition.positionals) { this.log.debug("Building positional string from: " + this.definition.name); let yargPositionalSyntax = this.definition.positionals.length > 0 ? " " : ""; this.definition.positionals.forEach((positional) => { yargPositionalSyntax += "[" + positional.name + "] "; }); const posString = yargPositionalSyntax.substring(0, yargPositionalSyntax.lastIndexOf(" ")); this.log.debug("Positional String: " + posString); return posString; } else { return ""; } } /** * Invoke the "chain" of command handlers provided for this definition. * @param {ICommandDefinition[]} handlers: The array of handlers to invoke. * @param {number} index: The current index in the handler array. * @param {yargs.Argv} argsForHandler: The arguments passed on the command line for the handler. * @param {ICommandResponse[]} responses: The collection of responses from each handler. * @return {Promise<ICommandResponse[]>}: The promise to be fulfilled when all handlers are complete. */ invokeHandlers(handlers, index, argsForHandler, responses) { return new Promise((invokeHandlersResponse, invokeHandlersError) => { var _a; /** * If the index is greater than the handler array, fulfill the promise. */ if (index > handlers.length - 1) { invokeHandlersResponse(responses); } else { // TODO: figure out a better way to handle the fact that yargs keeps going after fail() if (!AbstractCommandYargs_1.AbstractCommandYargs.STOP_YARGS) { // Determine if we should print JSON const printJson = index === handlers.length - 1 && argsForHandler[constants_1.Constants.JSON_OPTION]; // Protect against issues allocating the command processor try { new CommandProcessor_1.CommandProcessor({ definition: handlers[index], fullDefinition: this.constructDefinitionTree(), helpGenerator: this.helpGeneratorFactory.getHelpGenerator({ commandDefinition: handlers[index], fullCommandTree: this.constructDefinitionTree(), experimentalCommandsDescription: this.yargsParms.experimentalCommandDescription }), rootCommandName: this.rootCommandName, commandLine: utilities_1.ImperativeConfig.instance.commandLine, envVariablePrefix: this.envVariablePrefix, promptPhrase: this.promptPhrase, config: utilities_1.ImperativeConfig.instance.config, daemonContext: utilities_1.ImperativeConfig.instance.daemonContext }).invoke({ arguments: argsForHandler, silent: false, responseFormat: printJson ? "json" : "default" }).then((commandHandlerResponse) => { /** * Push the responses - If an error occurs, reject the promise with the error response. */ responses.push(commandHandlerResponse); if (!commandHandlerResponse.success) { invokeHandlersError(responses); } else { /** * Re-invoke with the next index. */ return this.invokeHandlers(handlers, ++index, argsForHandler, responses) .then((recursiveResponses) => { invokeHandlersResponse(recursiveResponses); }) .catch((recursiveError) => { invokeHandlersError(recursiveError); }); } }).catch((error) => { invokeHandlersError(error); }); } catch (processorError) { const response = new CommandResponse_1.CommandResponse({ silent: false, responseFormat: printJson ? "json" : "default", stream: (_a = utilities_1.ImperativeConfig.instance.daemonContext) === null || _a === void 0 ? void 0 : _a.stream }); response.failed(); response.console.errorHeader("Internal Command Error"); response.console.error(processorError.message); response.setError({ msg: processorError.message }); if (response.responseFormat === "json") { response.writeJsonResponse(); } invokeHandlersError(processorError); } } } }); } } exports.CommandYargs = CommandYargs; //# sourceMappingURL=CommandYargs.js.map