Schema Definition
Define type-safe database schemas with VibORM
Schema Definition
The schema module is the foundation of VibORM. It provides a fluent, chainable API for defining database models, fields, and relations with full TypeScript type inference.
Overview
import { s } from "viborm";
const user = s.model({
id: s.string().id().ulid(),
email: s.string().unique(),
name: s.string().nullable(),
posts: s.relation.oneToMany(() => post),
}).map("users");Key Concepts
The s Builder
All schema definitions use the s builder object:
import { s } from "viborm";
s.model({ ... }) // Create a model
s.string() // String field
s.int() // Integer field
s.relation.oneToMany(...) // One-to-many relation
// ... and moreChainable API
Every method returns a new instance, enabling fluent definitions:
s.string() // Basic string
.nullable() // Can be null
.unique() // Unique constraint
.default("value") // Default value
.map("column_name") // Custom column nameType Inference
Types are inferred automatically from your schema:
const user = s.model({
id: s.string().id(),
email: s.string(),
age: s.int().nullable(),
});
// Inferred type:
// { id: string; email: string; age: number | null }Components
Models
Define database tables with fields and relations
Fields
Scalar field types: string, int, boolean, etc.
Relations
Define relationships between models
Native Types
Database-specific type overrides
Validation
Schema validation rules and error handling
Architecture
The schema module consists of:
| Component | Purpose |
|---|---|
| Model | Represents a database table |
| Fields | Scalar columns (string, int, etc.) |
| Relations | Connections between models |
| Validation | Schema correctness checks |
| Runtime Schemas | ArkType validation schemas |
State-Based Generics
VibORM uses a single State generic pattern for future-proof type inference:
// Field state tracks all modifiers
class StringField<State extends FieldState<"string">> {
nullable(): StringField<UpdateState<State, { nullable: true }>>
// ...
}
// Model state tracks fields and constraints
class Model<State extends ModelState> {
id(fields: ...): Model<ModelState<...>>
// ...
}This pattern ensures that adding new features won't break existing code.