diff --git a/packages/app/api-common/src/paginationUtils.ts b/packages/app/api-common/src/paginationUtils.ts index 34ebfe88..46d7522f 100644 --- a/packages/app/api-common/src/paginationUtils.ts +++ b/packages/app/api-common/src/paginationUtils.ts @@ -201,3 +201,22 @@ export async function getPaginatedEntriesByHasMore, +>( + pagination: OptionalPaginationParams, + apiCall: (params: OptionalPaginationParams) => Promise>, + processPage: (pageData: PaginatedResponse['data']) => Promise, +): Promise { + let hasMore: boolean | undefined + let currentCursor: string | undefined = pagination.after + + do { + const pageResult = await apiCall({ ...pagination, after: currentCursor }) + hasMore = pageResult.meta.hasMore + currentCursor = pageResult.meta.cursor + + await processPage(pageResult.data) + } while (hasMore) +} diff --git a/packages/app/api-common/test/paginationUtils.spec.ts b/packages/app/api-common/test/paginationUtils.spec.ts index 5a4e4aea..e3ee2ac0 100644 --- a/packages/app/api-common/test/paginationUtils.spec.ts +++ b/packages/app/api-common/test/paginationUtils.spec.ts @@ -8,6 +8,7 @@ import { getPaginatedEntries, getPaginatedEntriesByHasMore, } from '../src' +import { traversePaginatedSourceByHasMore } from '../src' describe('paginationUtils', () => { describe('createPaginatedResponse', () => { @@ -276,6 +277,49 @@ describe('paginationUtils', () => { expect(result).toEqual([{ id: 'red' }]) }) }) + describe('traversePaginatedSourceByHasMore', () => { + it.only('should perform callback per each page', async () => { + // Given + const spy = vi + .spyOn(market, 'getApples') + .mockResolvedValueOnce({ + data: [{ id: 'red' }], + meta: { + count: 1, + cursor: 'red', + hasMore: true, + }, + }) + .mockResolvedValueOnce({ + data: [{ id: 'blue' }], + meta: { + count: 1, + cursor: 'blue', + hasMore: false, + }, + }) + + const processPage = vi.fn() + + // When + await traversePaginatedSourceByHasMore( + { limit: 1 }, + (params) => { + return market.getApples(params) + }, + processPage, + ) + + // Then + expect(spy).toHaveBeenCalledTimes(2) + expect(spy).toHaveBeenNthCalledWith(1, { limit: 1 }) + expect(spy).toHaveBeenNthCalledWith(2, { after: 'red', limit: 1 }) + + expect(processPage).toHaveBeenCalledTimes(2) + expect(processPage).toHaveBeenNthCalledWith(1, [{ id: 'red' }]) + expect(processPage).toHaveBeenNthCalledWith(2, [{ id: 'blue' }]) + }) + }) }) type Entity = {