feat: allow user to choose between limit/offset and take/skip. (#508)

This commit is contained in:
David Sanchez 2023-03-06 09:25:52 +01:00 committed by GitHub
parent 629b5fb4b5
commit 735b7905c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 2 deletions

View File

@ -259,6 +259,14 @@ const paginateConfig: PaginateConfig<CatEntity> {
* Description: Overrides the origin of absolute resource links if set.
*/
origin: 'http://cats.example',
/**
* Required: false
* Type: string
* Description: Allow user to choose between limit/offset and take/skip.
* Default: PaginationType.TAKE_AND_SKIP
*/
paginationType: PaginationType.LIMIT_AND_OFFSET,
}
```
@ -343,6 +351,29 @@ const config: PaginateConfig<CatEntity> = {
const result = await paginate<CatEntity>(query, catRepo, config)
```
## Usage of pagination type
You can use either `limit`/`offset` or `take`/`skip` to return paginated results.
### Example
#### Code
```typescript
const config: PaginateConfig<CatEntity> = {
paginationType: PaginationType.LIMIT_AND_OFFSET,
// Or
paginationType: PaginationType.TAKE_AND_SKIP,
}
const result = await paginate<CatEntity>(query, catRepo, config)
```
> However, using `limit`/`offset` can return unexpected results.
> For more information
> see [#477](https://github.com/ppetzold/nestjs-paginate/issues/477), [#4742](https://github.com/typeorm/typeorm/issues/4742)
> and [#5670](https://github.com/typeorm/typeorm/issues/5670).
## Single Filters
Filter operators must be whitelisted per column in `PaginateConfig`.

View File

@ -52,6 +52,11 @@ export class Paginated<T> {
}
}
export enum PaginationType {
LIMIT_AND_OFFSET = 'limit',
TAKE_AND_SKIP = 'take',
}
export interface PaginateConfig<T> {
relations?: FindOptionsRelations<T> | RelationColumn<T>[]
sortableColumns: Column<T>[]
@ -69,11 +74,13 @@ export interface PaginateConfig<T> {
withDeleted?: boolean
relativePath?: boolean
origin?: string
paginationType?: PaginationType
}
export const DEFAULT_MAX_LIMIT = 100
export const DEFAULT_LIMIT = 20
export const NO_PAGINATION = 0
export const DEFAULT_PAGINATE_TYPE = PaginationType.TAKE_AND_SKIP
export async function paginate<T extends ObjectLiteral>(
query: PaginateQuery,
@ -85,6 +92,7 @@ export async function paginate<T extends ObjectLiteral>(
const defaultLimit = config.defaultLimit || DEFAULT_LIMIT
const maxLimit = positiveNumberOrDefault(config.maxLimit, DEFAULT_MAX_LIMIT)
const queryLimit = positiveNumberOrDefault(query.limit, defaultLimit)
const paginationType = config.paginationType || DEFAULT_PAGINATE_TYPE
const isPaginated = !(queryLimit === NO_PAGINATION && maxLimit === NO_PAGINATION)
@ -159,10 +167,14 @@ export async function paginate<T extends ObjectLiteral>(
if (isPaginated) {
// Switch from take and skip to limit and offset
// due to this problem https://github.com/typeorm/typeorm/issues/5670
// (anyway this creates more clean query without double dinstict)
// (anyway this creates more clean query without double distinct)
// queryBuilder.limit(limit).offset((page - 1) * limit)
if (paginationType === PaginationType.LIMIT_AND_OFFSET) {
queryBuilder.limit(limit).offset((page - 1) * limit)
} else {
queryBuilder.take(limit).skip((page - 1) * limit)
}
}
if (config.relations) {
// relations: ["relation"]