API reference › @evolu/common › local‑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);