64 lines
No EOL
2.1 KiB
TypeScript
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'],
|
|
}; |