import { createContext, use, type PropsWithChildren } from 'react'; import { createTanstackApi, createApi } from '../lib/api'; import axios from 'axios'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useNavigate } from 'react-router'; type ApiProviderProps = PropsWithChildren; type ApiContextType = { apiClient: ReturnType; tanstackApiClient: ReturnType; }; const ApiContext = createContext(null); const queryClient = new QueryClient(); /** * Example usage: * ```ts * const { tanstackApiClient } = useApi(); * const { queryOptions } = tanstackApiClient.get('/api/health/info'); * useQuery({ * ...queryOptions, * queryFn: async (...args) => { * console.log('Fetching health info...'); * const data = await queryOptions.queryFn!(...args); * console.log('Health Info:', data); * return data; * }, * }); * ``` */ export const ApiProvider: React.FC = ({ children }) => { const navigate = useNavigate(); const axiosInstance = axios.create({ withCredentials: true, }); const internalAxiosInstance = axios.create({ withCredentials: true, }); internalAxiosInstance.interceptors.response.use( (response) => response, (error) => { // only handle 403 errors if (!error.response) return Promise.reject(error); if (error.response.status === 401) { // redirect to login page return navigate('/login', {}); } return Promise.reject(error); } ); const apiClient = createApi(axiosInstance); const tanstackApiClient = createTanstackApi(internalAxiosInstance); return ( {children} ); }; export function useApi() { const context = use(ApiContext); if (!context) { throw new Error('useApi must be used within an ApiProvider'); } return context; }