Skip to content
VibORM
Esc
navigateopen⌘Jpreview
On this page

Relations Overview

Define relationships between models — oneToOne, oneToMany, manyToOne, and manyToMany

Chainable API

VibORM uses a chainable API for defining relations:

s.manyToOne(() => targetModel).fields("fk").references("id")

The thunk () => targetModel comes first to handle circular references between models, then configuration methods are chained.

Relation Types

Relation Description Example
s.oneToOne() One record relates to one other User → Profile
s.oneToMany() One record relates to many User → Posts
s.manyToOne() Many records relate to one Post → Author
s.manyToMany() Many relate to many Post ↔ Tags

Quick Example

import { s } from "viborm";

const user = s.model({
  id: s.string().id().ulid(),
  email: s.string().unique(),
  profile: s.oneToOne(() => profile).optional(),
  posts: s.oneToMany(() => post),
});

const profile = s.model({
  id: s.string().id().ulid(),
  bio: s.string(),
  userId: s.string().unique(),
  user: s.oneToOne(() => user)
    .fields("userId")
    .references("id"),
});

const post = s.model({
  id: s.string().id().ulid(),
  title: s.string(),
  authorId: s.string(),
  author: s.manyToOne(() => user)
    .fields("authorId")
    .references("id"),
  tags: s.manyToMany(() => tag),
});

const tag = s.model({
  id: s.string().id().ulid(),
  name: s.string().unique(),
  posts: s.manyToMany(() => post),
});

Methods by Relation Type

ToOne Relations (oneToOne, manyToOne)

s.manyToOne(() => target)
  .fields("authorId")       // FK field on current model
  .references("id")         // Referenced field on target model
  .optional()               // Mark as optional (FK can be null)
  .onDelete("cascade")      // Referential action on delete
  .onUpdate("cascade")      // Referential action on update
  .name("author")           // Custom relation name

ToMany Relations (oneToMany)

s.oneToMany(() => target)
  .name("posts")            // Custom relation name (only method needed)

The FK configuration is done on the manyToOne side, not here.

ManyToMany Relations

s.manyToMany(() => target)
  .through("post_tags")     // Junction table name
  .A("postId")              // Source FK in junction table
  .B("tagId")               // Target FK in junction table
  .onDelete("cascade")      // Referential action (applies to both FKs)
  .onUpdate("cascade")      // Referential action (applies to both FKs)
  .name("tags")             // Custom relation name

Referential Actions

.onDelete() and .onUpdate() accept one of four actions:

Action Description
cascade Delete/update related records
setNull Set FK to NULL (requires nullable FK and .optional())
restrict Prevent delete/update if related records exist
noAction Database default behavior

This is the canonical reference — the per-relation pages link back here.

Pages

Was this page helpful?