import axios, { AxiosBasicCredentials, type AxiosRequestConfig, type Method, type RawAxiosRequestHeaders, } from "axios"; import { APIError } from "./api_error"; interface Params { endpoint: string; method?: Method; data?: unknown; headers?: RawAxiosRequestHeaders; config?: AxiosRequestConfig; } export class API { private static get api_baseurl(): string { // in production mode, return "proto://hostname/api" if (process.env.NODE_ENV === "production") { return `${window.location.protocol}//${window.location.host}/api`; } else if (process.env.NODE_ENV !== "development") { // not in prouction or development mode console.warn("Unexpected NODE_ENV value"); } // in development mode, return "proto://hostname:8000/api" return `${window.location.protocol}//${window.location.hostname}:8000/api`; } private static readonly axios = axios.create({ timeout: 10e3, baseURL: this.api_baseurl, }); private static readonly creds_key = "advent22/credentials"; public static set creds(value: AxiosBasicCredentials | null) { if (value === null) { localStorage.removeItem(this.creds_key); } else { localStorage.setItem(this.creds_key, JSON.stringify(value)); } } public static get creds(): AxiosBasicCredentials { const auth_json = localStorage.getItem(this.creds_key); if (auth_json !== null) { return JSON.parse(auth_json); } else { return { username: "", password: "" }; } } private static get_axios_config({ endpoint, method = "GET", data, headers = {}, config = {}, }: Params): AxiosRequestConfig { return { url: endpoint, method: method, data: data, auth: this.creds, headers: headers, ...config, }; } public static async request(p: Params): Promise; public static async request(p: string): Promise; public static async request(p: Params | string): Promise { if (typeof p === "string") p = { endpoint: p }; try { const response = await this.axios.request(this.get_axios_config(p)); return response.data; } catch (reason) { console.error(`Failed to query ${p.endpoint}: ${reason}`); throw new APIError(reason, p.endpoint); } } }