{"id":15823299,"url":"https://github.com/kaltsoon/sequelize-cursor-pagination","last_synced_at":"2025-04-07T05:11:55.883Z","repository":{"id":37493132,"uuid":"104241806","full_name":"Kaltsoon/sequelize-cursor-pagination","owner":"Kaltsoon","description":"➡️ Cursor-based pagination queries for Sequelize models","archived":false,"fork":false,"pushed_at":"2023-03-13T21:46:37.000Z","size":1660,"stargazers_count":86,"open_issues_count":9,"forks_count":27,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-06T08:07:06.368Z","etag":null,"topics":["cursor-pagination","pagination","sequelize","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kaltsoon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-20T16:41:34.000Z","updated_at":"2024-07-19T06:26:40.000Z","dependencies_parsed_at":"2024-06-18T15:22:56.186Z","dependency_job_id":"415b85c3-da0f-4149-b20a-4730742de9b6","html_url":"https://github.com/Kaltsoon/sequelize-cursor-pagination","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kaltsoon%2Fsequelize-cursor-pagination","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kaltsoon%2Fsequelize-cursor-pagination/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kaltsoon%2Fsequelize-cursor-pagination/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kaltsoon%2Fsequelize-cursor-pagination/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kaltsoon","download_url":"https://codeload.github.com/Kaltsoon/sequelize-cursor-pagination/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595335,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cursor-pagination","pagination","sequelize","typescript"],"created_at":"2024-10-05T08:08:06.884Z","updated_at":"2025-04-07T05:11:55.849Z","avatar_url":"https://github.com/Kaltsoon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ➡️ sequelize-cursor-pagination\n\n[![Test](https://github.com/Kaltsoon/sequelize-cursor-pagination/actions/workflows/test.yml/badge.svg)](https://github.com/Kaltsoon/sequelize-cursor-pagination/actions/workflows/test.yml) [![npm](https://img.shields.io/npm/v/sequelize-cursor-pagination)](https://www.npmjs.com/package/sequelize-cursor-pagination)\n\nCursor-based pagination queries for Sequelize models. [Some motivation and background](https://dev-blog.apollodata.com/understanding-pagination-rest-graphql-and-relay-b10f835549e7).\n\n## Install\n\nWith npm:\n\n```bash\nnpm install sequelize-cursor-pagination\n```\n\nWith Yarn:\n\n```bash\nyarn add sequelize-cursor-pagination\n```\n\n## How to use?\n\nDefine a static pagination method for a Sequelize model with the `makePaginate` function:\n\n```javascript\nconst { makePaginate } = require('sequelize-cursor-pagination');\n\nconst Counter = sequelize.define('counter', {\n  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },\n  value: Sequelize.INTEGER,\n});\n\nCounter.paginate = makePaginate(Counter);\n```\n\nThe first argument of the `makePaginate` function is the model class. The function also has a second, optional argument, which is the options object. The options object has the following properties:\n\n- `primaryKeyField`: The primary key field of the model. With a composite primary key, provide an array containing the keys, for example `['key1', 'key2']`. If not provided, the primary key is resolved from the model's attributes (attributes with `primaryKey: true`). This is the desired behavior in most cases.\n- `omitPrimaryKeyFromOrder`: By default, the primary key is automatically included in the order if it is missing. Setting this option to `true` will override this behavior. The default value is `false`.\n\nCall the `paginate` method:\n\n```javascript\nconst result = await Counter.paginate({\n  where: { value: { [Op.gt]: 2 } },\n  limit: 10,\n});\n```\n\nThe `paginate` method returns a promise, which resolves an object with the following properties:\n\n- `edges`: An array containing the results of the query. Each item in the array contains an object with the following properties:\n  - `node`: The model instance\n  - `cursor`: Cursor for the model instance\n- `totalCount`: The total numbers rows matching the query\n- `pageInfo`: An object containing the pagination related data with the following properties:\n  - `startCursor`: The cursor for the first node in the result edges\n  - `endCursor`: The cursor for the last node in the result edges\n  - `hasNextPage`: A boolean that indicates whether there are edges _after_ the `endCursor` (`false` indicates that there are no more edges after the `endCursor`)\n  - `hasPreviousPage`: A boolean that indicates whether there are edges _before_ the `startCursor` (`false` indicates that there are no more edges before the `startCursor`)\n\nThe `paginate` method has the following options:\n\n- `after`: The cursor that indicates _after_ which edge the next set of edges should be fetched\n- `before`: The cursor that indicates _before_ which edge next set of edges should be fetched\n- `limit`: The maximum number of edges returned\n\nOther options passed to the `paginate` method will be directly passed to the model's `findAll` method.\n\n**⚠️ NB:** The `order` option format only supports the `['field']` and `['field', 'DESC']` variations (field name and the optional order direction). For example, ordering by an associated model's field won't work.\n\n## Examples\n\nThe examples use the `Counter` model defined above.\n\nFetch the first `20` edges ordered by the `id` field (the `primaryKeyField` field) in ascending order:\n\n```javascript\nconst result = await Counter.paginate({\n  limit: 20,\n});\n```\n\nFirst, fetch the first `10` edges ordered by the `value` field in a descending order. Second, fetch the first `10` edges after the `endCursor`. Third, fetch the last `10` edges before `startCursor`:\n\n```javascript\nconst firstResult = await Counter.paginate({\n  order: [['value', 'DESC']],\n  limit: 10,\n});\n\nconst secondResult = await Counter.paginate({\n  order: [['value', 'DESC']],\n  limit: 10,\n  after: firstResult.pageInfo.endCursor,\n});\n\nconst thirdResult = await Counter.paginate({\n  order: [['value', 'DESC']],\n  limit: 10,\n  before: secondResult.pageInfo.startCursor,\n});\n```\n\n## Only fetching specific pagination connection attributes\n\nOne pagination operation (including `edges`, `totalCount` and `pageInfo`) requires three database queries, but if you are only insterested in the `edges`, one database query is enough. The `makePaginateLazy` function can be used to create a \"lazy evaluation\" version of the `paginate` function. With this version, the `paginateLazy` function returns a `LazyPaginationConnection` object, containing methods `getEdges`, `getTotalCount`, and `getPageInfo`. These methods can be used to fetch the edges, total count, and page info, respectively:\n\n```javascript\nconst { makePaginateLazy } = require('sequelize-cursor-pagination');\n\n// Same options are supported as with the makePaginate function\nCounter.paginateLazy = makePaginateLazy(Counter);\n\n// Same options are supported as with the regular paginate function\nconst connection = Counter.paginateLazy({\n  limit: 10,\n});\n\n// Only one database query is performed in case we are only insterested in the edges\nconst edges = await connection.getEdges();\n\n// Otherwise, we can fetch the total count and page info as well\nconst totalCount = await connection.getTotalCount(); \nconst pageInfo = await connection.getPageInfo();\n```\n\nThe database queries are cached, so there's no extra overhead when fetching the edges, total count, or page info multiple times.\n\n## TypeScript\n\nThe library is written in TypeScript, so types are on the house!\n\nIf you are using a static method like in the previous examples, just declare the method on your model class:\n\n```ts\nimport {\n  PaginateOptions,\n  PaginationConnection,\n  makePaginate,\n  LazyPaginationConnection,\n} from 'sequelize-cursor-pagination';\n\nexport class Counter extends Model\u003c\n  InferAttributes\u003cCounter\u003e,\n  InferCreationAttributes\u003cCounter\u003e\n\u003e {\n  declare id: CreationOptional\u003cnumber\u003e;\n  declare value: number;\n\n  declare static paginate: (\n    options: PaginateOptions\u003cCounter\u003e,\n  ) =\u003e Promise\u003cPaginationConnection\u003cCounter\u003e\u003e;\n\n  declare static paginateLazy: (\n    options: PaginateOptions\u003cCounter\u003e,\n  ) =\u003e LazyPaginationConnection\u003cCounter\u003e;\n}\n\n// ...\n\nCounter.paginate = makePaginate(Counter);\n```\n\n## Migrating from version 2\n\nThe `withPagination` function is deprecated starting from version 3, but the migration is fairly simple.\n\nVersion 2:\n\n```js\nconst withPagination = require('sequelize-cursor-pagination');\n\nconst Counter = sequelize.define('counter', {\n  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },\n  value: Sequelize.INTEGER,\n});\n\nwithPagination({ primaryKeyField: 'id' })(Counter);\n```\n\nVersion 3 onwards:\n\n```js\nconst { makePaginate } = require('sequelize-cursor-pagination');\n\nconst Counter = sequelize.define('counter', {\n  id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },\n  value: Sequelize.INTEGER,\n});\n\nCounter.paginate = makePaginate(Counter);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaltsoon%2Fsequelize-cursor-pagination","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkaltsoon%2Fsequelize-cursor-pagination","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaltsoon%2Fsequelize-cursor-pagination/lists"}