/
ApiResponseHandler.ts
86 lines (77 loc) · 2.98 KB
/
ApiResponseHandler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import type HandlesApiResponse from '../Contracts/HandlesApiResponse';
import type { ApiResponse } from '../Contracts/HandlesApiResponse';
import type { Method } from '../Calliope/Concerns/CallsApi';
/**
* The default HandlesApiResponse implementation used by upfrontjs.
*
* @link {HandlesApiResponse}
*/
export default class ApiResponseHandler implements HandlesApiResponse {
/**
* @inheritDoc
*/
public async handle(
promise: Promise<
ApiResponse &
{ request: { method: 'CONNECT' | 'connect' | 'HEAD' | 'head' | 'OPTIONS' | 'options' | 'TRACE' | 'trace' } }
>
// omit to discourage accessing such on response where it's not available
): Promise<Omit<ApiResponse, 'data' | 'json'> | undefined>;
public async handle<T>(promise: Promise<ApiResponse<T>>): Promise<T | undefined>;
public async handle(promise: Promise<ApiResponse>): Promise<unknown> {
return promise
.then(async response => this.handleResponse(response))
.catch(async error => this.handleError(error))
.finally(() => this.handleFinally());
}
/**
* Handle successful request.
*
* @param {ApiResponse} response
*
* @return {Promise<any>}
*
* @throws {ApiResponse}
*/
public async handleResponse(
response: ApiResponse &
{ request: { method: 'CONNECT' | 'connect' | 'HEAD' | 'head' | 'OPTIONS' | 'options' | 'TRACE' | 'trace' } }
): Promise<Omit<ApiResponse, 'data' | 'json'> | undefined>;
public async handleResponse<T>(response: ApiResponse<T>): Promise<T | undefined>;
public async handleResponse(response: ApiResponse): Promise<unknown> {
if (response.status >= 400) {
// eslint-disable-next-line @typescript-eslint/no-throw-literal
throw response;
}
if (response.status < 200 || response.status > 299 || response.status === 204) return;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
const method = response.request?.method?.toUpperCase() as Uppercase<Method> | undefined;
if (method && ['OPTIONS', 'HEAD', 'TRACE', 'CONNECT'].includes(method)) {
// the user might just want the headers or debug info
// so just return the whole response
return response;
}
if (typeof response.json === 'function') {
return response.json();
}
return;
}
/**
* Handle errors that occurred during the promise execution.
*
* @param {any} rejectReason
*
* @return {void}
*/
public async handleError(rejectReason: unknown): Promise<unknown> {
return Promise.reject(rejectReason);
}
/**
* If extending, you may do any final operations after the request.
*
* @return {void}
*/
public handleFinally(): void {
//
}
}