Relations
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 nameToMany 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 nameReferential Actions
| Action | Description |
|---|---|
cascade | Delete/update related records |
setNull | Set FK to NULL (requires nullable FK) |
restrict | Prevent delete/update if related records exist |
noAction | Database default behavior |
Class Structure
VibORM uses standalone classes for different relation types:
ToOneRelation → oneToOne, manyToOne
ToManyRelation → oneToMany
ManyToManyRelation → manyToManyEach class only exposes methods relevant to that relation type.