homebox/frontend/lib/requests/requests.ts

103 lines
2.5 KiB
TypeScript
Raw Normal View History

2022-08-31 00:06:57 +00:00
export enum Method {
2022-08-31 02:11:36 +00:00
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE',
2022-08-31 00:06:57 +00:00
}
2022-09-04 06:19:13 +00:00
export type RequestInterceptor = (r: Response) => void;
export type ResponseInterceptor = (r: Response) => void;
2022-08-31 00:06:57 +00:00
export interface TResponse<T> {
2022-08-31 02:11:36 +00:00
status: number;
error: boolean;
data: T;
response: Response;
2022-08-31 00:06:57 +00:00
}
export class Requests {
2022-08-31 02:11:36 +00:00
private baseUrl: string;
private token: () => string;
private headers: Record<string, string> = {};
2022-09-04 06:19:13 +00:00
private responseInterceptors: ResponseInterceptor[] = [];
addResponseInterceptor(interceptor: ResponseInterceptor) {
this.responseInterceptors.push(interceptor);
}
private callResponseInterceptors(response: Response) {
this.responseInterceptors.forEach(i => i(response));
}
2022-08-31 02:11:36 +00:00
private url(rest: string): string {
return this.baseUrl + rest;
}
2022-09-04 06:19:13 +00:00
constructor(baseUrl: string, token: string | (() => string) = '', headers: Record<string, string> = {}) {
2022-08-31 02:11:36 +00:00
this.baseUrl = baseUrl;
this.token = typeof token === 'string' ? () => token : token;
this.headers = headers;
}
public get<T>(url: string): Promise<TResponse<T>> {
return this.do<T>(Method.GET, url);
}
public post<T, U>(url: string, payload: T): Promise<TResponse<U>> {
return this.do<U>(Method.POST, url, payload);
}
public put<T, U>(url: string, payload: T): Promise<TResponse<U>> {
return this.do<U>(Method.PUT, url, payload);
}
public delete<T>(url: string): Promise<TResponse<T>> {
return this.do<T>(Method.DELETE, url);
}
private methodSupportsBody(method: Method): boolean {
return method === Method.POST || method === Method.PUT;
}
private async do<T>(method: Method, url: string, payload: Object = {}): Promise<TResponse<T>> {
const args: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
...this.headers,
},
};
const token = this.token();
if (token !== '' && args.headers !== undefined) {
args.headers['Authorization'] = token;
}
if (this.methodSupportsBody(method)) {
args.body = JSON.stringify(payload);
}
const response = await fetch(this.url(url), args);
2022-09-04 06:19:13 +00:00
this.callResponseInterceptors(response);
2022-08-31 02:11:36 +00:00
const data: T = await (async () => {
2022-09-01 22:32:03 +00:00
if (response.status === 204) {
return {} as T;
}
2022-08-31 02:11:36 +00:00
try {
return await response.json();
} catch (e) {
return {} as T;
}
})();
return {
status: response.status,
error: !response.ok,
data,
response,
};
}
2022-08-31 00:06:57 +00:00
}