radiator-web/src/api/index.ts

104 lines
2.2 KiB
TypeScript
Raw Normal View History

import { cSite, LoginResponse, Site, token } from "./types";
import { get as idbGet, set as idbSet, del as idbDel } from "idb-keyval";
export * from "./types";
const enum HTTPMethod {
GET = "GET",
POST = "POST",
PATCH = "PATCH",
}
const url = "http://192.168.178.5:8080/api";
let token: token;
let ready = false;
export async function init() {
if (ready) return;
await idbGet("token").then((val: token) => {
if (val !== undefined) {
token = val;
}
});
ready = true;
}
export async function logout(): Promise<void> {
token = { jwt: "", expiration: 0 };
await idbDel("token");
}
export async function isLoggedIn(): Promise<boolean> {
await init();
return token?.expiration > Date.now();
}
interface ReqOptions extends RequestInit {
method: HTTPMethod;
auth?: boolean;
}
async function request<T = unknown>(
endpoint: string,
options: ReqOptions,
data?: any
): Promise<T> {
if (options.auth) {
await init();
options.headers = {
...options.headers,
Authorization: `Bearer ${token.jwt}`,
};
}
if (
options.method === HTTPMethod.POST ||
options.method === HTTPMethod.PATCH
) {
options.headers = {
...options.headers,
"Content-Type": "application/json",
};
options.body = JSON.stringify(data);
}
const response = await fetch(`${url}${endpoint}`, {
...options,
headers: { ...options.headers, Accept: "application/json" },
});
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json();
}
export async function login(
username: string,
password: string
): Promise<boolean> {
const login = await request<LoginResponse>(
"/auth",
{ method: HTTPMethod.POST },
{ username, password }
);
if (!login.success) {
throw new Error(login.message);
}
token = {
jwt: login.token,
expiration: Date.parse(login.expiration),
};
idbSet("token", token).catch((error) => console.error(error));
return true;
}
export async function getSites(): Promise<Site[]> {
return request<Site[]>("/sites", { auth: true, method: HTTPMethod.GET });
}
export async function createSite(site: Site) {
return request<cSite>("/sites", { auth: true, method: HTTPMethod.POST }, site);
}