db
Connect your database so every request can use it.
kitr doesn't ship an ORM. Use the one you like: Drizzle, Prisma, Kysely, or a plain pg pool. kitr/db does the part that every app repeats. It opens the connection when the app starts, makes it available to every controller and action, and closes it cleanly when the server stops.
Install
kitr add dbFirst time? Run npm i -g kitr once. Inside a project, the global kitr runs your project's own version.
This needs the server package. It writes config/db.ts and adds DATABASE_URL to .env.
Connect
Fill in config/db.ts with your ORM. With Drizzle and postgres.js (pnpm add drizzle-orm postgres):
// config/db.ts
import { defineDb } from 'kitr/db'
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
export default defineDb({
connect: () => drizzle(postgres(process.env.DATABASE_URL!)),
disconnect: (db) => db.$client.end(),
})
export type AppDb = ReturnType<typeof drizzle>
| Option | Default | Description |
|---|---|---|
connect(app) |
required | Returns the client. It runs once, the first time something uses db. |
disconnect(db, app) |
none | Runs when the server shuts down. |
onReady(db, app) |
none | Runs once the app has started, for example to check for pending migrations. |
Use it
In a controller, ctx.app is the app for the current request:
import { useDb } from 'kitr/db'
import type { AppDb } from '#config/db'
import type { HttpContext } from 'kitr/api'
export default class ProjectsController {
async index(ctx: HttpContext) {
const db = useDb<AppDb>(ctx.app)
return db.select().from(projects)
}
}
In an action or a service, use useDb<AppDb>(useRequestApp(app)) from kitr/server. ctx.app.container.use('db') returns the same client without the type.
Migrations
Run migrations with your ORM's own tools, such as drizzle-kit migrate or prisma migrate deploy. kitr stays out of the way so their docs apply unchanged.
Tests
Point DATABASE_URL at a test database. Or, in testing, bind a fake before the app boots:
const app = await createTestApp()
app.container.value('db', fakeDb)