Skip to content

Commit a3a6899

Browse files
committed
feat: re-routing latest page have items
1 parent 4ede828 commit a3a6899

File tree

6 files changed

+221
-58
lines changed

6 files changed

+221
-58
lines changed

README.md

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ Pagination helper method for TypeORM repositories or queryBuilders with strict t
2121
```bash
2222
$ yarn add nestjs-typeorm-paginate
2323
```
24+
2425
or
26+
2527
```bash
2628
$ npm i nestjs-typeorm-paginate
2729
```
@@ -91,7 +93,13 @@ export class CatService {
9193
##### Controller
9294

9395
```ts
94-
import { Controller, DefaultValuePipe, Get, ParseIntPipe, Query } from '@nestjs/common';
96+
import {
97+
Controller,
98+
DefaultValuePipe,
99+
Get,
100+
ParseIntPipe,
101+
Query,
102+
} from '@nestjs/common';
95103
import { CatService } from './cat.service';
96104
import { CatEntity } from './cat.entity';
97105
import { Pagination } from 'nestjs-typeorm-paginate';
@@ -180,7 +188,6 @@ export class CatsController {
180188
`links.next`: A URL for the next page to call | `""` (blank) if no page to call
181189
`links.last`: A URL for the last page to call | `""` (blank) if no `route` is defined
182190

183-
184191
> Do note that `links.first` may not have the 'page' query param defined
185192
186193
## Find Parameters
@@ -210,7 +217,7 @@ import { Entity, OneToMany } from 'typeorm';
210217

211218
@Entity()
212219
export class CatEntity {
213-
@OneToMany(t => TigerKingEntity, tigerKing.cats, {
220+
@OneToMany((t) => TigerKingEntity, tigerKing.cats, {
214221
eager: true,
215222
})
216223
tigerKings: TigerKingEntity[];
@@ -268,12 +275,11 @@ Let's assume there's a joined table that matches each cat with its cat toys.
268275
And we want to bring how many toys each cat has.
269276

270277
```typescript
271-
272278
const queryBuilder = this.repository
273279
.createQueryBuilder<{ type: string; totalLives: string }>('cat')
274-
.leftJoinAndSelect('cat.toys', 'toys')
275-
.addSelect('COUNT(toys)::INTEGER', 'toyCount')
276-
.groupBy('cat.name');
280+
.leftJoinAndSelect('cat.toys', 'toys')
281+
.addSelect('COUNT(toys)::INTEGER', 'toyCount')
282+
.groupBy('cat.name');
277283
```
278284

279285
This will allow us to get the paginated cats information with the additional raw query to build our actual response value.
@@ -329,41 +335,48 @@ The rawResults array will look something like this:
329335
If you wanted to alter the meta data that is returned from the pagination object. Then use the `metaTransformer` in the options like so
330336

331337
```ts
332-
333338
class CustomPaginationMeta {
334339
constructor(
335340
public readonly count: number,
336341
public readonly total: number,
337342
) {}
338343
}
339344

340-
return paginate<MyEntity, CustomPaginationMeta>(this.repository, {
345+
return paginate<MyEntity, CustomPaginationMeta>(this.repository, {
341346
page,
342347
limit,
343-
metaTransformer: (meta: IPaginationMeta): CustomPaginationMeta => new CustomPaginationMeta(
344-
meta.itemCount,
345-
meta.totalItems,
346-
),
347-
});
348+
metaTransformer: (meta: IPaginationMeta): CustomPaginationMeta =>
349+
new CustomPaginationMeta(meta.itemCount, meta.totalItems),
350+
});
348351
```
349352

350353
This will result in the above returning `CustomPaginationMeta` in the `meta` property instead of the default `IPaginationMeta`.
351354

352-
353355
## Custom links query params labels
354356

355357
If you want to alter the `limit` and/or `page` labels in meta links, then use `routingLabels` in the options like so
356358

357359
```ts
358-
359-
return paginate<MyEntity>(this.repository, {
360+
return paginate<MyEntity>(this.repository, {
360361
page,
361362
limit,
362363
routingLabels: {
363364
limitLabel: 'page-size', // default: limit
364365
pageLabel: 'current-page', //default: page
365-
}
366-
});
366+
},
367+
});
367368
```
368369

369370
This will result links like `http://example.com/something?current-page=1&page-size=3`.
371+
372+
## Custom re-routing latest page have items
373+
374+
If you just want to return latest has items when the parameter `page` was over than `page` calculated in the database at the moment, then use `routingLatest` as the options. Make sure you not set countQueries to `false`. It will be ignored when pagination is disabled and `routingLatest` option won't be affect anymore.
375+
376+
```ts
377+
return paginate<MyEntity>(this.repository, {
378+
page,
379+
limit,
380+
routingLatest: true,
381+
});
382+
```

