You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
3.2 KiB
JavaScript

"use strict";
const chalk = require("chalk");
const { validateArguments } = require("@validatem/core");
const required = require("@validatem/required");
const defaultTo = require("@validatem/default-to");
const isBoolean = require("@validatem/is-boolean");
const oneOf = require("@validatem/one-of");
const stripErrorFromStack = require("./strip-error-from-stack");
const isInstanceOf = require("./is-instance-of");
const getChain = require("../get-chain");
function formattedErrorHeading(error, colorAll = false) {
let formattedMessage = error.message.trim().replace(/\n/g, " \\n ");
let formattedName = chalk.red(`${chalk.bold(error.name)}:`);
let coloredMessage = (colorAll === true) ? chalk.red(formattedMessage) : formattedMessage;
return `${formattedName} ${coloredMessage}`;
// return chalk.red(`${chalk.bold(error.name)}: ${formattedMessage}`);
}
module.exports = function renderError(_error, _options) {
let [ error, options ] = validateArguments(arguments, {
error: [ required, isInstanceOf(Error) ],
options: [ defaultTo({}), {
// color: [ oneOf([ true, false, "auto" ]), defaultTo("auto") ], // FIXME: Implement
allStacktraces: [ isBoolean, defaultTo(false) ]
}]
});
let {allStacktraces} = options;
let errors = getChain(error);
let detailedErrorsToDisplay = (allStacktraces === true) ? errors : errors.slice(-1);
let summary = errors.map((error, i) => {
let prefix = (i > 0) ? "⤷ " : "";
/* IDEA: After every summarized error, add a summarized stacktrace; that is, a stacktrace that only contains the 'user code' entries that might point the developer at the source of the problem. To do that, we should filter out all node_modules and error-chain stuff, as well as internals like timers.js. Then, we should deduplicate lines across stacktraces, and hide the function name if it's boilerplate (eg. Promise.try.then stuff). Try this out with the 'rpm' regex in the CVM smartctl wrapper, as that covers all bases; duplication, stacktraces without user code, etc. */
// let cleanStack = error.stack.split("\n").filter((line) => {
// return (!line.includes("node_modules")
// && !line.includes("node-error-chain")
// && !line.includes("(timers.js")
// && !line.includes("<anonymous>")
// );
// }).join("\n");
// console.log(cleanStack);
return prefix + formattedErrorHeading(error);
}).join("\n");
let stacktraces = detailedErrorsToDisplay.map((error, i) => {
let causedByPrefix = (i > 0 ? "Caused by: " : "");
let causedByPadding = (i > 0) ? " " : "";
let strippedStack = stripErrorFromStack(error.stack);
let formattedStack = strippedStack.split("\n").map((line) => {
if (line.trim().length === 0) {
return null;
} else if (line[0] === " ") {
return causedByPadding + line;
} else {
return causedByPadding + ` ${line}`;
}
}).filter(line => line != null).join("\n");
let heading = causedByPadding + causedByPrefix + formattedErrorHeading(error);
return `${heading}\n${formattedStack}`;
}).join("\n\n");
let stacktraceSection = (allStacktraces === true)
? `${chalk.cyan("All stacktraces:")}\n\n${stacktraces}`
: `${chalk.cyan("Stacktrace for original error:")}\n\n${stacktraces}`;
return `${summary}\n\n${stacktraceSection}`;
};