Inference, not generation
Types flow from immutable schema definitions into every client operation and result.
Define a schema in TypeScript and query PostgreSQL, MySQL, or SQLite with a fully inferred, Prisma-inspired client. No code generation. No stale types.
pnpm add vibormYour schema is the type source. Every filter, relation, selection, and result is inferred directly from it.
import { s } from "viborm";
export const user = s.model({
id: s.string().id().ulid(),
email: s.string().unique(),
posts: s.oneToMany(() => post),
});
export const post = s.model({
id: s.string().id().ulid(),
title: s.string(),
published: s.boolean().default(false),
authorId: s.string(),
author: s.manyToOne(() => user)
.fields("authorId")
.references("id"),
});const authors = await client.user.findMany({
where: {
email: { contains: "@company.com" },
},
include: {
posts: {
where: { published: true },
orderBy: { title: "asc" },
},
},
});Everything stays connected
Change a field and TypeScript follows the change into filters, writes, relations, selections, and returned records immediately.
Types flow from immutable schema definitions into every client operation and result.
Use familiar create, find, update, upsert, delete, aggregation, and transaction APIs.
Keep one schema and one query surface across PostgreSQL, MySQL, and SQLite.
Model one-to-one, one-to-many, and many-to-many relations with typed nested reads and writes.
Validate through the Standard Schema interface and interoperate with its growing ecosystem.
Run on Node.js, Bun, serverless databases, and Cloudflare D1 through focused drivers.
A typed relational core, database extensions, and production tooling in one ORM.
Adapter-owned SQL
VibORM keeps query intent separate from dialect syntax. You keep the same model and client API while the adapter handles the SQL each database needs.
Explore every driverpg, postgres.js, Neon HTTP, PGlite, and Bun SQL
mysql2, PlanetScale, and Bun SQL
sqlite3, libSQL, Bun SQLite, and Cloudflare D1
Database isomorphisms
VibORM gives PostgreSQL, MySQL, and SQLite one portable schema and client API, so switching drivers does not require rewriting application code.
s.string().array()text[]JSONJSON texts.enum([…])Named ENUM typeENUM(…)TEXT + CHECKs.boolean()booleanTINYINT(1)INTEGER 0/1s.dateTime()timestamptzDATETIME(3)ISO TEXTs.decimal()numericDECIMAL(65,30)TEXTOne schema. One query API. Three database engines.
Start with an in-process PostgreSQL database, then move to your production driver without changing the way you model or query data.