Skip to content
VibORM
Esc
navigateopen⌘Jpreview
On this page

Client API

Query and mutate data with full type safety — all operations inferred from your schema, no code generation required

Creating a Client

import { createClient } from "viborm/pg";
import { user, post } from "./schema";

const client = createClient({
  schema: { user, post },
  databaseUrl: process.env.DATABASE_URL,
});

Operations

Every operation works identically on every database. Prisma-inspired, not a drop-in replacement — see Compatibility for the differences.

Queries

Operation Description Returns
findMany Find multiple records T[]
findFirst Find first matching record T | null
findUnique Find by unique identifier T | null
exist Check if any record matches boolean
count Count records number
aggregate Compute min/max/sum/avg/count { _count, _avg, ... }
groupBy Group records and aggregate per group grouped rows

findFirstOrThrow and findUniqueOrThrow throw NotFoundError instead of returning null — documented on their base operation’s page.

Mutations

Operation Description Returns
create Create a record, with relations T
createMany Create multiple records { count }, or T[] with select
update Update a record T
updateMany Update every match { count }, or T[] with select
upsert Create or update T
delete Delete a record T
deleteMany Delete every match { count }, or T[] with select
Nested writes Write related records in one call

createMany, updateMany, and deleteMany return the affected rows instead of a count when the call carries a select — there are no separate createManyAndReturn / updateManyAndReturn methods, and deleteMany gains a returning form Prisma does not have. See each operation’s page.

Quick Examples

// Find many with filters
const users = await client.user.findMany({
  where: { role: "ADMIN" },
  orderBy: { createdAt: "desc" },
  take: 10,
});

// Find unique by ID
const user = await client.user.findUnique({
  where: { id: "user_123" },
});

// Create a record
const newUser = await client.user.create({
  data: {
    email: "alice@example.com",
    name: "Alice",
  },
});

// Update with relations
const updated = await client.user.update({
  where: { id: "user_123" },
  data: {
    name: "Alice Smith",
    posts: {
      create: { title: "New Post" },
    },
  },
  include: { posts: true },
});

// Count with filters
const count = await client.user.count({
  where: { role: "ADMIN" },
});

Type Safety

Every operation is fully typed:

// ✅ TypeScript knows the exact return type
const user = await client.user.findUnique({
  where: { id: "user_123" },
  select: { id: true, email: true },
});
// Type: { id: string; email: string } | null

// ❌ TypeScript catches invalid fields
await client.user.create({
  data: {
    email: "bob@example.com",
    invalidField: "value",  // Error!
  },
});

// ❌ TypeScript catches missing required fields
await client.user.create({
  data: {
    name: "Bob",
    // Error: 'email' is required
  },
});

Sections

Was this page helpful?