85 lines
1.8 KiB
TypeScript
85 lines
1.8 KiB
TypeScript
import { AuthApi } from "./AuthApi";
|
|
|
|
interface APIResponse {
|
|
data: any;
|
|
status: number;
|
|
}
|
|
|
|
export class ApiError extends Error {
|
|
constructor(message: string, public code: number, public data: any) {
|
|
super(message);
|
|
}
|
|
}
|
|
|
|
export class APIClient {
|
|
/**
|
|
* Get backend URL
|
|
*/
|
|
static backendURL(): string {
|
|
const URL = import.meta.env.VITE_APP_BACKEND ?? "";
|
|
if (URL.length === 0) throw new Error("Backend URL undefined!");
|
|
return URL;
|
|
}
|
|
|
|
/**
|
|
* Check out whether the backend is accessed through
|
|
* HTTPS or not
|
|
*/
|
|
static IsBackendSecure(): boolean {
|
|
return this.backendURL().startsWith("https");
|
|
}
|
|
|
|
/**
|
|
* Perform a request on the backend
|
|
*/
|
|
static async exec(args: {
|
|
uri: string;
|
|
method: "GET" | "POST" | "DELETE" | "PATCH" | "PUT";
|
|
allowFail?: boolean;
|
|
jsonData?: any;
|
|
formData?: FormData;
|
|
}): Promise<APIResponse> {
|
|
let body = undefined;
|
|
let headers: any = {
|
|
"X-auth-token": AuthApi.SignedIn ? AuthApi.AuthToken : "none",
|
|
};
|
|
|
|
// JSON request
|
|
if (args.jsonData) {
|
|
headers["Content-Type"] = "application/json";
|
|
body = JSON.stringify(args.jsonData);
|
|
}
|
|
|
|
// Form data request
|
|
else if (args.formData) {
|
|
body = args.formData;
|
|
}
|
|
|
|
const res = await fetch(this.backendURL() + args.uri, {
|
|
method: args.method,
|
|
body: body,
|
|
headers: headers,
|
|
});
|
|
|
|
// Process response
|
|
let data;
|
|
if (res.headers.get("content-type") === "application/json")
|
|
data = await res.json();
|
|
else data = await res.blob();
|
|
|
|
// Handle expired tokens
|
|
if (res.status === 412) {
|
|
AuthApi.RemoveAuthToken();
|
|
window.location.href = "/";
|
|
}
|
|
|
|
if (!args.allowFail && !res.ok)
|
|
throw new ApiError("Request failed!", res.status, data);
|
|
|
|
return {
|
|
data: data,
|
|
status: res.status,
|
|
};
|
|
}
|
|
}
|