matrix-public-archive/server/lib/rethrown-error.js

61 lines
2.0 KiB
JavaScript
Raw Normal View History

'use strict';
// via https://stackoverflow.com/a/42755876/796832
// Standard error extender from @deployable/errors
class ExtendedError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
this.message = message;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = new Error(message).stack;
}
}
}
// A way to create a new error with a custom message but keep the stack trace of
// the original error. Useful to give more context and why the action was tried
// in the first place.
//
// For example, if you get a generic EACCES disk error of a certain file, you
// want to know why and what context the disk was trying to be read. A
// stack-trace is not human digestable and only gives the where in the code.
// What I actually need to know is that I was trying to read the `ratelimit` key
// from the config when this error occured.
//
// `new RethrownError('Failed to get the ratelimit key from the config', originalError)` (failed to read the disk)
class RethrownError extends ExtendedError {
constructor(message, error) {
super(message);
if (!error) throw new Error('RethrownError requires a message and error');
this.original = error;
this.newStack = this.stack;
// The number of lines that make up the message itself. We count this by the
// number of `\n` and `+ 1` for the first line because it doesn't start with
// new line.
const messageLines = (this.message.match(/\n/g) || []).length + 1;
const indentedOriginalError = error.stack
.split('\n')
.map((line) => ` ${line}`)
.join('\n');
this.stack =
this.stack
.split('\n')
// We use `+ 1` here so that we include the first line of the stack to
// people know where the error was thrown from.
.slice(0, messageLines + 1)
.join('\n') +
'\n' +
' --- Original Error ---\n' +
indentedOriginalError;
}
}
module.exports = RethrownError;