Skip to main content

Getting Started

This guide walks you through setting up @casekit/orm in a new project.

Prerequisites

  • Node.js 20+
  • PostgreSQL database
  • npm, yarn, or pnpm
  • TypeScript with strict: true in your tsconfig.json
TypeScript Strict Mode Required

The ORM's type inference for queries (especially include clauses for relations) requires TypeScript strict mode. Without it, included relations won't appear in the result types.

tsconfig.json
{
"compilerOptions": {
"strict": true
}
}

Installation

npm add @casekit/orm @casekit/orm-cli @casekit/orm-migrate pg zod

Initialize Your Project

The CLI can scaffold your project structure:

npx orm init --directory ./src/db

This creates:

  • src/db/index.ts — Database connection
  • src/db/models/index.ts — Model exports
  • orm.config.ts — CLI configuration

Define Your Models

Create a model file for each table. Here's an example author model:

// src/db/models/author.ts
import type { ModelDefinition } from "@casekit/orm";
import { sql } from "@casekit/sql";

export const author = {
fields: {
id: { type: "serial", primaryKey: true },
name: { type: "text" },
email: { type: "text", unique: true },
bio: { type: "text", nullable: true },
createdAt: { type: "timestamptz", default: sql`now()` },
},
relations: {
books: {
type: "1:N",
model: "book",
fromField: "id",
toField: "authorId",
},
},
} as const satisfies ModelDefinition;

And a related book model:

// src/db/models/book.ts
import type { ModelDefinition } from "@casekit/orm";
import { sql } from "@casekit/sql";

export const book = {
fields: {
id: { type: "serial", primaryKey: true },
title: { type: "text" },
authorId: {
type: "integer",
references: { model: "author", field: "id" },
},
published: { type: "boolean", default: false },
createdAt: { type: "timestamptz", default: sql`now()` },
},
relations: {
author: {
type: "N:1",
model: "author",
fromField: "authorId",
toField: "id",
},
},
} as const satisfies ModelDefinition;

Export your models from the index:

// src/db/models/index.ts
export { author } from "./author.js";
export { book } from "./book.js";

Configure the Database

Set up your database connection:

// src/db/index.ts
import { orm, type Config, type ModelType, type Orm } from "@casekit/orm";
import { snakeCase } from "es-toolkit";
import * as models from "./models/index.js";

const config = {
models,
naming: { column: snakeCase },
connection: {
host: "localhost",
port: 5432,
database: "myapp",
user: "postgres",
password: "password",
},
} as const satisfies Config;

export const db = orm(config);

// Type exports for use elsewhere
export type DB = Orm<typeof config>;
export type Models = typeof models;
export type Model<M extends keyof Models> = ModelType<Models[M]>;

Push Schema to Database

Create the tables in your database:

createdb myapp
npx orm db push

Basic Operations

Create a Record

const author = await db.createOne("author", {
values: {
name: "Jane Austen",
email: "jane@example.com",
},
returning: ["id", "name", "createdAt"],
});

Find a Record

const author = await db.findOne("author", {
select: ["id", "name", "email"],
where: { id: 1 },
});

Find Many Records

const authors = await db.findMany("author", {
select: ["id", "name"],
orderBy: [["name", "asc"]],
});

Update a Record

const updated = await db.updateOne("author", {
set: { bio: "English novelist known for romantic fiction" },
where: { id: 1 },
returning: ["id", "name", "bio"],
});

Delete a Record

const deleted = await db.deleteOne("author", {
where: { id: 1 },
returning: ["id"],
});

Development Setup

For development, you'll want to reuse the database connection across hot reloads:

// src/db/index.ts
import { orm, type Config, type Orm } from "@casekit/orm";

const config = { /* ... */ } as const satisfies Config;

let db: Orm<typeof config>;

declare global {
var __db: Orm<typeof config>;
}

if (process.env.NODE_ENV === "production") {
db = orm(config);
await db.connect();
} else {
if (!global.__db) {
global.__db = orm(config);
await global.__db.connect();
}
db = global.__db;
}

export { db };

Next Steps