import { QueryObserver } from './queryObserver' import { hasNextPage, hasPreviousPage, infiniteQueryBehavior, } from './infiniteQueryBehavior' import type { Subscribable } from './subscribable' import type { DefaultError, DefaultedInfiniteQueryObserverOptions, FetchNextPageOptions, FetchPreviousPageOptions, InfiniteData, InfiniteQueryObserverBaseResult, InfiniteQueryObserverOptions, InfiniteQueryObserverResult, QueryKey, } from './types' import type { QueryClient } from './queryClient' import type { Query } from './query' type InfiniteQueryObserverListener = ( result: InfiniteQueryObserverResult, ) => void export class InfiniteQueryObserver< TQueryFnData = unknown, TError = DefaultError, TData = InfiniteData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown, > extends QueryObserver< TQueryFnData, TError, TData, InfiniteData, TQueryKey > { // Type override subscribe!: Subscribable< InfiniteQueryObserverListener >['subscribe'] // Type override getCurrentResult!: ReplaceReturnType< QueryObserver< TQueryFnData, TError, TData, InfiniteData, TQueryKey >['getCurrentResult'], InfiniteQueryObserverResult > // Type override protected fetch!: ReplaceReturnType< QueryObserver< TQueryFnData, TError, TData, InfiniteData, TQueryKey >['fetch'], Promise> > constructor( client: QueryClient, options: InfiniteQueryObserverOptions< TQueryFnData, TError, TData, TQueryKey, TPageParam >, ) { super(client, options) } protected bindMethods(): void { super.bindMethods() this.fetchNextPage = this.fetchNextPage.bind(this) this.fetchPreviousPage = this.fetchPreviousPage.bind(this) } setOptions( options: InfiniteQueryObserverOptions< TQueryFnData, TError, TData, TQueryKey, TPageParam >, ): void { super.setOptions({ ...options, behavior: infiniteQueryBehavior(), }) } getOptimisticResult( options: DefaultedInfiniteQueryObserverOptions< TQueryFnData, TError, TData, TQueryKey, TPageParam >, ): InfiniteQueryObserverResult { options.behavior = infiniteQueryBehavior() return super.getOptimisticResult(options) as InfiniteQueryObserverResult< TData, TError > } fetchNextPage( options?: FetchNextPageOptions, ): Promise> { return this.fetch({ ...options, meta: { fetchMore: { direction: 'forward' }, }, }) } fetchPreviousPage( options?: FetchPreviousPageOptions, ): Promise> { return this.fetch({ ...options, meta: { fetchMore: { direction: 'backward' }, }, }) } protected createResult( query: Query< TQueryFnData, TError, InfiniteData, TQueryKey >, options: InfiniteQueryObserverOptions< TQueryFnData, TError, TData, TQueryKey, TPageParam >, ): InfiniteQueryObserverResult { const { state } = query const parentResult = super.createResult(query, options) const { isFetching, isRefetching, isError, isRefetchError } = parentResult const fetchDirection = state.fetchMeta?.fetchMore?.direction const isFetchNextPageError = isError && fetchDirection === 'forward' const isFetchingNextPage = isFetching && fetchDirection === 'forward' const isFetchPreviousPageError = isError && fetchDirection === 'backward' const isFetchingPreviousPage = isFetching && fetchDirection === 'backward' const result: InfiniteQueryObserverBaseResult = { ...parentResult, fetchNextPage: this.fetchNextPage, fetchPreviousPage: this.fetchPreviousPage, hasNextPage: hasNextPage(options, state.data), hasPreviousPage: hasPreviousPage(options, state.data), isFetchNextPageError, isFetchingNextPage, isFetchPreviousPageError, isFetchingPreviousPage, isRefetchError: isRefetchError && !isFetchNextPageError && !isFetchPreviousPageError, isRefetching: isRefetching && !isFetchingNextPage && !isFetchingPreviousPage, } return result as InfiniteQueryObserverResult } } type ReplaceReturnType< TFunction extends (...args: Array) => unknown, TReturn, > = (...args: Parameters) => TReturn