Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.
Merged
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
4 changes: 1 addition & 3 deletions frontend/client/lib/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export type RefreshTokenResponse = {
refreshToken: string;
};

const baseURL = apiBaseUrl();

export async function login(data: LoginRequest): Promise<AuthResponse> {
const { data: res } = await apiClient.post<AuthResponse>("/api/v1/auth/login", data);
return res;
Expand Down Expand Up @@ -72,7 +70,7 @@ export async function changePassword(
}

export async function refreshToken(token: string): Promise<RefreshTokenResponse> {
const { data } = await axios.post<RefreshTokenResponse>(`${baseURL}/api/v1/auth/refresh`, {
const { data } = await axios.post<RefreshTokenResponse>(`${apiBaseUrl()}/api/v1/auth/refresh`, {
refreshToken: token,
});
return data;
Expand Down
10 changes: 5 additions & 5 deletions frontend/client/lib/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ export type ApiError = {

type RetryableConfig = InternalAxiosRequestConfig & { _retry?: boolean };

const baseURL = apiBaseUrl();

export const apiClient: AxiosInstance = axios.create({
baseURL,
headers: { "Content-Type": "application/json" },
});

// Attach access token from in-memory Zustand store on every request.
// Resolve the API base per-request + attach the access token. window.__ENV (runtime config)
// may not be populated at module-load on a hard page load (e.g. the OAuth callback), which
// would otherwise cache the localhost fallback and send requests to the wrong origin.
apiClient.interceptors.request.use((config) => {
config.baseURL = apiBaseUrl();
const token = useAuthStore.getState().token;
if (token) {
config.headers.set("Authorization", `Bearer ${token}`);
Expand Down Expand Up @@ -97,7 +97,7 @@ apiClient.interceptors.response.use(

try {
const { data } = await axios.post<{ accessToken: string; refreshToken: string }>(
`${baseURL}/api/v1/auth/refresh`,
`${apiBaseUrl()}/api/v1/auth/refresh`,
{ refreshToken },
);
setToken(data.accessToken);
Expand Down
4 changes: 1 addition & 3 deletions frontend/client/lib/auth/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ function isExpiredSoon(token: string | null, bufferMs = 30_000): boolean {
return exp * 1000 < Date.now() + bufferMs;
}

const BASE_URL = apiBaseUrl();

export async function getValidAccessToken(force = false): Promise<string | null> {
const token = getAccessToken();
// `force` refreshes even a still-valid token — used by the idle keep-alive timer so
Expand All @@ -68,7 +66,7 @@ export async function getValidAccessToken(force = false): Promise<string | null>
const { refreshToken, setToken, setRefreshToken, logout } = useAuthStore.getState();
if (!refreshToken) { logout(); return null; }

const res = await fetch(`${BASE_URL}/api/v1/auth/refresh`, {
const res = await fetch(`${apiBaseUrl()}/api/v1/auth/refresh`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ refreshToken }),
Expand Down
Loading