diff options
Diffstat (limited to 'web/pw-server')
-rw-r--r-- | web/pw-server/src/lib/api_client.ts | 70 | ||||
-rw-r--r-- | web/pw-server/src/lib/utils.ts | 37 | ||||
-rw-r--r-- | web/pw-server/src/routes/bots/[bot_name].svelte | 41 |
3 files changed, 92 insertions, 56 deletions
diff --git a/web/pw-server/src/lib/api_client.ts b/web/pw-server/src/lib/api_client.ts new file mode 100644 index 0000000..93135ab --- /dev/null +++ b/web/pw-server/src/lib/api_client.ts @@ -0,0 +1,70 @@ +import { get_session_token } from "./auth"; + +export type FetchFn = (input: RequestInfo, init?: RequestInit) => Promise<Response>; + +export class ApiError extends Error { + constructor(public status: number, message?: string) { + super(message); + } +} + +export class ApiClient { + private fetch_fn: FetchFn; + private sessionToken?: string; + + constructor(fetch_fn?: FetchFn) { + if (fetch_fn) { + this.fetch_fn = fetch_fn; + } else { + this.fetch_fn = fetch; + } + + // TODO: maybe it is cleaner to pass this as a parameter + this.sessionToken = get_session_token(); + } + + async get(url: string, params?: Record<string, string>): Promise<any> { + const headers = { "Content-Type": "application/json" }; + + if (this.sessionToken) { + headers["Authorization"] = `Bearer ${this.sessionToken}`; + } + + if (params) { + let searchParams = new URLSearchParams(params); + url = `${url}?${searchParams}`; + } + + const response = await this.fetch_fn(url, { + method: "GET", + headers, + }); + + return await this.getJsonResponse(response); + } + + async post(url: string, data: any): Promise<any> { + const headers = { "Content-Type": "application/json" }; + + const token = get_session_token(); + if (token) { + headers["Authorization"] = `Bearer ${token}`; + } + + const response = await this.fetch_fn(url, { + method: "POST", + headers, + body: JSON.stringify(data), + }); + + return await this.getJsonResponse(response); + } + + private async getJsonResponse(response: Response): Promise<any> { + if (response.ok) { + return await response.json(); + } else { + throw new ApiError(response.status, response.statusText); + } + } +} diff --git a/web/pw-server/src/lib/utils.ts b/web/pw-server/src/lib/utils.ts index 155d952..ab1faa5 100644 --- a/web/pw-server/src/lib/utils.ts +++ b/web/pw-server/src/lib/utils.ts @@ -1,4 +1,4 @@ -import { get_session_token } from "./auth"; +import { ApiClient, FetchFn } from "./api_client"; export function debounce(func: Function, timeout: number = 300) { let timer: ReturnType<typeof setTimeout>; @@ -10,35 +10,12 @@ export function debounce(func: Function, timeout: number = 300) { }; } -export async function get(url: string, fetch_fn: Function = fetch) { - const headers = { "Content-Type": "application/json" }; - - const token = get_session_token(); - if (token) { - headers["Authorization"] = `Bearer ${token}`; - } - - const response = await fetch_fn(url, { - method: "GET", - headers, - }); - - return JSON.parse(response); +export async function get(url: string, params?: Record<string, string>, fetch_fn: FetchFn = fetch) { + const client = new ApiClient(fetch_fn); + return await client.get(url, params); } -export async function post(url: string, data: any, fetch_fn: Function = fetch) { - const headers = { "Content-Type": "application/json" }; - - const token = get_session_token(); - if (token) { - headers["Authorization"] = `Bearer ${token}`; - } - - const response = await fetch_fn(url, { - method: "POST", - headers, - body: JSON.stringify(data), - }); - - return JSON.parse(response); +export async function post(url: string, data: any, fetch_fn: FetchFn = fetch) { + const client = new ApiClient(fetch_fn); + return await client.post(url, data); } diff --git a/web/pw-server/src/routes/bots/[bot_name].svelte b/web/pw-server/src/routes/bots/[bot_name].svelte index 48aef21..d110e4b 100644 --- a/web/pw-server/src/routes/bots/[bot_name].svelte +++ b/web/pw-server/src/routes/bots/[bot_name].svelte @@ -1,27 +1,16 @@ <script lang="ts" context="module"> - import { get_session_token } from "$lib/auth"; + import { ApiClient } from "$lib/api_client"; export async function load({ params, fetch }) { - const token = get_session_token(); - const res = await fetch(`/api/bots/${params["bot_name"]}`, { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - }); - - const matches_res = await fetch(`/api/matches?bot=${params["bot_name"]}`, { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - }); - - - if (res.ok && matches_res.ok) { - const { bot, owner, versions } = await res.json(); - const matches = await matches_res.json(); - // sort most recent first + const apiClient = new ApiClient(fetch); + + try { + const [botData, matches] = await Promise.all([ + apiClient.get(`/api/bots/${params["bot_name"]}`), + apiClient.get("/api/matches", { bot: params["bot_name"] }), + ]); + + const { bot, owner, versions } = botData; versions.sort((a: string, b: string) => dayjs(a["created_at"]).isAfter(b["created_at"]) ? -1 : 1 ); @@ -33,12 +22,12 @@ matches, }, }; + } catch (error) { + return { + status: error.status, + error: error, + }; } - - return { - status: res.status, - error: new Error("Could not find bot"), - }; } </script> |