radiator-web/src/api/index.ts

178 lines
3.9 KiB
TypeScript

import {
AccessPoint,
AccessPointCreateResponse,
cSite,
LoginResponse,
RegisterAccessPointResponse,
Site,
StateOfTask,
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 = import.meta.env.API_URL ?? import.meta.env.VITE_API_URL;
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 getSite(id: number): Promise<Site> {
return request<Site>(`/sites/${id}`, { auth: true, method: HTTPMethod.GET });
}
export async function createSite(site: Site) {
return request<cSite>(
"/sites",
{ auth: true, method: HTTPMethod.POST },
site
);
}
export async function getAccessPointDetails(
sideID?: number
): Promise<AccessPoint[]> {
const endpoint = `${sideID ? "/sites/" + sideID : ""}/aps`;
return request<AccessPoint[]>(endpoint, {
auth: true,
method: HTTPMethod.GET,
});
}
export async function getAccessPointByID(id: number): Promise<AccessPoint> {
return request<AccessPoint>(`/aps/${id}`, {
auth: true,
method: HTTPMethod.GET,
});
}
export async function createAccessPoint(
ap: AccessPoint
): Promise<AccessPointCreateResponse> {
return request<AccessPointCreateResponse>(
`/aps${ap.id ? "/" + ap.id : ""}`,
{ auth: true, method: ap.id ? HTTPMethod.PATCH : HTTPMethod.POST },
Object.fromEntries(
Object.entries(ap).filter(([k, v]) =>
[
"ap_name",
"site_id",
"mac_address",
"serialnumber",
"location",
"model",
"group",
"appointment",
"comment",
].includes(k)
)
)
);
}
export async function registerAccessPoint(
apName: string
): Promise<RegisterAccessPointResponse> {
return request<RegisterAccessPointResponse>(
`/${import.meta.env.DEV ? "test" : "register-ap"}/${apName}`,
{ auth: true, method: HTTPMethod.POST }
);
}
export async function getStateOfTask(id: string): Promise<StateOfTask> {
return request<StateOfTask>(`/tasks/${id}`, {
auth: true,
method: HTTPMethod.GET,
});
}