API reference@evolu/commonlocal‑first/Schema › EvoluSchema

type EvoluSchema = ReadonlyRecord<string, TableSchema>;

Defined in: packages/common/src/local-first/Schema.ts:140

Defines the schema of an Evolu database.

Column types are Standard Schema v1 compatible — use Evolu Type, Zod, Valibot, ArkType, or any library that implements Standard Schema.

Each column schema's inferred output must be compatible with SQLite. Numeric outputs must be assignable to FiniteNumber. Standard Schema does not standardize nominal brands, so a library-specific finite validator whose output remains number must brand its validated output compatibly.

Table schema defines columns that are required for table rows. For optional columns, use a schema whose output type includes null.

Prefer applying defaults when reading or displaying data. A nullable column can preserve the distinction between "not specified" and an explicitly chosen value. For example, null can mean no notification preference, while an explicit false value means notifications were disabled.

Use withDefault only when replacing absence is intentional. Storing defaulted values can add unnecessary data to database rows and erase that distinction. Store a value when it represents a user's decision or another fact your application needs to retain.

Example

import * as z from "zod";
import {
  assertOk,
  assertType,
  assertTrue,
  type FiniteNumber,
  id,
  NonEmptyTrimmedString100,
  nullOr,
  SqliteBoolean,
} from "@evolu/common";

// Evolu Type
const TodoId = id("Todo");
type TodoId = typeof TodoId.Output;

const Schema = {
  todo: {
    id: TodoId,
    title: NonEmptyTrimmedString100,
    isCompleted: nullOr(SqliteBoolean),
  },
};
assertOk(Schema.todo.title.fromUnknown("Write docs"), "Write docs");

// Zod, or another Standard Schema library
// Zod 4 numbers are finite by default; Evolu Type Number models all JavaScript numbers.
const ZodFiniteNumber = z
  .number()
  .transform((value): FiniteNumber => value as FiniteNumber);
assertType<z.output<typeof ZodFiniteNumber>, FiniteNumber>();

const ZodSchema = {
  todo: {
    id: TodoId,
    title: z.string().min(1).max(100),
    position: ZodFiniteNumber,
    isCompleted: z.union([z.literal(0), z.literal(1)]).nullable(),
  },
};
assertTrue(ZodSchema.todo.title.safeParse("Write docs").success);