oneuptime/Common/Utils/API.ts

291 lines
8.2 KiB
TypeScript
Raw Normal View History

2022-07-26 19:47:36 +00:00
import axios, { AxiosError, AxiosResponse } from 'axios';
2022-04-10 21:21:18 +00:00
import URL from '../Types/API/URL';
2022-05-23 21:06:12 +00:00
import { JSONObject, JSONArray } from '../Types/JSON';
2022-04-10 21:21:18 +00:00
import Headers from '../Types/API/Headers';
2022-05-23 11:45:32 +00:00
import HTTPResponse from '../Types/API/HTTPResponse';
import HTTPErrorResponse from '../Types/API/HTTPErrorResponse';
2022-04-10 21:21:18 +00:00
import HTTPMethod from '../Types/API/HTTPMethod';
2022-04-10 21:28:33 +00:00
import APIException from '../Types/Exception/ApiException';
2022-04-10 21:21:18 +00:00
import Protocol from '../Types/API/Protocol';
import Hostname from '../Types/API/Hostname';
import Route from '../Types/API/Route';
2022-05-23 11:45:32 +00:00
import BaseModel from '../Models/BaseModel';
2022-07-12 20:44:17 +00:00
import Dictionary from '../Types/Dictionary';
2022-04-08 12:07:15 +00:00
export default class API {
private _protocol: Protocol = Protocol.HTTPS;
public get protocol(): Protocol {
return this._protocol;
}
public set protocol(v: Protocol) {
this._protocol = v;
}
2022-05-23 11:45:32 +00:00
private _hostname!: Hostname;
2022-04-08 12:07:15 +00:00
public get hostname(): Hostname {
return this._hostname;
}
public set hostname(v: Hostname) {
this._hostname = v;
}
2022-05-25 18:24:43 +00:00
private _baseRoute!: Route;
public get baseRoute(): Route {
2022-05-23 21:06:12 +00:00
return this._baseRoute;
}
2022-05-25 18:24:43 +00:00
public set baseRoute(v: Route) {
2022-05-23 21:06:12 +00:00
this._baseRoute = v;
}
2022-05-25 18:24:43 +00:00
public constructor(
protocol: Protocol,
hostname: Hostname,
baseRoute?: Route
) {
2022-04-08 12:07:15 +00:00
this.protocol = protocol;
this.hostname = hostname;
2022-05-23 21:06:12 +00:00
if (baseRoute) {
this.baseRoute = baseRoute;
} else {
2022-05-25 18:24:43 +00:00
this.baseRoute = new Route('/');
2022-05-23 21:06:12 +00:00
}
2022-04-08 12:07:15 +00:00
}
2022-05-25 18:24:43 +00:00
public async get<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
path: Route,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-05-23 11:45:32 +00:00
return await API.get<T>(
2022-05-25 18:24:43 +00:00
new URL(
this.protocol,
this.hostname,
this.baseRoute.addRoute(path)
),
2022-04-08 12:07:15 +00:00
data,
headers
);
}
2022-05-25 18:24:43 +00:00
public async delete<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
path: Route,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-05-23 11:45:32 +00:00
return await API.delete<T>(
2022-05-25 18:24:43 +00:00
new URL(
this.protocol,
this.hostname,
this.baseRoute.addRoute(path)
),
2022-04-08 12:07:15 +00:00
data,
headers
);
}
2023-07-26 11:48:54 +00:00
public async head<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
path: Route,
data?: JSONObject | JSONArray,
headers?: Headers
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
return await API.head<T>(
new URL(
this.protocol,
this.hostname,
this.baseRoute.addRoute(path)
),
data,
headers
);
}
2022-05-25 18:24:43 +00:00
public async put<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
path: Route,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-05-23 11:45:32 +00:00
return await API.put<T>(
2022-05-25 18:24:43 +00:00
new URL(
this.protocol,
this.hostname,
this.baseRoute.addRoute(path)
),
2022-04-08 12:07:15 +00:00
data,
headers
);
}
2022-05-25 18:24:43 +00:00
public async post<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
path: Route,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-05-23 11:45:32 +00:00
return await API.post<T>(
2022-05-25 18:24:43 +00:00
new URL(
this.protocol,
this.hostname,
this.baseRoute.addRoute(path)
),
2022-04-08 12:07:15 +00:00
data,
headers
);
}
2022-05-23 12:46:00 +00:00
protected static handleError(
error: HTTPErrorResponse | APIException
): HTTPErrorResponse | APIException {
2022-04-08 12:07:15 +00:00
return error;
}
2022-07-26 19:47:36 +00:00
protected static async onResponseSuccessHeaders(
headers: Dictionary<string>
): Promise<Dictionary<string>> {
return Promise.resolve(headers);
}
2022-04-08 12:07:15 +00:00
public static getDefaultHeaders(): Headers {
2022-04-14 13:57:52 +00:00
const defaultHeaders: Headers = {
2022-04-08 12:07:15 +00:00
'Access-Control-Allow-Origin': '*',
Accept: 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
};
return defaultHeaders;
}
protected static getHeaders(headers?: Headers): Headers {
let defaultHeaders: Headers = this.getDefaultHeaders();
if (headers) {
defaultHeaders = {
...defaultHeaders,
...headers,
};
}
return defaultHeaders;
}
2022-05-25 18:24:43 +00:00
public static async get<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
url: URL,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-05-23 11:45:32 +00:00
return await this.fetch<T>(HTTPMethod.GET, url, data, headers);
2022-04-08 12:07:15 +00:00
}
2022-05-25 18:24:43 +00:00
public static async delete<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
url: URL,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-04-08 12:07:15 +00:00
return await this.fetch(HTTPMethod.DELETE, url, data, headers);
}
2023-07-26 11:48:54 +00:00
public static async head<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
url: URL,
data?: JSONObject | JSONArray,
headers?: Headers
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
return await this.fetch(HTTPMethod.HEAD, url, data, headers);
}
2022-05-25 18:24:43 +00:00
public static async put<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
url: URL,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-04-08 12:07:15 +00:00
return await this.fetch(HTTPMethod.PUT, url, data, headers);
}
2022-05-25 18:24:43 +00:00
public static async post<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
url: URL,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-04-08 12:07:15 +00:00
headers?: Headers
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-04-08 12:07:15 +00:00
return await this.fetch(HTTPMethod.POST, url, data, headers);
}
2022-06-29 20:51:49 +00:00
public static async fetch<
2022-05-25 18:24:43 +00:00
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
2022-04-08 12:07:15 +00:00
method: HTTPMethod,
url: URL,
2022-05-23 21:06:12 +00:00
data?: JSONObject | JSONArray,
2022-07-12 20:44:17 +00:00
headers?: Headers,
params?: Dictionary<string>
2022-06-29 21:17:30 +00:00
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
2022-04-08 12:07:15 +00:00
const apiHeaders: Headers = this.getHeaders(headers);
2022-07-12 20:44:17 +00:00
if (params) {
url.addQueryParams(params);
}
2022-04-08 12:07:15 +00:00
try {
2022-07-29 19:22:59 +00:00
const result: AxiosResponse = await axios({
2022-04-17 14:01:39 +00:00
method: method,
url: url.toString(),
2022-07-23 08:51:18 +00:00
headers: { ...apiHeaders, ...headers },
2022-04-17 14:01:39 +00:00
data,
});
2022-04-17 13:29:14 +00:00
2022-07-29 19:22:59 +00:00
result.headers = await this.onResponseSuccessHeaders(
result.headers as Dictionary<string>
);
2022-07-26 19:47:36 +00:00
2022-05-23 11:45:32 +00:00
const response: HTTPResponse<T> = new HTTPResponse<T>(
2022-04-14 13:59:38 +00:00
result.status,
2023-01-27 11:45:11 +00:00
result.data,
result.headers
2022-04-14 13:59:38 +00:00
);
2022-05-23 11:45:32 +00:00
2022-04-08 12:07:15 +00:00
return response;
} catch (e) {
2022-04-17 13:29:14 +00:00
const error: Error | AxiosError = e as Error | AxiosError;
2022-06-29 21:17:30 +00:00
let errorResponse: HTTPErrorResponse;
2022-04-08 12:07:15 +00:00
if (axios.isAxiosError(error)) {
2022-04-15 22:14:01 +00:00
// Do whatever you want with native error
2022-04-08 12:07:15 +00:00
errorResponse = this.getErrorResponse(error);
} else {
2022-06-29 23:13:28 +00:00
throw new APIException(error.message);
2022-04-08 12:07:15 +00:00
}
2022-05-23 12:46:00 +00:00
this.handleError(errorResponse);
2023-03-07 12:40:46 +00:00
return errorResponse;
2022-04-08 12:07:15 +00:00
}
}
2022-05-23 12:46:00 +00:00
private static getErrorResponse(error: AxiosError): HTTPErrorResponse {
2022-04-08 12:07:15 +00:00
if (error.response) {
2022-05-23 12:46:00 +00:00
return new HTTPErrorResponse(
2022-04-08 12:07:15 +00:00
error.response.status,
2023-01-27 11:45:11 +00:00
error.response.data,
error.response.headers
2022-04-08 12:07:15 +00:00
);
}
throw new APIException('No error response body');
}
}