{"version":3,"file":"useApiClient.mjs","sources":["../../../../src/lib/api/hooks/useApiClient.tsx"],"sourcesContent":["/**\n * @file useApiClient Hook\n * @description React hook for accessing and configuring the API client instance\n * with context-aware configuration and request utilities.\n *\n * @example\n * ```typescript\n * import { useApiClient } from '@/lib/api';\n *\n * function UserProfile() {\n *   const { client, get, post, isConfigured } = useApiClient();\n *\n *   const fetchUser = async (id: string) => {\n *     const response = await get<User>(`/users/${id}`);\n *     return response.data;\n *   };\n *\n *   return <div>...</div>;\n * }\n * ```\n */\n\n/* eslint-disable react-refresh/only-export-components */\n\nimport type { Context } from 'react';\nimport {\n  type ReactElement,\n  type ReactNode,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useState,\n} from 'react';\nimport { ApiClientContext as ImportedApiClientContext } from '../../contexts/ApiClientContext';\nimport { type ApiClient, apiClient, createApiClient } from '../api-client';\nimport type {\n  ApiClientConfig,\n  ApiError,\n  ApiResponse,\n  ErrorInterceptor,\n  RequestConfig,\n  RequestInterceptor,\n  ResponseInterceptor,\n} from '../types';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * API client context value\n */\nexport interface ApiClientContextValue {\n  /** API client instance */\n  client: ApiClient;\n  /** Whether client is configured */\n  isConfigured: boolean;\n  /** Current configuration */\n  config: ApiClientConfig | null;\n\n  /** Make a GET request */\n  get: <T>(url: string, options?: Partial<RequestConfig>) => Promise<ApiResponse<T>>;\n  /** Make a POST request */\n  post: <T, B = unknown>(\n    url: string,\n    body?: B,\n    options?: Partial<RequestConfig>\n  ) => Promise<ApiResponse<T>>;\n  /** Make a PUT request */\n  put: <T, B = unknown>(\n    url: string,\n    body?: B,\n    options?: Partial<RequestConfig>\n  ) => Promise<ApiResponse<T>>;\n  /** Make a PATCH request */\n  patch: <T, B = unknown>(\n    url: string,\n    body?: B,\n    options?: Partial<RequestConfig>\n  ) => Promise<ApiResponse<T>>;\n  /** Make a DELETE request */\n  del: <T>(url: string, options?: Partial<RequestConfig>) => Promise<ApiResponse<T>>;\n  /** Make a generic request */\n  request: <T>(config: RequestConfig) => Promise<ApiResponse<T>>;\n\n  /** Add request interceptor */\n  addRequestInterceptor: (interceptor: RequestInterceptor) => () => void;\n  /** Add response interceptor */\n  addResponseInterceptor: (interceptor: ResponseInterceptor) => () => void;\n  /** Add error interceptor */\n  addErrorInterceptor: (interceptor: ErrorInterceptor) => () => void;\n\n  /** Set token refresh function */\n  setTokenRefresh: (fn: () => Promise<string>) => void;\n  /** Cancel a specific request */\n  cancelRequest: (requestId: string) => void;\n  /** Cancel all pending requests */\n  cancelAllRequests: () => void;\n\n  /** Reconfigure the client */\n  configure: (config: Partial<ApiClientConfig>) => void;\n}\n\n/**\n * API client provider props\n */\nexport interface ApiClientProviderProps {\n  /** Child components */\n  children: ReactNode;\n  /** Initial client configuration */\n  config?: ApiClientConfig;\n  /** Custom client instance */\n  client?: ApiClient;\n  /** Token refresh function */\n  onTokenRefresh?: () => Promise<string>;\n  /** Global error handler */\n  onError?: (error: ApiError) => void;\n}\n\n// =============================================================================\n// CONTEXT\n// =============================================================================\n\n/**\n * Re-export the imported context for use within this module.\n * IMPORTANT: Do NOT create a new context here - use the one from contexts/ApiClientContext.\n * Creating a duplicate context would cause provider/consumer mismatches.\n */\nconst ApiClientContext = ImportedApiClientContext as Context<ApiClientContextValue | null>;\n\n// =============================================================================\n// PROVIDER COMPONENT\n// =============================================================================\n\n/**\n * API client provider component\n *\n * @example\n * ```typescript\n * function App() {\n *   return (\n *     <ApiClientProvider\n *       config={{\n *         baseUrl: 'https://api.example.com',\n *         timeout: 30000,\n *       }}\n *       onTokenRefresh={refreshToken}\n *       onError={(error) => toast.error(error.message)}\n *     >\n *       <Router />\n *     </ApiClientProvider>\n *   );\n * }\n * ```\n */\nexport function ApiClientProvider({\n  children,\n  config,\n  client: customClient,\n  onTokenRefresh,\n  onError,\n}: ApiClientProviderProps): ReactElement {\n  // Create or use provided client\n  const [client] = useState<ApiClient>(() => {\n    if (customClient) return customClient;\n    if (config) return createApiClient(config);\n    return apiClient;\n  });\n\n  const [currentConfig, setCurrentConfig] = useState<ApiClientConfig | null>(config ?? null);\n\n  // Set up token refresh\n  useEffect(() => {\n    if (onTokenRefresh) {\n      client.setTokenRefresh(onTokenRefresh);\n    }\n  }, [client, onTokenRefresh]);\n\n  // Set up global error handler\n  useEffect(() => {\n    if (onError) {\n      return client.addErrorInterceptor((error) => {\n        onError(error);\n        return error;\n      });\n    }\n    return undefined;\n  }, [client, onError]);\n\n  // Memoized request methods\n  const get = useCallback(\n    async <T,>(url: string, options?: Partial<RequestConfig>) => client.get<T>(url, options),\n    [client]\n  );\n\n  const post = useCallback(\n    async <T, B = unknown>(url: string, body?: B, options?: Partial<RequestConfig>) =>\n      client.post<T, B>(url, body, options),\n    [client]\n  );\n\n  const put = useCallback(\n    async <T, B = unknown>(url: string, body?: B, options?: Partial<RequestConfig>) =>\n      client.put<T, B>(url, body, options),\n    [client]\n  );\n\n  const patch = useCallback(\n    async <T, B = unknown>(url: string, body?: B, options?: Partial<RequestConfig>) =>\n      client.patch<T, B>(url, body, options),\n    [client]\n  );\n\n  const del = useCallback(\n    async <T,>(url: string, options?: Partial<RequestConfig>) => client.delete<T>(url, options),\n    [client]\n  );\n\n  const request = useCallback(\n    async <T,>(requestConfig: RequestConfig) => client.request<T>(requestConfig),\n    [client]\n  );\n\n  // Interceptor methods\n  const addRequestInterceptor = useCallback(\n    (interceptor: RequestInterceptor) => client.addRequestInterceptor(interceptor),\n    [client]\n  );\n\n  const addResponseInterceptor = useCallback(\n    (interceptor: ResponseInterceptor) => client.addResponseInterceptor(interceptor),\n    [client]\n  );\n\n  const addErrorInterceptor = useCallback(\n    (interceptor: ErrorInterceptor) => client.addErrorInterceptor(interceptor),\n    [client]\n  );\n\n  // Token refresh setter\n  const setTokenRefresh = useCallback(\n    (fn: () => Promise<string>) => client.setTokenRefresh(fn),\n    [client]\n  );\n\n  // Cancellation methods\n  const cancelRequest = useCallback(\n    (requestId: string) => client.cancelRequest(requestId),\n    [client]\n  );\n\n  const cancelAllRequests = useCallback(() => client.cancelAllRequests(), [client]);\n\n  // Configuration method\n  const configure = useCallback((newConfig: Partial<ApiClientConfig>) => {\n    setCurrentConfig((prev) => ({ ...prev, ...newConfig }) as ApiClientConfig);\n    // Note: ApiClient doesn't support runtime reconfiguration\n    // This would require creating a new client instance\n  }, []);\n\n  // Build context value\n  const contextValue = useMemo<ApiClientContextValue>(\n    () => ({\n      client,\n      isConfigured: currentConfig !== null,\n      config: currentConfig,\n      get,\n      post,\n      put,\n      patch,\n      del,\n      request,\n      addRequestInterceptor,\n      addResponseInterceptor,\n      addErrorInterceptor,\n      setTokenRefresh,\n      cancelRequest,\n      cancelAllRequests,\n      configure,\n    }),\n    [\n      client,\n      currentConfig,\n      get,\n      post,\n      put,\n      patch,\n      del,\n      request,\n      addRequestInterceptor,\n      addResponseInterceptor,\n      addErrorInterceptor,\n      setTokenRefresh,\n      cancelRequest,\n      cancelAllRequests,\n      configure,\n    ]\n  );\n\n  return <ApiClientContext.Provider value={contextValue}>{children}</ApiClientContext.Provider>;\n}\n\n// =============================================================================\n// HOOK\n// =============================================================================\n\n/**\n * Hook to access the API client and utilities\n *\n * @returns API client context with request methods and configuration\n * @throws Error if used outside ApiClientProvider\n *\n * @example\n * ```typescript\n * function UserList() {\n *   const { get, isConfigured } = useApiClient();\n *   const [users, setUsers] = useState<User[]>([]);\n *\n *   useEffect(() => {\n *     if (isConfigured) {\n *       get<User[]>('/users').then((res) => setUsers(res.data));\n *     }\n *   }, [get, isConfigured]);\n *\n *   return <ul>{users.map(user => <li key={user.id}>{user.name}</li>)}</ul>;\n * }\n * ```\n */\nexport function useApiClient(): ApiClientContextValue {\n  const context = useContext(ApiClientContext);\n\n  if (!context) {\n    // Return a default context using the singleton client\n    // This allows useApiClient to work without a provider\n    return {\n      client: apiClient,\n      isConfigured: true,\n      config: null,\n      get: async (url, options) => apiClient.get(url, options),\n      post: async (url, body, options) => apiClient.post(url, body, options),\n      put: async (url, body, options) => apiClient.put(url, body, options),\n      patch: async (url, body, options) => apiClient.patch(url, body, options),\n      del: async (url, options) => apiClient.delete(url, options),\n      request: async (config) => apiClient.request(config),\n      addRequestInterceptor: (interceptor) => apiClient.addRequestInterceptor(interceptor),\n      addResponseInterceptor: (interceptor) => apiClient.addResponseInterceptor(interceptor),\n      addErrorInterceptor: (interceptor) => apiClient.addErrorInterceptor(interceptor),\n      setTokenRefresh: (fn) => apiClient.setTokenRefresh(fn),\n      cancelRequest: (id) => apiClient.cancelRequest(id),\n      cancelAllRequests: () => apiClient.cancelAllRequests(),\n      configure: () => {\n        console.warn('[useApiClient] configure() requires ApiClientProvider');\n      },\n    };\n  }\n\n  return context;\n}\n\n/**\n * Hook to get only the API client instance\n *\n * @returns API client instance\n */\nexport function useApiClientInstance(): ApiClient {\n  const { client } = useApiClient();\n  return client;\n}\n\n/**\n * Hook to check if API client is configured\n *\n * @returns Whether the client is configured\n */\nexport function useApiClientStatus(): { isConfigured: boolean; config: ApiClientConfig | null } {\n  const { isConfigured, config } = useApiClient();\n  return { isConfigured, config };\n}\n\n// =============================================================================\n// UTILITY HOOKS\n// =============================================================================\n\n/**\n * Hook to add interceptors with automatic cleanup\n *\n * @example\n * ```typescript\n * useApiInterceptors({\n *   request: (config) => {\n *     config.headers['X-Custom-Header'] = 'value';\n *     return config;\n *   },\n *   response: (response) => {\n *     console.log('Response received:', response.status);\n *     return response;\n *   },\n * });\n * ```\n */\nexport function useApiInterceptors(interceptors: {\n  request?: RequestInterceptor;\n  response?: ResponseInterceptor;\n  error?: ErrorInterceptor;\n}): void {\n  const { addRequestInterceptor, addResponseInterceptor, addErrorInterceptor } = useApiClient();\n\n  useEffect(() => {\n    const cleanups: Array<() => void> = [];\n\n    if (interceptors.request) {\n      cleanups.push(addRequestInterceptor(interceptors.request));\n    }\n    if (interceptors.response) {\n      cleanups.push(addResponseInterceptor(interceptors.response));\n    }\n    if (interceptors.error) {\n      cleanups.push(addErrorInterceptor(interceptors.error));\n    }\n\n    return () => {\n      cleanups.forEach((cleanup) => cleanup());\n    };\n  }, [\n    interceptors.request,\n    interceptors.response,\n    interceptors.error,\n    addRequestInterceptor,\n    addResponseInterceptor,\n    addErrorInterceptor,\n  ]);\n}\n"],"names":["ApiClientContext","ImportedApiClientContext","ApiClientProvider","children","config","customClient","onTokenRefresh","onError","client","useState","createApiClient","apiClient","currentConfig","setCurrentConfig","useEffect","error","get","useCallback","url","options","post","body","put","patch","del","request","requestConfig","addRequestInterceptor","interceptor","addResponseInterceptor","addErrorInterceptor","setTokenRefresh","fn","cancelRequest","requestId","cancelAllRequests","configure","newConfig","prev","contextValue","useMemo","useApiClient","context","useContext","id","useApiClientInstance","useApiClientStatus","isConfigured","useApiInterceptors","interceptors","cleanups","cleanup"],"mappings":"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"}