import {ResponseFactory} from "./ResponseFactory" import {ErrorWithContext, HTTPStatus} from "@extollo/util" import {Request} from "../lifecycle/Request"; import * as api from "./api" export function error( error: Error | string, status: HTTPStatus = HTTPStatus.INTERNAL_SERVER_ERROR, output: 'json' | 'html' | 'auto' = 'auto' ): ErrorResponseFactory { if ( typeof error === 'string' ) error = new Error(error) return new ErrorResponseFactory(error, status, output) } export class ErrorResponseFactory extends ResponseFactory { protected targetMode: 'json' | 'html' | 'auto' = 'auto' constructor( public readonly error: Error, status: HTTPStatus, output: 'json' | 'html' | 'auto' = 'auto' ) { super() this.status(status) this.mode(output) } public mode(output: 'json' | 'html' | 'auto'): ErrorResponseFactory { this.targetMode = output return this } public async write(request: Request) { request = await super.write(request) const wants = request.wants() if ( this.targetMode === 'json' || (this.targetMode === 'auto' && wants === 'json') ) { request.response.setHeader('Content-Type', 'application/json') request.response.body = this.buildJSON(this.error) } else if ( this.targetMode === 'html' || (this.targetMode === 'auto' && (wants === 'html' || wants === 'unknown')) ) { request.response.setHeader('Content-Type', 'text/html') request.response.body = this.buildHTML(this.error) } // FIXME XML support return request } /** * Build the HTML display for the given error. * @param {Error} error * @return string */ protected buildHTML(error: Error) { let context: any if ( error instanceof ErrorWithContext ) { context = error.context if ( error.originalError ) { error = error.originalError } } let str = ` Sorry, an unexpected error occurred while processing your request.

Name: ${error.name}
Message: ${error.message}
Stack trace:
    - ${error.stack ? error.stack.split(/\s+at\s+/).slice(1).join('
- ') : 'none'}
` if ( context && typeof context === 'object' ) { str += `

Context:
${Object.keys(context).map(key => `    - ${key} : ${context[key]}`)}
                
` } return str } protected buildJSON(error: Error) { return JSON.stringify(api.error(error)) } }