import ResponseFactory from './ResponseFactory.ts' import {Request} from '../Request.ts' import * as api from '../../support/api.ts' import {HTTPStatus} from '../../const/http.ts' /** * Response factory to render a handled request-level error. * @extends ResponseFactory */ export default class ErrorResponseFactory extends ResponseFactory { /** * The target output mode. * @type 'json' | 'html' */ protected target_mode: 'json' | 'html' = 'html' constructor( /** * The error to display. * @type Error */ public readonly error: Error, /** * THe HTTP status to use for the response. * @type HTTPStatus */ status: HTTPStatus = HTTPStatus.INTERNAL_SERVER_ERROR, /** * The output format. * @type 'json' | 'html' */ output: 'json' | 'html' = 'html', ) { super() this.status(status) this.mode(output) } /** * Override the output mode. * @param {'json' | 'html'} output * @return ErrorResponseFactory */ public mode(output: 'json' | 'html'): ErrorResponseFactory { this.target_mode = output return this } /** * Write this response factory to the given request's response. * @param {Request} request * @return Request */ public async write(request: Request): Promise { request = await super.write(request) if ( this.target_mode === 'json' ) { request.response.headers.set('Content-Type', 'application/json') request.response.body = this.build_json(this.error) } else if ( this.target_mode === 'html' ) { request.response.headers.set('Content-Type', 'text/html') request.response.body = this.build_html(this.error) } return request } /** * Build the HTML display for the given error. * @param {Error} error * @return string */ protected build_html(error: Error) { return ` 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'}
` } protected build_json(error: Error) { return JSON.stringify(api.error(error)) } }