import * as color from 'colors/safe' import {Logging} from "../service/Logging"; import {Inject} from "@extollo/di"; import {ErrorWithContext} from "@extollo/util"; 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) } } 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 return error } /** * Log the error to the logger. * @param {Error} e */ display(e: Error) { 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(' ')} ${e.constructor ? e.constructor.name : e.name} ${color.red(`---------------------------------------------------`)} ${e.stack} ` if ( contextDisplay ) { errorString += ` With the following context: ${contextDisplay} ` } this.logging.error(errorString, true) } catch (display_e) { // The error display encountered an error... // just throw the original so it makes it out console.error('RunLevelErrorHandler encountered an error:', display_e.message) throw operativeError } } }