PageSourceSearch

https://kysely.dev/assets/js/3021cf83.665db948.js

js kysely.dev collected 2026-10-02 02:57:39 UTC 28,096 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkkysely_site=globalThis.webpackChunkkysely_site||[]).push([[2857],{1098(e,n,t){t.r(n),t.d(n,{assets:()=>ee,contentTitle:()=>Z,default:()=>se,frontMatter:()=>X,metadata:()=>s,toc:()=>ne});const s=JSON.parse('{"id":"getting-started","title":"Getting started","description":"Get started with Kysely: install the package, define database types, configure a dialect, and write your first type-safe SQL queries.","source":"@site/docs/getting-started.mdx","sourceDirName":".","slug":"/getting-started","permalink":"/docs/getting-started","draft":false,"unlisted":false,"editUrl":"https://github.com/kysely-org/kysely/tree/master/site/docs/getting-started.mdx","tags":[],"version":"current","sidebarPosition":2,"frontMatter":{"sidebar_position":2,"title":"Getting started","description":"Get started with Kysely: install the package, define database types, configure a dialect, and write your first type-safe SQL queries."},"sidebar":"tutorialSidebar","previous":{"title":"Introduction","permalink":"/docs/intro"},"next":{"title":"Execution flow","permalink":"/docs/execution"}}');var a=t(1058),r=t(4801);function i(e){const n={a:"a",code:"code",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://www.typescriptlang.org/",children:"TypeScript"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["Minimum supported version ",(0,a.jsx)(n.a,{href:"https://devblogs.microsoft.com/typescript/announcing-typescript-5.4",children:"5.4"}),"."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["For improved compilation performance, use version ",(0,a.jsx)(n.a,{href:"https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/#cache-instantiations-on-mappers",children:"5.9"})," or later."]}),"\n"]}),"\n",(0,a.jsxs)(n.li,{children:["\n",(0,a.jsxs)(n.p,{children:["You must enable ",(0,a.jsx)(n.code,{children:"strict"})," mode in your ",(0,a.jsx)(n.code,{children:"tsconfig.json"})," file's ",(0,a.jsx)(n.code,{children:"compilerOptions"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",metastring:'title="tsconfig.json"',children:'{\n  // ...\n  "compilerOptions": {\n    // ...\n    "strict": true\n    // ...\n  }\n  // ...\n}\n'})}),"\n"]}),"\n"]}),"\n"]}),"\n"]})}function o(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(i,{...e})}):i(e)}
1var l=t(8482),c=t(2451),d=t(9912),p=t(2394),u=t(577),m=t(3706),y=t(8330);const h=["postgresql","mysql","sqlite","mssql","pglite"],g="postgresql",f=["npm","pnpm","yarn","deno","bun"],b="npm",x={bun:["sqlite"],deno:["sqlite","mssql"],npm:[],pnpm:[],yarn:[]};function j(e,n){return!x[n].includes(e)}const w={postgresql:"PostgresDialect",mysql:"MysqlDialect",mssql:"MssqlDialect",sqlite:"SqliteDialect",pglite:"PGliteDialect"},v=(e="npm")=>({postgresql:"deno"===e?"pg-pool":"pg",mysql:"mysql2",mssql:"tedious",sqlite:"better-sqlite3",pglite:"@electric-sql/pglite"}),q={mssql:"tarn"},P={postgresql:"PostgreSQL",mysql:"MySQL",mssql:"Microsoft SQL Server (MSSQL)",sqlite:"SQLite",pglite:"PGlite"},k={npm:"npm",pnpm:"pnpm",yarn:"Yarn",deno:"Deno",bun:"Bun"},S={npm:"npm install",pnpm:"pnpm install",yarn:"yarn add",bun:"bun install"};function T(e,n,t){if("deno"===e)throw new Error("Deno has no bash command");return{content:`${S[e]} ${n}${t?.length?` ${t.join(" ")}`:""}`,intro:"Run the following command in your terminal:",language:"bash",title:"terminal"}}function D(e){return{content:JSON.stringify({imports:{kysely:`npm:kysely@^${y.rE}`,...e}},null,2),intro:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("strong",{children:"Your root "}),(0,a.jsx)("code",{children:"deno.json"}),(0,a.jsx)("strong",{children:'\'s "imports" field should include the following dependencies:'})]}),language:"json",title:"deno.json"}}function $(e){const{defaultValue:n,searchParam:t,validator:s,value:a}=e,[r,i]=(0,m.useState)(a||n),{search:o}=(0,u.zy)();return(0,m.useEffect)(function(){if(a||!t)return;const e=new URLSearchParams(o).get(t);null==e||e===r||s&&!s(e)||i(e)},[o]),(0,m.useEffect)(()=>{a&&a!==r&&i(a)},[a,r]),r}const I=()=>(0,a.jsx)(c.A,{to:"https://developer.mozilla.org/en-US/docs/Web/JavaScript",children:"JavaScript"}),A=()=>(0,a.jsx)(c.A,{to:"https://nodejs.org",children:"Node.js"}),K=[{value:"npm",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.A,{to:"https://npmjs.com",children:k.npm})," ","is the default package manager for ",(0,a.jsx)(A,{}),", and to where Kysely is published.",(0,a.jsx)("br",{}),"Your project is using ",k.npm," if it has a"," ",(0,a.jsx)("code",{children:"package-lock.json"})," file in its root folder."]}),command:T("npm","kysely")},{value:"pnpm",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.A,{to:"https://pnpm.io",children:k.pnpm})," is a fast, disk space efficient package manager for ",(0,a.jsx)(A,{}),".",(0,a.jsx)("br",{}),"Your project is using ",k.pnpm," if it has a"," ",(0,a.jsx)("code",{children:"pnpm-lock.yaml"})," file in its root folder."]}),command:T("pnpm","kysely")},{value:"yarn",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.A,{to:"https://yarnpkg.com",children:k.yarn})," ","is a fast, reliable and secure dependency manager for ",(0,a.jsx)(A,{}),".",(0,a.jsx)("br",{}),"Your project is using ",k.yarn," if it has a"," ",(0,a.jsx)("code",{children:"yarn.lock"})," file in its root folder."]}),command:T("yarn","kysely")},{value:"deno",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.A,{to:"https://deno.com/runtime",children:k.deno})," ","is a secure runtime for ",(0,a.jsx)(I,{})," and"," ",(0,a.jsx)(c.A,{to:"https://www.typescriptlang.org",children:"TypeScript"}),"."]}),command:D()},{value:"bun",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.A,{to:"https://bun.sh",children:k.bun})," is a new ",(0,a.jsx)(I,{})," runtime built for speed, with a native bundler, transpiler, test runner, and ",k.npm,"-compatible package manager baked-in."]}),command:T("bun","kysely")}];function C(){return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Kysely can be installed using any of the following package managers:"}),(0,a.jsx)(d.A,{queryString:"package-manager",children:K.map(({command:e,value:n,...t})=>(0,a.jsxs)(p.A,{value:n,label:k[n],children:[(0,a.jsx)("p",{children:t.description}),(0,a.jsx)("p",{children:(0,a.jsx)("strong",{children:e.intro})}),(0,a.jsx)(l.A,{language:e.language,title:e.title,children:e.content})]},n))})]})}function _(e){const n={a:"a",admonition:"admonition",code:"code",p:"p",pre:"pre",strong:"strong",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(n.p,{children:["For Kysely's type-safety and autocompletion to work, it needs to know y
1our\ndatabase structure. This requires a TypeScript ",(0,a.jsx)("code",{children:"Database"}),"\ninterface, that contains table names as keys and table schema interfaces as\nvalues."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Let's define our first database interface:"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-ts",metastring:'title="src/types.ts"',children:"import {\n  ColumnType,\n  Generated,\n  Insertable,\n  JSONColumnType,\n  Selectable,\n  Updateable,\n} from 'kysely'\n\nexport interface Database {\n  person: PersonTable\n  pet: PetTable\n}\n\n// This interface describes the `person` table to Kysely. Table\n// interfaces should only be used in the `Database` type above\n// and never as a result type of a query!. See the `Person`,\n// `NewPerson` and `PersonUpdate` types below.\nexport interface PersonTable {\n  // Columns that are generated by the database should be marked\n  // using the `Generated` type. This way they are automatically\n  // made optional in inserts and updates.\
1n  id: Generated<number>\n\n  first_name: string\n  gender: 'man' | 'woman' | 'other'\n\n  // If the column is nullable in the database, make its type nullable.\n  // Don't use optional properties. Optionality is always determined\n  // automatically by Kysely.\n  last_name: string | null\n\n  // You can specify a different type for each operation (select, insert and\n  // update) using the `ColumnType<SelectType, InsertType, UpdateType>`\n  // wrapper. Here we define a column `created_at` that is selected as\n  // a `Date`, can optionally be provided as a `string` in inserts and\n  // can never be updated:\n  created_at: ColumnType<Date, string | undefined, never>\n\n  // You can specify JSON columns using the `JSONColumnType` wrapper.\n  // It is a shorthand for `ColumnType<T, string, string>`, where T\n  // is the type of the JSON object/array retrieved from the database,\n  // and the insert and update types are always `string` since you're\n  // always stringifying insert/update values.\n  metadata: JSONColumnType<{\n    login_at: string\n    ip: string | null\n    agent: string | null\n    plan: 'free' | 'premium'\n  }>\n}\n\n// You should not use the table schema interfaces directly. Instead, you should\n// use the `Selectable`, `Insertable` and `Updateable` wrappers. These wrappers\n// make sure that the correct types are used in each operation.\n//\n// Most of the time you should trust the type inference and not use explicit\n// types at all. These types can be useful when typing function arguments.\nexport type Person = Selectable<PersonTable>\nexport type NewPerson = Insertable<PersonTable>\nexport type PersonUpdate = Updateable<PersonTable>\n\nexport interface PetTable {\n  id: Generated<number>\n  name: string\n  owner_id: number\n  species: 'dog' | 'cat'\n}\n\nexport type Pet = Selectable<PetTable>\nexport type NewPet = Insertable<PetTable>\nexport type PetUpdate = Updateable<PetTable>\n"})}),"\n",(0,a.jsx)(n.admonition,{title:"Codegen",type:"tip",children:(0,a.jsxs)(n.p,{children:["For production apps, it is recommended to automatically generate your ",(0,a.jsx)("code",{children:"Database"}),"\ninterface by introspecting your production database or Prisma schemas. Generated types\nmight differ in naming convention, internal order, etc. Find out more at ",(0,a.jsx)(n.a,{href:"https://kysely.dev/docs/generating-types",children:'"Generating types"'}),"."]})}),"\n",(0,a.jsx)(n.admonition,{title:"Runtime types",type:"info",children:(0,a.jsxs)(n.p,{children:["Kysely only deals with types in the TypeScript level. The runtime JavaScript types are decided\nby the underlying third-party driver such as ",(0,a.jsx)(n.code,{children:"pg"})," or ",(0,a.jsx)(n.code,{children:"mysql2"})," and it's up to you to select the correct\nTypeScript types in the database interface. Kysely never touches the runtime output types in\nany way. Find out more at ",(0,a.jsx)(n.a,{href:"https://kysely.dev/docs/recipes/data-types",children:'"Data types"'}),"."]})})]})}function F(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(_,{...e})}):_(e)}var N=t(5460),L=t(1620);function M(e){const{packageManager:n,packageManagerSelectionID:t}=e;if(!t)return null;const s=k[n||b];return(0,a.jsx)("p",{style:{display:"flex",justifyContent:"end"},children:(0,a.jsxs)(c.A,{to:`#${t}`,children:["I use a different package manager (not ",s,")"]})})}const R=[{value:"postgresql",driverDocsURL:"https://node-postgres.com/"},{value:"mysql",driverDocsURL:"https://github.com/sidorares/node-mysql2/tree/master/documentation"},{value:"mssql",driverDocsURL:"https://tediousjs.github.io/tedious/index.html",poolDocsURL:"https://github.com/vincit/tarn.js"},{value:"sqlite",driverDocsURL:"https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md"},{value:"pglite",driverDocsURL:"https://pglite.dev/docs"}];function U(e){const n=$({defaultValue:b,searchParam:e.packageManagerSearchParam,validator:e=>f.includes(e),value:e.packageManager});return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:["For Kysely's query compilation and execution to work, it needs to understand your database's SQL specification and how to communicate with it. This requires a ",(0,a.jsx)("code",{children:"Dialect"})," implementation.",(0,a.jsx)("br",{}),(0,a.jsx)("br",{}),"There are ",R.length," built-in dialects for PostgreSQL, MySQL, Microsoft SQL Server (MSSQL), SQLite, and PGlite. Additionally, the community has implemented several dialects to choose from. Find out more at ",(0,a.jsx)(c.A,{to:"/docs/dialects",children:'"Dialects"'}),"."]}),(0,a.jsx)(L.A,{as:"h3",children:"Driver installation"}),(0,a.jsxs)("p",{children:["A ",(0,a.jsx)("code",{children:"Dialect"})," implementation usually requires a database driver library as a peer dependency. Let's install it using the same package manager command from before:"]}),(0,a.jsx)(d.A,{queryString:"dialect",children:R.map(({driverDocsURL:e,poolDocsURL:t,value:s})=>{const r=v()[s],i=q[s],o=P[s],d="deno"===n?D({[r]:`npm:${r}`,[`${r}-pool`]:"pg"===r?"npm:pg-pool":void 0}):T(n,r,[i]);return(0,a.jsx)(p.A,{value:s,label:o,children:j(s,n)?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:["Kysely's built-in ",o,' dialect uses the "',r,'" driver library under the hood. Please refer to its'," ",(0,a.jsx)(c.A,{to:e,children:"official documentation"})," for configuration options."]}),i?(0,a.jsxs)("p",{children:["Additionally, Kysely's ",o,' dialect uses the "',i,'" resource pool package for connection pooling. Please refer to its'," ",(0,a.jsx)(c.A,{to:t,children:"official documentation"})," for configuration options."]}):null,(0,a.jsx)("p",{children:(0,a.jsx)("strong",{children:d.intro})}),(0,a.jsx)(l.A,{language:d.language,title:d.title,children:d.content})]}):(0,a.jsx)(Q,{dialect:o,driverNPMPackage:r,packageManager:n})},s)})}),(0,a.jsx)(M,{packageManager:n,packageManagerSelectionID:e.packageManagerSelectionID}),(0,a.jsxs)(N.A,{type:"info",title:"Driverless",children:["Kysely can also work in compile-only mode that doesn't require a database driver. Find out more at"," ",(0,a.jsx)(c.A,{to:"/docs/recipes/splitting-query-building-and-execution",children:'"Splitting query building and execution"'}),"."]})]})}function Q(e){const{dialect:n,packageManager:t}=e,s=k[t||"npm"];return(0,a.jsxs)(N.A,{type:"danger",title:"Driver unsupported",children:["Kysely's built-in ",n," dialect does not work in ",s," ",'because the driver library it uses, "',e.driverNPMPackage,"\", doesn't. You have to use a community ",n," dialect that works in"," ",s,", or implement your own."]})}function G(e){const{dialect:n,dialectSelectionID:t}=e;if(!t)return null;const s=P[n||g];return(0,a.jsx)("p",{style:{display:"flex",justifyContent:"end"},children:(0,a.jsxs)(c.A,{to:`#${t}`,children:["I use a different dialect (not ",s,")"]})})}function O(e){const{dialectSelectionID:n,packageManagerSelectionID:t}=e,s=$({defaultValue:g,searchParam:e.dialectSearchParam,validator:e=>h.includes(e),value:e.dialect}),r=$({defaultValue:b,searchParam:e.packageManagerSearchParam,validator:e=>f.includes(e),value:e.packageManager}),i=j(s,r)?function(e,n){const t=v(n)[e],s=w[e],a="Pool",r="deno"===n?a:`{ ${a} }`;if("postgresql"===e)return`import ${r} from '${t}'\nimport { Kysely, ${s} } from 'kysely'\n\nconst dialect = new ${s}({\n  pool: new ${a}({\n    database: 'test',\n    host: 'localhost',\n    user: 'admin',\n    port: 5434,\n    max: 10,\n  })\n})`;if("mysql"===e){const e="createPool";return`import { ${e} } from '${t}' // do not use 'mysql2/promises'!\nimport { Kysely, ${s} } from 'kysely'\n\nconst dialect = new ${s}({\n  pool: ${e}({\n    database: 'test',\n    host: 'localhost',\n    user: 'admin',\n    password: '123',\n    port: 3308,\n    connectionLimit: 10,\n  })\n})`}if("mssql"===e){const e=q.mssql;return`import * as ${t} from '${t}'\nimport * as ${e} from '${e}'\nimport { Kysely, ${s} } from 'kysely'\n\nconst dialect = new ${s}({\n  ${e}: {\n    ...${e},\n    options: {\n      min: 0,\n      max: 10,\n    },\n  },\n  ${t}: {\n    ...${t},\n    connectionFactory: () => new ${t}.Connection({\n      authentication: {\n        options: {\n          password: 'password',\n          userName: 'username',\n        },\n        type: 'default',\n      },\n      options: {\n        database: 'some_db',\n        port: 1433,\n        trustServerCertificate: true,\n      },\n      server: 'localhost',\n    }),\n  },\n})`}if("sqlite"===e){const e="SQLite";return`import ${e} from '${t}'\nimport { Kysely, ${s} } from 'kysely'\n\nconst dialect = new ${s}({\n  database: new ${e}(':memory:'),\n})`}if("pglite"===e){const e="PGlite";return`import { ${e} } from '${t}'\nimport { Kysely, ${s} } from 'kysely'\n\nconst dialect = new ${s}({\n  pglite: new ${e}(),\n})`}throw new Error(`Unsupported dialect: ${e}`)}(s,r):function(e,n){return`/* Kysely doesn't support ${P[e]} + ${k[n||"npm"]} out of the box. Import a community dialect that does here. */\nimport { Kysely } from 'kysely'\n\nconst dialect = /* instantiate the dialect here */`}(s,r),o=w[s];return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:[(0,a.jsx)("strong",{children:"Let's create a Kysely instance"}),j(s,r)?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("strong",{children:" using the built-in "}),(0,a.jsx)("code",{children:o}),(0,a.jsx)("strong",{children:" dialect"})]}):(0,a.jsx)("strong",{children:" assuming a compatible community dialect exists"}),(0,a.jsx)("strong",{children:":"})]}),(0,a.jsx)(l.A,{language:"ts",title:"src/database.ts",children:`import { Database } from './types.ts' // this is the Database interface we defined earlier\n${i}\n\n// Database interface is passed to Kysely's constructor, and from now on, Kysely \n// knows your database structure.\n// Dialect is passed to Kysely's constructor, and from now on, Kysely knows how \n// to communicate with your database.\nexport const db = new Kysely<Database>({\n  dialect,\n})`}),n||t?(0,a.jsxs)("div",{style:{display:"flex",gap:"25px",justifyContent:"end"},children:[(0,a.jsx)(M,{packageManager:r,packageManagerSelectionID:t}),(0,a.jsx)(G,{dialect:s,dialectSelectionID:n})]}):null,(0,a.jsx)(N.A,{type:"tip",title:"Singleton",children:"In most cases, you should only create a single Kysely instance per database. Most dialects use a connection pool internally, or no connections at all, so there's no need to create a new instance for each request."}),(0,a.jsx)(N.A,{type:"warning",title:"keeping secrets",children:"Use a secrets manager, environment variables (DO NOT commit `.env` files to your repository), or a similar solution, to avoid hardcoding database credentials in your code."}),(0,a.jsxs)(N.A,{type:"info",title:"kill it with fire",children:["When needed, you can dispose of the Kysely instance, release resources and close all connections by invoking the ",(0,a.jsx)("code",{children:"db.destroy()"})," ","function."]})]})}const E="export async function createPerson(person: NewPerson) {\
1n  return await db.insertInto('person')\n    .values(person)\n    .returningAll()\n    .executeTakeFirstOrThrow()\n}\n\nexport async function deletePerson(id: number) {\n  return await db.deleteFrom('person').where('id', '=', id)\n    .returningAll()\n    .executeTakeFirst()\n}",J={postgresql:E,mysql:"export async function createPerson(person: NewPerson) {\n  const { insertId } = await db.insertInto('person')\n    .values(person)\n    .executeTakeFirstOrThrow()\n\n  return await findPersonById(Number(insertId!))\n}\n\nexport async function deletePerson(id: number) {\n  const person = await findPersonById(id)\n\n  if (person) {\n    await db.deleteFrom('person').where('id', '=', id).execute()\n  }\n\n  return person\n}",mssql:"// As of v0.27.0, Kysely doesn't support the `OUTPUT` clause. This will change\n// in the future. For now, the following implementations achieve the same results\n// as other dialects' examples, but with extra steps.\n\nexport async function createPerson(person: NewPerson) {\n  const compiledQuery = db.insertInto('person').values(person).compile()\n\n  const {\n    rows: [{ id }],\n  } = await db.executeQuery<Pick<Person, 'id'>>({\n    ...compiledQuery,\n    sql: `${compiledQuery.sql}; select scope_identity() as id`\n  })\n\n  return await findPersonById(id)\n}\n\nexport async function deletePerson(id: number) {\n  const person = await findPersonById(id)\n\n  if (person) {\n    await db.deleteFrom('person').where('id', '=', id).execute()\n  }\n\n  return person\n}",sqlite:E,pglite:E};function Y(e){const n=$({defaultValue:g,searchParam:e.dialectSearchParam,validator:e=>h.includes(e),value:e.dialect}),t=J[n];return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:(0,a.jsx)("strong",{children:"Let's implement the person repository:"})}),(0,a.jsx)(l.A,{language:"ts",title:"src/PersonRepository.ts",children:`import { db } from './database'\nimport { PersonUpdate, Person, NewPerson } from './types'\n\nexport async function findPersonById(id: number) {\n  return await db.selectFrom('person')\n    .where('id', '=', id)\n    .selectAll()\n    .executeTakeFirst()\n}\n\nexport async function findPeople(criteria: Partial<Person>) {\n  let query = db.selectFrom('person')\n\n  if (criteria.id) {\n    query = query.where('id', '=', criteria.id) // Kysely is immutable, you must re-assign!\n  }\n\n  if (criteria.first_name) {\n    query = query.where('first_name', '=', criteria.first_name)\n  }\n\n  if (criteria.last_name !== undefined) {\n    query = query.where(\n      'last_name',\n      criteria.last_name === null ? 'is' : '=',\n      criteria.last_name\n    )\n  }\n\n  if (criteria.gender) {\n    query = query.where('gender', '=', criteria.gender)\n  }\n\n  if (criteria.created_at) {\n    query = query.where('created_at', '=', criteria.created_at)\n  }\n\n  return await query.selectAll().execute()\n}\n\nexport async function updatePerson(id: number, updateWith: PersonUpdate) {\n  await db.updateTable('person').set(updateWith).where('id', '=', id).execute()\n}\n\n${t}`}),(0,a.jsx)(G,{dialect:n,dialectSelectionID:e.dialectSelectionID}),(0,a.jsxs)(N.A,{type:"info",title:"But wait, there's more!",children:["This is a simplified example with basic CRUD operations. Kysely supports many more SQL features including: joins, subqueries, complex boolean logic, set operations, CTEs, functions (aggregate and window functions included), raw SQL, transactions, DDL queries, etc.",(0,a.jsx)("br",{}),"Find out more at ",(0,a.jsx)(c.A,{to:"/docs/category/examples",children:"Examples"}),"."]})]})}const B="    await db.schema.createTable('person')\n      .addColumn('id', 'serial', (cb) => cb.primaryKey())\n      .addColumn('first_name', 'varchar', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'timestamp', (cb) =>\n        cb.notNull().defaultTo(sql`now()`)\n      )\n      .execute()",W={postgresql:B,mysql:"    await db.schema.createTable('person')\n      .addColumn('id', 'integer', (cb) => cb.primaryKey().autoIncrement())\n      .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar(255)')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'timestamp', (cb) =>\n        cb.notNull().defaultTo(sql`now()`)\n      )\n      .execute()",mssql:"    await db.schema.createTable('person')\n      .addColumn('id', 'integer', (cb) => cb.primaryKey().modifyEnd(sql`identity`))\n      .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar(255)')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'datetime', (cb) =>\n        cb.notNull().defaultTo(sql`GETDATE()`)\n      )\n      .execute()",sqlite:"    await db.schema.createTable('person')\n      .addColumn('id', 'integer', (cb) => cb.primaryKey().autoIncrement().notNull())\n      .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())\n      .addColumn('last_name', 'varchar(255)')\n      .addColumn('gender', 'varchar(50)', (cb) => cb.notNull())\n      .addColumn('created_at', 'timestamp', (cb) =>\n        cb.notNull().defaultTo(sql`current_timestamp`)\n      )\n      .execute()",pglite:B},V="await sql`truncate table ${sql.table('person')}`.execute(db)",z={postgresql:V,mysql:V,mssql:V,sqlite:"await sql`delete from ${sql.table('person')}`.execute(db)",pglite:V};function H(e){const n=$({defaultValue:g,searchParam:e.dialectSearchParam,validator:e=>h.includes(e),value:e.dialect}),t=W[n],s=z[n];return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:["We've seen how to install and instantiate Kysely, its dialects and underlying drivers. We've also seen how to use Kysely to query a database.",(0,a.jsx)("br",{}),(0,a.jsx)("br",{}),(0,a.jsx)("strong",{children:"Let's put it all to the test:"})]}),(0,a.jsx)(l.A,{language:"ts",title:"src/PersonRepository.spec.ts",children:`import { sql } from 'kysely'\nimport { db } from './database'\nimport * as PersonRepository from './PersonRepository'\n\ndescribe('PersonRepository', () => {\n  before(async () => {\n${t}\n  }
1)\n    \n  afterEach(async () => {\n    ${s}\n  })\n    \n  after(async () => {\n    await db.schema.dropTable('person').execute()\n  })\n    \n  it('should find a person with a given id', async () => {\n    await PersonRepository.findPersonById(123)\n  })\n    \n  it('should find all people named Arnold', async () => {\n    await PersonRepository.findPeople({ first_name: 'Arnold' })\n  })\n    \n  it('should update gender of a person with a given id', async () => {\n    await PersonRepository.updatePerson(123, { gender: 'woman' })\n  })\n    \n  it('should create a person', async () => {\n    await PersonRepository.createPerson({\n      first_name: 'Jennifer',\n      last_name: 'Aniston',\n      gender: 'woman',\n    })\n  })\n    \n  it('should delete a person with a given id', async () => {\n    await PersonRepository.deletePerson(123)\n  })\n})`}),(0,a.jsx)(G,{dialect:n,dialectSelectionID:e.dialectSelectionID}),(0,a.jsxs)(N.A,{type:"info",title:"Migrations",children:['As you can see, Kysely supports DDL queries. It also supports classic "up/down" migrations. Find out more at'," ",(0,a.jsx)(c.A,{to:"/docs/migrations",children:"Migrations"}),"."]})]})}const X={sidebar_position:2,title:"Getting started",description:"Get started with Kysely: install the package, define database types, configure a dialect, and write your first type-safe SQL queries."},Z="Getting started",ee={},ne=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Types",id:"types",level:2},{value:"Dialects",id:"dialects",level:2},{value:"Instantiation",id:"instantiation",level:2},{value:"Querying",id:"querying",level:2},{value:"Summary",id:"summary",level:2}];function te(e){const n={h1:"h1",h2:"h2",header:"header",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"getting-started",children:"Getting started"})}),"\n",(0,a.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,a.jsx)(o,{}),"\n",(0,a.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,a.jsx)(C,{}),"\n",(0,a.jsx)(n.h2,{id:"types",children:"Types"}),"\n",(0,a.jsx)(F,{}),"\n",(0,a.jsx)(n.h2,{id:"dialects",children:"Dialects"}),"\n",(0,a.jsx)(U,{packageManagerSearchParam:"package-manager",packageManagerSelectionID:"installation"}),"\n",(0,a.jsx)(n.h2,{id:"instantiation",children:"Instantiation"}),"\n",(0,a.jsx)(O,{dialectSearchParam:"dialect",dialectSelectionID:"dialects",packageManagerSearchParam:"package-manager",packageManagerSelectionID:"installation"}),"\n",(0,a.jsx)(n.h2,{id:"querying",children:"Querying"}),"\n",(0,a.jsx)(Y,{dialectSearchParam:"dialect",dialectSelectionID:"dialects"}),"\n",(0,a.jsx)(n.h2,{id:"summary",children:"Summary"}),"\n",(0,a.jsx)(H,{dialectSearchParam:"dialect",dialectSelectionID:"dialects"})]})}function se(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(te,{...e})}):te(e)}},8330(e){e.exports={rE:"0.29.6"}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.