aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/pw-server/src/lib/api_client.ts70
-rw-r--r--web/pw-server/src/lib/utils.ts37
-rw-r--r--web/pw-server/src/routes/bots/[bot_name].svelte41
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>