@beyonk/http 12.4.2 → 12.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +4 -0
- package/dist/index.cjs +22 -4
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +22 -4
- package/package.json +1 -1
package/README.MD
CHANGED
|
@@ -192,10 +192,14 @@ Handlers have a signature with two items:
|
|
|
192
192
|
})
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
+
Every error carries the request that failed as `e.request` (`{ method, url }`), and HTTP failures also carry `e.status` and the parsed response as `e.body`. Errors thrown by `fetch` itself, such as network failures or aborts, have `e.request` but no `e.status`.
|
|
196
|
+
|
|
195
197
|
ctx can be whatever you want really - it is whatever you pass in as `context(...)`.
|
|
196
198
|
|
|
197
199
|
However, if the `context` object you pass in has a `fetch` function, this is used as the `fetch` for XHR requests.
|
|
198
200
|
|
|
201
|
+
If it has a `logger` with an `error(details, message)` method, such as a pino logger, every failure that reaches a `default` handler (request-level or global) is logged through it before the handler runs, with `err`, `status`, `method`, `url` and `body`. Without one the console is used. Failures caught by a status-specific handler such as `.notFound()` are not logged.
|
|
202
|
+
|
|
199
203
|
```js
|
|
200
204
|
export async function preload () {
|
|
201
205
|
await Api
|
package/dist/index.cjs
CHANGED
|
@@ -29,10 +29,13 @@ var HttpError = class extends Error {
|
|
|
29
29
|
* Create a new HTTP error
|
|
30
30
|
* @param {string} message - Error message
|
|
31
31
|
* @param {any} body - Error response body
|
|
32
|
+
* @param {number} [status] - HTTP status code, absent when the request never got a response
|
|
32
33
|
*/
|
|
33
|
-
constructor(message, body) {
|
|
34
|
+
constructor(message, body, status) {
|
|
34
35
|
super(message);
|
|
35
36
|
this.body = body;
|
|
37
|
+
this.status = status;
|
|
38
|
+
this.request = void 0;
|
|
36
39
|
}
|
|
37
40
|
};
|
|
38
41
|
var AccessDeniedError = class extends HttpError {
|
|
@@ -141,11 +144,26 @@ var Api = class {
|
|
|
141
144
|
handle(e, ctx) {
|
|
142
145
|
const constructorName = Object.getPrototypeOf(e).constructor.name;
|
|
143
146
|
const globalHandlerName = `${constructorName[0].toLowerCase()}${constructorName.slice(1, -5)}`;
|
|
144
|
-
const
|
|
147
|
+
const specificHandler = this.handlers[constructorName] || this.options.handlers && this.options.handlers[globalHandlerName];
|
|
148
|
+
const handler = specificHandler || this.defaultHandler || this.options.handlers && this.options.handlers.default || ((e2) => {
|
|
145
149
|
console.error(constructorName, e2.message, e2);
|
|
146
150
|
});
|
|
151
|
+
if (!specificHandler) {
|
|
152
|
+
this.log(e, ctx);
|
|
153
|
+
}
|
|
147
154
|
return handler(e, ctx);
|
|
148
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Log a failed request through the context logger, or the console
|
|
158
|
+
* @param {HttpError} e - Error instance
|
|
159
|
+
* @param {ApiContext} [ctx] - API context
|
|
160
|
+
*/
|
|
161
|
+
log(e, ctx) {
|
|
162
|
+
const logger = ctx && ctx.logger || console;
|
|
163
|
+
const { method, url } = e.request || {};
|
|
164
|
+
const reason = e.status ? `with ${e.status}` : `(${e.message})`;
|
|
165
|
+
logger.error({ err: e, status: e.status, method, url, body: e.body }, `${method} ${url} failed ${reason}`);
|
|
166
|
+
}
|
|
149
167
|
/**
|
|
150
168
|
* Send the HTTP request
|
|
151
169
|
* @template T
|
|
@@ -175,7 +193,7 @@ var Api = class {
|
|
|
175
193
|
try {
|
|
176
194
|
result = await this.#doQuery(1, client, ep, options);
|
|
177
195
|
} catch (e) {
|
|
178
|
-
|
|
196
|
+
e.request = { method: options.method, url: ep };
|
|
179
197
|
return this.handle(e, this.ctx);
|
|
180
198
|
} finally {
|
|
181
199
|
this.resetRequest();
|
|
@@ -228,7 +246,7 @@ var Api = class {
|
|
|
228
246
|
console.log("Failed to parse error body when asked.");
|
|
229
247
|
}
|
|
230
248
|
const ClientError = getErrorByCode(r.status);
|
|
231
|
-
throw new ClientError(r.statusText, content);
|
|
249
|
+
throw new ClientError(r.statusText, content, r.status);
|
|
232
250
|
} catch (e) {
|
|
233
251
|
if (retry.attempts && retry.errors && attempt < retry.attempts && retry.errors.includes(e.code)) {
|
|
234
252
|
console.warn(`Got ${e.code} when calling ${endpoint}. Retrying request (${attempt}/${retry.attempts})`);
|
package/dist/index.d.cts
CHANGED
|
@@ -30,6 +30,10 @@ type RetryOptions = {
|
|
|
30
30
|
type ApiContext = {
|
|
31
31
|
/** Fetch client */
|
|
32
32
|
fetch?: FetchClient;
|
|
33
|
+
/** Logger for failed requests, defaults to console */
|
|
34
|
+
logger?: {
|
|
35
|
+
error: (details: Record<string, any>, message: string) => void;
|
|
36
|
+
};
|
|
33
37
|
/** Additional context properties */
|
|
34
38
|
[key: string]: any;
|
|
35
39
|
};
|
|
@@ -98,9 +102,16 @@ declare class HttpError extends Error {
|
|
|
98
102
|
* Create a new HTTP error
|
|
99
103
|
* @param {string} message - Error message
|
|
100
104
|
* @param {any} body - Error response body
|
|
105
|
+
* @param {number} [status] - HTTP status code, absent when the request never got a response
|
|
101
106
|
*/
|
|
102
|
-
constructor(message: string, body: any);
|
|
107
|
+
constructor(message: string, body: any, status?: number);
|
|
103
108
|
body: any;
|
|
109
|
+
status: number;
|
|
110
|
+
/** @type {{ method: string, url: string } | undefined} The request that failed */
|
|
111
|
+
request: {
|
|
112
|
+
method: string;
|
|
113
|
+
url: string;
|
|
114
|
+
} | undefined;
|
|
104
115
|
}
|
|
105
116
|
declare namespace _default {
|
|
106
117
|
export { create };
|
|
@@ -145,6 +156,12 @@ declare class Api {
|
|
|
145
156
|
* @returns {any} Result of error handler
|
|
146
157
|
*/
|
|
147
158
|
handle(e: HttpError, ctx?: ApiContext): any;
|
|
159
|
+
/**
|
|
160
|
+
* Log a failed request through the context logger, or the console
|
|
161
|
+
* @param {HttpError} e - Error instance
|
|
162
|
+
* @param {ApiContext} [ctx] - API context
|
|
163
|
+
*/
|
|
164
|
+
log(e: HttpError, ctx?: ApiContext): void;
|
|
148
165
|
/**
|
|
149
166
|
* Send the HTTP request
|
|
150
167
|
* @template T
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ type RetryOptions = {
|
|
|
30
30
|
type ApiContext = {
|
|
31
31
|
/** Fetch client */
|
|
32
32
|
fetch?: FetchClient;
|
|
33
|
+
/** Logger for failed requests, defaults to console */
|
|
34
|
+
logger?: {
|
|
35
|
+
error: (details: Record<string, any>, message: string) => void;
|
|
36
|
+
};
|
|
33
37
|
/** Additional context properties */
|
|
34
38
|
[key: string]: any;
|
|
35
39
|
};
|
|
@@ -98,9 +102,16 @@ declare class HttpError extends Error {
|
|
|
98
102
|
* Create a new HTTP error
|
|
99
103
|
* @param {string} message - Error message
|
|
100
104
|
* @param {any} body - Error response body
|
|
105
|
+
* @param {number} [status] - HTTP status code, absent when the request never got a response
|
|
101
106
|
*/
|
|
102
|
-
constructor(message: string, body: any);
|
|
107
|
+
constructor(message: string, body: any, status?: number);
|
|
103
108
|
body: any;
|
|
109
|
+
status: number;
|
|
110
|
+
/** @type {{ method: string, url: string } | undefined} The request that failed */
|
|
111
|
+
request: {
|
|
112
|
+
method: string;
|
|
113
|
+
url: string;
|
|
114
|
+
} | undefined;
|
|
104
115
|
}
|
|
105
116
|
declare namespace _default {
|
|
106
117
|
export { create };
|
|
@@ -145,6 +156,12 @@ declare class Api {
|
|
|
145
156
|
* @returns {any} Result of error handler
|
|
146
157
|
*/
|
|
147
158
|
handle(e: HttpError, ctx?: ApiContext): any;
|
|
159
|
+
/**
|
|
160
|
+
* Log a failed request through the context logger, or the console
|
|
161
|
+
* @param {HttpError} e - Error instance
|
|
162
|
+
* @param {ApiContext} [ctx] - API context
|
|
163
|
+
*/
|
|
164
|
+
log(e: HttpError, ctx?: ApiContext): void;
|
|
148
165
|
/**
|
|
149
166
|
* Send the HTTP request
|
|
150
167
|
* @template T
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,13 @@ var HttpError = class extends Error {
|
|
|
4
4
|
* Create a new HTTP error
|
|
5
5
|
* @param {string} message - Error message
|
|
6
6
|
* @param {any} body - Error response body
|
|
7
|
+
* @param {number} [status] - HTTP status code, absent when the request never got a response
|
|
7
8
|
*/
|
|
8
|
-
constructor(message, body) {
|
|
9
|
+
constructor(message, body, status) {
|
|
9
10
|
super(message);
|
|
10
11
|
this.body = body;
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.request = void 0;
|
|
11
14
|
}
|
|
12
15
|
};
|
|
13
16
|
var AccessDeniedError = class extends HttpError {
|
|
@@ -116,11 +119,26 @@ var Api = class {
|
|
|
116
119
|
handle(e, ctx) {
|
|
117
120
|
const constructorName = Object.getPrototypeOf(e).constructor.name;
|
|
118
121
|
const globalHandlerName = `${constructorName[0].toLowerCase()}${constructorName.slice(1, -5)}`;
|
|
119
|
-
const
|
|
122
|
+
const specificHandler = this.handlers[constructorName] || this.options.handlers && this.options.handlers[globalHandlerName];
|
|
123
|
+
const handler = specificHandler || this.defaultHandler || this.options.handlers && this.options.handlers.default || ((e2) => {
|
|
120
124
|
console.error(constructorName, e2.message, e2);
|
|
121
125
|
});
|
|
126
|
+
if (!specificHandler) {
|
|
127
|
+
this.log(e, ctx);
|
|
128
|
+
}
|
|
122
129
|
return handler(e, ctx);
|
|
123
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Log a failed request through the context logger, or the console
|
|
133
|
+
* @param {HttpError} e - Error instance
|
|
134
|
+
* @param {ApiContext} [ctx] - API context
|
|
135
|
+
*/
|
|
136
|
+
log(e, ctx) {
|
|
137
|
+
const logger = ctx && ctx.logger || console;
|
|
138
|
+
const { method, url } = e.request || {};
|
|
139
|
+
const reason = e.status ? `with ${e.status}` : `(${e.message})`;
|
|
140
|
+
logger.error({ err: e, status: e.status, method, url, body: e.body }, `${method} ${url} failed ${reason}`);
|
|
141
|
+
}
|
|
124
142
|
/**
|
|
125
143
|
* Send the HTTP request
|
|
126
144
|
* @template T
|
|
@@ -150,7 +168,7 @@ var Api = class {
|
|
|
150
168
|
try {
|
|
151
169
|
result = await this.#doQuery(1, client, ep, options);
|
|
152
170
|
} catch (e) {
|
|
153
|
-
|
|
171
|
+
e.request = { method: options.method, url: ep };
|
|
154
172
|
return this.handle(e, this.ctx);
|
|
155
173
|
} finally {
|
|
156
174
|
this.resetRequest();
|
|
@@ -203,7 +221,7 @@ var Api = class {
|
|
|
203
221
|
console.log("Failed to parse error body when asked.");
|
|
204
222
|
}
|
|
205
223
|
const ClientError = getErrorByCode(r.status);
|
|
206
|
-
throw new ClientError(r.statusText, content);
|
|
224
|
+
throw new ClientError(r.statusText, content, r.status);
|
|
207
225
|
} catch (e) {
|
|
208
226
|
if (retry.attempts && retry.errors && attempt < retry.attempts && retry.errors.includes(e.code)) {
|
|
209
227
|
console.warn(`Got ${e.code} when calling ${endpoint}. Retrying request (${attempt}/${retry.attempts})`);
|