{"_id":"@adam_park/nestjs-paginate","_rev":"3-d78a96a87a4e15cf6962c7d0128f8796","name":"@adam_park/nestjs-paginate","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@adam_park/nestjs-paginate","version":"0.1.0","keywords":["nestjs","typeorm","express","pagination","paginate","filtering","search"],"author":{"name":"Adam Park","email":"run.eunsong@gmail.com"},"license":"MIT","_id":"@adam_park/nestjs-paginate@0.1.0","maintainers":[{"name":"adam_park","email":"run.eunsong@gmail.com"}],"homepage":"https://github.com/ppetzold/nestjs-paginate#readme","bugs":{"url":"https://github.com/ppetzold/nestjs-paginate/issues"},"dist":{"shasum":"245f8b19bbae0c55aa0db7a03db320856e4040cb","tarball":"https://registry.npmjs.org/@adam_park/nestjs-paginate/-/nestjs-paginate-0.1.0.tgz","fileCount":67,"integrity":"sha512-mq9NQoAVAHHIFl49nhhfRZpgBXBGwVUbJ+nYQ11VI9WJJP/pW3Cc2kGmKPM38N1M/vrKDRoPYxBPPKc0TmGhDg==","signatures":[{"sig":"MEYCIQDSB8FRM/fcLi9+tYRHpjEh0Zq6ElfivK5UsZZZx1l1IQIhALPUdYooVvKVTigXqomT1v5nUTogVp/jj4JXoYFPRYCi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":632499},"jest":{"rootDir":"src","testRegex":".spec.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"setupFiles":["<rootDir>/../jest.setup.ts"],"testEnvironment":"node","coverageDirectory":"../coverage","moduleFileExtensions":["js","json","ts"]},"main":"lib/index.js","gitHead":"8b37b5df1fad3bb3e25a96decb1a22603566eef8","release":{"branches":["master"]},"scripts":{"lint":"eslint -c .eslintrc.json --ext .ts --max-warnings 0 src","test":"jest","build":"tsc","format":"prettier --write \"src/**/*.ts\"","prepare":"tsc","dev:yalc":"nodemon --watch src --ext ts --exec 'npm run build && yalc push'","prebuild":"rimraf lib","test:cov":"jest --coverage","format:ci":"prettier --list-different \"src/**/*.ts\"","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch "},"typings":"lib/index.d.ts","_npmUser":{"name":"adam_park","email":"run.eunsong@gmail.com"},"repository":{"url":"git+https://github.com/ppetzold/nestjs-paginate.git","type":"git"},"_npmVersion":"10.8.2","description":"Pagination and filtering helper method for TypeORM repositories or query builders using Nest.js framework.","directories":{},"_nodeVersion":"20.17.0","dependencies":{"lodash":"^4.17.21"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.13.1","jest":"^29.7.0","rxjs":"^7.8.1","mysql":"^2.18.1","dotenv":"^16.4.7","eslint":"^8.57.1","fastify":"^5.2.1","sqlite3":"^5.1.7","ts-jest":"^29.2.5","ts-node":"^10.9.2","typeorm":"^0.3.17","prettier":"^3.0.3","typescript":"^5.5.4","@types/jest":"^29.5.14","@types/node":"^22.10.5","@types/lodash":"^4.17.15","@nestjs/common":"^11.0.3","@types/express":"^5.0.0","@nestjs/testing":"^11.0.3","reflect-metadata":"^0.1.14","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.2.3","@nestjs/platform-express":"^11.0.3","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/eslint-plugin":"^7.18.0"},"peerDependencies":{"express":"^4.21.2 || ^5.0.0","fastify":"^4.0.0 || ^5.0.0","typeorm":"^0.3.17","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^8.0.0 || ^11.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-paginate_0.1.0_1741244306099_0.3211139684282909","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@adam_park/nestjs-paginate","version":"0.1.1","keywords":["nestjs","typeorm","express","pagination","paginate","filtering","search"],"author":{"name":"Adam Park","email":"run.eunsong@gmail.com"},"license":"MIT","_id":"@adam_park/nestjs-paginate@0.1.1","maintainers":[{"name":"adam_park","email":"run.eunsong@gmail.com"}],"homepage":"https://github.com/ppetzold/nestjs-paginate#readme","bugs":{"url":"https://github.com/ppetzold/nestjs-paginate/issues"},"dist":{"shasum":"7fac2f555907eb6231464f7c2031a152a49f28c9","tarball":"https://registry.npmjs.org/@adam_park/nestjs-paginate/-/nestjs-paginate-0.1.1.tgz","fileCount":67,"integrity":"sha512-zMUxMlkzkCodtl5mJynFdUBFzXzWL0ULRGUwDUilRFkeJgD15y/1ECu6F7IRyPbQwNnY9Hzp3KmS5RxorIFlEw==","signatures":[{"sig":"MEUCIQCMLjOu5zZTSf50cnNZcjBj6LaHZOmSeChDwNjPQ80uDAIgEWhJAEmim7+HqZdvAp94IAKadO02/dVqiWbfRvuySmI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":637356},"jest":{"rootDir":"src","testRegex":".spec.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"setupFiles":["<rootDir>/../jest.setup.ts"],"testEnvironment":"node","coverageDirectory":"../coverage","moduleFileExtensions":["js","json","ts"]},"main":"lib/index.js","gitHead":"7fdc1dcbcfb1fa99c2d00364798f0ba2a37f4e0c","release":{"branches":["master"]},"scripts":{"lint":"eslint -c .eslintrc.json --ext .ts --max-warnings 0 src","test":"jest","build":"tsc","format":"prettier --write \"src/**/*.ts\"","prepare":"tsc","dev:yalc":"nodemon --watch src --ext ts --exec 'npm run build && yalc push'","prebuild":"rimraf lib","test:cov":"jest --coverage","format:ci":"prettier --list-different \"src/**/*.ts\"","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand","test:watch":"jest --watch "},"typings":"lib/index.d.ts","_npmUser":{"name":"adam_park","email":"run.eunsong@gmail.com"},"repository":{"url":"git+https://github.com/ppetzold/nestjs-paginate.git","type":"git"},"_npmVersion":"10.8.2","description":"Pagination and filtering helper method for TypeORM repositories or query builders using Nest.js framework.","directories":{},"_nodeVersion":"20.17.0","dependencies":{"lodash":"^4.17.21"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.13.1","jest":"^29.7.0","rxjs":"^7.8.1","mysql":"^2.18.1","dotenv":"^16.4.7","eslint":"^8.57.1","fastify":"^5.2.1","sqlite3":"^5.1.7","ts-jest":"^29.2.5","ts-node":"^10.9.2","typeorm":"^0.3.17","prettier":"^3.0.3","typescript":"^5.5.4","@types/jest":"^29.5.14","@types/node":"^22.10.5","@types/lodash":"^4.17.15","@nestjs/common":"^11.0.3","@types/express":"^5.0.0","@nestjs/testing":"^11.0.3","reflect-metadata":"^0.1.14","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.2.3","@nestjs/platform-express":"^11.0.3","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/eslint-plugin":"^7.18.0"},"peerDependencies":{"express":"^4.21.2 || ^5.0.0","fastify":"^4.0.0 || ^5.0.0","typeorm":"^0.3.17","@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^8.0.0 || ^11.0.0"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-paginate_0.1.1_1741260921290_0.5944942891192309","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@adam_park/nestjs-paginate","version":"0.1.2","author":{"name":"Adam Park","email":"run.eunsong@gmail.com"},"license":"MIT","main":"lib/index.js","typings":"lib/index.d.ts","description":"Pagination and filtering helper method for TypeORM repositories or query builders using Nest.js framework.","keywords":["nestjs","typeorm","express","pagination","paginate","filtering","search"],"scripts":{"prebuild":"rimraf lib","build":"tsc","prepare":"tsc","dev:yalc":"nodemon --watch src --ext ts --exec 'npm run build && yalc push'","format":"prettier --write \"src/**/*.ts\"","format:ci":"prettier --list-different \"src/**/*.ts\"","lint":"eslint -c .eslintrc.json --ext .ts --max-warnings 0 src","test":"jest","test:watch":"jest --watch ","test:cov":"jest --coverage","test:debug":"node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand"},"devDependencies":{"@nestjs/common":"^11.0.11","@nestjs/platform-express":"^11.0.11","@nestjs/testing":"^11.0.11","@types/express":"^5.0.0","@types/jest":"^29.5.14","@types/lodash":"^4.17.16","@types/node":"^22.13.10","@typescript-eslint/eslint-plugin":"^7.18.0","@typescript-eslint/parser":"^7.18.0","dotenv":"^16.4.7","eslint":"^8.57.1","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.2.3","fastify":"^5.2.1","jest":"^29.7.0","mysql2":"^3.14.0","pg":"^8.14.0","prettier":"^3.0.3","reflect-metadata":"^0.2.2","rxjs":"^7.8.2","sqlite3":"^5.1.7","ts-jest":"^29.2.6","ts-node":"^10.9.2","typeorm":"^0.3.17","typescript":"^5.5.4"},"dependencies":{"lodash":"^4.17.21"},"peerDependencies":{"@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/swagger":"^8.0.0 || ^11.0.0","express":"^4.21.2 || ^5.0.0","fastify":"^4.0.0 || ^5.0.0","typeorm":"^0.3.17"},"jest":{"moduleFileExtensions":["js","json","ts"],"rootDir":"src","testRegex":".spec.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"coverageDirectory":"../coverage","testEnvironment":"node","setupFiles":["<rootDir>/../jest.setup.ts"]},"repository":{"type":"git","url":"git+https://github.com/ppetzold/nestjs-paginate.git"},"homepage":"https://github.com/ppetzold/nestjs-paginate#readme","bugs":{"url":"https://github.com/ppetzold/nestjs-paginate/issues"},"publishConfig":{"access":"public"},"release":{"branches":["master"]},"_id":"@adam_park/nestjs-paginate@0.1.2","gitHead":"a1d746c5b028930a18e04a4e0a29ad39577b6c75","_nodeVersion":"20.17.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-TipieWZ92yVrqQlSCtl68jo4tXdFcusLNVEgQPdvw536eEUXlgh1O4hRX0wk8xznFqPjYmsmAKQ9mRZgpuu4hA==","shasum":"279001138a55b803229f123f9b8aaf2e10cac60e","tarball":"https://registry.npmjs.org/@adam_park/nestjs-paginate/-/nestjs-paginate-0.1.2.tgz","fileCount":73,"unpackedSize":715149,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAPbPZ+rs+dTse3Kb9MsOK8pAV5XImvbRlTwpBkdxGxzAiEAp91/VpCSMzeLBQZo7vte1NxTrJUpCwkQtHCA0R7RyjU="}]},"_npmUser":{"name":"adam_park","email":"run.eunsong@gmail.com"},"directories":{},"maintainers":[{"name":"adam_park","email":"run.eunsong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-paginate_0.1.2_1743743888760_0.44675206663677036"},"_hasShrinkwrap":false}},"time":{"created":"2025-03-06T06:58:26.044Z","modified":"2025-04-04T05:18:09.200Z","0.1.0":"2025-03-06T06:58:26.273Z","0.1.1":"2025-03-06T11:35:21.503Z","0.1.2":"2025-04-04T05:18:09.030Z"},"bugs":{"url":"https://github.com/ppetzold/nestjs-paginate/issues"},"author":{"name":"Adam Park","email":"run.eunsong@gmail.com"},"license":"MIT","homepage":"https://github.com/ppetzold/nestjs-paginate#readme","keywords":["nestjs","typeorm","express","pagination","paginate","filtering","search"],"repository":{"type":"git","url":"git+https://github.com/ppetzold/nestjs-paginate.git"},"description":"Pagination and filtering helper method for TypeORM repositories or query builders using Nest.js framework.","maintainers":[{"name":"adam_park","email":"run.eunsong@gmail.com"}],"readme":"# Nest.js Paginate\n\n![Main CI](https://github.com/ppetzold/nestjs-paginate/workflows/Main%20CI/badge.svg)\n[![npm](https://img.shields.io/npm/v/nestjs-paginate.svg)](https://www.npmjs.com/package/nestjs-paginate)\n[![downloads](https://img.shields.io/npm/dt/nestjs-paginate.svg)](https://www.npmjs.com/package/nestjs-paginate)\n[![codecov](https://codecov.io/gh/ppetzold/nestjs-paginate/branch/master/graph/badge.svg)](https://codecov.io/gh/ppetzold/nestjs-paginate)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n![GitHub](https://img.shields.io/github/license/ppetzold/nestjs-paginate)\n\nPagination and filtering helper method for TypeORM repositories or query builders using [Nest.js](https://nestjs.com/) framework.\n\n- Pagination conforms to [JSON:API](https://jsonapi.org/)\n- Sort by multiple columns\n- Search across columns\n- Select columns\n- Filter using operators (`$eq`, `$not`, `$null`, `$in`, `$gt`, `$gte`, `$lt`, `$lte`, `$btw`, `$ilike`, `$sw`, `$contains`)\n- Include relations and nested relations\n- Virtual column support\n- Cursor-based pagination\n\n## Installation\n\n```\nnpm install nestjs-paginate\n```\n\n## Usage\n\n### Example\n\nThe following code exposes a route that can be utilized like so:\n\n#### Endpoint\n\n```url\nhttp://localhost:3000/cats?limit=5&page=2&sortBy=color:DESC&search=i&filter.age=$gte:3&select=id,name,color,age\n```\n\n#### Result\n\n```json\n{\n  \"data\": [\n    {\n      \"id\": 4,\n      \"name\": \"George\",\n      \"color\": \"white\",\n      \"age\": 3\n    },\n    {\n      \"id\": 5,\n      \"name\": \"Leche\",\n      \"color\": \"white\",\n      \"age\": 6\n    },\n    {\n      \"id\": 2,\n      \"name\": \"Garfield\",\n      \"color\": \"ginger\",\n      \"age\": 4\n    },\n    {\n      \"id\": 1,\n      \"name\": \"Milo\",\n      \"color\": \"brown\",\n      \"age\": 5\n    },\n    {\n      \"id\": 3,\n      \"name\": \"Kitty\",\n      \"color\": \"black\",\n      \"age\": 3\n    }\n  ],\n  \"meta\": {\n    \"itemsPerPage\": 5,\n    \"totalItems\": 12,\n    \"currentPage\": 2,\n    \"totalPages\": 3,\n    \"sortBy\": [[\"color\", \"DESC\"]],\n    \"search\": \"i\",\n    \"filter\": {\n      \"age\": \"$gte:3\"\n    }\n  },\n  \"links\": {\n    \"first\": \"http://localhost:3000/cats?limit=5&page=1&sortBy=color:DESC&search=i&filter.age=$gte:3\",\n    \"previous\": \"http://localhost:3000/cats?limit=5&page=1&sortBy=color:DESC&search=i&filter.age=$gte:3\",\n    \"current\": \"http://localhost:3000/cats?limit=5&page=2&sortBy=color:DESC&search=i&filter.age=$gte:3\",\n    \"next\": \"http://localhost:3000/cats?limit=5&page=3&sortBy=color:DESC&search=i&filter.age=$gte:3\",\n    \"last\": \"http://localhost:3000/cats?limit=5&page=3&sortBy=color:DESC&search=i&filter.age=$gte:3\"\n  }\n}\n```\n\n### Example (Cursor-based Pagination)\n\nThe following code exposes a route using cursor-based pagination:\n\n#### Endpoint\n\n```url\nhttp://localhost:3000/cats?limit=5&sortBy=lastVetVisit:ASC&cursor=V998328469600000\n```\n\n#### Result\n\n```json\n{\n  \"data\": [\n    {\n      \"id\": 3,\n      \"name\": \"Shadow\",\n      \"lastVetVisit\": \"2022-12-21T10:00:00.000Z\"\n    },\n    {\n      \"id\": 4,\n      \"name\": \"Luna\",\n      \"lastVetVisit\": \"2022-12-22T10:00:00.000Z\"\n    },\n    {\n      \"id\": 5,\n      \"name\": \"Pepper\",\n      \"lastVetVisit\": \"2022-12-23T10:00:00.000Z\"\n    },\n    {\n      \"id\": 6,\n      \"name\": \"Simba\",\n      \"lastVetVisit\": \"2022-12-24T10:00:00.000Z\"\n    },\n    {\n      \"id\": 7,\n      \"name\": \"Tiger\",\n      \"lastVetVisit\": \"2022-12-25T10:00:00.000Z\"\n    }\n  ],\n  \"meta\": {\n    \"itemsPerPage\": 5,\n    \"cursor\": \"V998328469600000\"\n  },\n  \"links\": {\n    \"previous\": \"http://localhost:3000/cats?limit=5&sortBy=lastVetVisit:DESC&cursor=V001671616800000\",\n    \"current\": \"http://localhost:3000/cats?limit=5&sortBy=lastVetVisit:ASC&cursor=V998328469600000\",\n    \"next\": \"http://localhost:3000/cats?limit=5&sortBy=lastVetVisit:ASC&cursor=V998328037600000\"\n  }\n}\n```\n\n#### Code\n\n```ts\nimport { Controller, Injectable, Get } from '@nestjs/common'\nimport { InjectRepository } from '@nestjs/typeorm'\nimport { FilterOperator, FilterSuffix, Paginate, PaginateQuery, paginate, Paginated } from 'nestjs-paginate'\nimport { Repository, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'\n\n@Entity()\nexport class CatEntity {\n  @PrimaryGeneratedColumn()\n  id: number\n\n  @Column('text')\n  name: string\n\n  @Column('text')\n  color: string\n\n  @Column('int')\n  age: number\n\n  @Column({ nullable: true })\n  lastVetVisit: Date | null\n\n  @CreateDateColumn()\n  createdAt: string\n}\n\n@Injectable()\nexport class CatsService {\n  constructor(\n    @InjectRepository(CatEntity)\n    private readonly catsRepository: Repository<CatEntity>\n  ) {}\n\n  public findAll(query: PaginateQuery): Promise<Paginated<CatEntity>> {\n    return paginate(query, this.catsRepository, {\n      sortableColumns: ['id', 'name', 'color', 'age'],\n      nullSort: 'last',\n      defaultSortBy: [['id', 'DESC']],\n      searchableColumns: ['name', 'color', 'age'],\n      select: ['id', 'name', 'color', 'age', 'lastVetVisit'],\n      filterableColumns: {\n        name: [FilterOperator.EQ, FilterSuffix.NOT],\n        age: true,\n      },\n    })\n  }\n}\n\n@Controller('cats')\nexport class CatsController {\n  constructor(private readonly catsService: CatsService) {}\n\n  @Get()\n  public findAll(@Paginate() query: PaginateQuery): Promise<Paginated<CatEntity>> {\n    return this.catsService.findAll(query)\n  }\n}\n```\n\n### Config\n\n```ts\nconst paginateConfig: PaginateConfig<CatEntity> {\n  /**\n   * Required: true (must have a minimum of one column)\n   * Type: (keyof CatEntity)[]\n   * Description: These are the columns that are valid to be sorted by.\n   */\n  sortableColumns: ['id', 'name', 'color'],\n\n  /**\n   * Required: false\n   * Type: 'first' | 'last'\n   * Description: Define whether to put null values at the beginning\n   * or end of the result set.\n   */\n  nullSort: 'last',\n\n  /**\n   * Required: false\n   * Type: [keyof CatEntity, 'ASC' | 'DESC'][]\n   * Default: [[sortableColumns[0], 'ASC]]\n   * Description: The order to display the sorted entities.\n   */\n  defaultSortBy: [['name', 'DESC']],\n\n  /**\n   * Required: false\n   * Type: (keyof CatEntity)[]\n   * Description: These columns will be searched through when using the search query\n   * param. Limit search scope further by using `searchBy` query param.\n   */\n  searchableColumns: ['name', 'color'],\n\n  /**\n   * Required: false\n   * Type: (keyof CatEntity)[]\n   * Default: None\n   * Description: TypeORM partial selection. Limit selection further by using `select` query param.\n   * https://typeorm.io/select-query-builder#partial-selection\n   * Note: You must include the primary key in the selection.\n   */\n  select: ['id', 'name', 'color'],\n\n  /**\n   * Required: false\n   * Type: number\n   * Default: 100\n   * Description: The maximum amount of entities to return per page.\n   * Set it to -1, in conjunction with limit=-1 on query param, to disable pagination.\n   */\n  maxLimit: 20,\n\n  /**\n   * Required: false\n   * Type: number\n   * Default: 20\n   */\n  defaultLimit: 50,\n\n  /**\n   * Required: false\n   * Type: TypeORM find options\n   * Default: None\n   * https://typeorm.io/#/find-optionsfind-options.md\n   */\n  where: { color: 'ginger' },\n\n  /**\n   * Required: false\n   * Type: { [key in CatEntity]?: FilterOperator[] } - Operators based on TypeORM find operators\n   * Default: None\n   * https://typeorm.io/#/find-options/advanced-options\n   */\n  filterableColumns: { age: [FilterOperator.EQ, FilterOperator.IN] },\n\n  /**\n   * Required: false\n   * Type: RelationColumn<CatEntity>\n   * Description: Indicates what relations of entity should be loaded.\n   */\n  relations: [],\n\n  /**\n   * Required: false\n   * Type: boolean\n   * Default: false\n   * Description: Load eager relations using TypeORM's eager property.\n   * Only works if `relations` is not defined.\n   */\n  loadEagerRelations: true,\n\n  /**\n   * Required: false\n   * Type: boolean\n   * Description: Disables the global condition of \"non-deleted\" for the entity with delete date columns.\n   * https://typeorm.io/select-query-builder#querying-deleted-rows\n   */\n  withDeleted: false,\n\n  /**\n   * Required: false\n   * Type: string\n   * Description: Allow user to choose between limit/offset and take/skip, or cursor-based pagination.\n   * Default: PaginationType.TAKE_AND_SKIP\n   * Options: PaginationType.LIMIT_AND_OFFSET, PaginationType.TAKE_AND_SKIP, PaginationType.CURSOR\n   *\n   * However, using limit/offset can cause problems with relations.\n   */\n  paginationType: PaginationType.LIMIT_AND_OFFSET,\n\n  /**\n   * Required: false\n   * Type: boolean\n   * Default: false\n   * Description: Generate relative paths in the resource links.\n   */\n  relativePath: true,\n\n  /**\n   * Required: false\n   * Type: string\n   * Description: Overrides the origin of absolute resource links if set.\n   */\n  origin: 'http://cats.example',\n\n  /**\n   * Required: false\n   * Type: boolean\n   * Default: false\n   * Description: Prevent `searchBy` query param from limiting search scope further. Search will depend upon `searchableColumns` config option only\n   */\n  ignoreSearchByInQueryParam: true,\n\n  /**\n   * Required: false\n   * Type: boolean\n   * Default: false\n   * Description: Prevent `select` query param from limiting selection further. Partial selection will depend upon `select` config option only\n   */\n  ignoreSelectInQueryParam: true,\n\n  /**\n   * Required: false\n   * Type: 'leftJoinAndSelect' | 'innerJoinAndSelect'\n   * Default: 'leftJoinAndSelect'\n   * Description: Relationships will be joined with either LEFT JOIN or INNER JOIN, and their columns selected. Can be specified per column with `joinMethods` configuration.\n   */\n  defaultJoinMethod: 'leftJoinAndSelect',\n\n  /**\n   * Required: false\n   * Type: MappedColumns<T, JoinMethod>\n   * Default: false\n   * Description: Overrides the join method per relationship.\n   */\n  joinMethods: {age: 'innerJoinAndSelect', size: 'leftJoinAndSelect'},\n\n  /**\n   * Required: false\n   * Type: boolean\n   * Default: false\n   * Description: Enable multi-word search behavior. When true, each word in the search query\n   * will be treated as a separate search term, allowing for more flexible matching.\n   */\n  multiWordSearch: false,\n}\n```\n\n## Usage with Query Builder\n\nYou can paginate custom queries by passing on the query builder:\n\n### Example\n\n```typescript\nconst queryBuilder = repo\n  .createQueryBuilder('cats')\n  .leftJoinAndSelect('cats.owner', 'owner')\n  .where('cats.owner = :ownerId', { ownerId })\n\nconst result = await paginate<CatEntity>(query, queryBuilder, config)\n```\n\n## Usage with Relations\n\nSimilar as with repositories, you can utilize `relations` as a simplified left-join form:\n\n### Example\n\n#### Endpoint\n\n```url\nhttp://localhost:3000/cats?filter.toys.name=$in:Mouse,String\n```\n\n#### Code\n\n```typescript\nconst config: PaginateConfig<CatEntity> = {\n  relations: ['toys'],\n  sortableColumns: ['id', 'name', 'toys.name'],\n  filterableColumns: {\n    'toys.name': [FilterOperator.IN],\n  },\n}\n\nconst result = await paginate<CatEntity>(query, catRepo, config)\n```\n\n**Note:** Embedded columns on relations have to be wrapped with brackets:\n\n```typescript\nconst config: PaginateConfig<CatEntity> = {\n  sortableColumns: ['id', 'name', 'toys.(size.height)', 'toys.(size.width)'],\n  searchableColumns: ['name'],\n  relations: ['toys'],\n}\n```\n\n## Usage with Nested Relations\n\nSimilar as with relations, you can specify nested relations for sorting, filtering and searching:\n\n### Example\n\n#### Endpoint\n\n```url\nhttp://localhost:3000/cats?filter.home.pillows.color=pink\n```\n\n#### Code\n\n```typescript\nconst config: PaginateConfig<CatEntity> = {\n  relations: { home: { pillows: true } },\n  sortableColumns: ['id', 'name', 'home.pillows.color'],\n  searchableColumns: ['name', 'home.pillows.color'],\n  filterableColumns: {\n    'home.pillows.color': [FilterOperator.EQ],\n  },\n}\n\nconst result = await paginate<CatEntity>(query, catRepo, config)\n```\n\n## Usage with Eager Loading\n\nEager loading should work with TypeORM's eager property out of the box:\n\n### Example\n\n#### Code\n\n```typescript\n@Entity()\nexport class CatEntity {\n  // ...\n\n  @OneToMany(() => CatToyEntity, (catToy) => catToy.cat, {\n    eager: true,\n  })\n  toys: CatToyEntity[]\n}\n\nconst config: PaginateConfig<CatEntity> = {\n  loadEagerRelations: true,\n  sortableColumns: ['id', 'name', 'toys.name'],\n  filterableColumns: {\n    'toys.name': [FilterOperator.IN],\n  },\n}\n\nconst result = await paginate<CatEntity>(query, catRepo, config)\n```\n\n## Filters\n\nFilter operators must be whitelisted per column in `PaginateConfig`.\n\n### Examples\n\n#### Code\n\n```typescript\nconst config: PaginateConfig<CatEntity> = {\n  // ...\n  filterableColumns: {\n    // Enable individual operators on a column\n    id: [FilterOperator.EQ, FilterSuffix.NOT],\n\n    // Enable all operators on a column\n    age: true,\n  },\n}\n```\n\n`?filter.name=$eq:Milo` is equivalent with `?filter.name=Milo`\n\n`?filter.age=$btw:4,6` where column `age` is between `4` and `6`\n\n`?filter.id=$not:$in:2,5,7` where column `id` is **not** `2`, `5` or `7`\n\n`?filter.summary=$not:$ilike:term` where column `summary` does **not** contain `term`\n\n`?filter.summary=$sw:term` where column `summary` starts with `term`\n\n`?filter.seenAt=$null` where column `seenAt` is `NULL`\n\n`?filter.seenAt=$not:$null` where column `seenAt` is **not** `NULL`\n\n`?filter.createdAt=$btw:2022-02-02,2022-02-10` where column `createdAt` is between the dates `2022-02-02` and `2022-02-10`\n\n`?filter.createdAt=$lt:2022-12-20T10:00:00.000Z` where column `createdAt` is before iso date `2022-12-20T10:00:00.000Z`\n\n`?filter.roles=$contains:moderator` where column `roles` is an array and contains the value `moderator`\n\n`?filter.roles=$contains:moderator,admin` where column `roles` is an array and contains the values `moderator` and `admin`\n\n## Jsonb Filters\n\nYou can filter on jsonb columns by using the dot notation. Json columns is limited to `$eq` operators only.\n\n`?filter.metadata.enabled=$eq:true` where column `metadata` is jsonb and contains an object with the key `enabled`.\n\n## Multi Filters\n\nMulti filters are filters that can be applied to a single column with a comparator.\n\n### Examples\n\n`?filter.createdAt=$gt:2022-02-02&filter.createdAt=$lt:2022-02-10` where column `createdAt` is after `2022-02-02` **and** before `2022-02-10`\n\n`?filter.roles=$contains:moderator&filter.roles=$or:$contains:admin` where column `roles` is an array and contains `moderator` **or** `admin`\n\n`?filter.id=$gt:3&filter.id=$and:$lt:5&filter.id=$or:$eq:7` where column `id` is greater than `3` **and** less than `5` **or** equal to `7`\n\n**Note:** The `$and` comparators are not required. The above example is equivalent to:\n\n`?filter.id=$gt:3&filter.id=$lt:5&filter.id=$or:$eq:7`\n\n**Note:** The first comparator on the the first filter is ignored because the filters are grouped by the column name and chained with an `$and` to other filters.\n\n`...&filter.id=5&filter.id=$or:7&filter.name=Milo&...`\n\nis resolved to:\n\n`WHERE ... AND (id = 5 OR id = 7) AND name = 'Milo' AND ...`\n\n## Cursor-based Pagination\n\n- `paginationType: PaginationType.CURSOR`\n- Cursor format:\n  - Numbers: `[prefix1][integer:11 digits][prefix2][decimal:4 digits]` (e.g., `Y00000000001V2500` for -1.25 in ASC).\n  - Dates: `[prefix][value:15 digits]` (e.g., `V001671444000000` for a timestamp in DESC).\n- Prefixes:\n  - `null`: `A` (lowest priority, last in results).\n  - ASC:\n    - positive-int: `V` (greater than or equal to 1), `X` (less than 1)\n    - positive-decimal: `V` (not zero), `X` (zero)\n    - zero-int: `X`\n    - zero-decimal: `X`\n    - negative-int: `Y`\n    - negative-decimal: `V`\n  - DESC:\n    - positive-int: `V`\n    - positive-decimal: `V`\n    - zero-int: `N`\n    - zero-decimal: `X`\n    - negative-int: `M` (less than or equal to -1), `N` (greater than -1)\n    - negative-decimal: `V` (not zero), `X` (zero)\n- Logic:\n  - Numbers: Split into integer (11 digits) and decimal (4 digits) parts, with separate prefixes. Supports negative values, with sorting adjusted per direction.\n  - Dates: Single prefix with 15-digit timestamp padded with zeros.\n  - ASC: Negative → Zero → Positive → Null.\n  - DESC: Positive → Zero → Negative → Null.\n- Notes:\n  - Multiple columns: `sortBy` can include multiple columns to create and sort by the cursor (e.g., `sortBy=age:ASC,createdAt:DESC`), but at least one column must be unique to ensure consistent ordering.\n  - Supported columns: Cursor sorting is available for numeric and date-related columns (string columns are not supported).\n  - Decimal support: Numeric columns can include decimals, limited to 11 digits for the integer part and 4 digits for the decimal part.\n\n## Swagger\n\nYou can use two default decorators @ApiOkResponsePaginated and @ApiPagination to generate swagger documentation for your endpoints\n\n`@ApiOkPaginatedResponse` is for response body, return http[](https://) status is 200\n\n`@ApiPaginationQuery` is for query params\n\n```typescript\n  @Get()\n  @ApiOkPaginatedResponse(\n    UserDto,\n    USER_PAGINATION_CONFIG,\n  )\n  @ApiPaginationQuery(USER_PAGINATION_CONFIG)\n  async findAll(\n    @Paginate()\n    query: PaginateQuery,\n  ): Promise<Paginated<UserEntity>> {\n\n  }\n```\n\nThere is also some syntax sugar for this, and you can use only one decorator `@PaginatedSwaggerDocs` for both response body and query params\n\n```typescript\n  @Get()\n  @PaginatedSwaggerDocs(UserDto, USER_PAGINATION_CONFIG)\n  async findAll(\n    @Paginate()\n    query: PaginateQuery,\n  ): Promise<Paginated<UserEntity>> {\n\n  }\n```\n\n## Troubleshooting\n\nThe package does not report error reasons in the response bodies. They are instead\nreported as `debug` level [logging](https://docs.nestjs.com/techniques/logger#logger).\n\nCommon errors include missing `sortableColumns` or `filterableColumns` (the latter only affects filtering).\n","readmeFilename":"README.md"}