/
client.ts
72 lines (58 loc) · 1.82 KB
/
client.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
import { queryToString, Request, requestInternalFx } from './common';
requestInternalFx.use(requestClient);
export type ResponseResult<Data> = string | Record<string, Data> | null;
export const API_PREFIX = process.env.CLIENT_BACKEND_URL ?? `/api/internal`;
async function requestClient({ path, method, ...params }: Request) {
const headers = new Headers(params.headers);
contentDefault(headers, 'application/json; charset=utf-8');
const query = queryToString(params.query);
const body =
contentIs(headers, 'application/json') && params.body ? JSON.stringify(params.body) : undefined;
const response = await fetch(`${API_PREFIX}${path}${query}`, {
method,
headers,
body,
credentials: 'same-origin',
});
// TODO: rewrite error system
const answer = await getResponseAnswer(response);
const responder = {
ok: response.ok,
body: answer,
status: response.status,
headers: toObject(response.headers),
};
if (response.ok) {
return responder;
}
throw responder;
}
/**
* Check if content-type JSON
*/
function contentIs(headers: Headers, type: string): boolean {
return headers.get('content-type')?.includes(type) ?? false;
}
function contentDefault(headers: Headers, type: string): Headers {
if (!headers.has('content-type')) {
headers.set('content-type', type);
}
return headers;
}
async function getResponseAnswer<Data>(response: Response): Promise<ResponseResult<Data>> {
if (contentIs(response.headers, 'application/json')) {
return response.json();
}
const hasEmptyResponse = !response.headers.get('content-type');
if (hasEmptyResponse) {
return null;
}
return response.text();
}
function toObject(headers: Headers): Record<string, string> {
const object = {};
headers.forEach((value, key) => {
object[key] = value;
});
return object;
}