From 8f2c2581949a17975529ce3f381b4352b8faa65a Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Sun, 27 Sep 2020 13:58:57 +0200 Subject: [PATCH] Don't collapse newlines in error messages --- src/packages/render/index.js | 70 +++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/src/packages/render/index.js b/src/packages/render/index.js index b89d787..2ec2a9e 100644 --- a/src/packages/render/index.js +++ b/src/packages/render/index.js @@ -1,6 +1,7 @@ "use strict"; const chalk = require("chalk"); +const syncpipe = require("syncpipe"); const { validateArguments } = require("@validatem/core"); const required = require("@validatem/required"); @@ -12,8 +13,27 @@ 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 "); +function prefixExtraLines(string, prefix) { + return string + .split("\n") + .map((line, i) => { + if (i > 0) { + return prefix + line; + } else { + return line; + } + }) + .join("\n"); +} + +function formattedErrorHeading(error, colorAll = false, indentation) { + let formattedMessage = syncpipe(error.message, [ + (_) => _.trim(), + (_) => (indentation != null) + ? prefixExtraLines(_, indentation) + : _ + ]); + let formattedName = chalk.red(`${chalk.bold(error.name)}:`); let coloredMessage = (colorAll === true) ? chalk.red(formattedMessage) : formattedMessage; @@ -56,36 +76,36 @@ module.exports = function renderError(_error, _options) { // Special case: there's not actually a cause chain, so we should render the error more simply return formattedError(errors[0]); } else { - let detailedErrorsToDisplay = (allStacktraces === true) ? errors : errors.slice(-1); + let detailedErrorsToDisplay = (allStacktraces === true) ? errors : errors.slice(-1); - let summary = errors.map((error, i) => { - let prefix = (i > 0) ? "⤷ " : ""; + 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("") - // ); - // }).join("\n"); + /* 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("") + // ); + // }).join("\n"); - // console.log(cleanStack); - - return prefix + formattedErrorHeading(error); - }).join("\n"); + // console.log(cleanStack); + + return prefix + formattedErrorHeading(error, false, " "); + }).join("\n"); - let stacktraces = detailedErrorsToDisplay.map((error, i) => { - let causedByPrefix = (i > 0 ? "Caused by: " : ""); - let causedByPadding = (i > 0) ? " " : ""; + let stacktraces = detailedErrorsToDisplay.map((error, i) => { + let causedByPrefix = (i > 0 ? "Caused by: " : ""); + let causedByPadding = (i > 0) ? " " : ""; return formattedError(error, causedByPadding, causedByPrefix); - }).join("\n\n"); + }).join("\n\n"); - let stacktraceSection = (allStacktraces === true) - ? `${chalk.cyan("All stacktraces:")}\n\n${stacktraces}` - : `${chalk.cyan("Stacktrace for original error:")}\n\n${stacktraces}`; + 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}`; + return `${summary}\n\n${stacktraceSection}`; } };