UNPKG

@k4l3b4/query-adapters

Version:

@tanstack/query fetching adapters to make your life a little bit easier.

1 lines 12.5 kB
{"version":3,"sources":["../src/data-fetcher/index.tsx","../src/lib/utils.ts","../src/lib/fetcher.ts","../src/provider.tsx","../src/infinite-data-fetcher/index.tsx"],"sourcesContent":["'use client';\n\nimport React, { type ReactNode } from 'react';\nimport {\n useQuery,\n type UseQueryResult,\n type UseQueryOptions,\n type QueryKey,\n} from '@tanstack/react-query';\nimport { fetchWithSettings } from '../lib/fetcher';\nimport { useFetcherSettings } from '../provider';\n\n// Props for the DataFetcher component\ninterface DataFetcherProps<TData, TError> {\n queryKey: QueryKey;\n url?: string;\n queryFn?: () => Promise<TData>;\n queryParams?: Record<string, unknown>;\n options?: Omit<\n UseQueryOptions<TData, TError, TData, QueryKey>,\n 'queryKey' | 'queryFn'\n >;\n children: (props: {\n data: TData | undefined;\n error: TError | null;\n isLoading: boolean;\n isError: boolean;\n status: UseQueryResult['status'];\n refetch: UseQueryResult<TData, TError>['refetch'];\n }) => ReactNode; // Render prop for custom UI\n}\n\nexport function DataFetcher<TData, TError>({\n queryKey,\n queryFn,\n url,\n queryParams,\n options = {},\n children,\n}: DataFetcherProps<TData, TError>) {\n const { baseUrl, ...globalOptions } = useFetcherSettings();\n const fetcher = queryFn\n ? queryFn\n : async () => {\n if (!url) {\n throw new Error('URL must be provided if no queryFn is specified');\n }\n return fetchWithSettings<TData>(url, undefined, queryParams, baseUrl, globalOptions);\n };\n\n const queryResult = useQuery<TData, TError>({\n queryKey,\n queryFn: fetcher,\n ...options,\n });\n\n return (\n <>\n {children({ ...queryResult })}\n </>\n );\n}\n\nexport default DataFetcher;\n","const buildQueryString = (params: Record<string, unknown>): string => {\n const query = Object.entries(params)\n .filter(([_, value]) => value !== undefined && value !== null)\n .map(\n ([key, value]) =>\n `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`\n )\n .join('&');\n return query ? `?${query}` : '';\n}\n\n\nconst isDev = () => {\n // Vite\n if (typeof import.meta !== 'undefined' && (import.meta as any)?.env?.DEV) {\n return true;\n }\n // Other frameworks (Next.js, Create React App)\n if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {\n return true;\n }\n return false;\n};\n\nexport { buildQueryString, isDev }","import { buildQueryString } from \"./utils\";\n\nexport const fetchWithSettings = async<T>(\n endpoint: string,\n requestOptions: RequestInit = {},\n queryParams?: Record<string, unknown>, // Optional query parameters\n baseUrl?: string, // Optional base URL\n globalOptions?: RequestInit // Optional global options\n): Promise<T> => {\n\n const queryString = queryParams ? buildQueryString(queryParams) : '';\n const url = `${baseUrl}${endpoint}${queryString}`;\n\n const mergedOptions: RequestInit = {\n ...globalOptions,\n ...requestOptions,\n headers: {\n ...(globalOptions?.headers || {}),\n ...(requestOptions.headers || {}),\n },\n };\n\n const response = await fetch(url, mergedOptions);\n\n if (!response.ok) {\n throw new Error(`Error: ${response.status} - ${response.statusText}`);\n }\n\n return response.json();\n};\n","import type React from 'react'\nimport { createContext, useContext, type ReactNode } from 'react'\n\n\n// this provider will be used to set the default settings for the fetcher\n// if ya'll don't want to pass a queryfn each time and your mostly\n// using it to pull data from an api or a url in general\n\ninterface FetcherSettings extends RequestInit {\n baseUrl?: string; // Optional base URL for requests\n}\n\n// Default settings for the fetcher\nconst defaultSettings: FetcherSettings = {\n baseUrl: '',\n headers: { 'Content-Type': 'application/json' },\n};\n\nconst FetcherContext = createContext<FetcherSettings>(defaultSettings);\n\ninterface DataFetcherProviderProps {\n settings: FetcherSettings;\n children: ReactNode;\n}\n\nexport const DataFetcherProvider: React.FC<DataFetcherProviderProps> = ({\n settings,\n children,\n}) => {\n return (\n <FetcherContext.Provider value={{ ...defaultSettings, ...settings }}>\n {children}\n </FetcherContext.Provider>\n );\n};\n\nexport const useFetcherSettings = () => {\n return useContext(FetcherContext);\n};\n","'use client';\n\nimport { useEffect, useMemo, useRef } from 'react';\nimport {\n type InfiniteData,\n type QueryFunctionContext,\n type QueryKey,\n useInfiniteQuery,\n} from '@tanstack/react-query';\nimport type { InfiniteDataFetcherProps } from '../types';\nimport { fetchWithSettings } from '../lib/fetcher';\nimport { useFetcherSettings } from '../provider';\n\nexport function InfiniteDataFetcher<TPage, TError>({\n queryKey,\n queryFn,\n url,\n queryParams = () => ({}),\n options = {\n initialPageParam: 1,\n getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {\n throw new Error(\"This function is not implemented\")\n },\n },\n children,\n enableManualFetch = false,\n triggerComponent,\n loadingComponent,\n noMoreDataComponent,\n threshold = [0.75],\n rootMargin = '0px',\n}: InfiniteDataFetcherProps<TPage, TError> & {\n threshold?: number | number[];\n rootMargin?: string;\n}) {\n const { baseUrl, ...globalOptions } = useFetcherSettings();\n\n\n if (!queryKey) {\n throw new Error('queryKey is required.');\n }\n\n if (queryFn && url) {\n throw new Error('Only one of queryFn or url should be provided.');\n }\n\n // Define the fetcher function\n const fetcher = queryFn\n ? (context: QueryFunctionContext<QueryKey, number>) =>\n queryFn({ ...context, pageParam: context.pageParam ?? 1 })\n : url\n ? (context: QueryFunctionContext<QueryKey, number>) => {\n const queryParamsObj =\n typeof queryParams === 'function'\n ? queryParams(context.pageParam ?? 1)\n : queryParams;\n return fetchWithSettings<TPage>(\n url,\n undefined,\n queryParamsObj,\n baseUrl,\n globalOptions\n );\n }\n : undefined;\n\n if (!fetcher) {\n throw new Error('Either queryFn or url must be provided.');\n }\n\n const {\n data,\n error,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n refetch,\n } = useInfiniteQuery<TPage, TError, InfiniteData<TPage>, QueryKey, number>({\n queryKey,\n queryFn: fetcher,\n ...options,\n getNextPageParam: options?.getNextPageParam,\n });\n\n const observerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!observerRef.current || enableManualFetch) return;\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting && hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n },\n { threshold: threshold, rootMargin: rootMargin }\n );\n\n observer.observe(observerRef.current);\n return () => observer.disconnect();\n }, [enableManualFetch, fetchNextPage, hasNextPage, isFetchingNextPage]);\n\n const renderFetchTrigger = useMemo(() => {\n if (isFetchingNextPage && loadingComponent) {\n return loadingComponent;\n }\n if (!hasNextPage && noMoreDataComponent) {\n return noMoreDataComponent;\n }\n return triggerComponent || (\n <button\n type=\"button\"\n onClick={() => fetchNextPage()}\n aria-label=\"Load more\"\n disabled={isFetchingNextPage}\n >\n {isFetchingNextPage ? 'Loading...' : 'Load More'}\n </button>\n );\n }, [isFetchingNextPage, hasNextPage, loadingComponent, noMoreDataComponent, triggerComponent, fetchNextPage]);\n\n return (\n <>\n {children({\n data: data?.pages,\n error,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n refetch: refetch,\n })}\n {enableManualFetch ? renderFetchTrigger : <div ref={observerRef} />}\n </>\n );\n}\n\nexport default InfiniteDataFetcher;\n"],"mappings":"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","names":["jsx","Fragment","jsx"]}