src/__tests__/paginate-raw-and-entities.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,17 @@ describe('Test paginateRawAndEntities function', () => {
186186
expect(result.meta.totalItems).toBe(undefined);
187187
expect(result.meta.totalPages).toBe(undefined);
188188
});
189+
190+
it('Can routing to latest page have items', async () => {
191+
const [result] = await paginateRawAndEntities(queryBuilder, {
192+
limit: 10,
193+
page: 2,
194+
countQueries: true,
195+
routingLatest: true,
196+
});
197+
198+
expect(result).toBeInstanceOf(Pagination);
199+
expect(result.meta.totalItems).toEqual(10);
200+
expect(result.meta.currentPage).toEqual(1);
201+
});
189202
});

src/__tests__/paginate-raw.spec.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('Test paginateRaw function', () => {
5151
});
5252

5353
afterAll(async () => {
54-
await queryBuilder.delete();
54+
queryBuilder.delete();
5555
await app.close();
5656
});
5757

@@ -180,4 +180,17 @@ describe('Test paginateRaw function', () => {
180180
expect(result.meta.totalItems).toBe(undefined);
181181
expect(result.meta.totalPages).toBe(undefined);
182182
});
183+
184+
it('Can routing to latest page have items', async () => {
185+
const result = await paginateRaw(queryBuilder, {
186+
limit: 10,
187+
page: 2,
188+
countQueries: true,
189+
routingLatest: true,
190+
});
191+
192+
expect(result).toBeInstanceOf(Pagination);
193+
expect(result.meta.totalItems).toEqual(10);
194+
expect(result.meta.currentPage).toEqual(1);
195+
});
183196
});

src/__tests__/paginate.query.builder.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,30 @@ describe('Paginate with queryBuilder', () => {
113113
expect(result).toBeInstanceOf(Pagination);
114114
expect(result.meta.totalItems).toEqual(10);
115115
});
116+
117+
it('Can routing to latest page have items', async () => {
118+
await testRelatedQueryBuilder
119+
.createQueryBuilder()
120+
.insert()
121+
.into(TestRelatedEntity)
122+
.values([
123+
{ id: 1, testId: 1 },
124+
{ id: 2, testId: 1 },
125+
{ id: 3, testId: 1 },
126+
])
127+
.execute();
128+
129+
const qb = queryBuilder.leftJoinAndSelect('t.related', 'r');
130+
131+
const result = await paginate(qb, {
132+
limit: 15,
133+
page: 2,
134+
routingLatest: true,
135+
countQueries: true,
136+
});
137+
138+
expect(result).toBeInstanceOf(Pagination);
139+
expect(result.meta.totalItems).toEqual(10);
140+
expect(result.meta.currentPage).toEqual(1);
141+
});
116142
});

src/interfaces/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ export interface IPaginationOptions<CustomMetaType = IPaginationMeta> {
5050
* Enables or disables query result caching.
5151
*/
5252
cacheQueries?: TypeORMCacheType;
53+
54+
/**
55+
* @default false
56+
* Enables or disables routing to the latest page have items
57+
*/
58+
routingLatest?: boolean;
5359
}
5460

5561
export type TypeORMCacheType =

0 commit comments

Comments
 (0)