49 lines
1.7 KiB
JavaScript
49 lines
1.7 KiB
JavaScript
'use strict';
|
|
|
|
const ExtendedError = require('./extended-error');
|
|
|
|
// 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)
|
|
//
|
|
// via https://stackoverflow.com/a/42755876/796832
|
|
class RethrownError extends ExtendedError {
|
|
constructor(message, error) {
|
|
super(message);
|
|
if (!error) throw new Error('RethrownError requires a message and error');
|
|
this.original = error;
|
|
this.originalStack = 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(/\r?\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;
|