Skip to content

Commit

Permalink
feat: re-routing latest page have items
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyDo99 committed Jan 11, 2025
1 parent 4ede828 commit a3a6899
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 58 deletions.
51 changes: 32 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ Pagination helper method for TypeORM repositories or queryBuilders with strict t
```bash
$ yarn add nestjs-typeorm-paginate
```

or

```bash
$ npm i nestjs-typeorm-paginate
```
Expand Down Expand Up @@ -91,7 +93,13 @@ export class CatService {
##### Controller

```ts
import { Controller, DefaultValuePipe, Get, ParseIntPipe, Query } from '@nestjs/common';
import {
Controller,
DefaultValuePipe,
Get,
ParseIntPipe,
Query,
} from '@nestjs/common';
import { CatService } from './cat.service';
import { CatEntity } from './cat.entity';
import { Pagination } from 'nestjs-typeorm-paginate';
Expand Down Expand Up @@ -180,7 +188,6 @@ export class CatsController {
`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
Expand Down Expand Up @@ -210,7 +217,7 @@ import { Entity, OneToMany } from 'typeorm';

@Entity()
export class CatEntity {
@OneToMany(t => TigerKingEntity, tigerKing.cats, {
@OneToMany((t) => TigerKingEntity, tigerKing.cats, {
eager: true,
})
tigerKings: TigerKingEntity[];
Expand Down Expand Up @@ -268,12 +275,11 @@ 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.

```typescript

const queryBuilder = this.repository
.createQueryBuilder<{ type: string; totalLives: string }>('cat')
.leftJoinAndSelect('cat.toys', 'toys')
.addSelect('COUNT(toys)::INTEGER', 'toyCount')
.groupBy('cat.name');
.leftJoinAndSelect('cat.toys', 'toys')
.addSelect('COUNT(toys)::INTEGER', 'toyCount')
.groupBy('cat.name');
```

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

```ts

class CustomPaginationMeta {
constructor(
public readonly count: number,
public readonly total: number,
) {}
}

return paginate<MyEntity, CustomPaginationMeta>(this.repository, {
return paginate<MyEntity, CustomPaginationMeta>(this.repository, {
page,
limit,
metaTransformer: (meta: IPaginationMeta): CustomPaginationMeta => new CustomPaginationMeta(
meta.itemCount,
meta.totalItems,
),
});
metaTransformer: (meta: IPaginationMeta): CustomPaginationMeta =>
new CustomPaginationMeta(meta.itemCount, meta.totalItems),
});
```

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

```ts

return paginate<MyEntity>(this.repository, {
return paginate<MyEntity>(this.repository, {
page,
limit,
routingLabels: {
limitLabel: 'page-size', // default: limit
pageLabel: 'current-page', //default: page
}
});
},
});
```

This will result links like `http://example.com/something?current-page=1&page-size=3`.

## Custom re-routing latest page have items

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.

```ts
return paginate<MyEntity>(this.repository, {
page,
limit,
routingLatest: true,
});
```
13 changes: 13 additions & 0 deletions src/__tests__/paginate-raw-and-entities.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,17 @@ describe('Test paginateRawAndEntities function', () => {
expect(result.meta.totalItems).toBe(undefined);
expect(result.meta.totalPages).toBe(undefined);
});

it('Can routing to latest page have items', async () => {
const [result] = await paginateRawAndEntities(queryBuilder, {
limit: 10,
page: 2,
countQueries: true,
routingLatest: true,
});

expect(result).toBeInstanceOf(Pagination);
expect(result.meta.totalItems).toEqual(10);
expect(result.meta.currentPage).toEqual(1);
});
});
15 changes: 14 additions & 1 deletion src/__tests__/paginate-raw.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('Test paginateRaw function', () => {
});

afterAll(async () => {
await queryBuilder.delete();
queryBuilder.delete();
await app.close();
});

Expand Down Expand Up @@ -180,4 +180,17 @@ describe('Test paginateRaw function', () => {
expect(result.meta.totalItems).toBe(undefined);
expect(result.meta.totalPages).toBe(undefined);
});

it('Can routing to latest page have items', async () => {
const result = await paginateRaw(queryBuilder, {
limit: 10,
page: 2,
countQueries: true,
routingLatest: true,
});

expect(result).toBeInstanceOf(Pagination);
expect(result.meta.totalItems).toEqual(10);
expect(result.meta.currentPage).toEqual(1);
});
});
26 changes: 26 additions & 0 deletions src/__tests__/paginate.query.builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,30 @@ describe('Paginate with queryBuilder', () => {
expect(result).toBeInstanceOf(Pagination);
expect(result.meta.totalItems).toEqual(10);
});

it('Can routing to latest page have items', async () => {
await testRelatedQueryBuilder
.createQueryBuilder()
.insert()
.into(TestRelatedEntity)
.values([
{ id: 1, testId: 1 },
{ id: 2, testId: 1 },
{ id: 3, testId: 1 },
])
.execute();

const qb = queryBuilder.leftJoinAndSelect('t.related', 'r');

const result = await paginate(qb, {
limit: 15,
page: 2,
routingLatest: true,
countQueries: true,
});

expect(result).toBeInstanceOf(Pagination);
expect(result.meta.totalItems).toEqual(10);
expect(result.meta.currentPage).toEqual(1);
});
});
6 changes: 6 additions & 0 deletions src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export interface IPaginationOptions<CustomMetaType = IPaginationMeta> {
* Enables or disables query result caching.
*/
cacheQueries?: TypeORMCacheType;

/**
* @default false
* Enables or disables routing to the latest page have items
*/
routingLatest?: boolean;
}

export type TypeORMCacheType =
Expand Down
Loading

0 comments on commit a3a6899

Please sign in to comment.