|
| 1 | +const statusCodes = { |
| 2 | + ACCEPTED: 202, |
| 3 | + BAD_GATEWAY: 502, |
| 4 | + BAD_REQUEST: 400, |
| 5 | + CONFLICT: 409, |
| 6 | + CONTINUE: 100, |
| 7 | + CREATED: 201, |
| 8 | + EXPECTATION_FAILED: 417, |
| 9 | + FAILED_DEPENDENCY: 424, |
| 10 | + FORBIDDEN: 403, |
| 11 | + GATEWAY_TIMEOUT: 504, |
| 12 | + GONE: 410, |
| 13 | + HTTP_VERSION_NOT_SUPPORTED: 505, |
| 14 | + IM_A_TEAPOT: 418, |
| 15 | + INSUFFICIENT_SPACE_ON_RESOURCE: 419, |
| 16 | + INSUFFICIENT_STORAGE: 507, |
| 17 | + INTERNAL_SERVER_ERROR: 500, |
| 18 | + LENGTH_REQUIRED: 411, |
| 19 | + LOCKED: 423, |
| 20 | + METHOD_FAILURE: 420, |
| 21 | + METHOD_NOT_ALLOWED: 405, |
| 22 | + MOVED_PERMANENTLY: 301, |
| 23 | + MOVED_TEMPORARILY: 302, |
| 24 | + MULTI_STATUS: 207, |
| 25 | + MULTIPLE_CHOICES: 300, |
| 26 | + NETWORK_AUTHENTICATION_REQUIRED: 511, |
| 27 | + NO_CONTENT: 204, |
| 28 | + NON_AUTHORITATIVE_INFORMATION: 203, |
| 29 | + NOT_ACCEPTABLE: 406, |
| 30 | + NOT_FOUND: 404, |
| 31 | + NOT_IMPLEMENTED: 501, |
| 32 | + NOT_MODIFIED: 304, |
| 33 | + OK: 200, |
| 34 | + PARTIAL_CONTENT: 206, |
| 35 | + PAYMENT_REQUIRED: 402, |
| 36 | + PERMANENT_REDIRECT: 308, |
| 37 | + PRECONDITION_FAILED: 412, |
| 38 | + PRECONDITION_REQUIRED: 428, |
| 39 | + PROCESSING: 102, |
| 40 | + PROXY_AUTHENTICATION_REQUIRED: 407, |
| 41 | + REQUEST_HEADER_FIELDS_TOO_LARGE: 431, |
| 42 | + REQUEST_TIMEOUT: 408, |
| 43 | + REQUEST_TOO_LONG: 413, |
| 44 | + REQUEST_URI_TOO_LONG: 414, |
| 45 | + REQUESTED_RANGE_NOT_SATISFIABLE: 416, |
| 46 | + RESET_CONTENT: 205, |
| 47 | + SEE_OTHER: 303, |
| 48 | + SERVICE_UNAVAILABLE: 503, |
| 49 | + SWITCHING_PROTOCOLS: 101, |
| 50 | + TEMPORARY_REDIRECT: 307, |
| 51 | + TOO_MANY_REQUESTS: 429, |
| 52 | + UNAUTHORIZED: 401, |
| 53 | + UNAVAILABLE_FOR_LEGAL_REASONS: 451, |
| 54 | + UNPROCESSABLE_ENTITY: 422, |
| 55 | + UNSUPPORTED_MEDIA_TYPE: 415, |
| 56 | + USE_PROXY: 305, |
| 57 | +} as const; |
| 58 | + |
| 59 | +type StatusCode = typeof statusCodes[keyof typeof statusCodes]; |
| 60 | + |
| 61 | +export class ExtendableError extends Error { |
| 62 | + constructor(message: string) { |
| 63 | + super(message); |
| 64 | + |
| 65 | + /* |
| 66 | + * Due to a known issue (https://github.com/microsoft/TypeScript/issues/13965) |
| 67 | + * we need to set prototype manually, in order to get `instanceof` to work |
| 68 | + * for classes that extend `Error` |
| 69 | + */ |
| 70 | + Object.setPrototypeOf(this, ExtendableError.prototype); |
| 71 | + |
| 72 | + this.name = this.constructor.name; |
| 73 | + |
| 74 | + if (typeof Error.captureStackTrace === 'function') { |
| 75 | + Error.captureStackTrace(this, this.constructor); |
| 76 | + } else { |
| 77 | + this.stack = new Error(message).stack; |
| 78 | + } |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +type ErrorBody = { |
| 83 | + status: string; |
| 84 | + code: string; |
| 85 | + message: string; |
| 86 | +}; |
| 87 | + |
| 88 | +export class ForbiddenError extends ExtendableError { |
| 89 | + private readonly _originalError?: Error; |
| 90 | + private readonly namespace: string; |
| 91 | + private readonly body: ErrorBody; |
| 92 | + private readonly statusCode: StatusCode; |
| 93 | + |
| 94 | + constructor(message: string, namespace?: string, originalError?: Error) { |
| 95 | + super(message); |
| 96 | + |
| 97 | + /* |
| 98 | + * Due to a known issue (https://github.com/microsoft/TypeScript/issues/13965) |
| 99 | + * we need to set prototype manually, in order to get `instanceof` to work |
| 100 | + * for classes that extend `Error` |
| 101 | + */ |
| 102 | + Object.setPrototypeOf(this, ForbiddenError.prototype); |
| 103 | + |
| 104 | + this.namespace = namespace + ':forbidden'; |
| 105 | + this.name = 'ForbiddenError'; |
| 106 | + this.statusCode = 403; |
| 107 | + |
| 108 | + if (originalError) { |
| 109 | + this._originalError = originalError; |
| 110 | + } |
| 111 | + |
| 112 | + this.body = { status: 'error', code: this.name, message }; |
| 113 | + } |
| 114 | +} |
0 commit comments