{"_id":"@chavesnamao2022/nestjs-paginate","_rev":"25-50a06f2e28aae12da3b51d55001aefad","name":"@chavesnamao2022/nestjs-paginate","dist-tags":{"latest":"0.3.0"},"versions":{"0.3.0":{"name":"@chavesnamao2022/nestjs-paginate","version":"0.3.0","keywords":["nestjs","typeorm","express","pagination","paginate","filtering","search"],"author":{"name":"Philipp Petzold","email":"ppetzold@protonmail.com"},"license":"MIT","_id":"@chavesnamao2022/nestjs-paginate@0.3.0","maintainers":[{"name":"chavesnamao","email":"tecnologia@chavesnamao.com.br"}],"homepage":"https://github.com/ppetzold/nestjs-paginate#readme","bugs":{"url":"https://github.com/ppetzold/nestjs-paginate/issues"},"dist":{"shasum":"584d7e95667fb17e5b1b37a711cb4a3ddab6727a","tarball":"https://registry.npmjs.org/@chavesnamao2022/nestjs-paginate/-/nestjs-paginate-0.3.0.tgz","fileCount":43,"integrity":"sha512-g9GYFXAVA5wyiNvrTmEZv5lLu2PWStueOHiIjTu9Zx1PocV0CjHDHaS9q3PjakUPJp2VO6DQflztNPU2cVnFiA==","signatures":[{"sig":"MEYCIQC1BCn4fGxO8xjGBMP+ugYMRHMIWm9bax7L6sIDRekYpQIhAMT2x3ybxNO7MCMSPf6D0znkBtC34fYCaYZG1R0n5x1J","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":407701,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkC455ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrkkRAAnggX85etuFtP5Q0KeQ/6XEEHISr9/ij+hT5k5F2HAVG7Cqot\r\nCj1SGm5RNMzCa60xGBQTAXqMPAp9LyUCf3VsVS0chnLFGZP32LCEYpnS6xYQ\r\ni8rb6wFh6cIKDl7ShWZgyqyBiVMYocAozkzQx847u1tSiwyhRIXmA+NQEYR0\r\nMtfmLiIUjnPlwOLkhKmujogidws8dJ3f6BbJ1GTMpiqTsKwcNG+GRzDc7kgL\r\n8q67dF07r9xJJynoFLTMtk9OlItTL8NwV38tj8GnwDXoHzt3m9b6Y4bTJfaS\r\n+D6e6Ew7OSXLDF7hYlttBj9LQ44pk7OuFUlgLA/Eht1lv+0AIYYCaBmFm4/k\r\nGTb1f7LbrCkMkMpbUJmkef9RlHTGe1bthbrG0oQ3n2NUxULpN3ynTm+d+YP6\r\nEny4c7Plzdu8p3JF2F4mZM8Kh/Bn9xtF2Sf3yXrPpj8GpgDklQEQKDETzsqr\r\ny3XXSDRfHUZ9w7s/rh5/Y8H4CS2PasP7Xdl1V+919yvf5EYn7UxASf/q3Syq\r\naQjXKXLGtHLHBLNbnEouW7C3L4Qj/JHy0Fu/vVrsdC85SBTC6+2pMwILzTOt\r\nOzplbto+/xyEtDiyVlG633Og3gaXgNxshfQaU/88mkmFLOGg6DezN6lr7YH1\r\ncE5TAEGhdT58a1WcATkZxA+/DjvIE+oBeno=\r\n=R7AD\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"rootDir":"src","testRegex":".spec.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","coverageDirectory":"../coverage","moduleFileExtensions":["js","json","ts"]},"main":"lib/index.js","gitHead":"63a0c8b51e54012785bcdd317535dc9f09487ee7","release":{"branches":["master"]},"scripts":{"lint":"eslint -c .eslintrc.json --ext .ts --max-warnings 0 src","test":"jest","build":"tsc","format":"prettier --write \"src/**/*.ts\"","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":"chavesnamao","email":"tecnologia@chavesnamao.com.br"},"repository":{"url":"git+https://github.com/ppetzold/nestjs-paginate.git","type":"git"},"_npmVersion":"8.19.2","description":"Pagination and filtering helper method for TypeORM repostiories or query builders using Nest.js framework.","directories":{},"_nodeVersion":"18.12.1","dependencies":{"lodash":"^4.17.21"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.4.3","rxjs":"^7.8.0","eslint":"^8.35.0","fastify":"^4.13.0","sqlite3":"^5.1.4","ts-jest":"^29.0.5","ts-node":"^10.9.1","typeorm":"^0.3.12","prettier":"^2.8.4","typescript":"^4.9.5","@types/jest":"^29.4.0","@types/node":"^18.14.2","@types/lodash":"^4.14.191","@nestjs/common":"^9.3.9","@types/express":"^4.17.17","reflect-metadata":"^0.1.13","eslint-config-prettier":"^8.6.0","eslint-plugin-prettier":"^4.2.1","@typescript-eslint/parser":"^5.54.0","@typescript-eslint/eslint-plugin":"^5.54.0"},"peerDependencies":{"express":"^4.18.2","fastify":"^4.13.0","typeorm":"^0.3.12","@nestjs/common":"^9.3.9"},"_npmOperationalInternal":{"tmp":"tmp/nestjs-paginate_0.3.0_1678478969244_0.7458996718553899","host":"s3://npm-registry-packages"}}},"time":{"created":"2023-03-10T20:09:29.126Z","modified":"2026-08-10T19:00:05.147Z","0.1.0":"2023-01-24T19:59:21.389Z","0.2.0":"2023-02-15T18:12:30.872Z","0.2.1":"2023-02-28T20:16:13.937Z","0.2.2":"2023-02-28T20:36:18.211Z","0.3.0":"2023-03-10T20:09:29.500Z"},"bugs":{"url":"https://github.com/ppetzold/nestjs-paginate/issues"},"author":{"name":"Philipp Petzold","email":"ppetzold@protonmail.com"},"license":"MIT","homepage":"https://github.com/ppetzold/nestjs-paginate#readme","keywords":["nestjs","typeorm","express","pagination","paginate","filtering","search"],"repository":{"url":"git+https://github.com/ppetzold/nestjs-paginate.git","type":"git"},"description":"Pagination and filtering helper method for TypeORM repostiories or query builders using Nest.js framework.","maintainers":[{"email":"tecnologia@chavesnamao.com.br","name":"chavesnamao"},{"email":"leonardo.nascimento@chavesnamao.com.br","name":"leonardo.nascimento.cnm"},{"email":"lucas.borges@chavesnamao.com.br","name":"lucas-borges-cnm"},{"email":"maycon@chavesnamao.com.br","name":"mayconfabricio"},{"email":"nathan.molina@chavesnamao.com.br","name":"nathanfrontend"}],"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`)\n- Include relations\n- Virtual column support\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\nArray values for filter operators such as `$in` should be provided as comma-separated values:\n\n```\nhttp://localhost:3000/cats?filter.name=$in:George,Milo\n```\n\n#### Code\n\n```ts\nimport { Controller, Injectable, Get } from '@nestjs/common'\nimport { InjectRepository } from '@nestjs/typeorm'\nimport { FilterOperator, 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\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      searchableColumns: ['name', 'color', 'age'],\n      defaultSortBy: [['id', 'DESC']],\n      filterableColumns: {\n        age: [FilterOperator.GTE, FilterOperator.LTE],\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   * Default: 'first'\n   * Description: (ONLY WORKS WITH POSTGRES) Define whether to put null values\n   * at the beginning 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: TypeORM partial selection\n   * Default: None\n   * https://typeorm.io/select-query-builder#partial-selection\n   */\n  select: ['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 0, in conjunction with limit=0 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   * 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: 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\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## Single Filters\n\nFilter operators must be whitelisted per column in `PaginateConfig`.\n\n### Examples\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## Multi Filters\n\nMulti filters are filters that can be applied to a single column with a comparator. As for single filters, multi filters must be whitelisted per column in `PaginateConfig`.\n\n### Examples\n\n`?filter.id=$gt:3&filter.id=$lt:5` where column `id` is greater than `3` **and** less than `5`\n\n`?filter.id=$gt:3&filter.id=$or:$lt:5` where column `id` is greater than `3` **or** less than `5`\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## 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"}