UNPKG

@zowe/imperative

Version:
243 lines 9.42 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.ImperativeError = void 0; const os = require("node:os"); /** * * @export * @class ImperativeError * @extends {Error} */ class ImperativeError extends Error { /** * Construct the Imperative error object. Contains the defaults of the error and optionally captures diagnostics * and other information. * @param {IImperativeError} details - the error details and text (stack, messages, etc.) * @param {IImperativeErrorParms} parms - control parameters to indicate logging of node-report and more */ constructor(mDetails, parms) { super(); this.mDetails = mDetails; this.mMessage = mDetails.msg; /** * If parms are present, handle them, otherwise perform the default diagnostic collection */ if (parms) { /** * Append a tag if present */ if (parms.tag) { this.mMessage = parms.tag + ": " + this.mMessage; } } } /** * Within the Zowe client SDK, errors are often thrown, caught, modified, and re-thrown. * Sometimes the error that we catch is a standard JavaScript Error. Other times the * error is already an ImperativeError (which can contain more details). A hard-coded * reliance on ImperativeError properties like causeErrors and additionalDetails will not * work if the existingErr is a standard JavaScript Error. Also, the properties of an * ImperativeError can be nested under various properties within its causeErrors property. * * The purpose of this utility function is to interrogate the existing error to form the * most meaningful ImperativeError possible. * * @param {string} existingErr * An existing error to be incorporated into the resulting ImperativeError. * * @param {string} mainMsg * The main message text for the resulting ImperativeError. If not supplied, * the existingErr.message value will be used. * * @returns A newly created ImperativeError * @memberof ImperativeError */ static newImpErrorFromExistingError(existingErr, mainMsg = "") { var _a, _b, _c, _d, _e, _f, _g; if (!existingErr) { return new ImperativeError({ msg: "The supplied parameter 'existingErr' was incorrectly null or undefined", causeErrors: "Stupid programming error", additionalDetails: "Fix your program" }); } // set a mainMsg if one is not supplied as a parm let existingErrMsgUsed = false; if (!mainMsg) { if (existingErr.mMessage) { mainMsg = existingErr.mMessage; existingErrMsgUsed = true; } else if (existingErr.message) { mainMsg = existingErr.message; existingErrMsgUsed = true; } else { mainMsg = "No problem text was supplied."; } } // use the existingErr's message text as the cause (unless we already used that message) let causeToUse = ""; if (existingErr.mMessage && !existingErrMsgUsed) { causeToUse = existingErr.mMessage; } else if (existingErr.message && !existingErrMsgUsed) { causeToUse = existingErr.message; } else if ((_a = existingErr.causeErrors) === null || _a === void 0 ? void 0 : _a.mMessage) { causeToUse = existingErr.causeErrors.mMessage; } else if ((_b = existingErr.cause) === null || _b === void 0 ? void 0 : _b.message) { causeToUse = existingErr.cause.message; } const detailsOutput = { stringVal: "", rawVal: {} }; // Record existingErr's causeErrors property as a string or as raw data. // Sometimes causeErrors are nested. Try the nested one first. if (!ImperativeError.recordPropForOutput((_e = (_d = (_c = existingErr.mDetails) === null || _c === void 0 ? void 0 : _c.causeErrors) === null || _d === void 0 ? void 0 : _d.mDetails) === null || _e === void 0 ? void 0 : _e.causeErrors, detailsOutput)) { ImperativeError.recordPropForOutput((_f = existingErr.mDetails) === null || _f === void 0 ? void 0 : _f.causeErrors, detailsOutput); } // Append existingErr's additionalDetails-like property if it is a string, or record it as an object if (!ImperativeError.recordPropForOutput(existingErr.additionalDetails, detailsOutput)) { if (!ImperativeError.recordPropForOutput((_g = existingErr.causeErrors) === null || _g === void 0 ? void 0 : _g.additionalDetails, detailsOutput)) { if (!ImperativeError.recordPropForOutput(existingErr.cause, detailsOutput)) { if (!(existingErr instanceof ImperativeError)) { // only record the entire existingErr for other people's errors ImperativeError.recordPropForOutput(existingErr, detailsOutput); } } } } // if we could not discover a text message, dump the recorded raw data if (detailsOutput.stringVal.length === 0) { if (Object.keys(detailsOutput.rawVal).length > 0) { detailsOutput.stringVal = ImperativeError.RAW_ERR_MSG + JSON.stringify(detailsOutput.rawVal, null, 2); } } if (detailsOutput.stringVal.length === 0) { detailsOutput.stringVal = "No further details are available."; } const impErrProps = { msg: mainMsg, additionalDetails: detailsOutput.stringVal }; if (causeToUse.length > 0) { impErrProps.causeErrors = causeToUse; } return new ImperativeError(impErrProps); } /** * This function interrogates the supplied propertyVal. If it is a string, it it appended * to outputData.stringVal. If propertyVal is not a string and it is not null-or-undefined, * and outputData.rawVal is currently empty, propertyVal is placed into outputData.rawVal. * * @param {IErrOutputData} outputData [output] * One (or neither) of outputData.stringVal or outputData.rawVal properties are * populated by this function. Before the first call to recordPropForOutput, * stringVal should be an empty string and rawVal should be an empty object. * * @returns True if a property was recorded. False otherwise. * @memberof ImperativeError */ static recordPropForOutput(propertyVal, outputData) { if (!propertyVal) { return false; } if (typeof propertyVal === "string") { if (propertyVal.startsWith(ImperativeError.RAW_ERR_MSG)) { // do not append to our stringVal if propertyVal is already stringified raw data return false; } // append to the string output if (outputData.stringVal.length > 0 && propertyVal.length > 0) { outputData.stringVal += os.EOL; } outputData.stringVal += propertyVal; return true; } else if (Object.keys(outputData.rawVal).length === 0) { // only record one raw property outputData.rawVal = JSON.stringify(propertyVal); return true; } return false; } /** * Return causeErrors * @readonly * @type {any[]} * @memberof ImperativeError */ get causeErrors() { return this.mDetails.causeErrors; } /** * Return additionalDetails * @readonly * @type {string} * @memberof ImperativeError */ get additionalDetails() { return this.mDetails.additionalDetails; } /** * Return IImperativeError object * @readonly * @type {IImperativeError} * @memberof ImperativeError */ get details() { return this.mDetails; } /** * Return errorCode * @readonly * @type {string} * @memberof ImperativeError */ get errorCode() { return this.mDetails.errorCode; } /** * Return whether or not the error dump should be suppressed * @readonly * @type {string} * @memberof ImperativeError */ get suppressDump() { return this.mDetails.suppressDump; } /** * Return stack info * @readonly * @type {string} * @memberof ImperativeError */ get stack() { return this.mDetails.stack; } /** * Accessor for the error message. * @readonly * @return {string}: The error message * @memberof ImperativeError */ get message() { return this.mMessage; } } exports.ImperativeError = ImperativeError; ImperativeError.RAW_ERR_MSG = "Raw error data from operation:\n"; //# sourceMappingURL=ImperativeError.js.map