@algoan/nestjs-pagination
v6.0.2
Published
NestJS interceptor handling request's pagination
Downloads
5,523
Readme
NestJS Request Pagination
A simple NestJS interceptor catching query parameters and format a Link Header, based on GitHub pagination API. This module uses format-link-header node module to build the response Link Header.
Installation
npm install --save @algoan/nestjs-pagination
Requirements
- On this version, the API attached with this interceptor needs to return an object:
{
"totalResources": 1530,
"resources": [ { ... }, ..., { ... }]
}
- The resource has to be specified in the interceptor constructor
Limits
- This module does not take into account what is returned in the
resources
property. It may be inconsistent with headers set by the interceptor.
Quick Start
Import LinkHeaderInterceptor
next to a controller method.
import { LinkHeaderInterceptor } from '@algoan/nestjs-pagination';
import { Controller, Get, UseInterceptors } from '@nestjs/common';
@Controller()
/**
* Controller returning a lot of documents
*/
class AppController {
/**
* Find all documents
*/
@UseInterceptors(new LinkHeaderInterceptor({ resource: 'data' }))
@Get('/data')
public async findAll(): Promise<{ totalResources: number; resources: DataToReturn[] }> {
const data: DataToReturn = await model.find(...);
const count: number = await model.count();
return { totalResources: count, resources: data };
}
}
For instance, if you have 1015 resources, calling GET /data?page=4&per_page=100
will return:
Content-Range: data 300-399/1015
Link: </data?page=1&per_page=100>; rel="first", </data?page=11&per_page=100>; rel="last", </data?page=5&per_page=100>; rel="next", </data?page=3&per_page=100>; rel="prev"
If you use MongoDB as your database, we also provide a ParamDecorator
you can use to convert the request to a mongo query parameter.
import { LinkHeaderInterceptor, MongoPaginationParamDecorator, MongoPagination, Pageable } from '@algoan/nestjs-pagination';
import { Controller, Get, UseInterceptors } from '@nestjs/common';
@Controller()
/**
* Controller returning a lot of documents
*/
class AppController {
/**
* Find all documents
*/
@UseInterceptors(new LinkHeaderInterceptor({ resource: 'data' }))
@Get('/data')
public async findAll(@MongoPaginationParamDecorator() pagination: MongoPagination ): Promise<Pageable<DataToReturn>> {
const data: DataToReturn[] = await model.find(pagination);
const count: number = await model.count(pagination.filter);
return { totalResources: count, resources: data };
}
}
Usage
By default, the interceptor and the decorator will look for the query parameters page
and per_page
(which is 100 by default).
You can also change the name of those parameters and the default per page limit if you want, by passing a configuration object. Beware that if you use both the interceptor and the decorator, you need to pass the configuration to both of them.
new LinkHeaderInterceptor({ resource: 'data', pageName: '_page', perPageName: 'numberPerPage', defaultLimit: 50 })
@MongoPaginationParamDecorator({ pageName: '_page', perPageName: 'numberPerPage', defaultLimit: 50 })
You can also have the pagination in the response body by using the PaginationBodyInterceptor. By using this interceptor, the pagination is included in the response body instead of the header.
A paginated data response is returned.
{
"resources": [],
"pagination": {
"next": null,
"previous": null,
"first": null,
"last": null,
"totalPages": 1,
"totalResources": 0,
}
}
Import the PaginationBodyInterceptor
next to a controller method.
import { PaginationBodyInterceptor } from '@algoan/nestjs-pagination';
import { Controller, Get, UseInterceptors } from '@nestjs/common';
@Controller()
/**
* Controller returning a lot of documents
*/
class AppController {
/**
* Find all documents
*/
@UseInterceptors(new PaginationBodyInterceptor({pageName: 'page', perPageName: 'limit'}))
@Get('/data')
public async findAll(@MongoPaginationParamDecorator({pageName: 'page', perPageName: 'limit'}) pagination: MongoPagination): Promise<{ totalResources: number; resources: DataToReturn[] }> {
const data: DataToReturn = await model.find(...);
const count: number = await model.count();
return { totalResources: count, resources: data };
}
}