Naposledy aktivní 1710515426

Jigsaw1601 revidoval tento gist 1710515425. Přejít na revizi

1 file changed, 123 insertions

requests.ts(vytvořil soubor)

@@ -0,0 +1,123 @@
1 + export enum Method {
2 + GET = "GET",
3 + POST = "POST",
4 + PUT = "PUT",
5 + DELETE = "DELETE",
6 + PATCH = "PATCH",
7 + }
8 +
9 + export type ResponseInterceptor = (r: Response, rq?: RequestInit) => void;
10 +
11 + export interface TResponse<T> {
12 + status: number;
13 + error: boolean;
14 + data: T;
15 + response: Response;
16 + }
17 +
18 + export type RequestArgs<T> = {
19 + url: string;
20 + body?: T;
21 + data?: FormData;
22 + headers?: Record<string, string>;
23 + };
24 +
25 + export class Requests {
26 + private headers: Record<string, string> = {};
27 + private responseInterceptors: ResponseInterceptor[] = [];
28 + private bearer: () => string | null = () => null;
29 +
30 + withResponseInterceptor(interceptor: ResponseInterceptor) {
31 + this.responseInterceptors.push(interceptor);
32 + return this;
33 + }
34 +
35 + withBearer(bearer: () => string | null) {
36 + this.bearer = bearer;
37 + return this;
38 + }
39 +
40 + private callResponseInterceptors(response: Response, request?: RequestInit) {
41 + this.responseInterceptors.forEach(i => i(response, request));
42 + }
43 +
44 + constructor(headers: Record<string, string> = {}) {
45 + this.headers = headers;
46 + }
47 +
48 + public get<T>(args: RequestArgs<T>): Promise<TResponse<T>> {
49 + return this.do<T>(Method.GET, args);
50 + }
51 +
52 + public post<T, U>(args: RequestArgs<T>): Promise<TResponse<U>> {
53 + return this.do<U>(Method.POST, args);
54 + }
55 +
56 + public put<T, U>(args: RequestArgs<T>): Promise<TResponse<U>> {
57 + return this.do<U>(Method.PUT, args);
58 + }
59 +
60 + public delete<T>(args: RequestArgs<T>): Promise<TResponse<T>> {
61 + return this.do<T>(Method.DELETE, args);
62 + }
63 +
64 + public patch<T, U>(args: RequestArgs<T>): Promise<TResponse<U>> {
65 + return this.do<U>(Method.PATCH, args);
66 + }
67 +
68 + private methodSupportsBody(method: Method): boolean {
69 + return method === Method.POST || method === Method.PUT || method === Method.PATCH;
70 + }
71 +
72 + private async do<T>(method: Method, rargs: RequestArgs<unknown>): Promise<TResponse<T>> {
73 + const payload: RequestInit = {
74 + method,
75 + headers: {
76 + ...rargs.headers,
77 + ...this.headers,
78 + } as Record<string, string>,
79 + };
80 +
81 + if (this.methodSupportsBody(method)) {
82 + if (rargs.data) {
83 + payload.body = rargs.data;
84 + } else {
85 + // @ts-expect-error - we know that the header is there
86 + payload.headers["Content-Type"] = "application/json";
87 + payload.body = JSON.stringify(rargs.body);
88 + }
89 + }
90 +
91 + const maybeBearer = this.bearer();
92 + if (maybeBearer) {
93 + // @ts-expect-error - we know that the header is there
94 + payload.headers.Authorization = `Bearer ${maybeBearer}`;
95 + }
96 +
97 + const response = await fetch(rargs.url, payload);
98 + this.callResponseInterceptors(response, payload);
99 +
100 + const data: T = await (async () => {
101 + if (response.status === 204) {
102 + return {} as T;
103 + }
104 +
105 + if (response.headers.get("Content-Type")?.startsWith("application/json")) {
106 + try {
107 + return await response.json();
108 + } catch (e) {
109 + return {} as T;
110 + }
111 + }
112 +
113 + return response.body as unknown as T;
114 + })();
115 +
116 + return {
117 + status: response.status,
118 + error: !response.ok,
119 + data,
120 + response,
121 + };
122 + }
123 + }
Novější Starší