You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/lifecycle/RunLevelErrorHandler.ts

93 lines
2.6 KiB

import * as color from 'colors/safe'
import {Logging} from '../service/Logging'
import {Inject} from '../di'
import {ErrorWithContext} from '../util'
/**
* Class with logic for handling errors that are thrown at the run-level of the application.
*
* Colloquially, these are errors thrown ourside the request-lifecycle that are not caught by a unit.
*/
export class RunLevelErrorHandler {
@Inject()
protected logging!: Logging
/**
* Get the error handler function.
* @type (e: Error) => void
*/
get handle(): (e: Error) => void {
return (e: Error) => {
this.display(e)
process.exit(1)
}
}
/**
* Wrap the given base Error instance into an ErrorWithContext.
* @param e
* @param context
*/
wrapContext(e: Error, context: {[key: string]: any}): ErrorWithContext {
if ( e instanceof ErrorWithContext ) {
e.context = {...e.context,
...context}
return e
}
const error = new ErrorWithContext(e.message)
error.originalError = e
error.context = context
error.stack = e.stack
return error
}
/**
* Log the error to the logger.
* @param {Error} e
*/
display(e: Error): void {
let operativeError = e
let context: {[key: string]: string} = {}
if ( e instanceof ErrorWithContext ) {
if ( e.originalError ) {
operativeError = e.originalError
}
context = e.context
}
const contextDisplay = Object.keys(context).map(key => ` - ${key}: ${context[key]}`)
.join('\n')
try {
let errorString = `RunLevelErrorHandler invoked:
${color.bgRed(' ')}
${color.bgRed(' UNCAUGHT RUN-LEVEL ERROR ')}
${color.bgRed(' ')}
${operativeError.constructor ? operativeError.constructor.name : operativeError.name}
${color.red(`---------------------------------------------------`)}
${operativeError.stack}
`
if ( contextDisplay ) {
errorString += `
With the following context:
${contextDisplay}
`
}
this.logging.error(errorString, true)
} catch (displayError: unknown) {
if ( displayError instanceof Error ) {
// The error display encountered an error...
// just throw the original so it makes it out
console.error('RunLevelErrorHandler encountered an error:', displayError.message) // eslint-disable-line no-console
}
throw operativeError
}
}
}