{"id":38377477,"url":"https://github.com/wwwouter/typed-knex","last_synced_at":"2026-01-17T03:34:32.228Z","repository":{"id":33117542,"uuid":"129393049","full_name":"wwwouter/typed-knex","owner":"wwwouter","description":"A TypeScript wrapper for Knex.js","archived":false,"fork":false,"pushed_at":"2024-07-11T20:47:54.000Z","size":1567,"stargazers_count":112,"open_issues_count":14,"forks_count":13,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-12-27T02:22:46.741Z","etag":null,"topics":["knex","knexjs","orm","querybuilder","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/wwwouter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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":"2018-04-13T11:29:36.000Z","updated_at":"2025-12-13T12:49:58.000Z","dependencies_parsed_at":"2024-06-19T00:04:33.104Z","dependency_job_id":"c3599b2d-5e68-48bf-bc96-cbab457bd6cf","html_url":"https://github.com/wwwouter/typed-knex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wwwouter/typed-knex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwouter%2Ftyped-knex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwouter%2Ftyped-knex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwouter%2Ftyped-knex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwouter%2Ftyped-knex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wwwouter","download_url":"https://codeload.github.com/wwwouter/typed-knex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwouter%2Ftyped-knex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28493161,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T02:39:23.645Z","status":"ssl_error","status_checked_at":"2026-01-17T02:34:19.649Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["knex","knexjs","orm","querybuilder","typescript"],"created_at":"2026-01-17T03:34:32.155Z","updated_at":"2026-01-17T03:34:32.221Z","avatar_url":"https://github.com/wwwouter.png","language":"TypeScript","readme":"# Status of this module\n\nThis module is deprecated. I'm happy to say that in the last 8 years, a lot of good libraries have been created that help with type safety for sql queries. There is no real need anymore for this library, so it's deprecated.\n\nI recommend the following libraries:\n\n-   Knex.js with types.\n-   [Kysely](https://koskimas.github.io/kysely/index.html)\n-   [TypeORM](https://typeorm.io/#/)\n-   [Prisma](https://www.prisma.io/)\n-   [MikroORM](https://mikro-orm.io/)\n\n# typed-knex\n\n[![npm version](https://img.shields.io/npm/v/@wwwouter/typed-knex.svg)](https://www.npmjs.com/package/@wwwouter/typed-knex)\n[![Build Status](https://travis-ci.org/wwwouter/typed-knex.svg?branch=master)](https://travis-ci.org/wwwouter/typed-knex)\n\nStanding on the shoulders of [Knex.js](https://knexjs.org/), but now everything is typed!\n\n\u003e Goals:\n\u003e\n\u003e -   Be useful for 80% of the use cases, for the other 20% easily switch to lower-level Knex.js.\n\u003e -   Be as concise a possible.\n\u003e -   Mirror Knex.js as much a possible, with these exceptions:\n\u003e     -   Don't use `this`.\n\u003e     -   Be selective on what returns a `Promise` and what not.\n\u003e     -   Less overloading, which makes typings easier and code completion better.\n\u003e -   Get the most of the benefits TypeScript provides: type-checking of parameters, typed results, rename refactorings.\n\nInstall:\n\n    npm install @wwwouter/typed-knex\n\nMake sure experimentalDecorators and emitDecoratorMetadata are turned on in your tsconfig.json:\n\n```json\n{\n    \"compilerOptions\": {\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        ...\n    },\n    ...\n}\n```\n\n_Tested with Knex.js v2.2.0, TypeScript v4.7.4 and Node.js 14.x, 16.x, 18.x_\n\n# **Important upgrade notice**\n\nBecause TypeScript 4.1 supports template literal string types, the function syntax is no longer necessary. You can now use strings while maintaining type-safety. The function syntax is removed since version 4.\n\nTo help with the upgrade, you can run `npx typed-knex -u string-parameters` to automatically switch over to the string syntax.\n\n# Breaking changes in v4\n\n-   Because TypeScript 4.1 supports template literal string types, the function syntax is no longer necessary. You can now use strings while maintaining type-safety. The function syntax is removed.\n    Run `npx typed-knex -u string-parameters` to automatically upgrade.\n-   `.onColumn()` is deprecated. Use `.on()`. Remember that the columns switched eg `.onColumns(i=\u003ei.prop1, '=' j=\u003ej.prop2) should become .on(\"prop2\", '=', \"prop1\")`. Run `npx typed-knex -u join-on-columns-to-on` to automatically upgrade.\n-   The use of optional columns (`@Column() public nickName?: string;`) is deprecated. This was used to signal a nullable column. The correct way to do this is `@Column() public nickName: string | null;`.\n\n# Documentation\n\n## Quick example\n\nTo reference a column, use the name. Like this `.select(\"name\")` or this `.where(\"name\", \"Hejlsberg\")`\n\n```ts\nimport * as Knex from \"knex\";\nimport { TypedKnex } from \"@wwwouter/typed-knex\";\n\nconst knex = Knex({\n    client: \"pg\",\n    connection: \"postgres://user:pass@localhost:5432/dbname\",\n});\n\nasync function example() {\n    const typedKnex = new TypedKnex(knex);\n\n    const query = typedKnex.query(User).innerJoin(\"category\", UserCategory, \"id\", \"=\", \"categoryId\").where(\"name\", \"Hejlsberg\").select(\"id\", \"category.name\");\n\n    const oneUser = await query.getSingle();\n\n    console.log(oneUser.id); // Ok\n    console.log(oneUser.category.name); // Ok\n    console.log(oneUser.name); // Compilation error\n}\n```\n\n## Define tables\n\nUse the `Table` decorator to reference a table and use the `Column` decorator to reference a column.\n\nUse `@Column({ primary: true })` for primary key columns.\n\nUse `@Column({ name: '[column name]' })` on property with the type of another `Table` to reference another table.\n\n```ts\nimport { Column, Table } from \"@wwwouter/typed-knex\";\n\n@Table(\"userCategories\")\nexport class UserCategory {\n    @Column({ primary: true })\n    public id: string;\n    @Column()\n    public name: string;\n    @Column()\n    public year: number;\n}\n\n@Table(\"users\")\nexport class User {\n    @Column({ primary: true })\n    public id: string;\n    @Column()\n    public name: string;\n    @Column()\n    public categoryId: string;\n    @Column({ name: \"categoryId\" })\n    public category: UserCategory;\n    @Column()\n    public someNullableValue: string | null;\n}\n```\n\n## Create instance\n\n```ts\nimport * as Knex from \"knex\";\nimport { TypedKnex } from \"@wwwouter/typed-knex\";\n\nconst knex = Knex({\n    client: \"pg\",\n    connection: \"postgres://user:pass@localhost:5432/dbname\",\n});\n\nconst typedKnex = new TypedKnex(knex);\n```\n\n## Helper\n\n-   [getTableName](#getTableName)\n-   [getColumnName](#getColumnName)\n-   [registerBeforeInsertTransform](#registerBeforeInsertTransform)\n-   [registerBeforeUpdateTransform](#registerBeforeUpdateTransform)\n-   [validateTables](#validateTables)\n\n## Querybuilder\n\n### General\n\n-   [query](#query)\n-   [transacting](#transacting)\n-   [toQuery](#toQuery)\n-   [useKnexQueryBuilder](#useKnexQueryBuilder)\n-   [getKnexQueryBuilder](#getKnexQueryBuilder)\n-   [keepFlat](#keepFlat)\n-   [getColumnAlias](#getColumnAlias)\n\n### Getting the results (Promises)\n\n-   [findByPrimaryKey](#findByPrimaryKey) _deprecated_\n-   [getFirstOrNull](#getFirstOrNull)\n-   [getFirstOrUndefined](#getFirstOrUndefined)\n-   [getFirst](#getFirst)\n-   [getSingleOrNull](#getSingleOrNull)\n-   [getSingleOrUndefined](#getSingleOrUndefined)\n-   [getSingle](#getSingle)\n-   [getMany](#getMany)\n-   [getCount](#getCount)\n-   [insertItem](#insertItem)\n-   [insertItemWithReturning](#insertItemWithReturning)\n-   [insertItems](#insertItems)\n-   [insertSelect](#insertSelect)\n-   [del](#del)\n-   [delByPrimaryKey](#delByPrimaryKey) _deprecated_\n-   [updateItem](#updateItem)\n-   [updateItemWithReturning](#updateItemWithReturning)\n-   [updateItemByPrimaryKey](#updateItemByPrimaryKey) _deprecated_\n-   [updateItemsByPrimaryKey](#updateItemsByPrimaryKey) _deprecated_\n-   [execute](#execute)\n\n### Building the query\n\n-   [select](#select)\n-   [where](#where)\n-   [andWhere](#andWhere)\n-   [orWhere](#orWhere)\n-   [whereNot](#whereNot)\n-   [whereColumn](#whereColumn)\n-   [whereNull](#whereNull)\n-   [orWhereNull](#orWhereNull)\n-   [whereNotNull](#whereNotNull)\n-   [orWhereNotNull](#orWhereNotNull)\n-   [orderBy](#orderBy)\n-   [orderByRaw](#orderByRaw)\n-   [innerJoinColumn](#innerJoinColumn)\n-   [innerJoin](#innerJoin)\n-   [innerJoinTableOnFunction](#innerJoinTableOnFunction)\n-   [leftOuterJoin](#leftOuterJoin)\n-   [leftOuterJoinColumn](#leftOuterJoinColumn)\n-   [leftOuterJoinTableOnFunction](#leftOuterJoinTableOnFunction)\n-   [selectRaw](#selectRaw)\n-   [selectQuery](#selectQuery)\n-   [whereIn](#whereIn)\n-   [whereNotIn](#whereNotIn)\n-   [orWhereIn](#orWhereIn)\n-   [orWhereNotIn](#orWhereNotIn)\n-   [whereBetween](#whereBetween)\n-   [whereNotBetween](#whereNotBetween)\n-   [orWhereBetween](#orWhereBetween)\n-   [orWhereNotBetween](#orWhereNotBetween)\n-   [whereExists](#whereExists)\n-   [orWhereExists](#orWhereExists)\n-   [whereNotExists](#whereNotExists)\n-   [orWhereNotExists](#orWhereNotExists)\n-   [whereParentheses](#whereParentheses)\n-   [groupBy](#groupBy)\n-   [having](#having)\n-   [havingNull](#havingNull)\n-   [havingNotNull](#havingNotNull)\n-   [havingIn](#havingIn)\n-   [havingNotIn](#havingNotIn)\n-   [havingExists](#havingExists)\n-   [havingNotExists](#havingNotExists)\n-   [havingBetween](#havingBetween)\n-   [havingNotBetween](#havingNotBetween)\n-   [union](#union)\n-   [unionAll](#unionAll)\n-   [min](#min)\n-   [count](#count)\n-   [countDistinct](#countDistinct)\n-   [max](#max)\n-   [sum](#sum)\n-   [sumDistinct](#sumDistinct)\n-   [avg](#avg)\n-   [avgDistinct](#avgDistinct)\n-   [clearSelect](#clearSelect)\n-   [clearWhere](#clearWhere)\n-   [clearOrder](#clearOrder)\n-   [limit](#limit)\n-   [offset](#offset)\n-   [whereRaw](#whereRaw)\n-   [havingRaw](#havingRaw)\n-   [truncate](#truncate)\n-   [distinct](#distinct)\n-   [distinctOn](#distinctOn)\n-   [clone](#clone)\n-   [groupByRaw](#groupByRaw)\n\n### getTableName\n\n```ts\nconst tableName = getTableName(User);\n\n// tableName = 'users'\n```\n\n### getColumnName\n\n```ts\nconst columnName = getColumnName(User, \"id\");\n\n// columnName = 'id'\n```\n\n### registerBeforeInsertTransform\n\nHook that is run before doing an insert. Execute this function as soon as possible. For example at the top of `index.ts` or `server.ts`.\n\n```\nregisterBeforeInsertTransform((item: any, typedQueryBuilder: ITypedQueryBuilder\u003c{}, {}, {}\u003e) =\u003e {\n    if (typedQueryBuilder.columns.find(column =\u003e column.name === 'created_at') \u0026\u0026 !item.hasOwnProperty('created_at')) {\n        item.created_at = new Date();\n    }\n    if (typedQueryBuilder.columns.find(column =\u003e column.name === 'updated_at') \u0026\u0026 !item.hasOwnProperty('updated_at')) {\n        item.updated_at = new Date();\n    }\n    if (typedQueryBuilder.columns.find(column =\u003e column.name === 'id') \u0026\u0026 !item.hasOwnProperty('id')) {\n        item.id = guid();\n    }\n    return item;\n});\n```\n\n### registerBeforeUpdateTransform\n\nHook that is run before doing an update. Execute this function as soon as possible. For example at the top of `index.ts` or `server.ts`.\n\n```\nregisterBeforeUpdateTransform((item: any, typedQueryBuilder: ITypedQueryBuilder\u003c{}, {}, {}\u003e) =\u003e {\n    if (typedQueryBuilder.columns.find(\"name\" === 'updated_at') \u0026\u0026 !item.hasOwnProperty('updated_at')) {\n        item.updated_at = new Date();\n    }\n    return item;\n});\n```\n\n### query\n\nUse `typedKnex.query(Type)` to create a query for the table referenced by `Type`\n\n```ts\nconst query = typedKnex.query(User);\n```\n\n### getColumnAlias\n\nUse `getColumnAlias` to get the underlying alias of a column, to use in a `raw` function.\n\n```ts\nconst query = typedKnex.query(UserCategory);\nquery.selectRaw(\"hash\", String, `hashFunction(${query.getColumnAlias(\"name\")})`).select(\"id\");\n\n// select (hashFunction(\"userCategories\".\"name\")) as \"hash\", \"userCategories\".\"id\" as \"id\" from \"userCategories\"\n```\n\n### select\n\nhttps://knexjs.org/guide/query-builder.html#select\n\n```ts\ntypedKnex.query(User).select(\"id\");\n```\n\n```ts\ntypedKnex.query(User).select(\"id\", \"name\");\n```\n\n### where\n\nhttps://knexjs.org/guide/query-builder.html#where\n\n```ts\ntypedKnex.query(User).where(\"name\", \"name\");\n```\n\nOr with operator\n\n```ts\ntypedKnex.query(User).where(\"name\", \"like\", \"%user%\");\n\n// select * from \"users\" where \"users\".\"name\" like '%user%'\n```\n\n### andWhere\n\n```ts\ntypedKnex.query(User).where(\"name\", \"name\").andWhere(\"name\", \"name\");\n```\n\n```ts\ntypedKnex.query(User).where(\"name\", \"name\").andWhere(\"name\", \"like\", \"%na%\");\n```\n\n### orWhere\n\n```ts\ntypedKnex.query(User).where(\"name\", \"name\").orWhere(\"name\", \"name\");\n```\n\n```ts\ntypedKnex.query(User).where(\"name\", \"name\").orWhere(\"name\", \"like\", \"%na%\");\n```\n\n### whereNot\n\nhttps://knexjs.org/guide/query-builder.html#wherenot\n\n```ts\ntypedKnex.query(User).whereNot(\"name\", \"name\");\n```\n\n### whereColumn\n\nTo use in subqueries. First parameter is for sub query columns and the third parameter is for columns from the parent query.\n\n```ts\ntypedKnex.query(User).whereNotExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\nUse `getColumn` when nesting\n\n```ts\nquery.whereExists(User, (subQuery1) =\u003e {\n    subQuery1.whereColumn(\"status\", \"=\", \"status\"); // Compares subQuery1 with its parent (query).\n\n    subQuery1.whereExists(User, (subQuery2) =\u003e {\n        subQuery2.whereColumn(subQuery2.getColumn(\"status\"), \"=\", query.getColumn(\"status\")); // Compares subQuery2 with the first parent (query)\n\n        subQuery2.whereExists(User, (subQuery3) =\u003e {\n            subQuery3.whereColumn(subQuery3.getColumn(\"status\"), \"=\", subQuery1.getColumn(\"status\")); // Compares subQuery3 with the second parent (subQuery1)\n        });\n    });\n});\n```\n\n### whereNull\n\n```ts\ntypedKnex.query(User).whereNull(\"name\");\n```\n\n### orWhereNull\n\n```ts\ntypedKnex.query(User).whereNull(\"name\").orWhereNull(\"name\");\n```\n\n### whereNotNull\n\n```ts\ntypedKnex.query(User).whereNotNull(\"name\");\n```\n\n### orWhereNotNull\n\n```ts\ntypedKnex.query(User).whereNotNull(\"name\").orWhereNotNull(\"name\");\n```\n\n### orderBy\n\n```ts\ntypedKnex.query(User).orderBy(\"id\");\n```\n\n### orderByRaw\n\n```ts\nawait typedKnex.query(User).orderByRaw(\"SUM(??) DESC\", \"users.year\");\n\n//  select * from \"users\" order by SUM(\"users\".\"year\") DESC\n```\n\n### innerJoin\n\n```ts\ntypedKnex.query(User).innerJoin(\"category\", UserCategory, \"id\", \"=\", \"categoryId\");\n\n// select * from \"users\" inner join \"userCategories\" as \"category\" on \"category\".\"id\" = \"users\".\"categoryId\"\n```\n\n### innerJoinColumn\n\n```ts\ntypedKnex.query(User).innerJoinColumn(\"category\");\n```\n\n### innerJoinTableOnFunction\n\n```ts\ntypedKnex.query(User).innerJoinTableOnFunction(\"evilTwin\", User, (join) =\u003e {\n    join.on(\"id\", \"=\", \"id\").andOn(\"name\", \"=\", \"id\").orOn(\"someValue\", \"=\", \"id\").onVal(\"name\", \"=\", \"1\").andOnVal(\"name\", \"=\", \"2\").orOnVal(\"name\", \"=\", \"3\").onNull(\"name\");\n});\n```\n\n### leftOuterJoin\n\n```ts\ntypedKnex.query(User).leftOuterJoin(\"category\", UserCategory, \"id\", \"=\", \"categoryId\");\n\n// select * from \"users\" left outer join \"userCategories\" as \"category\" on \"category\".\"id\" = \"users\".\"categoryId\"\n```\n\n### leftOuterJoinColumn\n\n```ts\ntypedKnex.query(User).leftOuterJoinColumn(\"category\");\n```\n\n### leftOuterJoinTableOnFunction\n\n```ts\ntypedKnex.query(User).leftOuterJoinTableOnFunction(\"evilTwin\", User, (join) =\u003e {\n    join.on(\"id\", \"=\", \"id\").andOn(\"name\", \"=\", \"id\").orOn(\"someValue\", \"=\", \"id\").onVal(\"name\", \"=\", \"1\").andOnVal(\"name\", \"=\", \"2\").orOnVal(\"name\", \"=\", \"3\").onNull(\"name\");\n});\n```\n\n### selectRaw\n\n```ts\ntypedKnex.query(User).selectRaw(\"otherId\", Number, \"select other.id from other\");\n```\n\n### selectQuery\n\n```ts\ntypedKnex\n    .query(UserCategory)\n    .select(\"id\")\n    .selectQuery(\"total\", Number, User, (subQuery) =\u003e {\n        subQuery.count(\"id\", \"total\").whereColumn(\"categoryId\", \"=\", \"id\");\n    });\n```\n\n```sql\nselect \"userCategories\".\"id\" as \"id\", (select count(\"users\".\"id\") as \"total\" from \"users\" where \"users\".\"categoryId\" = \"userCategories\".\"id\") as \"total\" from \"userCategories\"\n```\n\n### findByPrimaryKey\n\n_deprecated_\n\n```ts\nconst user = await typedKnex.query(User).findByPrimaryKey(\"id\", \"d\", \"name\");\n```\n\n### whereIn\n\n```ts\ntypedKnex.query(User).whereIn(\"name\", [\"user1\", \"user2\"]);\n```\n\n### whereNotIn\n\n```ts\ntypedKnex.query(User).whereNotIn(\"name\", [\"user1\", \"user2\"]);\n```\n\n### orWhereIn\n\n```ts\ntypedKnex.query(User).whereIn(\"name\", [\"user1\", \"user2\"]).orWhereIn(\"name\", [\"user3\", \"user4\"]);\n```\n\n### orWhereNotIn\n\n```ts\ntypedKnex.query(User).whereIn(\"name\", [\"user1\", \"user2\"]).orWhereNotIn(\"name\", [\"user3\", \"user4\"]);\n```\n\n### whereBetween\n\n```ts\ntypedKnex.query(UserCategory).whereBetween(\"year\", [1, 2037]);\n```\n\n### whereNotBetween\n\n```ts\ntypedKnex.query(User).whereNotBetween(\"year\", [1, 2037]);\n```\n\n### orWhereBetween\n\n```ts\ntypedKnex.query(User).whereBetween(\"year\", [1, 10]).orWhereBetween(\"year\", [100, 1000]);\n```\n\n### orWhereNotBetween\n\n```ts\ntypedKnex.query(User).whereBetween(\"year\", [1, 10]).orWhereNotBetween(\"year\", [100, 1000]);\n```\n\n### whereExists\n\n```ts\ntypedKnex.query(User).whereExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\n### orWhereExists\n\n```ts\ntypedKnex.query(User).orWhereExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\n### whereNotExists\n\n```ts\ntypedKnex.query(User).whereNotExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\n### orWhereNotExists\n\n```ts\ntypedKnex.query(User).orWhereNotExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\n### whereParentheses\n\n```ts\ntypedKnex\n    .query(User)\n    .whereParentheses((sub) =\u003e sub.where(\"id\", \"1\").orWhere(\"id\", \"2\"))\n    .orWhere(\"name\", \"Tester\");\n\nconst queryString = query.toQuery();\nconsole.log(queryString);\n```\n\nOutputs:\n\n```sql\nselect * from \"users\" where (\"users\".\"id\" = '1' or \"users\".\"id\" = '2') or \"users\".\"name\" = 'Tester'\n```\n\n### groupBy\n\n```ts\ntypedKnex.query(User).select(\"someValue\").selectRaw(\"total\", Number, 'SUM(\"numericValue\")').groupBy(\"someValue\");\n```\n\n### having\n\n```ts\ntypedKnex.query(User).having(\"numericValue\", \"\u003e\", 10);\n```\n\n### havingNull\n\n```ts\ntypedKnex.query(User).havingNull(\"numericValue\");\n```\n\n### havingNotNull\n\n```ts\ntypedKnex.query(User).havingNotNull(\"numericValue\");\n```\n\n### havingIn\n\n```ts\ntypedKnex.query(User).havingIn(\"name\", [\"user1\", \"user2\"]);\n```\n\n### havingNotIn\n\n```ts\ntypedKnex.query(User).havingNotIn(\"name\", [\"user1\", \"user2\"]);\n```\n\n### havingExists\n\n```ts\ntypedKnex.query(User).havingExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\n### havingNotExists\n\n```ts\ntypedKnex.query(User).havingNotExists(UserSetting, (subQuery) =\u003e {\n    subQuery.whereColumn(\"userId\", \"=\", \"id\");\n});\n```\n\n### havingBetween\n\n```ts\ntypedKnex.query(User).havingBetween(\"numericValue\", [1, 10]);\n```\n\n### havingNotBetween\n\n```ts\ntypedKnex.query(User).havingNotBetween(\"numericValue\", [1, 10]);\n```\n\n### union\n\n```ts\ntypedKnex.query(User).union(User, (subQuery) =\u003e {\n    subQuery.select(\"id\").where(\"numericValue\", 12);\n});\n```\n\n### unionAll\n\n```ts\ntypedKnex\n    .query(User)\n    .select(\"id\")\n    .unionAll(User, (subQuery) =\u003e {\n        subQuery.select(\"id\").where(\"numericValue\", 12);\n    });\n```\n\n### min\n\n```ts\ntypedKnex.query(User).min(\"numericValue\", \"minNumericValue\");\n```\n\n### count\n\n```ts\ntypedKnex.query(User).count(\"numericValue\", \"countNumericValue\");\n```\n\n### countDistinct\n\n```ts\ntypedKnex.query(User).countDistinct(\"numericValue\", \"countDistinctNumericValue\");\n```\n\n### max\n\n```ts\ntypedKnex.query(User).max(\"numericValue\", \"maxNumericValue\");\n```\n\n### sum\n\n```ts\ntypedKnex.query(User).sum(\"numericValue\", \"sumNumericValue\");\n```\n\n### sumDistinct\n\n```ts\ntypedKnex.query(User).sumDistinct(\"numericValue\", \"sumDistinctNumericValue\");\n```\n\n### avg\n\n```ts\ntypedKnex.query(User).avg(\"numericValue\", \"avgNumericValue\");\n```\n\n### avgDistinct\n\n```ts\ntypedKnex.query(User).avgDistinct(\"numericValue\", \"avgDistinctNumericValue\");\n```\n\n### clearSelect\n\n```ts\ntypedKnex.query(User).select(\"id\").clearSelect().select(\"name\");\n```\n\n### clearWhere\n\n```ts\ntypedKnex\n    .query(User)\n    .where(\"id\", \"name\")\n    .clearWhere()\n    .where((\"name\", \"name\");\n```\n\n### clearOrder\n\n```ts\ntypedKnex\n    .query(User)\n    .orderBy(\"id\")\n    .clearOrder()\n    .orderBy((\"name\");\n```\n\n### limit\n\n```ts\ntypedKnex.query(User).limit(10);\n```\n\n### offset\n\n```ts\ntypedKnex.query(User).offset(10);\n```\n\n### useKnexQueryBuilder\n\nUse `useKnexQueryBuilder` to get to the underlying Knex.js query builder.\n\n```ts\nconst query = typedKnex.query(User)\n    .useKnexQueryBuilder(queryBuilder =\u003e queryBuilder.where('somethingelse', 'value'))\n    .select(\"name\");\n);\n```\n\n### getKnexQueryBuilder\n\nUse `getKnexQueryBuilder` to get to the underlying Knex.js query builder.\n\n```ts\nconst query = typedKnex.query(User).select(\"name\");\nconst knexQuery = query.getKnexQueryBuilder();\nqueryBuilder.where(\"somethingelse\", \"value\");\n```\n\n### keepFlat\n\nUse `keepFlat` to prevent unflattening of the result.\n\n```ts\nconst item = await typedKnex\n    .query(User)\n    .where(\"name\", 'name')\n    .innerJoinColumn(\"category\");\n    .select(\"name\", \"category.name\")\n    .getFirst();\n\n// returns { name: 'user name', category: { name: 'category name' }}\n\nconst item = await typedKnex\n    .query(User)\n    .where(\"name\", 'name')\n    .innerJoinColumn(\"category\");\n    .select(\"name\", \"category.name\")\n    .keepFlat()\n    .getFirst();\n\n// returns { name: 'user name', category.name: 'category name' }\n```\n\n### toQuery\n\n```ts\nconst query = typedKnex.query(User);\n\nconsole.log(query.toQuery()); // select * from \"users\"\n```\n\n### getFirstOrNull\n\n| Result                 | No item     | One item | Many items |\n| ---------------------- | ----------- | -------- | ---------- |\n| `getFirst`             | `Error`     | Item     | First item |\n| `getSingle`            | `Error`     | Item     | `Error`    |\n| `getFirstOrNull`       | `null`      | Item     | First item |\n| `getSingleOrNull`      | `null`      | Item     | `Error`    |\n| `getFirstOrUndefined`  | `undefined` | Item     | First item |\n| `getSingleOrUndefined` | `undefined` | Item     | `Error`    |\n\n```ts\nconst user = await typedKnex.query(User).where(\"name\", \"name\").getFirstOrNull();\n```\n\n### getFirstOrUndefined\n\n| Result                 | No item     | One item | Many items |\n| ---------------------- | ----------- | -------- | ---------- |\n| `getFirst`             | `Error`     | Item     | First item |\n| `getSingle`            | `Error`     | Item     | `Error`    |\n| `getFirstOrNull`       | `null`      | Item     | First item |\n| `getSingleOrNull`      | `null`      | Item     | `Error`    |\n| `getFirstOrUndefined`  | `undefined` | Item     | First item |\n| `getSingleOrUndefined` | `undefined` | Item     | `Error`    |\n\n```ts\nconst user = await typedKnex.query(User).where(\"name\", \"name\").getFirstOrUndefined();\n```\n\n### getFirst\n\n| Result                 | No item     | One item | Many items |\n| ---------------------- | ----------- | -------- | ---------- |\n| `getFirst`             | `Error`     | Item     | First item |\n| `getSingle`            | `Error`     | Item     | `Error`    |\n| `getFirstOrNull`       | `null`      | Item     | First item |\n| `getSingleOrNull`      | `null`      | Item     | `Error`    |\n| `getFirstOrUndefined`  | `undefined` | Item     | First item |\n| `getSingleOrUndefined` | `undefined` | Item     | `Error`    |\n\n```ts\nconst user = await typedKnex.query(User).where(\"name\", \"name\").getFirst();\n```\n\n### getSingleOrNull\n\n| Result                 | No item     | One item | Many items |\n| ---------------------- | ----------- | -------- | ---------- |\n| `getFirst`             | `Error`     | Item     | First item |\n| `getSingle`            | `Error`     | Item     | `Error`    |\n| `getFirstOrNull`       | `null`      | Item     | First item |\n| `getSingleOrNull`      | `null`      | Item     | `Error`    |\n| `getFirstOrUndefined`  | `undefined` | Item     | First item |\n| `getSingleOrUndefined` | `undefined` | Item     | `Error`    |\n\n```ts\nconst user = await typedKnex.query(User).where(\"name\", \"name\").getSingleOrNull();\n```\n\n### getSingleOrUndefined\n\n| Result                 | No item     | One item | Many items |\n| ---------------------- | ----------- | -------- | ---------- |\n| `getFirst`             | `Error`     | Item     | First item |\n| `getSingle`            | `Error`     | Item     | `Error`    |\n| `getFirstOrNull`       | `null`      | Item     | First item |\n| `getSingleOrNull`      | `null`      | Item     | `Error`    |\n| `getFirstOrUndefined`  | `undefined` | Item     | First item |\n| `getSingleOrUndefined` | `undefined` | Item     | `Error`    |\n\n```ts\nconst user = await typedKnex.query(User).where(\"name\", \"name\").getSingleOrUndefined();\n```\n\n### getSingle\n\n| Result                 | No item     | One item | Many items |\n| ---------------------- | ----------- | -------- | ---------- |\n| `getFirst`             | `Error`     | Item     | First item |\n| `getSingle`            | `Error`     | Item     | `Error`    |\n| `getFirstOrNull`       | `null`      | Item     | First item |\n| `getSingleOrNull`      | `null`      | Item     | `Error`    |\n| `getFirstOrUndefined`  | `undefined` | Item     | First item |\n| `getSingleOrUndefined` | `undefined` | Item     | `Error`    |\n\n```ts\nconst user = await typedKnex.query(User).where(\"name\", \"name\").getSingle();\n```\n\n### getMany\n\n```ts\nconst users = await typedKnex.query(User).whereNotNull(\"name\").getMany();\n```\n\n### getCount\n\nReturns the row count of the query.\n\n```ts\nconst count = await typedKnex.query(User).getCount();\n```\n\nThe return type is `Promise\u003cnumber|string\u003e`. This follows the Knex.js typing, see the [count documentation](https://knexjs.org/guide/query-builder.html#count).\n\n\u003e The value of count will, by default, have type of string | number. This may be counter-intuitive but some connectors (eg. postgres) will automatically cast BigInt result to string when javascript's Number type is not large enough for the value.\n\nThe return type can be changed by overriding the `ITypedQueryBuilder` interface.\n\nDeclare as `number`:\n\n```typescript\ndeclare module \"@wwwouter/typed-knex\" {\n    interface ITypedQueryBuilder\u003cModel, SelectableModel, Row\u003e {\n        getCount(): Promise\u003cnumber\u003e;\n    }\n}\n```\n\nDeclare as `BigInt`:\n\n```typescript\ndeclare module \"@wwwouter/typed-knex\" {\n    interface ITypedQueryBuilder\u003cModel, SelectableModel, Row\u003e {\n        getCount(): Promise\u003cBigInt\u003e;\n    }\n}\n```\n\nWhen using Postgres, `pg.types.setTypeParser` can be used to automatically convert the values.\n\nTo convert to `integer`, use this code:\n\n```typescript\npg.types.setTypeParser(20, \"text\", parseInt);\n```\n\nTo convert to `bigint`, use this code:\n\n```typescript\npg.types.setTypeParser(20, \"text\", BigInt);\n```\n\n### insertItem\n\n```ts\ntypedKnex.query(User);\n```\n\n### insertItemWithReturning\n\n```ts\nquery.insertItemWithReturning({ id: \"newId\" });\n\n// insert into \"users\" (\"id\") values ('newId') returning *\n```\n\n```ts\nquery.insertItemWithReturning({ id: \"newId\" }, [\"id\"]);\n\n// insert into \"users\" (\"id\") values ('newId') returning \"users\".\"id\"\n```\n\n### insertItems\n\n```ts\ntypedKnex.query(User);\n```\n\n### insertSelect\n\n```ts\nawait typedKnex.query(User);\n    .selectRaw('f', String, '\\'fixedValue\\'')\n    .select(\"name\")\n    .distinct()\n    .whereNotNull(\"name\")\n    .insertSelect(UserSetting, \"id\", \"initialValue\");\n\n// insert into \"userSettings\" (\"userSettings\".\"id\",\"userSettings\".\"initialValue\") select distinct ('fixedValue') as \"f\", \"users\".\"name\" as \"name\" from \"users\" where \"users\".\"name\" is not null\n```\n\n### del\n\n```ts\ntypedKnex.query(User);\n```\n\n### delByPrimaryKey\n\n_deprecated_\n\n```ts\ntypedKnex.query(User);\n```\n\n### updateItem\n\n```ts\ntypedKnex.query(User);\n```\n\n### updateItemWithReturning\n\n```ts\nquery.updateItemWithReturning({ id: \"newId\" });\n\n// update \"users\" set \"id\" = 'newId' returning *\n```\n\n```ts\nquery.updateItemWithReturning({ id: \"newId\" }, [\"id\"]);\n\n// update \"users\" set \"id\" = 'newId' returning \"users\".\"id\"\n```\n\n### updateItemByPrimaryKey\n\n_deprecated_\n\n```ts\ntypedKnex.query(User);\n```\n\n### updateItemsByPrimaryKey\n\n_deprecated_\n\n```ts\ntypedKnex.query(User);\n```\n\n### execute\n\n```ts\ntypedKnex.query(User);\n```\n\n### whereRaw\n\n```ts\ntypedKnex.query(User);\n```\n\n### havingRaw\n\n```ts\ntypedKnex.query(User);\n```\n\n### transacting\n\n```ts\nconst typedKnex = new TypedKnex(database);\nconst transaction = await typedKnex.beginTransaction();\ntry {\n    await typedKnex.query(User).transacting(transaction).insertItem(user1);\n    await typedKnex.query(User).transacting(transaction).insertItem(user2);\n    await transaction.commit();\n} catch (error) {\n    await transaction.rollback();\n    // handle error\n}\n```\n\n### truncate\n\n```ts\ntypedKnex.query(User);\n```\n\n### distinct\n\n```ts\ntypedKnex.query(User);\n```\n\n### distinctOn\n\n```ts\ntypedKnex.query(UserCategory).select(\"id\").distinctOn([\"name\"]);\n\n// select distinct on (\"userCategories\".\"name\") \"userCategories\".\"id\" as \"id\" from \"userCategories\"\n```\n\n### clone\n\n```ts\ntypedKnex.query(User);\n```\n\n### groupByRaw\n\n```ts\ntypedKnex.query(User);\n```\n\n## Transactions\n\n```ts\nconst typedKnex = new TypedKnex(database);\nconst transaction = await typedKnex.beginTransaction();\ntry {\n    await typedKnex.query(User).transacting(transaction).insertItem(user1);\n    await typedKnex.query(User).transacting(transaction).insertItem(user2);\n    await transaction.commit();\n} catch (error) {\n    await transaction.rollback();\n    // handle error\n}\n```\n\n## validateTables\n\nUse the `validateTables` function to make sure that the `Table`'s and `Column`'s in TypeScript exist in the database.\n\n```ts\nimport * as Knex from \"knex\";\nimport { validateTables } from \"@wwwouter/typed-knex\";\n\nconst knex = Knex({\n    client: \"pg\",\n    connection: \"postgres://user:pass@localhost:5432/dbname\",\n});\n\nawait validateTables(knex);\n```\n\nAdd an array of table names to the `validateTables` function to only validate those tables.\n\n```ts\nimport * as Knex from \"knex\";\nimport { validateTables } from \"@wwwouter/typed-knex\";\n\nconst knex = Knex({\n    client: \"pg\",\n    connection: \"postgres://user:pass@localhost:5432/dbname\",\n});\n\nawait validateTables(knex, [\"users\"]);\n```\n\n## Test\n\n    npm test\n\n## Update version\n\n    npm version major|minor|patch\n    update CHANGELOG.md\n    git commit --amend\n    npm publish --access=public --otp=CODE\n    git push\n\nfor beta\n\n    update version to x.x.x-beta.x\n    npm publish --access public --tag beta --otp=CODE\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwwwouter%2Ftyped-knex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwwwouter%2Ftyped-knex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwwwouter%2Ftyped-knex/lists"}