/** * Lets any layer fail a request with an HTTP status, which the error middleware * turns into the response. * * @module */ import { APIErrorCode } from "../../shared/api.ts"; /** Passed to an {@link APIException}; any other status is a type error. */ export type APIStatus = 400 | 401 | 403 | 404 | 409 | 429 | 500 | 502; const CODES: Record = { 400: APIErrorCode.BAD_REQUEST, 401: APIErrorCode.UNAUTHORIZED, 403: APIErrorCode.FORBIDDEN, 404: APIErrorCode.NOT_FOUND, 409: APIErrorCode.CONFLICT, 429: APIErrorCode.RATE_LIMITED, 500: APIErrorCode.SERVER_ERROR, 502: APIErrorCode.BAD_GATEWAY, }; /** * Thrown by a route, a service or a remote fetch to answer the request with an * error. The error middleware sends it as an `APIFailure`, message included, * so the message must be fit for the user. Use 401 for a caller who isn't * signed in, 403 for one who is but may not, and 404 rather than 403 when the * caller mustn't learn that the thing exists. */ export class APIException extends Error { readonly code: APIErrorCode; readonly status: APIStatus; constructor(status: APIStatus, message: string) { super(message); this.status = status; this.code = CODES[status]; } }