Installations
npm install nestjs-typeorm-paginate
Developer Guide
Typescript
No
Module System
CommonJS
Score
83.6
Supply Chain
80.4
Quality
74.7
Maintenance
100
Vulnerability
99.3
License
Releases
Unable to fetch releases
Contributors
Unable to fetch Contributors
Languages
TypeScript (98.27%)
JavaScript (1.73%)
Love this project? Help keep it running — sponsor us today! 🚀
Developer
nestjsx
Download Statistics
Total Downloads
8,913,380
Last Day
12,876
Last Week
67,762
Last Month
299,959
Last Year
3,589,482
GitHub Statistics
MIT License
856 Stars
763 Commits
129 Forks
9 Watchers
8 Branches
30 Contributors
Updated on Feb 14, 2025
Bundle Size
4.99 kB
Minified
1.67 kB
Minified + Gzipped
Package Meta Information
Latest Version
4.0.4
Package Id
nestjs-typeorm-paginate@4.0.4
Unpacked Size
34.20 kB
Size
10.31 kB
File Count
28
Published on
Jun 23, 2023
Total Downloads
Cumulative downloads
Total Downloads
8,913,380
Last Day
-0.3%
12,876
Compared to previous day
Last Week
1.2%
67,762
Compared to previous week
Last Month
28.1%
299,959
Compared to previous month
Last Year
66.5%
3,589,482
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Nestjs Typeorm paginate
Pagination helper method for TypeORM repositories or queryBuilders with strict typings
Install
1$ yarn add nestjs-typeorm-paginate
or
1$ npm i nestjs-typeorm-paginate
If you're using typeorm^0.2.6 please use nestjs-typeorm-paginate^3.2.0 For typeorm^0.3.0 please use nestjs-typeorm-paginate^4.0.0
Usage
Service
Repository
1import { Injectable } from '@nestjs/common'; 2import { Repository } from 'typeorm'; 3import { InjectRepository } from '@nestjs/typeorm'; 4import { CatEntity } from './entities'; 5import { 6 paginate, 7 Pagination, 8 IPaginationOptions, 9} from 'nestjs-typeorm-paginate'; 10 11@Injectable() 12export class CatService { 13 constructor( 14 @InjectRepository(CatEntity) 15 private readonly repository: Repository<CatEntity>, 16 ) {} 17 18 async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> { 19 return paginate<CatEntity>(this.repository, options); 20 } 21}
QueryBuilder
1import { Injectable } from '@nestjs/common'; 2import { Repository } from 'typeorm'; 3import { InjectRepository } from '@nestjs/typeorm'; 4import { CatEntity } from './entities'; 5import { 6 paginate, 7 Pagination, 8 IPaginationOptions, 9} from 'nestjs-typeorm-paginate'; 10 11@Injectable() 12export class CatService { 13 constructor( 14 @InjectRepository(CatEntity) 15 private readonly repository: Repository<CatEntity>, 16 ) {} 17 18 async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> { 19 const queryBuilder = this.repository.createQueryBuilder('c'); 20 queryBuilder.orderBy('c.name', 'DESC'); // Or whatever you need to do 21 22 return paginate<CatEntity>(queryBuilder, options); 23 } 24}
Controller
1import { Controller, DefaultValuePipe, Get, ParseIntPipe, Query } from '@nestjs/common'; 2import { CatService } from './cat.service'; 3import { CatEntity } from './cat.entity'; 4import { Pagination } from 'nestjs-typeorm-paginate'; 5 6@Controller('cats') 7export class CatsController { 8 constructor(private readonly catService: CatService) {} 9 @Get('') 10 async index( 11 @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number = 1, 12 @Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number = 10, 13 ): Promise<Pagination<CatEntity>> { 14 limit = limit > 100 ? 100 : limit; 15 return this.catService.paginate({ 16 page, 17 limit, 18 route: 'http://cats.com/cats', 19 }); 20 } 21}
If you use
ParseIntPipe
on the query params (as in the example), don't forget to also addDefaultValuePipe
. See issue 517 for more info.
the
route
property of the paginate options can also be the short version of an absolute path , In this case, it would be/cats
instead ofhttp://cats.com/cats
Example Response
1{ 2 "items": [ 3 { 4 "lives": 9, 5 "type": "tabby", 6 "name": "Bobby" 7 }, 8 { 9 "lives": 2, 10 "type": "Ginger", 11 "name": "Garfield" 12 }, 13 { 14 "lives": 6, 15 "type": "Black", 16 "name": "Witch's mate" 17 }, 18 { 19 "lives": 7, 20 "type": "Purssian Grey", 21 "name": "Alisdaya" 22 }, 23 { 24 "lives": 1, 25 "type": "Alistair", 26 "name": "ali" 27 }, 28 ... 29 ], 30 "meta": { 31 "itemCount": 10, 32 "totalItems": 20, 33 "itemsPerPage": 10, 34 "totalPages": 5, 35 "currentPage": 2 36 }, 37 "links" : { 38 "first": "http://cats.com/cats?limit=10", 39 "previous": "http://cats.com/cats?page=1&limit=10", 40 "next": "http://cats.com/cats?page=3&limit=10", 41 "last": "http://cats.com/cats?page=5&limit=10" 42 } 43}
items
: An array of SomeEntity
meta.itemCount
: The length of items array (i.e., the amount of items on this page)
meta.totalItems
: The total amount of SomeEntity matching the filter conditions
meta.itemsPerPage
: The requested items per page (i.e., the limit
parameter)
meta.totalPages
: The total amount of pages (based on the limit
)
meta.currentPage
: The current page this paginator "points" to
links.first
: A URL for the first page to call | ""
(blank) if no route
is defined
links.previous
: A URL for the previous page to call | ""
(blank) if no previous to call
links.next
: A URL for the next page to call | ""
(blank) if no page to call
links.last
: A URL for the last page to call | ""
(blank) if no route
is defined
Do note that
links.first
may not have the 'page' query param defined
Find Parameters
1@Injectable() 2export class CatService { 3 constructor( 4 @InjectRepository(CatEntity) 5 private readonly repository: Repository<CatEntity>, 6 ) {} 7 8 async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> { 9 return paginate<CatEntity>(this.repository, options, { 10 lives: 9, 11 }); 12 } 13}
Eager loading
Eager loading should work with typeorm's eager property out the box. Like so
1import { Entity, OneToMany } from 'typeorm'; 2 3@Entity() 4export class CatEntity { 5 @OneToMany(t => TigerKingEntity, tigerKing.cats, { 6 eager: true, 7 }) 8 tigerKings: TigerKingEntity[]; 9} 10 11// service 12class CatService { 13 constructor(private readonly repository: Repository<CatEntity>) {} 14 15 async paginate(page: number, limit: number): Promise<Pagination<CatEntity>> { 16 return paginate(this.repository, { page, limit }); 17 } 18}
QueryBuilder
However, when using the query builder you'll have to hydrate the entities yourself. Here is a crude example that I've used in the past. It's not great but this is partially what typeORM will do.
1const results = paginate(queryBuilder, { page, limit }); 2 3return new Pagination( 4 await Promise.all( 5 results.items.map(async (item: SomeEntity) => { 6 const hydrate = await this.someRepository.findByEntity(item); 7 item.hydrated = hydrate; 8 9 return item; 10 }), 11 ), 12 results.meta, 13 results.links, 14);
Raw queries
1const queryBuilder = this.repository 2 .createQueryBuilder<{ type: string; totalLives: string }>('c') 3 .select('c.type', 'type') 4 .addSelect('SUM(c.lives)', 'totalLives') 5 .groupBy('c.type') 6 .orderBy('c.type', 'DESC'); // Or whatever you need to do 7 8return paginateRaw(queryBuilder, options);
Raw and Entities
A similar approach is used for TypeORM's getRawAndEntities
Let's assume there's a joined table that matches each cat with its cat toys. And we want to bring how many toys each cat has.
1 2const queryBuilder = this.repository 3 .createQueryBuilder<{ type: string; totalLives: string }>('cat') 4 .leftJoinAndSelect('cat.toys', 'toys') 5 .addSelect('COUNT(toys)::INTEGER', 'toyCount') 6 .groupBy('cat.name');
This will allow us to get the paginated cats information with the additional raw query to build our actual response value. The return pagination object will be the same, but you're now able to handle or map the results and the raw objects as needed.
1const [pagination, rawResults] = await paginateRawAndEntities(query, options); 2pagination.items.map((item, index) => { 3 // we can do what we need with the items and raw results here 4 // change your items using rawResults.find(raw => raw.id === item.id) 5}); 6return pagination;
Note about joined tables and raw values
Since the values of the raw results will include all the joined table items as queried, you must make sure to handle the items as needed for your use case. Refer to TypeORM's getRawAndEntities implementation as needed.
The rawResults array will look something like this:
1[ 2 { // Bobby appears 3 times due to the joined query 3 "cat_lives": 9, 4 "cat_type": "tabby", 5 "cat_name": "Bobby", 6 "toyCount": 3 7 }, 8 { 9 "cat_lives": 9, 10 "cat_type": "tabby", 11 "cat_name": "Bobby", 12 "toyCount": 3 13 }, 14 { 15 "cat_lives": 9, 16 "cat_type": "tabby", 17 "cat_name": "Bobby", 18 "toyCount": 3 19 }, 20 { 21 "cat_lives": 2, 22 "cat_type": "Ginger", 23 "cat_name": "Garfield", 24 "toyCount": 1 25 }, 26 ... 27]
Custom meta data transformer
If you wanted to alter the meta data that is returned from the pagination object. Then use the metaTransformer
in the options like so
1 2class CustomPaginationMeta { 3 constructor( 4 public readonly count: number, 5 public readonly total: number, 6 ) {} 7} 8 9return paginate<MyEntity, CustomPaginationMeta>(this.repository, { 10 page, 11 limit, 12 metaTransformer: (meta: IPaginationMeta): CustomPaginationMeta => new CustomPaginationMeta( 13 meta.itemCount, 14 meta.totalItems, 15 ), 16 });
This will result in the above returning CustomPaginationMeta
in the meta
property instead of the default IPaginationMeta
.
Custom links query params labels
If you want to alter the limit
and/or page
labels in meta links, then use routingLabels
in the options like so
1 2return paginate<MyEntity>(this.repository, { 3 page, 4 limit, 5 routingLabels: { 6 limitLabel: 'page-size', // default: limit 7 pageLabel: 'current-page', //default: page 8 } 9 });
This will result links like http://example.com/something?current-page=1&page-size=3
.

No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
Found 1/2 approved changesets -- score normalized to 5
Reason
8 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-896r-f27r-55mw
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j
- Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6
- Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3
- Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/nestjsx/nestjs-typeorm-paginate/main.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/nestjsx/nestjs-typeorm-paginate/main.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:65: update your workflow using https://app.stepsecurity.io/secureworkflow/nestjsx/nestjs-typeorm-paginate/main.yml/master?enable=pin
- Info: 0 out of 1 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 2 third-party GitHubAction dependencies pinned
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/main.yml:1
- Info: no jobLevel write permissions found
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 29 are checked with a SAST tool
Score
3.2
/10
Last Scanned on 2025-02-10
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to nestjs-typeorm-paginate
nestjs-paginate
Pagination and filtering helper method for TypeORM repositories or query builders using Nest.js framework.
attapornamo-nestjs-typeorm-paginate
A simple pagination function to build a pagination object with types
@fuadmuhtaz/nestjs-typeorm-paginate
A simple pagination function to build a pagination object with types
@trmaphi/nestjs-typeorm-paginate
A simple pagination function to build a pagination object with types