Files
reflector/www/app/lib/apiClient.tsx
Mathieu Virbel a58a49aeb6 fix: resolve authentication race condition with React Query
Previously, API calls were being made before the auth token was configured,
causing initial 401 errors that would retry with 200 after token setup.

Changes:
- Add global auth readiness tracking in apiClient
- Create useAuthReady hook that checks both session and token state
- Update all API hooks to use isAuthReady instead of just session status
- Add AuthWrapper component at layout level for consistent loading UX
- Show spinner while authentication initializes across all pages

This ensures API calls only fire after authentication is fully configured,
eliminating the 401/retry pattern and improving user experience.
2025-08-29 15:53:51 -06:00

56 lines
1.6 KiB
TypeScript

"use client";
import createClient from "openapi-fetch";
import type { paths } from "../reflector-api";
import {
queryOptions,
useMutation,
useQuery,
useSuspenseQuery,
} from "@tanstack/react-query";
import createFetchClient from "openapi-react-query";
// Create the base openapi-fetch client with a default URL
// The actual URL will be set via middleware in ApiAuthProvider
export const client = createClient<paths>({
baseUrl: "http://127.0.0.1:1250",
});
// Create the React Query client wrapper
export const $api = createFetchClient<paths>(client);
// Store the current auth token and ready state
let currentAuthToken: string | null | undefined = null;
let authConfigured = false;
// Export function to check if auth is ready
export const isAuthConfigured = () => authConfigured;
// Set up authentication middleware once
client.use({
onRequest({ request }) {
if (currentAuthToken) {
request.headers.set("Authorization", `Bearer ${currentAuthToken}`);
}
// Only set Content-Type if not already set (FormData will set its own boundary)
if (
!request.headers.has("Content-Type") &&
!(request.body instanceof FormData)
) {
request.headers.set("Content-Type", "application/json");
}
return request;
},
});
// Configure authentication by updating the token
export const configureApiAuth = (token: string | null | undefined) => {
currentAuthToken = token;
authConfigured = true;
};
// Export typed hooks for convenience
export const useApiQuery = $api.useQuery;
export const useApiMutation = $api.useMutation;
export const useApiSuspenseQuery = $api.useSuspenseQuery;