VibORM

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 more

Chainable 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 name

Type 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

Architecture

The schema module consists of:

ComponentPurpose
ModelRepresents a database table
FieldsScalar columns (string, int, etc.)
RelationsConnections between models
ValidationSchema correctness checks
Runtime SchemasArkType 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.

On this page