UNPKG

4.93 kBJavaScriptView Raw
1import is from '@sindresorhus/is';
2// A hacky check to prevent circular references.
3function isRequest(x) {
4 return is.object(x) && '_onResponse' in x;
5}
6/**
7An error to be thrown when a request fails.
8Contains a `code` property with error class code, like `ECONNREFUSED`.
9*/
10export class RequestError extends Error {
11 input;
12 code;
13 stack;
14 response;
15 request;
16 timings;
17 constructor(message, error, self) {
18 super(message, { cause: error });
19 Error.captureStackTrace(this, this.constructor);
20 this.name = 'RequestError';
21 this.code = error.code ?? 'ERR_GOT_REQUEST_ERROR';
22 this.input = error.input;
23 if (isRequest(self)) {
24 Object.defineProperty(this, 'request', {
25 enumerable: false,
26 value: self,
27 });
28 Object.defineProperty(this, 'response', {
29 enumerable: false,
30 value: self.response,
31 });
32 this.options = self.options;
33 }
34 else {
35 this.options = self;
36 }
37 this.timings = this.request?.timings;
38 // Recover the original stacktrace
39 if (is.string(error.stack) && is.string(this.stack)) {
40 const indexOfMessage = this.stack.indexOf(this.message) + this.message.length;
41 const thisStackTrace = this.stack.slice(indexOfMessage).split('\n').reverse();
42 const errorStackTrace = error.stack.slice(error.stack.indexOf(error.message) + error.message.length).split('\n').reverse();
43 // Remove duplicated traces
44 while (errorStackTrace.length > 0 && errorStackTrace[0] === thisStackTrace[0]) {
45 thisStackTrace.shift();
46 }
47 this.stack = `${this.stack.slice(0, indexOfMessage)}${thisStackTrace.reverse().join('\n')}${errorStackTrace.reverse().join('\n')}`;
48 }
49 }
50}
51/**
52An error to be thrown when the server redirects you more than ten times.
53Includes a `response` property.
54*/
55export class MaxRedirectsError extends RequestError {
56 constructor(request) {
57 super(`Redirected ${request.options.maxRedirects} times. Aborting.`, {}, request);
58 this.name = 'MaxRedirectsError';
59 this.code = 'ERR_TOO_MANY_REDIRECTS';
60 }
61}
62/**
63An error to be thrown when the server response code is not 2xx nor 3xx if `options.followRedirect` is `true`, but always except for 304.
64Includes a `response` property.
65*/
66// TODO: Change `HTTPError<T = any>` to `HTTPError<T = unknown>` in the next major version to enforce type usage.
67// eslint-disable-next-line @typescript-eslint/naming-convention
68export class HTTPError extends RequestError {
69 constructor(response) {
70 super(`Response code ${response.statusCode} (${response.statusMessage})`, {}, response.request);
71 this.name = 'HTTPError';
72 this.code = 'ERR_NON_2XX_3XX_RESPONSE';
73 }
74}
75/**
76An error to be thrown when a cache method fails.
77For example, if the database goes down or there's a filesystem error.
78*/
79export class CacheError extends RequestError {
80 constructor(error, request) {
81 super(error.message, error, request);
82 this.name = 'CacheError';
83 this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_CACHE_ACCESS' : this.code;
84 }
85}
86/**
87An error to be thrown when the request body is a stream and an error occurs while reading from that stream.
88*/
89export class UploadError extends RequestError {
90 constructor(error, request) {
91 super(error.message, error, request);
92 this.name = 'UploadError';
93 this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_UPLOAD' : this.code;
94 }
95}
96/**
97An error to be thrown when the request is aborted due to a timeout.
98Includes an `event` and `timings` property.
99*/
100export class TimeoutError extends RequestError {
101 timings;
102 event;
103 constructor(error, timings, request) {
104 super(error.message, error, request);
105 this.name = 'TimeoutError';
106 this.event = error.event;
107 this.timings = timings;
108 }
109}
110/**
111An error to be thrown when reading from response stream fails.
112*/
113export class ReadError extends RequestError {
114 constructor(error, request) {
115 super(error.message, error, request);
116 this.name = 'ReadError';
117 this.code = this.code === 'ERR_GOT_REQUEST_ERROR' ? 'ERR_READING_RESPONSE_STREAM' : this.code;
118 }
119}
120/**
121An error which always triggers a new retry when thrown.
122*/
123export class RetryError extends RequestError {
124 constructor(request) {
125 super('Retrying', {}, request);
126 this.name = 'RetryError';
127 this.code = 'ERR_RETRYING';
128 }
129}
130/**
131An error to be thrown when the request is aborted by AbortController.
132*/
133export class AbortError extends RequestError {
134 constructor(request) {
135 super('This operation was aborted.', {}, request);
136 this.code = 'ERR_ABORTED';
137 this.name = 'AbortError';
138 }
139}