Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/src/api/controllers/leaderboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ export async function getLeaderboard(
}

const count = await LeaderboardsDAL.getCount(mode, mode2, language);
const normalizedLeaderboard = leaderboard.map((it) => _.omit(it, ["_id"]));
//const normalizedLeaderboard = leaderboard.map((it) => _.omit(it, ["_id"]));

return new MonkeyResponse("Leaderboard retrieved", {
count,
entries: normalizedLeaderboard,
//entries: normalizedLeaderboard,
pageSize,
});
}) as unknown as GetLeaderboardResponse;
}

export async function getRankFromLeaderboard(
Expand Down
57 changes: 42 additions & 15 deletions frontend/src/ts/ape/adapters/ts-rest-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { AppRouter, initClient, type ApiFetcherArgs } from "@ts-rest/core";
import {
AppRouter,
initClient,
tsRestFetchApi,
type ApiFetcherArgs,
} from "@ts-rest/core";
import { getIdToken } from "firebase/auth";
import { envConfig } from "../../constants/env-config";
import { getAuthenticatedUser, isAuthenticated } from "../../firebase";
import { ZodError, ZodIssue } from "zod";

function timeoutSignal(ms: number): AbortSignal {
const ctrl = new AbortController();
Expand All @@ -26,22 +32,19 @@ function buildApi(timeout: number): (args: ApiFetcherArgs) => Promise<{
headers["Authorization"] = `Bearer ${token}`;
}

const fetchOptions: RequestInit = {
method: request.method,
headers,
body: request.body,
};

const usePolyfill = AbortSignal?.timeout === undefined;

const response = await fetch(request.path, {
...fetchOptions,
signal: usePolyfill
? timeoutSignal(timeout)
: AbortSignal.timeout(timeout),
const response = await tsRestFetchApi({
...request,
headers,
fetchOptions: {
signal: usePolyfill
? timeoutSignal(timeout)
: AbortSignal.timeout(timeout),
},
validateResponse: true,
});

const body = (await response.json()) as object;
const body = response.body as object;
if (response.status >= 400) {
console.error(`${request.method} ${request.path} failed`, {
status: response.status,
Expand All @@ -54,7 +57,14 @@ function buildApi(timeout: number): (args: ApiFetcherArgs) => Promise<{
body,
headers: response.headers ?? new Headers(),
};
} catch (e: Error | unknown) {
} catch (e: Error | ZodError | unknown) {
if (isZodError(e)) {
const pretty = e.issues.map(prettyErrorMessage).join("\n");
console.log(
`Path: ${request.path} Method: ${request.method}\n ${pretty}`
);
throw new Error(pretty);
}
let message = "Unknown error";

if (e instanceof Error) {
Expand Down Expand Up @@ -87,6 +97,23 @@ export function buildClient<T extends AppRouter>(
baseHeaders: {
Accept: "application/json",
},
validateResponse: true,
});
}
/* eslint-enable @typescript-eslint/explicit-function-return-type */

function isZodError(error: unknown): error is ZodError {
if (!(error instanceof Error)) return false;

if (error instanceof ZodError) return true;
if (error.constructor.name === "ZodError") return true;
if ("issues" in error && error.issues instanceof Array) return true;

return false;
}

function prettyErrorMessage(issue: ZodIssue | undefined): string {
if (issue === undefined) return "";
const path = issue.path.length > 0 ? `"${issue.path.join(".")}" ` : "";
return `${path}${issue.message}`;
}
Loading