import type { QueryFunction } from '@tanstack/react-query';
import type { Metadata, ResourceListOptions } from '@dn-types/api';
type PaginatedResourceQueryFn<T> = (options: ResourceListOptions) => Promise<{ data: T[]; metadata?: Metadata }>;
/**
* Creates a query function for react-query which will:
*
* - fetch a 500-item page from a list endpoint,
* - check whether there are more rows,
* - fetch the next page and check again
* - repeat
*
* It does this until it has fetched all results or has made maxPages (default 10) pages of requests.
*/
export function makeMaxResourceQueryFn<T>(
queryFn: PaginatedResourceQueryFn<T>,
maxPages = 10
): QueryFunction<{ data: T[]; metadata?: Metadata }> {
return async ({ signal }) => {
let allResources: T[] = [];
let currentResponse;
let currentPage = 1;
do {
// Fetch resource at least once, append to `allResources`, then continue if we have more pages.
currentResponse = await queryFn({
cursor: currentResponse?.metadata?.nextCursor,
pageSize: 500,
init: { signal },
});
allResources = allResources.concat(currentResponse.data);
currentPage++;
} while (currentResponse.metadata?.hasNextPage && currentPage <= maxPages);
return {
data: allResources,
metadata: {
hasNextPage: false,
hasPrevPage: false,
totalCount: allResources.length,
nextCursor: '',
prevCursor: '',
} satisfies Metadata,
};
};
}