nyanimedb/modules/frontend/src/api/AuthClient/AuthClient.ts
2025-12-20 03:28:49 +03:00

64 lines
No EOL
2.1 KiB
TypeScript

import { createClient, createConfig } from "../client";
import type { ClientOptions as ClientOptions2 } from '../types.gen';
import type { Client, RequestOptions, RequestResult } from "../client";
import { refreshTokens } from "../../auth";
import type { ResponseStyle } from "../client";
let refreshPromise: Promise<boolean> | null = null;
async function getRefreshed(): Promise<boolean> {
if (!refreshPromise) {
refreshPromise = (async () => {
try {
const res = await refreshTokens({ throwOnError: true });
return !!res.data;
} catch {
return false;
}
})();
}
return refreshPromise;
}
const baseClient = createClient(createConfig<ClientOptions2>({ baseUrl: '/api/v1' }));
export const authClient: Client = {
...baseClient,
request: (async <
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = 'fields',
>(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>
): Promise<RequestResult<TData, TError, ThrowOnError, TResponseStyle>> => {
let result = await baseClient.request<TData, TError, ThrowOnError, TResponseStyle>(options);
// 1. Cast to a Record to allow the 'in' operator check on a generic
// We use 'unknown' instead of 'any' to maintain safety.
const resultObj = result as Record<string, unknown>;
// 2. Check if the object is valid and contains the error key
if (result && typeof result === 'object' && 'error' in resultObj) {
// 3. Narrow the error property specifically
const error = resultObj.error as { response?: { status?: number } } | null | undefined;
if (error?.response?.status === 401) {
const refreshed = await getRefreshed();
if (refreshed) {
result = await baseClient.request<TData, TError, ThrowOnError, TResponseStyle>(options);
} else {
localStorage.clear();
window.location.href = "/login";
}
}
}
return result;
}) as Client['request'],
};