Metadata field

Useful data about pagination.

In the PaginationService, let's first create a method to calculate the offset from the limit and page. This calculation is simple and standard.

calculateOffset(limit: number, page: number) {
  return (page - 1) * limit;
}

Then, before creating the method which will create the meta field, let's first create an interface to represent this metadata in querying -> interfaces -> pagination-meta.interface.

export interface PaginationMeta {
  readonly itemsPerPage: number;
  readonly totalItems: number;
  readonly currentPage: number;
  readonly totalPages: number;
  readonly hasNextPage: boolean;
  readonly hasPreviousPage: boolean;
}

And finally, the method that creates the meta field. Its steps are:

  • Calculate the page count, dividing the item count by the page size, and rounding it up in case of a decimal result

  • Check if the current page is greater than the last page, in such case no metadata will be returned

  • Define if there are next/previous pages from the current page

  • Return all the metadata

createMeta(limit: number, page: number, count: number): PaginationMeta {
  const totalPages = Math.ceil(count / limit);
  if (page > totalPages) return;

  const hasNextPage = page < totalPages;
  const hasPreviousPage = page > 1;

  return {
    itemsPerPage: limit,
    totalItems: count,
    currentPage: page,
    totalPages,
    hasNextPage,
    hasPreviousPage,
  };
}

What remains to be done now is to inject the PaginationService in the ProductsService and adjust the logic of the findAll() method.

async findAll(paginationDto: PaginationDto) {
  const { page } = paginationDto;
  const limit = paginationDto.limit ?? DefaultPageSize.PRODUCT;
  const offset = this.paginationService.calculateOffset(limit, page);

  const [data, count] = await this.productsRepository.findAndCount({
    skip: offset,
    take: limit,
  });
  const meta = this.paginationService.createMeta(limit, page, count);

  return { data, meta };
}

We can then do the same with the remaining findAll() methods to finish this part of pagination.

There is also another kind of pagination: the cursor-based pagination. It has some interesting advantages over the offset-based pagination but also some drawbacks. I recommend this article in case there is interest to learn more about it.

Commit - Incrementing pagination with metadata field

Last updated