diff --git a/README.md b/README.md index acadf4e..5577dab 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,14 @@ const paginateConfig: PaginateConfig { * 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 = { const result = await paginate(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 = { + paginationType: PaginationType.LIMIT_AND_OFFSET, + // Or + paginationType: PaginationType.TAKE_AND_SKIP, +} + +const result = await paginate(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`. diff --git a/src/paginate.ts b/src/paginate.ts index 59e4c71..cb31701 100644 --- a/src/paginate.ts +++ b/src/paginate.ts @@ -52,6 +52,11 @@ export class Paginated { } } +export enum PaginationType { + LIMIT_AND_OFFSET = 'limit', + TAKE_AND_SKIP = 'take', +} + export interface PaginateConfig { relations?: FindOptionsRelations | RelationColumn[] sortableColumns: Column[] @@ -69,11 +74,13 @@ export interface PaginateConfig { 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( query: PaginateQuery, @@ -85,6 +92,7 @@ export async function paginate( 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,9 +167,13 @@ export async function paginate( 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) - queryBuilder.take(limit).skip((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) {