{"id":13656707,"url":"https://github.com/TRUEPIC/queryql","last_synced_at":"2025-04-23T22:31:19.337Z","repository":{"id":35104973,"uuid":"193766632","full_name":"TRUEPIC/queryql","owner":"TRUEPIC","description":"Easily add filtering, sorting, and pagination to your Node.js REST API through your old friend: the query string!","archived":false,"fork":false,"pushed_at":"2025-03-18T03:26:25.000Z","size":794,"stargazers_count":120,"open_issues_count":0,"forks_count":13,"subscribers_count":5,"default_branch":"development","last_synced_at":"2025-04-20T15:52:11.812Z","etag":null,"topics":["api","filter","filtering","knex","orm","page","pagination","qs","query","querystring","rest","sort","sorting"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TRUEPIC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-06-25T18:58:48.000Z","updated_at":"2025-03-18T03:26:27.000Z","dependencies_parsed_at":"2023-01-15T13:56:17.904Z","dependency_job_id":"fe96fc42-18d4-4f52-9523-df1ab3fb2989","html_url":"https://github.com/TRUEPIC/queryql","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TRUEPIC%2Fqueryql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TRUEPIC%2Fqueryql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TRUEPIC%2Fqueryql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TRUEPIC%2Fqueryql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TRUEPIC","download_url":"https://codeload.github.com/TRUEPIC/queryql/tar.gz/refs/heads/development","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250526659,"owners_count":21445218,"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":["api","filter","filtering","knex","orm","page","pagination","qs","query","querystring","rest","sort","sorting"],"created_at":"2024-08-02T05:00:30.987Z","updated_at":"2025-04-23T22:31:19.038Z","avatar_url":"https://github.com/TRUEPIC.png","language":"JavaScript","readme":"# QueryQL\n\n[![npm](https://img.shields.io/npm/v/@truepic/queryql?color=0f4484)](https://www.npmjs.com/package/@truepic/queryql)\n![GitHub Actions](https://github.com/TRUEPIC/queryql/actions/workflows/ci.yml/badge.svg)\n![piratepx](https://app.piratepx.com/ship?p=e91ddd1b-31ad-4c36-b03e-be4a1e9a7678\u0026i=queryql)\n\nQueryQL makes it easy to add filtering, sorting, and pagination to your Node.js\nREST API through your old friend: the query string!\n[Read our introductory article](https://medium.com/truepicinc/queryql-easily-add-filtering-sorting-and-pagination-to-your-node-js-rest-api-9222135c93ae)\nto learn more about why we wrote it and the problems it solves at\n[Truepic](https://truepic.com).\n\nQueryQL works with any Node.js web framework (be it Express, Koa, etc.),\nsupports any query builder / ORM through _adapters_, and allows for custom\n_validators_ so you can define validation in a familiar way.\n\nOut of the box, QueryQL supports the following:\n\n- Adapter: [Knex](https://knexjs.org/) (works with\n  [Objection.js](https://vincit.github.io/objection.js) and other ORMs that use\n  Knex)\n- Validator: [Joi](https://github.com/hapijs/joi)\n\n## Installation\n\n```bash\nnpm install @truepic/queryql\n```\n\n## Getting Started\n\nQueryQL takes a parsed query string (like Express' `req.query`) and translates\nit into the appropriate function calls that your query builder / ORM understands\nto filter, sort, and paginate the records.\n\n(Make sure your framework uses a query string parser that supports nested\nobjects. Node.js's native\n[`querystring`](https://nodejs.org/api/querystring.html) module _does not_, but\na package like [qs](https://github.com/ljharb/qs) does. It's usually a simple\nconfig change to switch.)\n\nLet's consider an example to illustrate:\n\n```\n/images?filter[id][in][]=2\u0026filter[id][in][]=3\u0026filter[status]=open\u0026sort=name\u0026page[size]=10\n```\n\n```js\n{\n  filter: {\n    id: {\n      in: [2, 3],\n    },\n    status: 'open',\n  },\n  sort: 'name',\n  page: {\n    size: 10,\n  },\n}\n```\n\nTo support this query, QueryQL only requires you to define (whitelist) what's\nallowed through what we call a _querier_. Here's how one might look for the\n`/images` endpoint:\n\n```js\nconst QueryQL = require('@truepic/queryql')\n\nclass ImageQuerier extends QueryQL {\n  defineSchema(schema) {\n    schema.filter('id', 'in')\n    schema.filter('status', '=')\n    schema.sort('name')\n    schema.page()\n  }\n}\n```\n\nWith your querier defined, you can now call it in your router / controller.\nHere's how it might look in an Express route:\n\n```js\napp.get('/images', async (req, res, next) =\u003e {\n  const querier = new ImageQuerier(req.query, knex('images'))\n  let images\n\n  try {\n    images = await querier.run()\n  } catch (error) {\n    // Handle validation error, such as by passing to an Express error handler:\n    next(error)\n  }\n\n  res.send({ images })\n})\n```\n\nBehind-the-scenes, QueryQL takes your initial query builder (`knex('images')`),\nand applies the following Knex chain when `querier.run()` is called:\n\n```js\nbuilder\n  .where('id', 'in', [2, 3])\n  .where('status', '=', 'open')\n  .orderBy('name', 'asc')\n  .limit(10)\n  .offset(0)\n```\n\n(Remember: While Knex is our default adapter and the query builder used in this\nexample, adapters can be written for any query builder / ORM.)\n\nThis is a simple example, but hopefully it illustrates how easy it is to add\nfiltering, sorting, and pagination to your REST API _without_ manually touching\nyour query builder / ORM.\n\n[Read the full documentation](DOCS.md) to learn how to add validation, customize\nthe queries, and more.\n\n## Development\n\n### Prerequisites\n\nThe only prerequisite is a compatible version of Node.js (see `engines.node` in\n[`package.json`](package.json)).\n\n### Dependencies\n\nInstall dependencies with npm:\n\n```bash\nnpm install\n```\n\n### Tests\n\n[Jest](https://jestjs.io/) is our testing framework of choice. We strive for\n100% code coverage.\n\nTo run the tests:\n\n```bash\nnpm test\n```\n\nDuring development, it's recommended to run the tests automatically on file\nchange:\n\n```bash\nnpm test -- --watch [--notify]\n```\n\n### Code Style \u0026 Linting\n\n[Prettier](https://prettier.io/) is setup to enforce a consistent code style.\nIt's highly recommended to\n[add an integration to your editor](https://prettier.io/docs/en/editors.html)\nthat automatically formats on save.\n\n[ESLint](https://eslint.org/) is setup with the\n[\"recommended\" rules](https://eslint.org/docs/latest/rules/) to enforce a level\nof code quality. It's also highly recommended to\n[add an integration to your editor](https://eslint.org/docs/latest/use/integrations#editors)\nthat automatically formats on save.\n\nTo run via the command line:\n\n```bash\nnpm run lint\n```\n\n## Releasing\n\nWhen the `development` branch is ready for release,\n[Release It!](https://github.com/release-it/release-it) is used to orchestrate\nthe release process:\n\n```bash\nnpm run release\n```\n\nOnce the release process is complete, merge the `development` branch into the\n`main` branch, which should always reflect the latest release.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTRUEPIC%2Fqueryql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTRUEPIC%2Fqueryql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTRUEPIC%2Fqueryql/lists"}