feat: allow user to choose between limit/offset and take/skip. (#508)
This commit is contained in:
parent
629b5fb4b5
commit
735b7905c3
31
README.md
31
README.md
@ -259,6 +259,14 @@ const paginateConfig: PaginateConfig<CatEntity> {
|
|||||||
* Description: Overrides the origin of absolute resource links if set.
|
* Description: Overrides the origin of absolute resource links if set.
|
||||||
*/
|
*/
|
||||||
origin: 'http://cats.example',
|
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)
|
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
|
## Single Filters
|
||||||
|
|
||||||
Filter operators must be whitelisted per column in `PaginateConfig`.
|
Filter operators must be whitelisted per column in `PaginateConfig`.
|
||||||
|
@ -52,6 +52,11 @@ export class Paginated<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PaginationType {
|
||||||
|
LIMIT_AND_OFFSET = 'limit',
|
||||||
|
TAKE_AND_SKIP = 'take',
|
||||||
|
}
|
||||||
|
|
||||||
export interface PaginateConfig<T> {
|
export interface PaginateConfig<T> {
|
||||||
relations?: FindOptionsRelations<T> | RelationColumn<T>[]
|
relations?: FindOptionsRelations<T> | RelationColumn<T>[]
|
||||||
sortableColumns: Column<T>[]
|
sortableColumns: Column<T>[]
|
||||||
@ -69,11 +74,13 @@ export interface PaginateConfig<T> {
|
|||||||
withDeleted?: boolean
|
withDeleted?: boolean
|
||||||
relativePath?: boolean
|
relativePath?: boolean
|
||||||
origin?: string
|
origin?: string
|
||||||
|
paginationType?: PaginationType
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_MAX_LIMIT = 100
|
export const DEFAULT_MAX_LIMIT = 100
|
||||||
export const DEFAULT_LIMIT = 20
|
export const DEFAULT_LIMIT = 20
|
||||||
export const NO_PAGINATION = 0
|
export const NO_PAGINATION = 0
|
||||||
|
export const DEFAULT_PAGINATE_TYPE = PaginationType.TAKE_AND_SKIP
|
||||||
|
|
||||||
export async function paginate<T extends ObjectLiteral>(
|
export async function paginate<T extends ObjectLiteral>(
|
||||||
query: PaginateQuery,
|
query: PaginateQuery,
|
||||||
@ -85,6 +92,7 @@ export async function paginate<T extends ObjectLiteral>(
|
|||||||
const defaultLimit = config.defaultLimit || DEFAULT_LIMIT
|
const defaultLimit = config.defaultLimit || DEFAULT_LIMIT
|
||||||
const maxLimit = positiveNumberOrDefault(config.maxLimit, DEFAULT_MAX_LIMIT)
|
const maxLimit = positiveNumberOrDefault(config.maxLimit, DEFAULT_MAX_LIMIT)
|
||||||
const queryLimit = positiveNumberOrDefault(query.limit, defaultLimit)
|
const queryLimit = positiveNumberOrDefault(query.limit, defaultLimit)
|
||||||
|
const paginationType = config.paginationType || DEFAULT_PAGINATE_TYPE
|
||||||
|
|
||||||
const isPaginated = !(queryLimit === NO_PAGINATION && maxLimit === NO_PAGINATION)
|
const isPaginated = !(queryLimit === NO_PAGINATION && maxLimit === NO_PAGINATION)
|
||||||
|
|
||||||
@ -159,10 +167,14 @@ export async function paginate<T extends ObjectLiteral>(
|
|||||||
if (isPaginated) {
|
if (isPaginated) {
|
||||||
// Switch from take and skip to limit and offset
|
// Switch from take and skip to limit and offset
|
||||||
// due to this problem https://github.com/typeorm/typeorm/issues/5670
|
// 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)
|
// 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)
|
queryBuilder.take(limit).skip((page - 1) * limit)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (config.relations) {
|
if (config.relations) {
|
||||||
// relations: ["relation"]
|
// relations: ["relation"]
|
||||||
|
Loading…
Reference in New Issue
Block a user