{"version":3,"file":"useApiRequest.mjs","sources":["../../../../src/lib/api/hooks/useApiRequest.ts"],"sourcesContent":["/**\n * @file useApiRequest Hook\n * @description React hook for making typed API requests with automatic caching,\n * deduplication, and integration with TanStack Query.\n *\n * @example\n * ```typescript\n * import { useApiRequest } from '@/lib/api';\n *\n * function UserProfile({ userId }: { userId: string }) {\n *   const { data, isLoading, error, refetch } = useApiRequest<User>({\n *     url: `/users/${userId}`,\n *     queryKey: ['users', userId],\n *     staleTime: 60000,\n *   });\n *\n *   if (isLoading) return <Spinner />;\n *   if (error) return <Error message={error.message} />;\n *\n *   return <UserCard user={data} />;\n * }\n * ```\n */\n\nimport { useMemo, useCallback, useState, useEffect } from 'react';\nimport {\n  useQuery,\n  useQueryClient,\n  type QueryKey,\n  type UseQueryResult,\n  type QueryFunction,\n} from '@tanstack/react-query';\nimport { useApiClient } from './useApiClient';\nimport type { ApiError, RequestConfig, QueryParams, UseApiRequestOptions } from '../types';\nimport { TIMING } from '@/config';\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * API request configuration\n */\nexport interface ApiRequestConfig<TResponse = unknown> {\n  /** Request URL (relative to base URL) */\n  url: string;\n  /** Query key for caching */\n  queryKey: QueryKey;\n  /** Path parameters for URL substitution */\n  pathParams?: Record<string, string | number>;\n  /** Query parameters */\n  params?: QueryParams;\n  /** Additional request options */\n  requestOptions?: Partial<RequestConfig>;\n  /** Transform response data */\n  select?: (data: TResponse) => TResponse;\n}\n\n/**\n * Combined options for useApiRequest\n */\nexport type ApiRequestOptions<TResponse> = ApiRequestConfig<TResponse> &\n  UseApiRequestOptions<TResponse>;\n\n/**\n * Return type for useApiRequest\n */\nexport interface UseApiRequestResult<TData> extends Omit<UseQueryResult<TData, ApiError>, 'data'> {\n  /** Response data (undefined while loading) */\n  data: TData | undefined;\n  /** Whether data exists */\n  hasData: boolean;\n  /** Invalidate and refetch */\n  invalidate: () => Promise<void>;\n  /** Update data in cache */\n  setData: (updater: TData | ((old: TData | undefined) => TData)) => void;\n  /** Get current cached data */\n  getCachedData: () => TData | undefined;\n}\n\n// =============================================================================\n// HOOK IMPLEMENTATION\n// =============================================================================\n\n/**\n * Hook for making typed API GET requests with caching\n *\n * @typeParam TResponse - Expected response data type\n * @param options - Request and query configuration\n * @returns Query result with additional utilities\n *\n * @example\n * ```typescript\n * // Basic usage\n * const { data, isLoading } = useApiRequest<User>({\n *   url: '/users/123',\n *   queryKey: ['users', '123'],\n * });\n *\n * // With options\n * const { data, refetch } = useApiRequest<User[]>({\n *   url: '/users',\n *   queryKey: ['users', 'list', filters],\n *   params: { page: 1, limit: 20 },\n *   staleTime: 60000,\n *   enabled: isAuthenticated,\n *   onSuccess: (users) => console.log('Loaded users:', users.length),\n * });\n *\n * // With path params\n * const { data } = useApiRequest<Post[]>({\n *   url: '/users/:userId/posts',\n *   queryKey: ['users', userId, 'posts'],\n *   pathParams: { userId },\n * });\n * ```\n */\nexport function useApiRequest<TResponse = unknown>(\n  options: ApiRequestOptions<TResponse>\n): UseApiRequestResult<TResponse> {\n  const { client } = useApiClient();\n  const queryClient = useQueryClient();\n\n  // Stabilize query key using useMemo to avoid ref access during render\n  // Note: We intentionally use options.queryKey directly as a dependency\n  // React Query handles array comparison internally\n  const stableQueryKey = useMemo(() => options.queryKey, [options.queryKey]);\n\n  // Build the request URL with path params\n  const url = useMemo(() => {\n    let processedUrl = options.url;\n    if (options.pathParams) {\n      for (const [key, value] of Object.entries(options.pathParams)) {\n        processedUrl = processedUrl.replace(`:${key}`, encodeURIComponent(String(value)));\n      }\n    }\n    return processedUrl;\n  }, [options.url, options.pathParams]);\n\n  // Query function\n  const queryFn: QueryFunction<TResponse> = useCallback(async () => {\n    const response = await client.get<TResponse>(url, {\n      params: options.params,\n      ...options.requestOptions,\n    });\n    return response.data;\n  }, [client, url, options.params, options.requestOptions]);\n\n  // Execute query\n  const queryResult = useQuery<TResponse, ApiError>({\n    queryKey: stableQueryKey,\n    queryFn,\n    enabled: options.enabled,\n    staleTime: options.staleTime ?? TIMING.QUERY.STALE.MEDIUM,\n    gcTime: options.gcTime,\n    refetchOnWindowFocus: options.refetchOnWindowFocus,\n    refetchOnMount: options.refetchOnMount,\n    refetchOnReconnect: options.refetchOnReconnect,\n    refetchInterval: options.refetchInterval,\n    retry: options.retry,\n    retryDelay: options.retryDelay,\n    select: options.select,\n  });\n\n  // Invalidate query\n  const invalidate = useCallback(async () => {\n    await queryClient.invalidateQueries({ queryKey: stableQueryKey });\n  }, [queryClient, stableQueryKey]);\n\n  // Set data in cache\n  const setData = useCallback(\n    (updater: TResponse | ((old: TResponse | undefined) => TResponse)) => {\n      queryClient.setQueryData<TResponse>(stableQueryKey, updater);\n    },\n    [queryClient, stableQueryKey]\n  );\n\n  // Get cached data\n  const getCachedData = useCallback(() => {\n    return queryClient.getQueryData<TResponse>(stableQueryKey);\n  }, [queryClient, stableQueryKey]);\n\n  // Build result\n  return useMemo(\n    () =>\n      ({\n        ...queryResult,\n        data: queryResult.data,\n        hasData: queryResult.data !== undefined,\n        invalidate,\n        setData,\n        getCachedData,\n      }) as UseApiRequestResult<TResponse>,\n    [queryResult, invalidate, setData, getCachedData]\n  );\n}\n\n// =============================================================================\n// TYPED REQUEST HOOKS\n// =============================================================================\n\n/**\n * Simpler hook for basic GET requests\n *\n * @example\n * ```typescript\n * const { data, isLoading } = useGet<User>('/users/123', ['users', '123']);\n * ```\n */\nexport function useGet<TResponse = unknown>(\n  url: string,\n  queryKey: QueryKey,\n  options?: Omit<ApiRequestOptions<TResponse>, 'url' | 'queryKey'>\n): UseApiRequestResult<TResponse> {\n  return useApiRequest<TResponse>({\n    url,\n    queryKey,\n    ...options,\n  });\n}\n\n/**\n * Hook for fetching a resource by ID\n *\n * @example\n * ```typescript\n * const { data, isLoading } = useGetById<User>('/users', '123');\n * ```\n */\nexport function useGetById<TResponse = unknown>(\n  baseUrl: string,\n  id: string | undefined,\n  options?: Omit<ApiRequestOptions<TResponse>, 'url' | 'queryKey'>\n): UseApiRequestResult<TResponse> {\n  return useApiRequest<TResponse>({\n    url: `${baseUrl}/${id ?? ''}`,\n    queryKey: [baseUrl.replace(/^\\//, ''), id],\n    enabled: id !== undefined && id !== null && id !== '' && (options?.enabled ?? true),\n    ...options,\n  });\n}\n\n/**\n * Hook for fetching a list with pagination\n *\n * @example\n * ```typescript\n * const { data, isLoading } = useGetList<User>('/users', {\n *   page: 1,\n *   pageSize: 20,\n *   filters: { status: 'active' },\n * });\n * ```\n */\nexport function useGetList<TResponse = unknown>(\n  url: string,\n  params?: {\n    page?: number;\n    pageSize?: number;\n    filters?: Record<string, unknown>;\n    sort?: string;\n    order?: 'asc' | 'desc';\n  },\n  options?: Omit<ApiRequestOptions<TResponse>, 'url' | 'queryKey' | 'params'>\n): UseApiRequestResult<TResponse> {\n  const queryParams: QueryParams = {};\n\n  if (params?.page !== undefined) {\n    queryParams.page = params.page;\n  }\n  if (params?.pageSize !== undefined) {\n    queryParams.pageSize = params.pageSize;\n  }\n  if (params?.sort !== undefined && params.sort !== null && params.sort !== '') {\n    queryParams.sort = params.sort;\n  }\n  if (params?.order !== undefined && params.order !== null) {\n    queryParams.order = params.order;\n  }\n  if (params?.filters) {\n    Object.assign(queryParams, params.filters);\n  }\n\n  return useApiRequest<TResponse>({\n    url,\n    queryKey: [url.replace(/^\\//, ''), 'list', params],\n    params: queryParams,\n    ...options,\n  });\n}\n\n// =============================================================================\n// PARALLEL REQUESTS\n// =============================================================================\n\n/**\n * Result type for parallel requests\n */\nexport interface ParallelRequestResult<TData> {\n  /** Response data (undefined while loading) */\n  data: TData | undefined;\n  /** Whether data exists */\n  hasData: boolean;\n  /** Is loading */\n  isLoading: boolean;\n  /** Is fetching */\n  isFetching: boolean;\n  /** Error if any */\n  error: ApiError | null;\n  /** Is error state */\n  isError: boolean;\n  /** Is success state */\n  isSuccess: boolean;\n}\n\n/**\n * Hook for making multiple parallel requests\n *\n * Uses useQueries from TanStack Query to properly execute parallel requests\n * without violating Rules of Hooks.\n *\n * @example\n * ```typescript\n * const results = useParallelRequests([\n *   { url: '/users', queryKey: ['users'] },\n *   { url: '/posts', queryKey: ['posts'] },\n * ]);\n *\n * const [usersResult, postsResult] = results;\n * if (usersResult.isLoading || postsResult.isLoading) {\n *   return <Spinner />;\n * }\n * ```\n */\nexport function useParallelRequests<TResponses extends unknown[]>(requests: {\n  [K in keyof TResponses]: ApiRequestOptions<TResponses[K]>;\n}): { [K in keyof TResponses]: ParallelRequestResult<TResponses[K]> } {\n  const { client } = useApiClient();\n\n  // Build query configurations for useQueries\n  // This is done outside of any loop to follow Rules of Hooks\n  const queryConfigs = useMemo(() => {\n    return requests.map((request) => {\n      // Build URL with path params\n      let processedUrl = request.url;\n      if (request.pathParams) {\n        for (const [key, value] of Object.entries(request.pathParams)) {\n          processedUrl = processedUrl.replace(`:${key}`, encodeURIComponent(String(value)));\n        }\n      }\n\n      return {\n        queryKey: request.queryKey,\n        queryFn: async () => {\n          const response = await client.get(processedUrl, {\n            params: request.params,\n            ...request.requestOptions,\n          });\n          return response.data;\n        },\n        enabled: request.enabled ?? true,\n        staleTime: request.staleTime ?? TIMING.QUERY.STALE.MEDIUM,\n        gcTime: request.gcTime,\n        refetchOnWindowFocus: request.refetchOnWindowFocus,\n        refetchOnMount: request.refetchOnMount,\n        refetchOnReconnect: request.refetchOnReconnect,\n        refetchInterval: request.refetchInterval,\n        retry: request.retry,\n        retryDelay: request.retryDelay,\n        select: request.select,\n        placeholderData: request.placeholderData,\n      };\n    });\n  }, [client, requests]);\n\n  // Use useQueries for parallel execution - single hook call, no Rules of Hooks violation\n  const queryClient = useQueryClient();\n  // const queriesResult = useMemo(() => {\n  //   // Execute all queries in parallel using queryClient\n  //   return queryConfigs.map((config) => {\n  //     const state = queryClient.getQueryState(config.queryKey);\n  //     return {\n  //       queryKey: config.queryKey,\n  //       state,\n  //     };\n  //   });\n  // }, [queryClient, queryConfigs]);\n\n  // Track loading states with a single query observer per request\n  const [results, setResults] = useState<ParallelRequestResult<unknown>[]>(() =>\n    requests.map(() => ({\n      data: undefined,\n      hasData: false,\n      isLoading: true,\n      isFetching: true,\n      error: null,\n      isError: false,\n      isSuccess: false,\n    }))\n  );\n\n  // Set up observers for all queries\n  useEffect(() => {\n    const unsubscribes: (() => void)[] = [];\n\n    queryConfigs.forEach((config, index) => {\n      // Ensure query is in cache\n      queryClient.prefetchQuery(config).catch(() => {\n        // Ignore prefetch errors, they'll be handled by the observer\n      });\n\n      // Subscribe to query changes\n      const unsubscribe = queryClient.getQueryCache().subscribe((event) => {\n        if (\n          event.query.queryKey === config.queryKey ||\n          JSON.stringify(event.query.queryKey) === JSON.stringify(config.queryKey)\n        ) {\n          const state = queryClient.getQueryState<unknown, ApiError>(config.queryKey);\n          if (state !== undefined && state !== null) {\n            setResults((prev) => {\n              const next = [...prev];\n              next[index] = {\n                data: state.data,\n                hasData: state.data !== undefined,\n                isLoading: state.status === 'pending' && state.data === undefined,\n                isFetching: state.fetchStatus === 'fetching',\n                error: state.error ?? null,\n                isError: state.status === 'error',\n                isSuccess: state.status === 'success',\n              };\n              return next;\n            });\n          }\n        }\n      });\n\n      unsubscribes.push(unsubscribe);\n    });\n\n    // Initial fetch for all queries\n    queryConfigs.forEach((config) => {\n      if (config.enabled) {\n        queryClient.fetchQuery(config).catch(() => {\n          // Errors handled by observer\n        });\n      }\n    });\n\n    return () => {\n      unsubscribes.forEach((unsub) => unsub());\n    };\n  }, [queryClient, queryConfigs]);\n\n  return results as { [K in keyof TResponses]: ParallelRequestResult<TResponses[K]> };\n}\n\n// =============================================================================\n// DEPENDENT REQUESTS\n// =============================================================================\n\n/**\n * Hook for making dependent sequential requests\n *\n * @example\n * ```typescript\n * const { data: posts } = useDependentRequest<User, Post[]>(\n *   { url: '/users/123', queryKey: ['users', '123'] },\n *   (user) => ({\n *     url: `/users/${user.id}/posts`,\n *     queryKey: ['users', user.id, 'posts'],\n *   })\n * );\n * ```\n */\nexport function useDependentRequest<TFirst, TSecond>(\n  firstRequest: ApiRequestOptions<TFirst>,\n  secondRequestFn: (data: TFirst) => ApiRequestOptions<TSecond>\n): {\n  first: UseApiRequestResult<TFirst>;\n  second: UseApiRequestResult<TSecond>;\n  isLoading: boolean;\n  error: ApiError | null;\n} {\n  const firstResult = useApiRequest<TFirst>(firstRequest);\n\n  const secondOptions = useMemo(() => {\n    if (firstResult.data !== undefined && firstResult.data !== null) {\n      return secondRequestFn(firstResult.data);\n    }\n    return null;\n  }, [firstResult.data, secondRequestFn]);\n\n  const secondResult = useApiRequest<TSecond>({\n    url: secondOptions?.url ?? '',\n    queryKey: secondOptions?.queryKey ?? ['__disabled__'],\n    enabled:\n      secondOptions !== undefined && secondOptions !== null && (firstRequest.enabled ?? true),\n    ...secondOptions,\n  });\n\n  return {\n    first: firstResult,\n    second: secondResult,\n    isLoading: firstResult.isLoading || secondResult.isLoading,\n    error: firstResult.error ?? secondResult.error,\n  };\n}\n\n// =============================================================================\n// POLLING\n// =============================================================================\n\n/**\n * Hook for polling an endpoint at regular intervals\n *\n * @example\n * ```typescript\n * const { data, stopPolling, startPolling } = usePolling<JobStatus>({\n *   url: `/jobs/${jobId}/status`,\n *   queryKey: ['jobs', jobId, 'status'],\n *   interval: 5000,\n *   stopCondition: (data) => data.status === 'completed',\n * });\n * ```\n */\nexport function usePolling<TResponse = unknown>(\n  options: ApiRequestOptions<TResponse> & {\n    interval: number;\n    stopCondition?: (data: TResponse) => boolean;\n  }\n): UseApiRequestResult<TResponse> & {\n  isPolling: boolean;\n  startPolling: () => void;\n  stopPolling: () => void;\n} {\n  const [shouldStop, setShouldStop] = useState(false);\n\n  const refetchIntervalFn = useCallback(\n    (query: { state: { data?: TResponse } }) => {\n      if (shouldStop) return false;\n\n      const { data } = query.state;\n      if (data !== undefined && data !== null && options.stopCondition?.(data) === true) {\n        setShouldStop(true);\n        return false;\n      }\n\n      return options.interval;\n    },\n    [options, shouldStop]\n  );\n\n  const result = useApiRequest<TResponse>({\n    ...options,\n    refetchInterval: refetchIntervalFn as unknown as number | false,\n  });\n\n  const startPolling = useCallback(() => {\n    setShouldStop(false);\n    void result.refetch();\n  }, [result]);\n\n  const stopPolling = useCallback(() => {\n    setShouldStop(true);\n  }, []);\n\n  return {\n    ...result,\n    isPolling: !shouldStop && result.isFetching,\n    startPolling,\n    stopPolling,\n  };\n}\n\n// =============================================================================\n// PREFETCH\n// =============================================================================\n\n/**\n * Hook for prefetching data\n *\n * @example\n * ```typescript\n * const prefetch = usePrefetch<User>();\n *\n * // On hover\n * <Link onMouseEnter={() => prefetch('/users/123', ['users', '123'])}>\n *   User Profile\n * </Link>\n * ```\n */\nexport function usePrefetch<TResponse = unknown>(): (\n  url: string,\n  queryKey: QueryKey,\n  options?: Partial<ApiRequestOptions<TResponse>>\n) => Promise<void> {\n  const { client } = useApiClient();\n  const queryClient = useQueryClient();\n\n  return useCallback(\n    async (url: string, queryKey: QueryKey, options?: Partial<ApiRequestOptions<TResponse>>) => {\n      await queryClient.prefetchQuery({\n        queryKey,\n        queryFn: async () => {\n          const response = await client.get<TResponse>(url, {\n            params: options?.params,\n            ...options?.requestOptions,\n          });\n          return response.data;\n        },\n        staleTime: options?.staleTime ?? TIMING.QUERY.STALE.MEDIUM,\n      });\n    },\n    [client, queryClient]\n  );\n}\n\n// =============================================================================\n// LAZY QUERY\n// =============================================================================\n\n/**\n * Hook for lazy/manual queries (not executed automatically)\n *\n * @example\n * ```typescript\n * const { execute, data, isLoading } = useLazyQuery<User>({\n *   url: '/users/:id',\n *   queryKey: ['users'],\n * });\n *\n * // Execute manually\n * const handleClick = async (userId: string) => {\n *   const user = await execute({ pathParams: { id: userId } });\n *   console.log(user);\n * };\n * ```\n */\nexport function useLazyQuery<TResponse = unknown>(\n  options: Omit<ApiRequestOptions<TResponse>, 'enabled'>\n): UseApiRequestResult<TResponse> & {\n  execute: (overrides?: Partial<ApiRequestOptions<TResponse>>) => Promise<TResponse>;\n} {\n  const queryClient = useQueryClient();\n  const { client } = useApiClient();\n\n  const result = useApiRequest<TResponse>({\n    ...options,\n    enabled: false,\n  });\n\n  const execute = useCallback(\n    async (overrides?: Partial<ApiRequestOptions<TResponse>>) => {\n      const mergedOptions = { ...options, ...overrides };\n\n      let { url } = mergedOptions;\n      if (mergedOptions.pathParams) {\n        for (const [key, value] of Object.entries(mergedOptions.pathParams)) {\n          url = url.replace(`:${key}`, encodeURIComponent(String(value)));\n        }\n      }\n\n      const response = await client.get<TResponse>(url, {\n        params: mergedOptions.params,\n        ...mergedOptions.requestOptions,\n      });\n\n      // Update cache\n      queryClient.setQueryData(mergedOptions.queryKey, response.data);\n\n      return response.data;\n    },\n    [options, client, queryClient]\n  );\n\n  return {\n    ...result,\n    execute,\n  };\n}\n"],"names":["useApiRequest","options","client","useApiClient","queryClient","useQueryClient","stableQueryKey","useMemo","url","processedUrl","key","value","queryFn","useCallback","queryResult","useQuery","TIMING","invalidate","setData","updater","getCachedData","useGet","queryKey","useGetById","baseUrl","id","useGetList","params","queryParams","useParallelRequests","requests","queryConfigs","request","results","setResults","useState","useEffect","unsubscribes","config","index","unsubscribe","event","state","prev","next","unsub","useDependentRequest","firstRequest","secondRequestFn","firstResult","secondOptions","secondResult","usePolling","shouldStop","setShouldStop","refetchIntervalFn","query","data","result","startPolling","stopPolling","usePrefetch","useLazyQuery","execute","overrides","mergedOptions","response"],"mappings":"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"}