db
Connect your database so every request can use it.
What it is
@kitr/db connects your database to the app lifecycle. Describe the connection once with defineDb; the provider opens it at boot, hands it to useDb() everywhere on the server and closes it on shutdown.
It ships no ORM and runs on the server only. For data on the device, use storage.
Install
kitr add dbFirst time? Run npm i -g @kitr/kitr once. Inside a project, the global kitr runs your project's own version.
Adds @kitr/db, its provider, config/db.ts and DATABASE_URL in .env.example. Bring your own ORM. Every change.
Quick start
With Drizzle and postgres.js installed (pnpm add drizzle-orm postgres), describe the connection once:
// config/db.ts
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import { defineDb } from '@kitr/db'
import * as schema from '#server/db/schema'
const createDb = () => drizzle(postgres(process.env.DATABASE_URL!), { schema })
/** The client every controller and action gets from useDb<AppDb>(). */
export type AppDb = ReturnType<typeof createDb>
export default defineDb({
connect: () => createDb(),
disconnect: (db) => db.$client.end(),
})
Then read it anywhere on the server:
// server/controllers/orders_controller.ts
import type { HttpContext } from '@kitr/api'
import { useDb } from '@kitr/db'
import type { AppDb } from '#config/db'
export default class OrdersController {
async index({ app }: HttpContext) {
return useDb<AppDb>(app).query.orders.findMany()
}
}
Point DATABASE_URL at a running database and run kitr dev. The provider connects at boot and refuses to start if the database is unreachable. Next in the guide: Connect with Drizzle.
Built on
@kitr/db is built on the kitr server lifecycle and container. The database client itself is whichever you bring:
| ORM or driver | Docs |
|---|---|
| Drizzle (the guide's examples) | orm.drizzle.team |
| Prisma | prisma.io/docs |
| Kysely | kysely.dev |
| node-postgres | node-postgres.com |
kitr adds the typed definition, startup validation of DATABASE_URL, the migration check, useDb() and clean shutdown.
Problems it solves
- A client created in every file. Connect with Drizzle.
- Database code in controllers, actions and jobs looking different. Query from a controller.
- A bad connection string found on the first request. Validate DATABASE_URL at startup.
- Deploying code ahead of its migrations. Check migrations when the server starts.
- Connections left open on shutdown. Close the connection on shutdown.