UNPKG

@dbs-portal/core-api

Version:

HTTP client and API utilities for DBS Portal

197 lines 6.01 kB
/** * React Query hooks for common API operations */ import { useQuery, useMutation, useInfiniteQuery, useQueryClient, } from '@tanstack/react-query'; import { useCallback } from 'react'; import { queryKeys, queryOptions, mutationOptions } from './query-client'; /** * Hook to get the API client instance * This should be provided via context in a real application */ let globalApiClient = null; export function setGlobalApiClient(client) { globalApiClient = client; } function useApiClient() { if (!globalApiClient) { throw new Error('API client not configured. Call setGlobalApiClient() first.'); } return globalApiClient; } /** * Generic fetch hook */ export function useApiFetch(key, url, config, options) { const apiClient = useApiClient(); return useQuery({ ...queryOptions.standard(key, () => apiClient.get(url, config).then(response => response.data)), ...options, }); } /** * Generic mutation hook */ export function useApiMutation(mutationFn, options) { return useMutation({ ...mutationOptions.standard(mutationFn), ...options, }); } /** * GET request hook */ export function useGet(key, url, config, options) { return useApiFetch(key, url, config, options); } /** * POST request hook */ export function usePost(url, options) { const apiClient = useApiClient(); return useApiMutation(variables => apiClient.post(url, variables), options); } /** * PUT request hook */ export function usePut(url, options) { const apiClient = useApiClient(); return useApiMutation(variables => apiClient.put(url, variables), options); } /** * PATCH request hook */ export function usePatch(url, options) { const apiClient = useApiClient(); return useApiMutation(variables => apiClient.patch(url, variables), options); } /** * DELETE request hook */ export function useDelete(url, options) { const apiClient = useApiClient(); return useApiMutation(() => apiClient.delete(url), options); } /** * Paginated query hook */ export function usePaginatedQuery(key, url, page = 1, limit = 10, config, options) { const apiClient = useApiClient(); return useQuery({ ...queryOptions.standard([...key, 'paginated', { page, limit }], () => apiClient .get(url, { ...config, params: { ...config?.params, page, limit }, }) .then(response => response.data)), ...options, }); } /** * Infinite query hook for pagination */ export function useInfiniteApiQuery(key, url, config, options) { const apiClient = useApiClient(); return useInfiniteQuery({ queryKey: [...key, 'infinite'], queryFn: ({ pageParam = 1 }) => apiClient .get(url, { ...config, params: { ...config?.params, page: pageParam }, }) .then(response => response.data), getNextPageParam: lastPage => { if (lastPage.pagination.hasNext) { return lastPage.pagination.page + 1; } return undefined; }, initialPageParam: 1, ...options, }); } /** * Search query hook with debouncing */ export function useSearchQuery(query, url, config, options) { const apiClient = useApiClient(); return useQuery({ queryKey: queryKeys.search(query), queryFn: () => apiClient .get(url, { ...config, params: { ...config?.params, q: query }, }) .then(response => response.data), enabled: query.length > 0, staleTime: 30 * 1000, // 30 seconds ...options, }); } /** * Cache management hooks */ export function useCacheUtils() { const queryClient = useQueryClient(); const invalidateQueries = useCallback((key) => { return queryClient.invalidateQueries({ queryKey: key }); }, [queryClient]); const refetchQueries = useCallback((key) => { return queryClient.refetchQueries({ queryKey: key }); }, [queryClient]); const removeQueries = useCallback((key) => { return queryClient.removeQueries({ queryKey: key }); }, [queryClient]); const setQueryData = useCallback((key, data) => { return queryClient.setQueryData(key, data); }, [queryClient]); const getQueryData = useCallback((key) => { return queryClient.getQueryData(key); }, [queryClient]); const prefetchQuery = useCallback((key, fetcher, staleTime) => { return queryClient.prefetchQuery({ queryKey: key, queryFn: fetcher, ...(staleTime !== undefined && { staleTime }), }); }, [queryClient]); return { invalidateQueries, refetchQueries, removeQueries, setQueryData, getQueryData, prefetchQuery, }; } /** * Optimistic update hook */ export function useOptimisticMutation(mutationFn, queryKey, optimisticUpdate, options) { const queryClient = useQueryClient(); return useMutation({ mutationFn, onMutate: async (variables) => { // Cancel outgoing refetches await queryClient.cancelQueries({ queryKey }); // Snapshot previous value const previousData = queryClient.getQueryData(queryKey); // Optimistically update queryClient.setQueryData(queryKey, old => optimisticUpdate(old, variables)); // Return context with previous data return { previousData }; }, onError: (error, variables, context) => { // Rollback on error if (context?.previousData) { queryClient.setQueryData(queryKey, context.previousData); } options?.onError?.(error, variables, context); }, onSettled: () => { // Refetch after mutation queryClient.invalidateQueries({ queryKey }); }, ...options, }); } //# sourceMappingURL=hooks.js.map