VibORM

L3 - Query Schemas

Validation schemas generated for where, create, update, and args operations

Location: src/schema/model/schemas/

Why This Layer Exists

VibORM validates query inputs at runtime:

orm.user.findMany({
  where: { email: { contains: "@example.com" } },  // Validated!
  include: { posts: true },                         // Validated!
});

Query schemas define what's valid for each operation. They're built dynamically from model definitions.

Schema Categories

Core Schemas (Per Field)

Each field type generates its own schemas:

SchemaPurposeExample
BaseRaw input validationstring or null
FilterWhere clause operators{ contains: string }
CreateCreate operation inputRequired unless defaulted
UpdateUpdate operation inputOptional, can be null

Args Schemas (Per Model)

Models compose field schemas into operation schemas:

SchemaPurpose
WhereSchemaFull where clause with all fields
CreateDataSchemaFull data for create operations
UpdateDataSchemaFull data for update operations
FindArgswhere + select + include + orderBy
CreateArgsdata with nested relation creates
UpdateArgswhere + data with nested writes

Dynamic Schema Generation

Schemas are generated based on field state:

// If field is nullable + has default:
// - Filter: allows null comparisons
// - Create: optional (has default)  
// - Update: accepts null or value

The logic considers:

  • Is the field nullable?
  • Does it have a default value?
  • Is it an auto-generated field (UUID, timestamps)?
  • Is it optional vs required?

Handling Relations

Relations add complexity because queries can be nested:

orm.user.findMany({
  where: {
    posts: { some: { published: true } }  // Nested where
  },
  include: {
    posts: {
      where: { published: true },  // Nested filter
      select: { title: true }      // Nested select
    }
  }
});

Query schemas handle this with recursive definitions using thunks to avoid infinite loops.

Why Lazy Building?

Schemas are expensive to construct - they compose many nested objects. VibORM builds them only when first accessed:

model["~"].schemas.where  // Built on first access, then cached

This keeps schema definition fast, deferring the cost until query time.

Connection to Other Layers

  • L1 (Validation): Query schemas use v.* primitives
  • L2 (Fields): Field schemas are composed into model schemas
  • L4 (Relations): Relation schemas enable nested queries
  • L6 (Query Engine): Query engine validates against these schemas

On this page